Swiftの型システムを読む その18 - ConstraintLocator

December 19, 2017

ConstraintLocatorについて雑メモ。

ConstraintLocator

ConstraintLocatorの主な役割はExprがいくつかのSubExprから構成されている場合に「どの部分のSubExprを指すか」を表すもの。 どの部分を指すかの情報はConstraintLocator::PathElement を使って表す。 例えば (3, (x, 3.14)) のようなタプルのxを指したい場合は"tuple element #1" -> "tuple element #0" のような感じ。

PathElementにはPathElementKindで表された種類があって、上の例であればPathElementKind::TupleElementとなる。

PathElementKindPathElement::getKindで取れる。

PathElementKind getKind() const { ... }

また「何番目の」のような値を0~2つ持つことができ、それがvalue1, value2で表す。

unsigned getValue() const { ... }

unsigned getValue2() const { ... }

ConstraintLocatorが指しているExpranchorという名前で取得できる。

Expr *getAnchor() const { return anchor; }

Constraint

ConstraintConstraintLocatorを持っていて、そこからgetAnchor() を使ってどのExprに対するConstraintかを表すことができる。

ConstraintLocator *getLocator() const { return Locator; }
constraint->getLocator()->getAnchor()

ConstraintLocatorBuilder

/// \brief A simple stack-only builder object that constructs a
/// constraint locator without allocating memory.
///
/// Use this object to build a path when passing components down the
/// stack, e.g., when recursively breaking apart types as in \c matchTypes().

メモリをアロケートせずにConstraintLocatorを構築する、単純なスタック専用のBuilderオブジェクト。 このオブジェクトを使って、matchTypes() のように型を再帰的に分割する場合など、コンポーネントをスタックに渡すときにパスを構築する。

みたい。

ConstraintSystem

ConstraintSystemConstraintLocatorsを持っている。

llvm::FoldingSetVector<ConstraintLocator> ConstraintLocators;

getConstraintLocator 経由でConstraintLocatorで取るとConstraintLocatorsにあればそれを取得、なければ作ってConstraintLocatorsに追加してからそれを返す。

ConstraintLocator *ConstraintSystem::getConstraintLocator(
                     Expr *anchor,
                     ArrayRef<ConstraintLocator::PathElement> path,
                     unsigned summaryFlags) {
  assert(summaryFlags == ConstraintLocator::getSummaryFlagsForPath(path));

  // Check whether a locator with this anchor + path already exists.
  llvm::FoldingSetNodeID id;
  ConstraintLocator::Profile(id, anchor, path);
  void *insertPos = nullptr;
  auto locator = ConstraintLocators.FindNodeOrInsertPos(id, insertPos);
  if (locator)
    return locator;

  // Allocate a new locator and add it to the set.
  locator = ConstraintLocator::create(getAllocator(), anchor, path,
                                      summaryFlags);
  ConstraintLocators.InsertNode(locator, insertPos);
  return locator;
}

まとめ

主な用途はgetAnchor()してExprを取り出すことっぽいので、そう覚えておくことにする。

このエントリーをはてなブックマークに追加