/// <summary> /// Автовыведение типов в yield'ax. /// </summary> private void ProcessAssigntToAutoType(addressed_expression to, ref expression_node from) { var sequence = to.type as compiled_generic_instance_type_node; // SSM 26.06.16 - правка в связи с автовыведением типов в yieldах if (to.type is auto_type) { try_convert_typed_expression_to_function_call(ref from); if (to is class_field_reference) { var cfr = to as class_field_reference; cfr.field.type = from.type; cfr.type = from.type; // Это неверно работает когда yieldится процедура #1439 // SSM 1.11.18 попытка правки возвращения процедуры в yield //if (from.type.semantic_node_type == semantic_node_type.delegated_method) cfr.field.inital_value = context.GetInitalValueForVariable(cfr.field, cfr.field.inital_value); } 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; lvr.var.inital_value = context.GetInitalValueForVariable(lvr.var, lvr.var.inital_value); } else { AddError(to.location, "Не могу вывести тип при наличии yield: " + to.type.full_name); } //to.type = from.type; // и без всякого real_type! } else if (sequence?.instance_params[0] is ienumerable_auto_type) { type_node elem_type = null; try_convert_typed_expression_to_function_call(ref from); bool bb; // здесь bb не нужно. Оно нужно в foreach var b = FindIEnumerableElementType(from.type, ref elem_type, out bb); if (!b) { AddError(from.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", from.type.full_name); } 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; // замена типа у переменной } } }
/// <summary> /// Автовыведение типов в yield'ax. /// </summary> private void ProcessAssigntToAutoType(addressed_expression to, ref expression_node from) { var sequence = to.type as compiled_generic_instance_type_node; // SSM 26.06.16 - правка в связи с автовыведением типов в yieldах if (to.type is auto_type) { try_convert_typed_expression_to_function_call(ref from); if (to is class_field_reference) { var cfr = to as class_field_reference; if (from is typed_expression) // SSM 22.12.18 syntax_tree_visitor.cs 16066 - взял оттуда { base_function_call bfc = ((from as typed_expression).type as delegated_methods).proper_methods[0]; /*if (bfc.function.is_generic_function && _var_def_statement.vars_type == null) * { * AddError(inital_value.location, "CAN_NOT_DEDUCE_TYPE_{0}", null); * } * foreach (parameter p in bfc.simple_function_node.parameters) * { * if (p.type.is_generic_parameter) * AddError(inital_value.location, "USE_ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS"); * } */ common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); context.converted_namespace.types.AddElement(del); //- сомневаюсь - контекст уже поменялся! //tn = del; from = convertion_data_and_alghoritms.explicit_convert_type(from, del); from.type = del; } cfr.field.type = from.type; cfr.type = from.type; // Это неверно работает когда yieldится процедура #1439 // SSM 1.11.18 попытка правки возвращения процедуры в yield //if (from.type.semantic_node_type == semantic_node_type.delegated_method) //cfr.type.semantic_node_type = semantic_node_type.delegated_method; cfr.field.inital_value = context.GetInitalValueForVariable(cfr.field, cfr.field.inital_value); } 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; lvr.var.inital_value = context.GetInitalValueForVariable(lvr.var, lvr.var.inital_value); } else { AddError(to.location, "Не могу вывести тип при наличии yield: " + to.type.full_name); } //to.type = from.type; // и без всякого real_type! } else if (sequence?.instance_params[0] is ienumerable_auto_type) { type_node elem_type = null; try_convert_typed_expression_to_function_call(ref from); bool bb; // здесь bb не нужно. Оно нужно в foreach var b = FindIEnumerableElementType(from.type, ref elem_type, out bb); if (!b) { AddError(from.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", from.type.full_name); } 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; // замена типа у переменной } } }
public override void visit(template_type_reference _template_type_reference) { }
public virtual void visit(template_type_reference _template_type_reference) { DefaultVisit(_template_type_reference); }
public override void visit(template_type_reference _template_type_reference) { DefaultVisit(_template_type_reference); pre_do_visit(_template_type_reference); visit(template_type_reference.name); visit(template_type_reference.params_list); post_do_visit(_template_type_reference); }
public virtual void post_do_visit(template_type_reference _template_type_reference) { }
public virtual void visit(template_type_reference _template_type_reference) { }
public override void visit(template_type_reference _template_type_reference) { throw new NotImplementedException(); }
// 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; statement st = null; var curExpr = new dot_node(enumeratorIdent, "Current"); // С типом if (frch.type_name == null) // 1. foreach x in l do -> curr := en.Current; { st = new assign(currentIdent, curExpr); } else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do -> var curr := en.Current; { // Получаем служебное имя с $ и заменяем его в теле цикла 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); st = new var_statement(currentIdent, frch.type_name, curExpr); } // Добавляем тело цикла в stl 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); var sq = SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode); ReplaceStatement(frch, sq); visit(whileNode); // Lowering оставшегося whileNode }
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); }
public override void visit(template_type_reference _template_type_reference) { prepare_node(_template_type_reference.name, "name"); prepare_node(_template_type_reference.params_list, "params_list"); }
public override void visit(template_type_reference _template_type_reference) { executer.visit(_template_type_reference); if (_template_type_reference.name != null) this.visit((dynamic)_template_type_reference.name); if (_template_type_reference.params_list != null) this.visit((dynamic)_template_type_reference.params_list); if (_template_type_reference.names != null) foreach (dynamic x in _template_type_reference.names) if(x != null) this.visit(x); if (_template_type_reference.attr_list != null) this.visit((dynamic)_template_type_reference.attr_list); if (_template_type_reference.attributes != null) this.visit((dynamic)_template_type_reference.attributes); }