Множество правок, связанных с yield.
В частности, изменен алгоритм генерации конечного автомата, поправлен код для GetEnumerator и проч.
This commit is contained in:
parent
d635ad0d51
commit
c6eaba8f94
|
|
@ -470,7 +470,7 @@ namespace CodeCompletion
|
|||
List<SymInfo> result_names = new List<SymInfo>();
|
||||
if (elems == null) return null;
|
||||
for (int i=0; i<elems.Length; i++)
|
||||
if (pattern != null || pattern != "")
|
||||
if (pattern != null && pattern != "")
|
||||
{
|
||||
if (!elems[i].name.StartsWith("$"))
|
||||
if (all_names)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "1";
|
||||
public const string Build = "0";
|
||||
public const string Revision = "1256";
|
||||
public const string Revision = "1263";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%MINOR%=1
|
||||
%REVISION%=1256
|
||||
%COREVERSION%=0
|
||||
%REVISION%=1263
|
||||
%MINOR%=1
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -401,6 +401,8 @@ namespace PascalABCCompiler.NETGenerator
|
|||
private void AddTypeInstanceToFunction(ICommonFunctionNode func, IGenericTypeInstance gti)
|
||||
{
|
||||
List<IGenericTypeInstance> instances;
|
||||
//if (func == null) // SSM 3.07.16 Это решает проблему с оставшимся после перевода в сем. дерево узлом IEnumerable<UnknownType>, но очень грубо - пробую найти ошибку раньше
|
||||
// return;
|
||||
bool found = instances_in_functions.TryGetValue(func, out instances);
|
||||
if (!found)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -803,6 +803,181 @@
|
|||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="private Dictionary<Guid, semantic_type_node>">
|
||||
<FileName>\treeconverter\treeconversion\syntax_tree_visitor.cs</FileName>
|
||||
<Text>private Dictionary<Guid, semantic_type_node> _yieldForeachTypeMap = new Dictionary<Guid, semantic_type_node>();</Text>
|
||||
<OCtx>
|
||||
<i Type="Field">private Dictionary < Guid , semantic_type_node > _yieldForeachTypeMap = new Dictionary < Guid , semantic_type_node > ( )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="UnknownExprType">
|
||||
<Items>
|
||||
<Node Name=" visit(yield_unknown_expression_type">
|
||||
<FileName>\treeconverter\treeconversion\syntax_tree_visitor.cs</FileName>
|
||||
<Text>public override void visit(SyntaxTree.yield_unknown_expression_type _unk_expr)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( SyntaxTree . yield_unknown_expression_type _unk_expr )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="visit(SyntaxTree.assign">
|
||||
<FileName>\treeconverter\treeconversion\syntax_tree_visitor.cs</FileName>
|
||||
<Text>public override void visit(SyntaxTree.assign _assign)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( SyntaxTree . assign _assign )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name=" TypeInfo ti = helper.GetTypeReference(value.type);">
|
||||
<FileName>\netgenerator\netgenerator.cs</FileName>
|
||||
<Text>TypeInfo ti = helper.GetTypeReference(value.type);</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( SemanticTree . ICommonClassFieldNode value )</i>
|
||||
<i Type="ClassOrNamespace">public class ILConverter : AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . NETGenerator</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
</Items>
|
||||
</Node>
|
||||
<Node Name="UnknownForeachType">
|
||||
<Items>
|
||||
<Node Name="visit(yield_unknown_foreach_type">
|
||||
<FileName>\treeconverter\treeconversion\syntax_tree_visitor.cs</FileName>
|
||||
<Text>public override void visit(SyntaxTree.yield_unknown_foreach_type _unk)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( SyntaxTree . yield_unknown_foreach_type _unk )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="stl.Add(new assign(currentIdent">
|
||||
<FileName>\yield\syntaxvisitors\yieldvisitors\loweringvisitor.cs</FileName>
|
||||
<Text>stl.Add(new assign(currentIdent, new dot_node(enumeratorIdent, "Current")));</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( foreach_stmt frch )</i>
|
||||
<i Type="ClassOrNamespace">public class LoweringVisitor : BaseChangeVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace SyntaxVisitors</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="visit(SyntaxTree.assign">
|
||||
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
|
||||
<Text>public override void visit(SyntaxTree.assign _assign)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( SyntaxTree . assign _assign )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="if (to.type is compiled_type_node)">
|
||||
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
|
||||
<Text>else if (to.type is compiled_type_node)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( SyntaxTree . assign _assign )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="FindIEnumerableElementType">
|
||||
<FileName>\TreeConverter\TreeConversion\syntax_tree_visitor.cs</FileName>
|
||||
<OCtx>
|
||||
<i Type="Method">public bool FindIEnumerableElementType ( type_node tn , ref type_node elem_type )</i>
|
||||
<i Type="ClassOrNamespace">public class syntax_tree_visitor : SyntaxTree . AbstractVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeConverter</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="generic_convertions.all_type_instances.Add(instance);">
|
||||
<FileName>\TreeConverter\TreeRealization\generics.cs</FileName>
|
||||
<Text>generic_convertions.all_type_instances.Add(instance);</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public static void init_generic_instance ( type_node original , generic_instance_type_node instance , List < type_node > param_types )</i>
|
||||
<i Type="ClassOrNamespace">public static class generic_convertions</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeRealization</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="if (shouldAddToAllTypeInstances)">
|
||||
<FileName>\TreeConverter\TreeRealization\generics.cs</FileName>
|
||||
<Text>if (shouldAddToAllTypeInstances) //lroman// Если зашли сюда при выведении типов параметров лямбды, то тип инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. То данную инстанцию не добавляем</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public static void init_generic_instance ( type_node original , generic_instance_type_node instance , List < type_node > param_types )</i>
|
||||
<i Type="ClassOrNamespace">public static class generic_convertions</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . TreeRealization</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="ConstructFiniteAutomata">
|
||||
<FileName>\yield\syntaxvisitors\yieldvisitors\processyieldscapturedvars.cs</FileName>
|
||||
<OCtx>
|
||||
<i Type="ClassOrNamespace">class ConstructFiniteAutomata</i>
|
||||
<i Type="ClassOrNamespace">namespace SyntaxVisitors</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
<ICtx>
|
||||
<i Type="Field">public statement_list res = new statement_list ( )</i>
|
||||
<i Type="Field">statement_list stl</i>
|
||||
<i Type="Field">int curState = 0</i>
|
||||
<i Type="Field">statement_list curStatList</i>
|
||||
<i Type="Field">statement_list StatListAfterCase = new statement_list ( )</i>
|
||||
<i Type="Field">case_node cas</i>
|
||||
<i Type="Field">private labeled_statement OuterLabeledStatement</i>
|
||||
<i Type="Field">private Dictionary < int , labeled_statement > Dispatches = new Dictionary < int , labeled_statement > ( )</i>
|
||||
<i Type="Method">public ConstructFiniteAutomata ( statement_list stl )</i>
|
||||
<i Type="Method">private void AddState ( out int stateNumber , out ident resumeLabel )</i>
|
||||
</ICtx>
|
||||
</Node>
|
||||
</Items>
|
||||
</Node>
|
||||
<Node Name="NewConstructFiniteAutomata">
|
||||
<Items>
|
||||
<Node Name="ConstructFiniteAutomata1">
|
||||
<FileName>\yield\syntaxvisitors\yieldvisitors\processyieldscapturedvars.cs</FileName>
|
||||
<Text>public ConstructFiniteAutomata1(block bl)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public ConstructFiniteAutomata1 ( block bl )</i>
|
||||
<i Type="ClassOrNamespace">class ConstructFiniteAutomata1</i>
|
||||
<i Type="ClassOrNamespace">namespace SyntaxVisitors</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="GenClassesForYield">
|
||||
<FileName>\yield\syntaxvisitors\yieldvisitors\processyieldscapturedvars.cs</FileName>
|
||||
<Text>type_declarations GenClassesForYield(procedure_definition pd,</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">type_declarations GenClassesForYield ( procedure_definition pd , IEnumerable < var_def_statement > fields , IDictionary < string , string > localsMap , IDictionary < string , string > formalParamsMap , IDictionary < var_def_statement , var_def_statement > localsCloneMap , yield_locals_type_map_helper localTypeMapHelper )</i>
|
||||
<i Type="ClassOrNamespace">public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor</i>
|
||||
<i Type="ClassOrNamespace">namespace SyntaxVisitors</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
</Items>
|
||||
</Node>
|
||||
</Items>
|
||||
</Node>
|
||||
</Items>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.1.0.1256'
|
||||
!define VERSION '3.1.0.1263'
|
||||
|
|
|
|||
|
|
@ -708,7 +708,8 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
sb.Remove(0, 9);
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Insert(0, "function");
|
||||
sb.Append(": " + return_type.ToString() + ";");
|
||||
if (return_type!=null)
|
||||
sb.Append(": " + return_type.ToString() + ";");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1445,6 +1446,25 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
this.vars = vds;
|
||||
this.map_helper = map_helper;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.Append(vars.ToString());
|
||||
|
||||
/*if (vars_type != null)
|
||||
{
|
||||
sb.Append(": ");
|
||||
sb.Append(vars_type.ToString());
|
||||
}
|
||||
if (inital_value != null)
|
||||
{
|
||||
sb.Append(" := ");
|
||||
sb.Append(inital_value.ToString());
|
||||
}*/
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public partial class yield_variable_definitions_with_unknown_type : declaration
|
||||
|
|
@ -1579,5 +1599,13 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
}
|
||||
|
||||
public partial class array_type
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return "array of " + this.elements_type.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,10 +0,0 @@
|
|||
function f: sequence of integer;
|
||||
begin
|
||||
var t := Seq(1,3,5);
|
||||
foreach var k in t do
|
||||
yield k;
|
||||
end;
|
||||
|
||||
begin
|
||||
Assert(f.SequenceEqual(Seq(1,3,5)));
|
||||
end.
|
||||
|
|
@ -416,7 +416,7 @@ namespace TreeConverter.LambdaExpressions.Closure
|
|||
if (inWhat.type == null)
|
||||
inWhat = tmp;
|
||||
|
||||
_visitor.FindIEnumerableElementType(_foreach_stmt, inWhat.type, ref elemType);
|
||||
_visitor.FindIEnumerableElementType(/*_foreach_stmt, */inWhat.type, ref elemType);
|
||||
|
||||
if (_foreach_stmt.type_name == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -363,6 +363,8 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
public static string record_const_type_name = "RecordConst";
|
||||
public static string array_const_type_name = "ArrayConst";
|
||||
public static string auto_type_name = "AutoType"; // SSM 25.06.16 - тип, который определяется на этапе компиляции при первом присваивании
|
||||
public static string ienumerable_auto_type_name = "IEnumerableAutoType"; // SSM 05.07.16 - тип, который определяется на этапе компиляции при первом присваивании
|
||||
public static string recort_printable_name_template = "record{0}end";
|
||||
public static string set_name = "TypedSet";
|
||||
|
||||
|
|
|
|||
|
|
@ -15725,6 +15725,50 @@ namespace PascalABCCompiler.TreeConverter
|
|||
else
|
||||
{
|
||||
from = convert_strong(_assign.from);
|
||||
// SSM 26.06.16 - правка в связи с автовыведением типов в yieldах
|
||||
if (to.type is auto_type)
|
||||
{
|
||||
if (to is class_field_reference)
|
||||
{
|
||||
var cfr = to as class_field_reference;
|
||||
cfr.field.type = from.type;
|
||||
cfr.type = from.type;
|
||||
}
|
||||
else if (to is local_block_variable_reference)
|
||||
{
|
||||
var lvr = to as local_block_variable_reference;
|
||||
lvr.var.type = from.type;
|
||||
lvr.type = from.type;
|
||||
}
|
||||
else AddError(to.location, "Не могу вывести тип при наличии yield: "+ to.type.full_name);
|
||||
//to.type = from.type; // и без всякого real_type!
|
||||
}
|
||||
//else if (to.type is compiled_type_node)
|
||||
//else if (to.type.name.StartsWith("IEnumerable<IEnumerableAutoType>")) // Сделать не сравнением строк!!!
|
||||
else if (to.type is compiled_generic_instance_type_node && (to.type as compiled_generic_instance_type_node).instance_params[0] is ienumerable_auto_type)
|
||||
{
|
||||
var tt = to.type;
|
||||
type_node elem_type = null;
|
||||
var b = FindIEnumerableElementType(from.type, ref elem_type);
|
||||
if (!b)
|
||||
AddError(null, "FindIEnumerableElementType returns false");
|
||||
|
||||
var IEnumType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), new template_param_list(new semantic_type_node(elem_type)));
|
||||
if (to is class_field_reference)
|
||||
{
|
||||
var cfr = to as class_field_reference;
|
||||
|
||||
cfr.field.type = convert_strong(IEnumType);
|
||||
cfr.type = cfr.field.type;
|
||||
}
|
||||
else if (to is local_block_variable_reference)
|
||||
{
|
||||
var lvr = to as local_block_variable_reference;
|
||||
|
||||
lvr.var.type = convert_strong(IEnumType); // замена типа у описания переменной
|
||||
lvr.type = lvr.var.type; // замена типа у переменной
|
||||
}
|
||||
}
|
||||
}
|
||||
/// end
|
||||
|
||||
|
|
@ -16300,7 +16344,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool FindIEnumerableElementType(SyntaxTree.foreach_stmt _foreach_stmt, type_node tn, ref type_node elem_type)
|
||||
public bool FindIEnumerableElementType(/*SyntaxTree.foreach_stmt _foreach_stmt, */type_node tn, ref type_node elem_type)
|
||||
{
|
||||
var IEnstring = "System.Collections.IEnumerable";
|
||||
compiled_type_node ctn = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(IEnstring));
|
||||
|
|
@ -16465,7 +16509,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
in_what = tmp;
|
||||
//if (in_what.type.find_in_type("GetEnumerator") == null)
|
||||
|
||||
if (!FindIEnumerableElementType(_foreach_stmt, in_what.type, ref elem_type))
|
||||
if (!FindIEnumerableElementType(/*_foreach_stmt, */in_what.type, ref elem_type))
|
||||
//if (!IsGetEnumerator(in_what.type, ref elem_type))
|
||||
AddError(in_what.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", in_what.type.name);
|
||||
|
||||
|
|
@ -19054,13 +19098,17 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
public override void visit(SyntaxTree.yield_unknown_expression_type _unk_expr)
|
||||
{
|
||||
_unk_expr.MapHelper.vars_type_map[_unk_expr.Vds].visit(this);
|
||||
// Отвечает за типизацию всех переменных с автовыведением типа
|
||||
// Пробую сделать по-другому: перевести в auto_type и потом на присваивании перехватить
|
||||
// _unk_expr.MapHelper.vars_type_map[_unk_expr.Vds].visit(this);
|
||||
var t = new semantic_type_node(new auto_type(get_location(_unk_expr)));
|
||||
t.visit(this);
|
||||
}
|
||||
|
||||
// frninja - заполнение хелпера типов локальных переменных для yield
|
||||
public override void visit(SyntaxTree.yield_var_def_statement_with_unknown_type _vars)
|
||||
{
|
||||
if ((object)_vars.vars.vars_type != null)
|
||||
/*if ((object)_vars.vars.vars_type != null)
|
||||
{
|
||||
// Visit stored vars
|
||||
_vars.vars.visit(this);
|
||||
|
|
@ -19069,6 +19117,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
var t = convert_strong(_vars.vars.inital_value);
|
||||
_vars.map_helper.vars_type_map[_vars.vars] = new SyntaxTree.semantic_type_node(t.type);
|
||||
|
||||
*/
|
||||
// Visit stored vars
|
||||
_vars.vars.visit(this);
|
||||
}
|
||||
|
|
@ -19076,7 +19125,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
// frninja - заполнение хелпера типов локальных переменных для yield// frninja - заполнение хелпера типов локальных переменных для yield
|
||||
public override void visit(SyntaxTree.yield_variable_definitions_with_unknown_type _vars)
|
||||
{
|
||||
foreach (var vd in _vars.vars.list)
|
||||
/*foreach (var vd in _vars.vars.list)
|
||||
{
|
||||
if ((object)vd.vars_type != null)
|
||||
{
|
||||
|
|
@ -19084,7 +19133,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
var t = convert_strong(vd.inital_value);
|
||||
_vars.map_helper.vars_type_map[vd] = new SyntaxTree.semantic_type_node(t.type);
|
||||
}
|
||||
}*/
|
||||
|
||||
// Visit stored vars
|
||||
_vars.vars.visit(this);
|
||||
|
|
@ -19096,7 +19145,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
public override void visit(SyntaxTree.yield_unknown_foreach_type _unk)
|
||||
{
|
||||
|
||||
var _foreach_stmt = _unk.unknown_foreach;
|
||||
/*var _foreach_stmt = _unk.unknown_foreach;
|
||||
|
||||
semantic_type_node t;
|
||||
|
||||
|
|
@ -19115,8 +19164,10 @@ namespace PascalABCCompiler.TreeConverter
|
|||
t = new SyntaxTree.semantic_type_node(elem_type);
|
||||
// Add to map
|
||||
_yieldForeachTypeMap.Add(_foreach_stmt.Guid, t);
|
||||
}
|
||||
}*/
|
||||
// Visit type
|
||||
|
||||
var t = new semantic_type_node(new ienumerable_auto_type(get_location(_unk)));
|
||||
t.visit(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -344,7 +344,16 @@ namespace PascalABCCompiler.TreeRealization
|
|||
}
|
||||
|
||||
if (shouldAddToAllTypeInstances) //lroman// Если зашли сюда при выведении типов параметров лямбды, то тип инстанцироваться может с типом lambda_any_type_node. Поэтому, если выводим типы. То данную инстанцию не добавляем
|
||||
generic_convertions.all_type_instances.Add(instance);
|
||||
{
|
||||
if (instance.instance_params[0] is ienumerable_auto_type)
|
||||
{
|
||||
//instance = instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
generic_convertions.all_type_instances.Add(instance);
|
||||
}
|
||||
}
|
||||
|
||||
internal_interface ii = original.get_internal_interface(internal_interface_kind.delegate_interface);
|
||||
if (ii != null)
|
||||
|
|
|
|||
|
|
@ -4809,4 +4809,22 @@ namespace PascalABCCompiler.TreeRealization
|
|||
}
|
||||
}
|
||||
|
||||
// тип, который объявляется как auto и определяется при компиляции в момент первого присваивания
|
||||
// На 04.07.16 нужен только для генерации кода yield
|
||||
public class auto_type : undefined_type
|
||||
{
|
||||
//public type_node real_type = null;
|
||||
public auto_type(location loc)
|
||||
: base(compiler_string_consts.auto_type_name, loc) { }
|
||||
}
|
||||
|
||||
// тип, который объявляется как ienumerable_auto и определяется при компиляции в момент первого присваивания
|
||||
// На 04.07.16 нужен только для генерации кода yield
|
||||
public class ienumerable_auto_type : undefined_type
|
||||
{
|
||||
//public type_node real_type = null;
|
||||
public ienumerable_auto_type(location loc)
|
||||
: base(compiler_string_consts.ienumerable_auto_type_name, loc) { }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ namespace VisualPascalABC.Utils
|
|||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
//return null;
|
||||
}
|
||||
public string TempBatFile = null;
|
||||
public void Start(string command, string arguments, bool redirectIO, bool redirectErrors, bool RunWithPause, bool attachDebugger, bool fictive_attach)
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ namespace Converter
|
|||
{
|
||||
if (_word.Contains(specSymbol))
|
||||
{
|
||||
_word.Replace(specSymbol, "");
|
||||
_word = _word.Replace(specSymbol, "");
|
||||
return getWordValue(_word, specSymbol);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ namespace SyntaxVisitors
|
|||
OnEnter = Enter;
|
||||
OnLeave = Exit;
|
||||
this.filename = filename;
|
||||
if (filename != null)
|
||||
System.IO.File.Delete(filename);
|
||||
}
|
||||
|
||||
public void Println(string s)
|
||||
|
|
@ -44,6 +46,7 @@ namespace SyntaxVisitors
|
|||
}
|
||||
public void PrintNoOffset(string s)
|
||||
{
|
||||
s = s.Replace("PascalABCCompiler.SyntaxTree.", "").Replace("System.Collections.Generic.", "");
|
||||
if (filename == null)
|
||||
{
|
||||
Console.Write(s);
|
||||
|
|
@ -64,6 +67,8 @@ namespace SyntaxVisitors
|
|||
PrintNoOffset(st.GetType().Name + ": ");
|
||||
Println(""+st);
|
||||
}
|
||||
|
||||
|
||||
public virtual void Enter(syntax_tree_node st)
|
||||
{
|
||||
if (st is statement_list)
|
||||
|
|
@ -101,10 +106,8 @@ namespace SyntaxVisitors
|
|||
{
|
||||
var cd = st as class_definition;
|
||||
PrintNoOffset("class");
|
||||
if (cd.class_parents != null && cd.class_parents.types.Count > 0)
|
||||
{
|
||||
if (cd.class_parents?.types.Count > 0)
|
||||
PrintlnNoOffset("(" + cd.class_parents.ToString() + ")");
|
||||
}
|
||||
else
|
||||
PrintlnNoOffset("");
|
||||
off += 2;
|
||||
|
|
@ -114,23 +117,36 @@ namespace SyntaxVisitors
|
|||
else if (st is access_modifer_node)
|
||||
{
|
||||
var am = st as access_modifer_node;
|
||||
Println(am.access_level.ToString());
|
||||
|
||||
Println(am.access_level.ToString().Replace("_modifier",""));
|
||||
}
|
||||
else if (st is variable_definitions)
|
||||
{
|
||||
var vds = st as variable_definitions;
|
||||
Println("var");
|
||||
Print("var");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is var_def_statement)
|
||||
{
|
||||
var vds = st as var_def_statement;
|
||||
Println(vds.ToString());
|
||||
Println (vds.ToString());
|
||||
}
|
||||
else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members || st is case_variants || st is program_module)
|
||||
else if (st is yield_var_def_statement_with_unknown_type)
|
||||
{
|
||||
var vds = st as yield_var_def_statement_with_unknown_type;
|
||||
Println("var "+vds.ToString());
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members
|
||||
|| st is case_variants || st is program_module || st is no_type_foreach || st is template_param_list
|
||||
|| st is yield_unknown_foreach_type || st is yield_unknown_expression_type
|
||||
)
|
||||
{
|
||||
}
|
||||
/* else if (st is array_type)
|
||||
{
|
||||
var vds = st as array_type;
|
||||
Println ("array of "+vds.elements_type.ToString());
|
||||
}*/
|
||||
else if (st is if_node)
|
||||
{
|
||||
var ifn = st as if_node;
|
||||
|
|
@ -156,6 +172,13 @@ namespace SyntaxVisitors
|
|||
Println("while " + wn.expr.ToString() + " do");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is foreach_stmt)
|
||||
{
|
||||
var wn = st as foreach_stmt;
|
||||
|
||||
Println("foreach " + wn.identifier.ToString() + " in "+wn.in_what + " do");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is case_node)
|
||||
{
|
||||
var cn = st as case_node;
|
||||
|
|
@ -173,7 +196,10 @@ namespace SyntaxVisitors
|
|||
}
|
||||
else if (st is var_statement || st is procedure_header)
|
||||
{
|
||||
Println(st.ToString());
|
||||
var s = st.ToString();
|
||||
s = s.Replace("PascalABCCompiler.SyntaxTree.", "").Replace("System.Collections.Generic.","");
|
||||
|
||||
Println(s);
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is procedure_definition)
|
||||
|
|
@ -193,6 +219,13 @@ namespace SyntaxVisitors
|
|||
return;
|
||||
PrintlnNode(st);
|
||||
}
|
||||
/*else if (st is named_type_reference)
|
||||
{
|
||||
var s = st.ToString();
|
||||
s = s.Replace("PascalABCCompiler.SyntaxTree.", "").Replace("System.Collections.Generic.","");
|
||||
|
||||
PrintlnNoOffset(s);
|
||||
}*/
|
||||
else
|
||||
{
|
||||
var q = st.GetType().GetMethod("ToString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ namespace SyntaxVisitors
|
|||
}
|
||||
|
||||
private int _varnum = 0;
|
||||
private int _foreachCollectionNum = 0;
|
||||
private int _enumeratorNum = 0;
|
||||
|
||||
private VarNames NewVarNames(ident name)
|
||||
|
|
@ -52,6 +53,12 @@ namespace SyntaxVisitors
|
|||
return "$enumerator$" + _enumeratorNum;
|
||||
}
|
||||
|
||||
private ident NewForeachCollectionName()
|
||||
{
|
||||
++_foreachCollectionNum;
|
||||
return "$coll$" + _foreachCollectionNum;
|
||||
}
|
||||
|
||||
public static void Accept(procedure_definition pd)
|
||||
{
|
||||
New.ProcessNode(pd);
|
||||
|
|
@ -81,63 +88,99 @@ namespace SyntaxVisitors
|
|||
// frninja 21/05/16
|
||||
public override void visit(foreach_stmt frch)
|
||||
{
|
||||
// Полный код Loweringа c yield_unknown_foreach_type = integer
|
||||
// var a: System.Collections.Generic.IEnumerable<integer>;
|
||||
// a := l;
|
||||
// var en := a.GetEnumerator();
|
||||
// while en.MoveNext do
|
||||
// begin
|
||||
// var curr := en.Current; // var не нужно ставить если curr была описана раньше
|
||||
// Print(curr);
|
||||
// end;
|
||||
///
|
||||
|
||||
// var a: System.Collections.Generic.IEnumerable<yield_unknown_foreach_type> := l;
|
||||
var foreachCollIdent = this.NewForeachCollectionName();
|
||||
var foreachCollType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), new template_param_list(new yield_unknown_foreach_type(frch)));
|
||||
var foreachCollVarDef = new var_statement(foreachCollIdent, foreachCollType);
|
||||
|
||||
var ass = new assign(foreachCollIdent, frch.in_what);
|
||||
|
||||
// var en := a.GetEnumerator();
|
||||
var enumeratorIdent = this.NewEnumeratorName();
|
||||
var enumeratorVarDef = new var_statement(enumeratorIdent, new method_call(new dot_node(foreachCollIdent, new ident("GetEnumerator")), new expression_list()));
|
||||
|
||||
// Переменная цикла
|
||||
|
||||
//var curr := en.Current;
|
||||
// Переменная цикла foreach. Есть три варианта:
|
||||
// 1. foreach x in l do -> curr := en.Current;
|
||||
// 2. foreach var x in l do -> var curr := en.Current;
|
||||
// 3. foreach var x: T in l do -> var curr: T := en.Current;
|
||||
var currentIdent = frch.identifier;
|
||||
type_definition currentIdentType = null;
|
||||
statement st = null;
|
||||
|
||||
// Новое тело
|
||||
var stl = new statement_list();
|
||||
var curExpr = new dot_node(enumeratorIdent, "Current");
|
||||
|
||||
// С типом
|
||||
if (frch.type_name == null)
|
||||
if (frch.type_name == null) // 1. foreach x in l do -> curr := en.Current;
|
||||
{
|
||||
// Внешнее имя, создавать ниче не надо
|
||||
st = new assign(currentIdent, curExpr);
|
||||
}
|
||||
else
|
||||
else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do -> var curr := en.Current;
|
||||
{
|
||||
// var имеет место быть
|
||||
if (frch.type_name is no_type_foreach)
|
||||
{
|
||||
// автовывод
|
||||
currentIdentType = new yield_unknown_foreach_type(frch);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentIdentType = frch.type_name;
|
||||
}
|
||||
|
||||
// Получаем служебное имя с $ и заменяем его в теле цикла
|
||||
currentIdent = this.NewVarNames(frch.identifier).VarName;
|
||||
var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
|
||||
frch.visit(replacerVis);
|
||||
|
||||
st = new var_statement(currentIdent, curExpr);
|
||||
}
|
||||
else // 3. foreach var x: T in l do -> var curr: T := en.Current;
|
||||
{
|
||||
// Получаем служебное имя с $ и заменяем его в теле цикла
|
||||
currentIdent = this.NewVarNames(frch.identifier).VarName;
|
||||
var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
|
||||
frch.visit(replacerVis);
|
||||
|
||||
// Создаем переменную цикла и добавляем в stl
|
||||
stl.Add(new var_statement(currentIdent, currentIdentType));
|
||||
|
||||
st = new var_statement(currentIdent, frch.type_name, curExpr);
|
||||
}
|
||||
|
||||
// Получаем служебное имя с $ и заменяем его в теле цикла
|
||||
//currentIdent = this.NewVarNames(frch.identifier).VarName;
|
||||
//var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
|
||||
//frch.visit(replacerVis);
|
||||
|
||||
// Создаем переменную цикла и добавляем в stl
|
||||
//stl.Add(new var_statement(currentIdent, currentIdentType));
|
||||
|
||||
// Новое тело
|
||||
|
||||
//stl.Add(st);
|
||||
// SSM вернул всё назад 26.06.16
|
||||
// Добавляем $current$ = $enumerator$.Current
|
||||
//stl.Add(new assign(currentIdent, new dot_node(enumeratorIdent, "Current")));
|
||||
stl.Add(new assign(currentIdent, new method_call(new yield_unknown_foreach_type_ident(frch), new expression_list(new dot_node(enumeratorIdent, "Current")))));
|
||||
//var curExpr = new dot_node(enumeratorIdent, "Current");
|
||||
//stl.Add(new assign(currentIdent, new method_call(new yield_unknown_foreach_type_ident(frch), new expression_list(new dot_node(enumeratorIdent, "Current")))));
|
||||
|
||||
|
||||
// Добавляем тело цикла в stl
|
||||
ProcessNode(frch.stmt);
|
||||
var stl = new statement_list(st);
|
||||
ProcessNode(frch.stmt); //?? - видимо, для обработки вложенных конструкций
|
||||
stl.Add(frch.stmt);
|
||||
|
||||
var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()),
|
||||
stl,
|
||||
WhileCycleType.While);
|
||||
|
||||
ReplaceStatement(frch,
|
||||
/*ReplaceStatement(frch,
|
||||
SeqStatements(new var_statement(enumeratorIdent,
|
||||
new named_type_reference("System.Collections.IEnumerator"),
|
||||
// НЕБЕЗОПАСНО!
|
||||
new method_call(new dot_node(frch.in_what as addressed_value, new ident("GetEnumerator")), new expression_list())),
|
||||
whileNode));
|
||||
*/
|
||||
ReplaceStatement(frch,
|
||||
SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,8 @@ namespace SyntaxVisitors
|
|||
cm.Add(new var_def_statement(YieldConsts.Self, iteratorClassRef));
|
||||
}
|
||||
|
||||
var GetEnumeratorBody = new statement_list();
|
||||
|
||||
// Системные поля и методы для реализации интерфейса IEnumerable
|
||||
cm.Add(new var_def_statement(YieldConsts.State, "integer"),
|
||||
new var_def_statement(YieldConsts.Current, stels),
|
||||
|
|
@ -160,12 +162,10 @@ namespace SyntaxVisitors
|
|||
new procedure_definition("Reset"),
|
||||
new procedure_definition("MoveNext", "boolean", pd.proc_body),
|
||||
new procedure_definition("System.Collections.IEnumerator.get_Current", "object", new assign("Result", YieldConsts.Current)),
|
||||
new procedure_definition("System.Collections.IEnumerable.GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self"))
|
||||
//new procedure_definition("System.Collections.IEnumerable.GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self"))
|
||||
new procedure_definition("System.Collections.IEnumerable.GetEnumerator", "System.Collections.IEnumerator", GetEnumeratorBody)
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
// frninja 20/04/16 - поддержка шаблонных классов
|
||||
var yieldClassName = NewYieldClassName();
|
||||
var yieldClassHelperName = yieldClassName + "Helper";
|
||||
|
|
@ -242,7 +242,7 @@ namespace SyntaxVisitors
|
|||
var cm1 = cm.Add( //class_members.Public.Add(
|
||||
//procedure_definition.EmptyDefaultConstructor,
|
||||
new procedure_definition(new function_header("get_Current", stels), new assign("Result", YieldConsts.Current)),
|
||||
new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), new assign("Result", "Self")),
|
||||
new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), GetEnumeratorBody),
|
||||
new procedure_definition("Dispose")
|
||||
);
|
||||
|
||||
|
|
@ -260,10 +260,27 @@ namespace SyntaxVisitors
|
|||
helperClassDefinition.where_section = this.GetMethodWhereSection(pd);
|
||||
|
||||
var td1 = new type_declaration(className, helperClassDefinition);
|
||||
//SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1));
|
||||
//SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1));
|
||||
|
||||
|
||||
var stl1 = new statement_list(new var_statement("res", new new_expr(this.CreateClassReference(className), new expression_list())));
|
||||
|
||||
|
||||
stl1.AddMany(lid.Select(id => new assign(new dot_node("res", new ident(formalParamsMap[id.name])), new ident(formalParamsMap[id.name]))));
|
||||
|
||||
// Переприсваивание self
|
||||
if (iteratorClassName != null && !pd.proc_header.class_keyword)
|
||||
{
|
||||
stl1.Add(new assign(new dot_node("res", YieldConsts.Self), new ident(YieldConsts.Self)));
|
||||
}
|
||||
|
||||
stl1.Add(new assign("Result", "res"));
|
||||
|
||||
|
||||
GetEnumeratorBody.Add(new if_node(new bin_expr(new ident(YieldConsts.State), new int32_const(0), Operators.Equal),
|
||||
new assign("Result", "Self"),
|
||||
stl1));
|
||||
|
||||
var cct = new type_declarations(/*td*/);
|
||||
cct.Add(td1);
|
||||
|
||||
|
|
@ -937,7 +954,7 @@ namespace SyntaxVisitors
|
|||
// Обработать параметры!
|
||||
// Как? Ищем в mids formal_parametrs, но надо выделить именно обращение к параметрам - не полям класса, не глобальным переменным
|
||||
|
||||
var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code);
|
||||
var cfa = new ConstructFiniteAutomata(pd.proc_body as block);
|
||||
cfa.Transform();
|
||||
|
||||
(pd.proc_body as block).program_code = cfa.res;
|
||||
|
|
@ -976,7 +993,7 @@ namespace SyntaxVisitors
|
|||
}
|
||||
}
|
||||
|
||||
class ConstructFiniteAutomata
|
||||
/*class ConstructFiniteAutomata1
|
||||
{
|
||||
public statement_list res = new statement_list();
|
||||
statement_list stl;
|
||||
|
|
@ -992,9 +1009,9 @@ namespace SyntaxVisitors
|
|||
private labeled_statement OuterLabeledStatement;
|
||||
private Dictionary<int, labeled_statement> Dispatches = new Dictionary<int,labeled_statement>();
|
||||
|
||||
public ConstructFiniteAutomata(statement_list stl)
|
||||
public ConstructFiniteAutomata1(block bl)
|
||||
{
|
||||
this.stl = stl;
|
||||
this.stl = bl.program_code;
|
||||
}
|
||||
|
||||
private void AddState(out int stateNumber, out ident resumeLabel)
|
||||
|
|
@ -1064,6 +1081,69 @@ namespace SyntaxVisitors
|
|||
//statement_list res = new statement_list(cas);
|
||||
res = stl;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// SSM 07/07/16 - изменен алгоритм генерации конечного автомата на более простой. Вместо case генерируется последовательность if ... goto состояние.
|
||||
class ConstructFiniteAutomata
|
||||
{
|
||||
public statement_list res = new statement_list(); // сюда писать результат
|
||||
statement_list stl; // это исходные операторы тела функции
|
||||
declarations defs; // это декларации функции - для добавления меток
|
||||
|
||||
int curState = 0;
|
||||
|
||||
public ConstructFiniteAutomata(block bl)
|
||||
{
|
||||
this.stl = bl.program_code;
|
||||
defs = bl.defs;
|
||||
}
|
||||
|
||||
public void Process(statement st)
|
||||
{
|
||||
if (st is yield_node)
|
||||
{
|
||||
var yn = st as yield_node;
|
||||
curState += 1;
|
||||
res.AddMany(
|
||||
new assign(YieldConsts.Current, yn.ex),
|
||||
new assign(YieldConsts.State, curState),
|
||||
new assign("Result", true),
|
||||
new procedure_call("exit"),
|
||||
new labeled_statement(YieldConsts.LabelStatePrefix+curState.ToString())
|
||||
);
|
||||
}
|
||||
else if (st is labeled_statement)
|
||||
{
|
||||
var ls = st as labeled_statement;
|
||||
res.Add(new labeled_statement(ls.label_name));
|
||||
Process(ls.to_statement);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.Add(st);
|
||||
}
|
||||
}
|
||||
|
||||
public void Transform()
|
||||
{
|
||||
res.Add(new labeled_statement(YieldConsts.LabelStatePrefix+curState.ToString()));
|
||||
|
||||
foreach (var st in stl.subnodes)
|
||||
Process(st);
|
||||
|
||||
// добавим метки состояний
|
||||
var idseq = Enumerable.Range(0, curState + 1).Select(i => new ident("lbstate#" + i.ToString()));
|
||||
var idl = new ident_list(idseq.ToList());
|
||||
defs.Add(new label_definitions(idl));
|
||||
|
||||
statement ifgoto = new goto_statement(YieldConsts.LabelStatePrefix + curState.ToString());
|
||||
for (var i = curState - 1; i >= 0; i--)
|
||||
ifgoto = new if_node(new bin_expr(new ident(YieldConsts.State), new int32_const(i), Operators.Equal),
|
||||
new goto_statement(YieldConsts.LabelStatePrefix + i.ToString()),
|
||||
ifgoto
|
||||
);
|
||||
res.AddFirst(ifgoto);
|
||||
res.AddFirst(new assign("Result", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ namespace YieldDesugarSyntaxTreeConverter
|
|||
root.visit(new MarkMethodHasYieldVisitor());
|
||||
root.visit(new ProcessYieldCapturedVarsVisitor());
|
||||
|
||||
//root.visit(new SimplePrettyPrinterVisitor(@"d:\zzz.txt"));
|
||||
#if DEBUG
|
||||
root.visit(new SimplePrettyPrinterVisitor(@"d:\zzz.txt"));
|
||||
#endif
|
||||
|
||||
return root;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ namespace PascalABCCompiler.YieldHelpers
|
|||
{
|
||||
public static string Current = "<>2__current";
|
||||
public static string State = "<>1__state";
|
||||
public static string LabelStatePrefix = "lbstate#";
|
||||
|
||||
public static string Self = "<>4__self";
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in a new issue