Я изучаю внутренние компоненты компилятора f # (https://github.com/Microsoft/visualfsharp repo, dev16.0
branch), и я наткнулся на интересные части его абстрактного синтаксического дерева с проверкой типа. Вкратце, тип Expr
используется для представления некоторых узлов дерева, вот часть его определения:
Expr =
/// A constant expression.
| Const of Const * range * TType
///....
/// Typechecking residue: Indicates a free choice of typars that arises due to
/// minimization of polymorphism at let-rec bindings. These are
/// resolved to a concrete instantiation on subsequent rewrites.
| TyChoose of Typars * Expr * range
/// Typechecking residue: A Expr.Link occurs for every use of a recursively bound variable. While type-checking
/// the recursive bindings a dummy expression is stored in the mutable reference cell.
/// After type checking the bindings this is replaced by a use of the variable, perhaps at an
/// appropriate type instantiation. These are immediately eliminated on subsequent rewrites.
| Link of Expr ref
Что означают узлы TyChoose
и Link
? Комментарии дают некоторые объяснения, но они все еще слишком расплывчаты для меня. Есть ли код, который может прояснить такие выражения? По сути, я думал, что у typecheked ast не может быть некоторых остатков алгоритма вывода типов (другими словами, он используется только на этапе преобразования AST в AST с подписями). Final ast имеет только выражения с завершенными типами.
UPD : Кажется, что Link
узел не используется во время преобразования TAST -> ILX. Вот фрагмент кода, который показывает, что он удален:
let rec GenExpr (cenv:cenv) (cgbuf:CodeGenBuffer) eenv sp expr sequel =
let expr = stripExpr expr
//......
let rec stripExpr e =
match e with
| Expr.Link eref -> stripExpr !eref
| _ -> e