/*public override void visit(class_members cm) { foreach (var decl in cm.members) { if (decl is procedure_header || decl is procedure_definition) decl.visit(this); } base.visit(cm); }*/ type_declarations GenClassesForYield(procedure_definition pd, IEnumerable<var_def_statement> fields, IDictionary<string, string> localsMap, IDictionary<string, string> formalParamsMap) { 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); // Теперь на месте функции генерируем класс // Захваченные переменные var cm = class_members.Public; var capturedFields = fields.Select(vds => { ident_list ids = new ident_list(vds.vars.idents.Select(id => new ident(localsMap[id.name])).ToArray()); return new var_def_statement(ids, vds.vars_type, vds.inital_value); }); foreach (var m in capturedFields) cm.Add(m); // Параметры функции List<ident> lid = new List<ident>(); var pars = fh.parameters; 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); ident_list ids = new ident_list(ps.idents.list.Select(id => new ident(formalParamsMap[id.name])).ToArray()); var_def_statement vds = new var_def_statement(ids, ps.vars_type); cm.Add(vds); // все параметры функции делаем полями класса //lid.AddRange(vds.vars.idents); lid.AddRange(ps.idents.list); } var stels = seqt.elements_type; // frninja 08/18/15 - Для захвата self if ((object)GetClassName(pd) != null) cm.Add(new var_def_statement(Consts.Self, GetClassName(pd).name)); // Системные поля и методы для реализации интерфейса IEnumerable cm.Add(new var_def_statement(Consts.State, "integer"), new var_def_statement(Consts.Current, stels), procedure_definition.EmptyDefaultConstructor, new procedure_definition("Reset"), new procedure_definition("MoveNext", "boolean", pd.proc_body), new procedure_definition("get_Current", "object", new assign("Result", Consts.Current)), new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self")) ); var className = newClassName(); var classNameHelper = className + "Helper"; var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable"); var td = new type_declaration(classNameHelper, SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm)); // Изменение тела процедуры var stl = new statement_list(new var_statement("res", new new_expr(className))); //stl.AddMany(lid.Select(id => new assign(new dot_node("res", id), id))); stl.AddMany(lid.Select(id => new assign(new dot_node("res", new ident(formalParamsMap[id.name])), id))); // frninja 08/12/15 - захват self if ((object)GetClassName(pd) != null) stl.Add(new assign(new dot_node("res", Consts.Self), new ident("self"))); stl.Add(new assign("Result", "res")); // New body pd.proc_body = new block(stl); if ((object)GetClassName(pd) != null) { // frninja 10/12/15 - заменить на function_header и перенести описание тела в declarations Replace(pd, fh); var decls = UpperTo<declarations>(); if ((object)decls != null) { function_header nfh = new function_header(); nfh.name = new method_name(fh.name.meth_name.name); // Set name nfh.name.class_name = GetClassName(pd); nfh.parameters = fh.parameters; nfh.proc_attributes = fh.proc_attributes; procedure_definition npd = new procedure_definition(nfh, new block(stl)); // Update header //pd.proc_header.name.class_name = GetClassName(pd); // Add to decls decls.Add(npd); } } // Второй класс var tpl = new template_param_list(stels); var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl); var cm1 = class_members.Public.Add( procedure_definition.EmptyDefaultConstructor, new procedure_definition(new function_header("get_Current", stels), new assign("Result", Consts.Current)), new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), new assign("Result", "Self")), new procedure_definition("Dispose") ); var interfaces1 = new named_type_reference_list(classNameHelper); var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl); interfaces1.Add(IEnumerableT).Add(IEnumeratorT); 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(class_members cm) { foreach (var decl in cm.members) { if (decl is procedure_header || decl is procedure_definition) decl.visit(this); } base.visit(cm); }*/ 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) // вспомогательный узел для типов локальных переменных { 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); // Теперь на месте функции генерируем класс // Захваченные локальные переменные var cm = class_members.Public; var capturedFields = fields.Select(vds => { ident_list ids = new ident_list(vds.vars.idents.Select(id => new ident(localsMap[id.name])).ToArray()); if (vds.vars_type == null) //&& vds.inital_value != null) { if (vds.inital_value != null) { //return new var_def_statement(ids, new yield_unknown_expression_type(localsCloneMap[vds], varsTypeDetectorHelper), null); return new var_def_statement(ids, new yield_unknown_expression_type(localsCloneMap[vds], localTypeMapHelper), null); } else { throw new Exception("Variable defenition without type and value!"); } } else { return new var_def_statement(ids, vds.vars_type, null); } //return new var_def_statement(ids, vds.vars_type, vds.inital_value); }); foreach (var m in capturedFields) cm.Add(m); // Параметры функции List<ident> lid = new List<ident>(); var pars = fh.parameters; 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); ident_list ids = new ident_list(ps.idents.list.Select(id => new ident(formalParamsMap[id.name])).ToArray()); var_def_statement vds = new var_def_statement(ids, ps.vars_type); cm.Add(vds); // все параметры функции делаем полями класса //lid.AddRange(vds.vars.idents); lid.AddRange(ps.idents.list); } var stels = seqt.elements_type; var iteratorClassName = GetClassName(pd); // frninja 08/18/15 - Для захвата self if (iteratorClassName != null) { // frninja 20/04/16 - поддержка шаблонных классов var iteratorClassRef = CreateClassReference(iteratorClassName); cm.Add(new var_def_statement(YieldConsts.Self, iteratorClassRef)); } // Системные поля и методы для реализации интерфейса IEnumerable cm.Add(new var_def_statement(YieldConsts.State, "integer"), new var_def_statement(YieldConsts.Current, stels), procedure_definition.EmptyDefaultConstructor, 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")) ); // frninja 20/04/16 - поддержка шаблонных классов var yieldClassName = NewYieldClassName(); var yieldClassHelperName = yieldClassName + "Helper"; var className = this.CreateHelperClassName(yieldClassName, iteratorClassName, pd); var classNameHelper = this.CreateHelperClassName(yieldClassHelperName, iteratorClassName, pd); var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable"); // frninja 24/04/16 - поддержка шаблонных классов //var td = new type_declaration(classNameHelper, this.CreateHelperClassDefinition(classNameHelper, pd, interfaces, cm)); //SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm)); // Изменение тела процедуры // frninja 20/04/16 - поддержка шаблонных классов var stl = new statement_list(new var_statement("res", new new_expr(this.CreateClassReference(className), new expression_list()))); //stl.AddMany(lid.Select(id => new assign(new dot_node("res", id), id))); stl.AddMany(lid.Select(id => new assign(new dot_node("res", new ident(formalParamsMap[id.name])), id))); // frninja 08/12/15 - захват self if (iteratorClassName != null) { stl.Add(new assign(new dot_node("res", YieldConsts.Self), new ident("self"))); } stl.Add(new assign("Result", "res")); // New body pd.proc_body = new block(stl); if (iteratorClassName != null) { var cd = UpperTo<class_definition>(); if (cd != null) { // Если метод описан в классе // frninja 10/12/15 - заменить на function_header и перенести описание тела в declarations Replace(pd, fh); var decls = UpperTo<declarations>(); if (decls != null) { // frninja 12/05/16 - забыли копировать return function_header nfh = ObjectCopier.Clone(fh); //function_header nfh = new function_header(); //nfh.name = new method_name(fh.name.meth_name.name); // Set className nfh.name.class_name = iteratorClassName; //nfh.parameters = fh.parameters; //nfh.proc_attributes = fh.proc_attributes; //nfh.return_type = fh.return_type; procedure_definition npd = new procedure_definition(nfh, new block(stl)); // Update header //pd.proc_header.className.class_name = GetClassName(pd); // Add to decls decls.Add(npd); } } } // Второй класс var tpl = new template_param_list(stels); var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl); 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("Dispose") ); // frninja 20/04/16 - поддержка шаблонных классов var interfaces1 = new named_type_reference_list(/*this.CreateClassReference(classNameHelper) as named_type_reference*/); var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl); interfaces1.Add(IEnumerableT).Add(IEnumeratorT); // frninja 24/04/16 - поддержка шаблонных классов var td1 = new type_declaration(className, this.CreateHelperClassDefinition(className, pd, interfaces1, cm1)); //SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1)); var cct = new type_declarations(/*td*/); cct.Add(td1); return cct; }
/*public override void Enter(syntax_tree_node st) { base.Enter(st); countNodesVisited++; // сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов) if (st.GetType()==typeof(assign) || st.GetType()==typeof(var_def_statement) || st is procedure_call || st is procedure_header || st is expression) { visitNode = false; // фильтр - куда не заходить } }*/ /*public override void visit(class_members cm) { foreach (var decl in cm.members) { if (decl is procedure_header || decl is procedure_definition) decl.visit(this); } base.visit(cm); }*/ 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 // отображение для оберток локальных переменных ) { 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); // Теперь на месте функции генерируем класс // Захваченные локальные переменные var cm = class_members.Public; var capturedFields = fields.Select(vds => { ident_list ids = new ident_list(vds.vars.idents.Select(id => new ident(localsMap[id.name])).ToArray()); if (vds.vars_type == null) //&& vds.inital_value != null) { if (vds.inital_value != null) { //return new var_def_statement(ids, new yield_unknown_expression_type(localsCloneMap[vds], varsTypeDetectorHelper), null); return new var_def_statement(ids, new yield_unknown_expression_type(vds), null); // SSM - убрал localsCloneMap[vds] - заменил на vds - не знаю, зачем вообще это отображение делалось - всё равно оно было тождественным!!! } else { throw new SyntaxVisitorError("Variable defenition without type and value!",vds.source_context); // SSM - быть такого не может - грамматика не пропустит } } else { return new var_def_statement(ids, vds.vars_type, null); } //return new var_def_statement(ids, vds.vars_type, vds.inital_value); }); foreach (var m in capturedFields) cm.Add(m); // Параметры функции List<ident> lid = new List<ident>(); var pars = fh.parameters; if (pars != null) foreach (var ps in pars.params_list) { if (ps.param_kind != parametr_kind.none) throw new SyntaxVisitorError("FUNCTIONS_WITH_YIELDS_CANNOT_CONTAIN_VAR_CONST_PARAMS_MODIFIERS", pars.source_context); if (ps.inital_value != null) throw new SyntaxVisitorError("FUNCTIONS_WITH_YIELDS_CANNOT_CONTAIN_DEFAULT_PARAMETERS", pars.source_context); //var_def_statement vds = new var_def_statement(ps.idents, ps.vars_type); ident_list ids = new ident_list(ps.idents.list.Select(id => new ident(formalParamsMap[id.name])).ToArray()); var_def_statement vds = new var_def_statement(ids, ps.vars_type); cm.Add(vds); // все параметры функции делаем полями класса //lid.AddRange(vds.vars.idents); lid.AddRange(ps.idents.list); } var stels = seqt.elements_type; var iteratorClassName = GetClassName(pd); // frninja 08/18/15 - Для захвата self if (iteratorClassName != null) { // frninja 20/04/16 - поддержка шаблонных классов var iteratorClassRef = CreateClassReference(iteratorClassName); 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), procedure_definition.EmptyDefaultConstructor, 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", GetEnumeratorBody) ); // frninja 20/04/16 - поддержка шаблонных классов var yieldClassName = NewYieldClassName(); var yieldClassHelperName = yieldClassName + "Helper"; var className = this.CreateHelperClassName(yieldClassName, iteratorClassName, pd); var classNameHelper = this.CreateHelperClassName(yieldClassHelperName, iteratorClassName, pd); var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable"); // frninja 24/04/16 - поддержка шаблонных классов //var td = new type_declaration(classNameHelper, this.CreateHelperClassDefinition(classNameHelper, pd, interfaces, cm)); //SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm)); // Изменение тела процедуры // frninja 20/04/16 - поддержка шаблонных классов var stl = new statement_list(new var_statement("$res", new new_expr(this.CreateClassReference(className), new expression_list()))); //stl.AddMany(lid.Select(id => new assign(new dot_node("$res", id), id))); stl.AddMany(lid.Select(id => new assign(new dot_node("$res", new ident(formalParamsMap[id.name])), id))); // frninja 08/12/15 - захват self if (iteratorClassName != null && !pd.proc_header.class_keyword) { stl.Add(new assign(new dot_node("$res", YieldConsts.Self), new ident("self"))); } stl.Add(new assign("Result", "$res")); // New body pd.proc_body = new block(stl); if (iteratorClassName != null) { var cd = UpperTo<class_definition>(); if (cd != null) { // Если метод описан в классе // frninja 10/12/15 - заменить на function_header и перенести описание тела в declarations Replace(pd, fh); var decls = UpperTo<declarations>(); if (decls != null) { // frninja 12/05/16 - забыли копировать return function_header nfh = ObjectCopier.Clone(fh); //function_header nfh = new function_header(); //nfh.name = new method_name(fh.name.meth_name.name); // Set className nfh.name.class_name = iteratorClassName; //nfh.parameters = fh.parameters; //nfh.proc_attributes = fh.proc_attributes; //nfh.return_type = fh.return_type; procedure_definition npd = new procedure_definition(nfh, new block(stl)); // Update header //pd.proc_header.className.class_name = GetClassName(pd); // Add to decls decls.Add(npd); } } } // Второй класс var tpl = new template_param_list(stels); var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl); 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), GetEnumeratorBody), new procedure_definition("Dispose") ); // frninja 20/04/16 - поддержка шаблонных классов var interfaces1 = new named_type_reference_list(/*this.CreateClassReference(classNameHelper) as named_type_reference*/); var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl); interfaces1.Add(IEnumerableT).Add(IEnumeratorT); // frninja 24/04/16 - поддержка шаблонных классов // frninja 05/06/16 - фикс. Поддержка where секции var helperClassDefinition = this.CreateHelperClassDefinition(className, pd, interfaces1, cm1); helperClassDefinition.where_section = this.GetMethodWhereSection(pd); var td1 = new type_declaration(className, helperClassDefinition); //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); return cct; }
type_declarations GenClassesForYield(procedure_definition pd, IEnumerable<var_def_statement> fields) { 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); // Теперь на месте функции генерируем класс // Захваченные переменные var cm = class_members.Public; foreach (var m in fields) cm.Add(m); // Параметры функции List<ident> lid = new List<ident>(); var pars = fh.parameters; 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; // Системные поля и методы для реализации интерфейса IEnumerable cm.Add(new var_def_statement(Consts.State, "integer"), new var_def_statement(Consts.Current, stels), procedure_definition.EmptyDefaultConstructor, new procedure_definition("Reset"), new procedure_definition("MoveNext", "boolean", pd.proc_body), new procedure_definition("get_Current", "object", new assign("Result", Consts.Current)), new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self")) ); var className = newClassName(); var classNameHelper = className + "Helper"; var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable"); var td = new type_declaration(classNameHelper, SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm)); // Изменение тела процедуры var stl = new statement_list(new var_statement("res", new new_expr(className))); stl.AddMany(lid.Select(id => new assign(new dot_node("res", id), id))); stl.Add(new assign("Result", "res")); pd.proc_body = new block(stl); // Второй класс var tpl = new template_param_list(stels); var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl); var cm1 = class_members.Public.Add( procedure_definition.EmptyDefaultConstructor, new procedure_definition(new function_header("get_Current", stels), new assign("Result", Consts.Current)), new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), new assign("Result", "Self")), new procedure_definition("Dispose") ); var interfaces1 = new named_type_reference_list(classNameHelper); var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl); interfaces1.Add(IEnumerableT).Add(IEnumeratorT); var td1 = new type_declaration(className, SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1)); var cct = new type_declarations(td); cct.Add(td1); return cct; }