Небольшие правки в пробе реализации yield

This commit is contained in:
miks1965 2015-08-19 23:28:54 +03:00
parent 9460d4a471
commit 6e49d7c2b6
8 changed files with 162 additions and 90 deletions

View file

@ -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;

View file

@ -1,4 +1,4 @@
%MINOR%=2
%REVISION%=1013
%REVISION%=1014
%MAJOR%=2
%COREVERSION%=0

View file

@ -1 +1 @@
!define VERSION '2.2.0.1013'
!define VERSION '2.2.0.1014'

View file

@ -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()+")";

View file

@ -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;
}
}
}

View file

@ -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.

View file

@ -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.