Lowering для foreach: различия между версиями
Материал из Вики проекта PascalABC.NET
Перейти к навигацииПерейти к поиску
Mikst (обсуждение | вклад) (Новая страница: «Такой код <source lang="Delphi"> foreach var x in l do Print(x); </source> заменяется на <source lang="Delphi"> var a: IEnumerable<auto_…») |
Mikst (обсуждение | вклад) Нет описания правки |
||
Строка 21: | Строка 21: | ||
на синтаксическом уровне. | на синтаксическом уровне. | ||
После этого генератор yield преобразует синтаксическое дерево так, что строка: | |||
<source lang="Delphi"> | |||
var a: IEnumerable<auto_foreach> := l; | |||
</source> | |||
преобразуется в | |||
<source lang="Delphi"> | |||
// поле специального класса | |||
a: IEnumerable<auto_foreach> | |||
... | |||
// оператор в методе MoveNext этого класса | |||
a := l; | |||
</source> | |||
Так вот, auto_foreach при преобразовании синтаксиса в семантику переводится в специальный семантический тип auto_type, который исправляется в момент первого присваивания переменной a. | |||
Таким образом, в syntax_tree_visitor.cs в | |||
<source lang="Delphi"> | |||
public override void visit(SyntaxTree.assign _assign) | |||
</source> | |||
будет код, аналогичный автоопределению типа в момент первого присваивания для переменных типа auto_type: | |||
<source lang="Delphi"> | |||
public override void visit(SyntaxTree.assign _assign) | |||
{ | |||
... | |||
if (to.type is auto_type) | |||
{ | |||
if (to is class_field_reference) | |||
{ | |||
var cfr = to as class_field_reference; | |||
cfr.field.type = from.type; | |||
} | |||
else if (to is local_block_variable_reference) | |||
{ | |||
var lvr = to as local_block_variable_reference; | |||
lvr.var.type = from.type; | |||
} | |||
else AddError(to.location, "Не могу вывести тип при наличии yield: "+ to.type.full_name); | |||
//to.type = from.type; // и без всякого real_type! | |||
} | |||
</source> |
Версия от 11:07, 3 июля 2016
Такой код
foreach var x in l do
Print(x);
заменяется на
var a: IEnumerable<auto_foreach> := l;
var en := a.GetEnumerator();
var curr: auto_foreach; // или эта переменная была описана ранее если foreach x
while en.MoveNext do
begin
curr := en.Current;
Print(curr);
end;
на синтаксическом уровне.
После этого генератор yield преобразует синтаксическое дерево так, что строка:
var a: IEnumerable<auto_foreach> := l;
преобразуется в
// поле специального класса
a: IEnumerable<auto_foreach>
...
// оператор в методе MoveNext этого класса
a := l;
Так вот, auto_foreach при преобразовании синтаксиса в семантику переводится в специальный семантический тип auto_type, который исправляется в момент первого присваивания переменной a. Таким образом, в syntax_tree_visitor.cs в
public override void visit(SyntaxTree.assign _assign)
будет код, аналогичный автоопределению типа в момент первого присваивания для переменных типа auto_type:
public override void visit(SyntaxTree.assign _assign)
{
...
if (to.type is auto_type)
{
if (to is class_field_reference)
{
var cfr = to as class_field_reference;
cfr.field.type = from.type;
}
else if (to is local_block_variable_reference)
{
var lvr = to as local_block_variable_reference;
lvr.var.type = from.type;
}
else AddError(to.location, "Не могу вывести тип при наличии yield: "+ to.type.full_name);
//to.type = from.type; // и без всякого real_type!
}