Небольшие правки в пробе реализации yield
This commit is contained in:
parent
9460d4a471
commit
6e49d7c2b6
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "2";
|
||||
public const string Minor = "2";
|
||||
public const string Build = "0";
|
||||
public const string Revision = "1013";
|
||||
public const string Revision = "1014";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%MINOR%=2
|
||||
%REVISION%=1013
|
||||
%REVISION%=1014
|
||||
%MAJOR%=2
|
||||
%COREVERSION%=0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '2.2.0.1013'
|
||||
!define VERSION '2.2.0.1014'
|
||||
|
|
@ -257,6 +257,22 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
}
|
||||
}
|
||||
|
||||
public partial class template_type_reference
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.Append(this.name.ToString());
|
||||
sb.Append("<");
|
||||
sb.Append(params_list.params_list[0].ToString());
|
||||
for (int i = 1; i < params_list.params_list.Count; i++)
|
||||
sb.Append("," + params_list.params_list[i].ToString());
|
||||
sb.Append(">");
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public partial class variable_definitions
|
||||
{
|
||||
public variable_definitions(var_def_statement _var_def_statement, SourceContext sc = null)
|
||||
|
|
@ -386,6 +402,9 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
public var_def_statement(ident id, type_definition type) : this(new ident_list(id), type)
|
||||
{ }
|
||||
|
||||
public var_def_statement(ident id, type_definition type, expression iv) : this(new ident_list(id), type, iv)
|
||||
{ }
|
||||
|
||||
public var_def_statement(ident id, string type) : this(new ident_list(id), new named_type_reference(type))
|
||||
{ }
|
||||
|
||||
|
|
@ -708,6 +727,12 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
}
|
||||
|
||||
//for sugar
|
||||
public function_header(string name, type_definition returntype, formal_parameters fp) : this(fp, new procedure_attributes_list(), new method_name(name), null, returntype, null)
|
||||
{ }
|
||||
|
||||
public function_header(string name, type_definition returntype) : this(new formal_parameters(), new procedure_attributes_list(), new method_name(name), null, returntype, null)
|
||||
{ }
|
||||
|
||||
public function_header(string name, string returntype, formal_parameters fp, procedure_attributes_list pal) : this(fp, pal, new method_name(name), null, new named_type_reference(returntype), null)
|
||||
{ }
|
||||
|
||||
|
|
@ -933,7 +958,11 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return dereferencing_value.ToString() + "(" + parameters.ToString() + ")";
|
||||
string s = dereferencing_value.ToString();
|
||||
if (parameters != null)
|
||||
s += "(" + parameters.ToString() + ")";
|
||||
else s += "()";
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1078,14 +1107,16 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
|
||||
public partial class constructor
|
||||
{
|
||||
public constructor(formal_parameters fp, SourceContext sc = null) : this(null, fp, new procedure_attributes_list(), null, false, false, null, null, sc)
|
||||
public constructor(formal_parameters fp, SourceContext sc = null) : this(null, fp, new procedure_attributes_list(), new method_name("Create"), false, false, null, null, sc)
|
||||
{ }
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.Append("constructor ");
|
||||
|
||||
sb.Append("(" + parameters.ToString() + ")");
|
||||
if (parameters != null)
|
||||
sb.Append("(" + parameters.ToString() + ")");
|
||||
else
|
||||
sb.Append("()");
|
||||
sb.Append(";");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
|
@ -1257,6 +1288,10 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
public new_expr(type_definition type, expression_list pars, SourceContext sc = null) : this(type, pars, false, null, sc)
|
||||
{ }
|
||||
public new_expr(string type, expression_list pars) : this(new named_type_reference(type), pars, false, null)
|
||||
{ }
|
||||
public new_expr(string type) : this(new named_type_reference(type), expression_list.Empty, false, null)
|
||||
{ }
|
||||
public override string ToString()
|
||||
{
|
||||
return "new "+this.type.ToString()+"("+this.params_list.ToString()+")";
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace SyntaxVisitors
|
|||
}
|
||||
}
|
||||
|
||||
type_declaration GenClassForYield(procedure_definition pd, IEnumerable<var_def_statement> fields)
|
||||
type_declarations GenClassesForYield(procedure_definition pd, IEnumerable<var_def_statement> fields)
|
||||
{
|
||||
// Теперь на месте процедуры генерируем класс
|
||||
var cm = new class_members(access_modifer.public_modifer);
|
||||
|
|
@ -61,27 +61,30 @@ namespace SyntaxVisitors
|
|||
var st = new var_def_statement("state", "integer");
|
||||
|
||||
var fh = (pd.proc_header as function_header);
|
||||
if (fh == null)
|
||||
throw new SyntaxError("Only functions can contain yields", "", pd.proc_header.source_context, pd.proc_header);
|
||||
var seqt = fh.return_type as sequence_type;
|
||||
if (seqt == null)
|
||||
throw new SyntaxError("Functions with yields must return sequences", "", fh.return_type.source_context, fh.return_type);
|
||||
|
||||
List<ident> lid = new List<ident>();
|
||||
var pars = fh.parameters;
|
||||
foreach (var ps in pars.params_list)
|
||||
{
|
||||
if (ps.param_kind != parametr_kind.none)
|
||||
throw new SyntaxError("Parameters of functions with yields must not have 'var', 'const' or 'params' modifier", "", pars.source_context, pars);
|
||||
if (ps.inital_value != null)
|
||||
throw new SyntaxError("Parameters of functions with yields must not have initial values", "", pars.source_context, pars);
|
||||
var_def_statement vds = new var_def_statement(ps.idents, ps.vars_type);
|
||||
cm.Add(vds);
|
||||
lid.AddRange(vds.vars.idents);
|
||||
}
|
||||
if (pars != null)
|
||||
foreach (var ps in pars.params_list)
|
||||
{
|
||||
if (ps.param_kind != parametr_kind.none)
|
||||
throw new SyntaxError("Parameters of functions with yields must not have 'var', 'const' or 'params' modifier", "", pars.source_context, pars);
|
||||
if (ps.inital_value != null)
|
||||
throw new SyntaxError("Parameters of functions with yields must not have initial values", "", pars.source_context, pars);
|
||||
var_def_statement vds = new var_def_statement(ps.idents, ps.vars_type);
|
||||
cm.Add(vds);
|
||||
lid.AddRange(vds.vars.idents);
|
||||
}
|
||||
|
||||
var stels = seqt.elements_type;
|
||||
var cur = new var_def_statement("current", stels);
|
||||
|
||||
var Constr = new procedure_definition(new constructor(formal_parameters.Empty), block.Empty, null);
|
||||
var Constr = new procedure_definition(new constructor(null), block.Empty, null);
|
||||
|
||||
var MoveNext = new procedure_definition("MoveNext", "boolean", pd.proc_body);
|
||||
|
||||
|
|
@ -89,85 +92,59 @@ namespace SyntaxVisitors
|
|||
|
||||
var GetCurrent = new procedure_definition("get_Current", "object", new assign("Result", "current"));
|
||||
|
||||
var className = newClassName() + "Helper";
|
||||
var assG = new assign("Result", new new_expr(new named_type_reference(className),expression_list.Empty));
|
||||
var className = newClassName();
|
||||
|
||||
var vds1 = new var_statement(new var_def_statement("res", null, new new_expr(className)));
|
||||
//var assG = new assign("Result", new new_expr(className));
|
||||
var GetEnumerator = new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self"));
|
||||
|
||||
var stl = new statement_list(assG);
|
||||
var stl = new statement_list(vds1);
|
||||
foreach (var id in lid)
|
||||
{
|
||||
var ass = new assign(new dot_node(new ident("Result"), id),id);
|
||||
var ass = new assign(new dot_node(new ident("res"), id), id);
|
||||
stl.Add(ass);
|
||||
}
|
||||
stl.Add(new assign("Result", "res"));
|
||||
pd.proc_body = new block(stl);
|
||||
|
||||
|
||||
cm.Add(st, cur, Constr, Reset, MoveNext, GetCurrent, GetEnumerator);
|
||||
|
||||
var interfaces = new named_type_reference_list("System.Collections.IEnumerator","System.Collections.IEnumerable");
|
||||
var td = new type_declaration(className, SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm));
|
||||
return td;
|
||||
}
|
||||
var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable");
|
||||
var td = new type_declaration(className + "Helper", SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm));
|
||||
|
||||
class ConstructFiniteAutomata
|
||||
{
|
||||
public statement_list res = new statement_list();
|
||||
statement_list stl;
|
||||
int curState = 0;
|
||||
// Второй класс
|
||||
|
||||
statement_list curStatList;
|
||||
statement_list StatListAfterCase = new statement_list();
|
||||
var cm1 = new class_members(access_modifer.public_modifer);
|
||||
|
||||
case_node cas; // формируемый case
|
||||
var Constr1 = new procedure_definition(new constructor(null), block.Empty, null);
|
||||
|
||||
public ConstructFiniteAutomata(statement_list stl)
|
||||
{
|
||||
this.stl = stl;
|
||||
}
|
||||
var Dispose1 = new procedure_definition("Dispose", statement_list.Empty);
|
||||
|
||||
public void Process(statement st)
|
||||
{
|
||||
if (!(st is yield_node || st is labeled_statement))
|
||||
{
|
||||
curStatList.Add(st);
|
||||
}
|
||||
if (st is yield_node)
|
||||
{
|
||||
var yn = st as yield_node;
|
||||
curState += 1;
|
||||
curStatList.Add(new assign("current", yn.ex));
|
||||
curStatList.Add(new assign("state", curState));
|
||||
curStatList.Add(new assign("Result", new bool_const(true)));
|
||||
curStatList.Add(new procedure_call(new ident("exit")));
|
||||
var assG1 = new assign("Result", new new_expr(new named_type_reference(className), expression_list.Empty));
|
||||
|
||||
curStatList = new statement_list();
|
||||
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
|
||||
cas.conditions.variants.Add(cv);
|
||||
}
|
||||
if (st is labeled_statement)
|
||||
{
|
||||
var ls = st as labeled_statement;
|
||||
curStatList = StatListAfterCase;
|
||||
curStatList.Add(new labeled_statement(ls.label_name,empty_statement.New));
|
||||
Process(ls.to_statement);
|
||||
}
|
||||
}
|
||||
var tpl = new template_param_list(stels);
|
||||
//
|
||||
var ntr = new named_type_reference("System.Collections.Generic.IEnumerator");
|
||||
var ttr2 = new template_type_reference(ntr, tpl);
|
||||
var fh1 = new function_header("GetEnumerator", ttr2);
|
||||
var GetEnumerator1 = new procedure_definition(fh1, new block(new statement_list(new assign("Result", "Self"))));
|
||||
|
||||
public void Transform()
|
||||
{
|
||||
cas = new case_node(new ident("state"));
|
||||
var GetCurrent1 = new procedure_definition(new function_header("get_Current", stels), new block(new statement_list(new assign("Result", "current"))));
|
||||
|
||||
curStatList = new statement_list();
|
||||
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
|
||||
cas.conditions.variants.Add(cv);
|
||||
cm1.Add(Constr1, GetCurrent1, GetEnumerator1, Dispose1);
|
||||
//cm1.Add(Constr1, GetEnumerator1, Dispose1);
|
||||
|
||||
foreach (var st in stl.subnodes)
|
||||
Process(st);
|
||||
var interfaces1 = new named_type_reference_list(className+"Helper");
|
||||
var ttr1 = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), tpl);
|
||||
|
||||
stl.subnodes = SeqStatements(cas,StatListAfterCase).ToList();
|
||||
//statement_list res = new statement_list(cas);
|
||||
res = stl;
|
||||
}
|
||||
interfaces1.Add(ttr1).Add(ttr2);
|
||||
|
||||
var td1 = new type_declaration(className, SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1));
|
||||
|
||||
var cct = new type_declarations(td);
|
||||
cct.Add(td1);
|
||||
|
||||
return cct;
|
||||
}
|
||||
|
||||
public override void visit(procedure_definition pd)
|
||||
|
|
@ -193,11 +170,9 @@ namespace SyntaxVisitors
|
|||
(pd.proc_body as block).program_code = cfa.res;
|
||||
|
||||
// Конструируем определение класса
|
||||
var cc = GenClassForYield(pd, dld.BlockDeletedIds.Union(dld.LocalDeletedIds));
|
||||
var cct = new type_declarations(cc);
|
||||
var cct = GenClassesForYield(pd, dld.BlockDeletedIds.Union(dld.LocalDeletedIds));
|
||||
|
||||
var decls = UpperNodeAs<declarations>();
|
||||
decls.InsertBefore(pd, cct);
|
||||
UpperNodeAs<declarations>().InsertBefore(pd, cct);
|
||||
|
||||
mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть
|
||||
}
|
||||
|
|
@ -215,4 +190,66 @@ namespace SyntaxVisitors
|
|||
//base.visit(yn);
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructFiniteAutomata
|
||||
{
|
||||
public statement_list res = new statement_list();
|
||||
statement_list stl;
|
||||
int curState = 0;
|
||||
|
||||
statement_list curStatList;
|
||||
statement_list StatListAfterCase = new statement_list();
|
||||
|
||||
case_node cas; // формируемый case
|
||||
|
||||
public ConstructFiniteAutomata(statement_list stl)
|
||||
{
|
||||
this.stl = stl;
|
||||
}
|
||||
|
||||
public void Process(statement st)
|
||||
{
|
||||
if (!(st is yield_node || st is labeled_statement))
|
||||
{
|
||||
curStatList.Add(st);
|
||||
}
|
||||
if (st is yield_node)
|
||||
{
|
||||
var yn = st as yield_node;
|
||||
curState += 1;
|
||||
curStatList.Add(new assign("current", yn.ex));
|
||||
curStatList.Add(new assign("state", curState));
|
||||
curStatList.Add(new assign("Result", new bool_const(true)));
|
||||
curStatList.Add(new procedure_call(new ident("exit")));
|
||||
|
||||
curStatList = new statement_list();
|
||||
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
|
||||
cas.conditions.variants.Add(cv);
|
||||
}
|
||||
if (st is labeled_statement)
|
||||
{
|
||||
var ls = st as labeled_statement;
|
||||
curStatList = StatListAfterCase;
|
||||
curStatList.Add(new labeled_statement(ls.label_name, empty_statement.New));
|
||||
Process(ls.to_statement);
|
||||
}
|
||||
}
|
||||
|
||||
public void Transform()
|
||||
{
|
||||
cas = new case_node(new ident("state"));
|
||||
|
||||
curStatList = new statement_list();
|
||||
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
|
||||
cas.conditions.variants.Add(cv);
|
||||
|
||||
foreach (var st in stl.subnodes)
|
||||
Process(st);
|
||||
|
||||
stl.subnodes = BaseChangeVisitor.SeqStatements(cas, StatListAfterCase).ToList();
|
||||
//statement_list res = new statement_list(cas);
|
||||
res = stl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
function Gen: sequence of integer;
|
||||
begin
|
||||
for var i:=1 to 10 do
|
||||
yield i*i;
|
||||
yield 1;
|
||||
yield 5;
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
var q := Gen();
|
||||
foreach var x in q do
|
||||
Print(x);
|
||||
end.
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
type A = class
|
||||
j,k: integer;
|
||||
end;
|
||||
|
||||
function Gen(a,b: real): sequence of integer;
|
||||
function Gen(a,b: integer): sequence of integer;
|
||||
var j,k: real;
|
||||
begin
|
||||
var i := 1;
|
||||
|
|
@ -15,4 +11,6 @@ begin
|
|||
end;
|
||||
|
||||
begin
|
||||
foreach var x in Gen(1,2) do
|
||||
Print(x);
|
||||
end.
|
||||
Binary file not shown.
Loading…
Reference in a new issue