private base_function_call create_static_method_call_with_params(function_node fn, location loc, type_node tn, bool procedure_allowed, expressions_list parametrs) { base_function_call bfc = create_static_method_call(fn, loc, tn, procedure_allowed); bfc.parameters.AddRange(parametrs); return bfc; }
private expression_node find_operator(SyntaxTree.Operators ot, expression_node expr, location loc) { string name = name_reflector.get_name(ot); //#if (DEBUG) if (name == null) { if (ot == PascalABCCompiler.SyntaxTree.Operators.AddressOf) { if (expr.is_addressed == false) { AddError(expr.location, "CAN_NOT_GET_ADDRESS_FROM_EXPRESSION"); } expression_node res = new get_addr_node(expr, loc); return res; } if (ot == PascalABCCompiler.SyntaxTree.Operators.Dereference) { } throw new CompilerInternalError("Invalid operator name"); } //#endif SymbolInfo si = expr.type.find(name, context.CurrentScope); if (si == null || si.sym_info is wrapped_definition_node) { AddError(new OperatorCanNotBeAppliedToThisType(name, expr)); } expressions_list pars = new expressions_list(); pars.AddElement(expr); function_node fn = convertion_data_and_alghoritms.select_function(pars, si, loc); expr = pars[0]; if (fn == null) { AddError(new OperatorCanNotBeAppliedToThisType(name, expr)); } #if (DEBUG) convertion_data_and_alghoritms.check_operator(fn); #endif expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, expr); return exp_node; }
private expression_node make_pred_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) { AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node)); return null; } if (parameters.expressions.Count == 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression); basic_function_call bfc = null; int type_flag = 0; expressions_list el = new expressions_list(); el.AddElement(param0); function_node fn = null; try { fn = convertion_data_and_alghoritms.select_function(el,si,loc); } catch(Exception e) { } if (fn != null) { if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } } else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum) { el = new expressions_list(); el.AddElement(new int_const_node(1,null)); fn = convertion_data_and_alghoritms.select_function(el,si,loc); //bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); //bfc.ret_type = param0.type; if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); cnfc.type = param0.type; return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); cnfc.type = param0.type; return cnfc; } } else AddError(new NoFunctionWithSameArguments(loc,false)); bfc.parameters.AddElement(param0); if (type_flag == 0 || type_flag == 3) bfc.parameters.AddElement(new int_const_node(1,null)); else if (type_flag == 1) bfc.parameters.AddElement(new long_const_node(1,null)); else if (type_flag == 2) bfc.parameters.AddElement(new ulong_const_node(1,null)); return bfc; } AddError(new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node)); return null; }
private expression_node make_read_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { // вызов read(a,b,c) разбивается на несколько вызовов, последний возвращается узлом, а остальные добавляются здесь в теле expressions_list exl = new expressions_list(); expression_node last_call = null; expressions_list exl = new expressions_list(); expression_node file = null; bool read_from_file = false; bool read_from_text_file = false; bool read_from_typed_file = false; bool read_from_binary_file = false; bool readln_string_file = false; if (parameters != null) // если список параметров не пуст { if (parameters.expressions.Count >= 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (param0.type != null) { if (SystemLibrary.SystemLibInitializer.TextFileType.Found && param0.type == SystemLibrary.SystemLibInitializer.TextFileType.sym_info) { file = param0; read_from_text_file = true; } if (param0.type.type_special_kind == SemanticTree.type_special_kind.typed_file && parameters.expressions.Count > 1 //это можно внести во внутрь )//и побросать приличные исключения { if (!SystemLibrary.SystemLibInitializer.read_procedure.FromDll) { if (si == SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo) { file = param0; read_from_typed_file = true; } } else if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si)) { file = param0; read_from_typed_file = true; } } if (param0.type.type_special_kind == SemanticTree.type_special_kind.binary_file && parameters.expressions.Count > 1 //это можно внести во внутрь )//и побросать приличные исключения { if (!SystemLibrary.SystemLibInitializer.read_procedure.FromDll) { if (si == SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo) { file = param0; read_from_binary_file = true; } } else if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si)) { file = param0; read_from_binary_file = true; } } } read_from_file = read_from_text_file || read_from_typed_file || read_from_binary_file; } bool first_iteration = true; foreach (SyntaxTree.expression ex in parameters.expressions) { if (first_iteration && read_from_file) { first_iteration = false; continue; } if (last_call != null && convertion_data_and_alghoritms.statement_list_stack.size > 0) convertion_data_and_alghoritms.statement_list_stack.top().statements.AddElement(last_call); expression_node en = convert_strong(ex); check_on_loop_variable(en); //if (en.type == null) //throw new CanNotRead(en.location); exl.clear(); if (read_from_file) exl.AddElement(file); if (read_from_typed_file) { if (SystemLibrary.SystemLibInitializer.TypedFileReadProcedure == null) AddError(new NotSupportedError(loc)); if (en.type != file.type.element_type) AddError(new ExpectedExprHaveTypeTypedFile(file.type.element_type, en.type, true, get_location(ex))); bool is_char_getter = false; if (!en.is_addressed) { if (en is compiled_function_call) { compiled_function_call cfc = en as compiled_function_call; if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type && cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function)) { en = new simple_array_indexing((en as compiled_function_call).obj, (en as compiled_function_call).parameters[0], SystemLibrary.SystemLibrary.char_type, en.location); is_char_getter = true; } } } function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedFileReadProcedure.SymbolInfo, loc); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), file); //expression_node expr = convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.TypedFileReadProcedure.SymbolInfo, loc, context.converted_type, context.top_function, true); expr = convertion_data_and_alghoritms.explicit_convert_type(expr, file.type.element_type); if (is_char_getter) expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.sym_info as function_node, loc, (en as simple_array_indexing).simple_arr_expr, (en as simple_array_indexing).ind_expr, expr); else expr = find_operator(compiler_string_consts.assign_name, en, expr, loc); last_call = expr; } else if (read_from_binary_file) { if (SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure == null) AddError(new NotSupportedError(loc)); if (!CanUseThisTypeForBinaryFiles(en.type)) { AddError(en.location, "CAN_NOT_READ_REFERENCE_DATA_FROM_BINARY_FILE"); } exl.AddElement(new typeof_operator(en.type, loc)); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure.SymbolInfo, loc); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray()); expr = convertion_data_and_alghoritms.explicit_convert_type(expr, en.type); expr = find_operator(compiler_string_consts.assign_name, en, expr, loc); last_call = expr; } else { exl.AddElement(en); try { function_node fn = null; if (en.type.type_special_kind == SemanticTree.type_special_kind.short_string) { exl.AddElement(new int_const_node((en.type as short_string_type_node).Length,null)); if (!read_from_file) last_call = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.read_short_string_procedure.sym_info as function_node,get_location(ex),exl.ToArray()); else last_call = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure.sym_info as function_node,get_location(ex),exl.ToArray()); } else if (en.type.type_special_kind == SemanticTree.type_special_kind.diap_type) { exl.remove(en); en.type = en.type.base_type; exl.AddElement(en); fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc); last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray()); } else { if (SystemLibrary.SystemLibInitializer.readln_procedure.Equal(si) && parameters.expressions.Count == 2 && en.type == SystemLibrary.SystemLibrary.string_type) { fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo, loc); readln_string_file = true; } else fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc); last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray()); } //last_call = convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc, context.converted_type, context.top_function, true); } catch (NoFunctionWithSameArguments) { AddError(en.location, "CAN_NOT_READ"); } } first_iteration = false; } } if ((parameters == null) || (parameters.expressions.Count == 0)) // read(), readln() { if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si)) { if (read_from_file) exl.AddElement(file); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc); if (read_from_file) last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, file); else last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc); } } if (SystemLibrary.SystemLibInitializer.readln_procedure.Equal(si)) // readln(...) { if (!readln_string_file) { if (last_call != null && convertion_data_and_alghoritms.statement_list_stack.size > 0) convertion_data_and_alghoritms.statement_list_stack.top().statements.AddElement(last_call); exl.clear(); if (read_from_file) exl.AddElement(file); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo, loc); if (read_from_file) last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, file); else last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc); } } return last_call; }
public override void visit(SyntaxTree.pascal_set_constant _pascal_set_constant) { //throw new NotSupportedError(get_location(_pascal_set_constant)); if (SystemLibrary.SystemLibInitializer.TypedSetType == null || SystemLibrary.SystemLibInitializer.CreateSetProcedure == null) AddError(new NotSupportedError(get_location(_pascal_set_constant))); expressions_list consts = new expressions_list(); type_node el_type = null; type_node_list types = new type_node_list(); if (_pascal_set_constant.values != null && _pascal_set_constant.values != null) foreach (SyntaxTree.expression e in _pascal_set_constant.values.expressions) { if (e is SyntaxTree.nil_const) ErrorsList.Add(new SimpleSemanticError(get_location(e), "NIL_IN_SET_CONSTRUCTOR_NOT_ALLOWED")); else if (e is SyntaxTree.diapason_expr) { consts.AddElement(convert_diap_for_set((e as SyntaxTree.diapason_expr), out el_type)); if (el_type.IsPointer) ErrorsList.Add(new SimpleSemanticError(get_location(e), "POINTERS_IN_SETS_NOT_ALLOWED")); types.AddElement(el_type); } else { expression_node en = convert_strong(e); if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression); if (en.type.type_special_kind == SemanticTree.type_special_kind.short_string) en.type = SystemLibrary.SystemLibrary.string_type; consts.AddElement(en); types.AddElement(en.type); } } expressions_list consts_copy = new expressions_list(); consts_copy.AddRange(consts); type_node ctn = null; if (consts.Count > 0) { el_type = convertion_data_and_alghoritms.select_base_type(types); ctn = context.create_set_type(el_type, get_location(_pascal_set_constant)); } else ctn = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node; function_node fn = convertion_data_and_alghoritms.select_function(consts, SystemLibrary.SystemLibInitializer.CreateSetProcedure.SymbolInfo, (SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info is common_namespace_function_node)?(SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node).loc:null); if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, get_location(_pascal_set_constant)); add_set_initializer(cnfc, consts_copy); cnfc.ret_type = ctn; for (int i = 0; i < consts.Count; i++) cnfc.parameters.AddElement(consts[i]); return_value(cnfc); } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, get_location(_pascal_set_constant)); add_set_initializer(cnfc, consts_copy); cnfc.ret_type = ctn; for (int i = 0; i < consts.Count; i++) cnfc.parameters.AddElement(consts[i]); return_value(cnfc); } //return_value(new common_namespace_function_call_as_constant(cnfc,cnfc.location)); }
private void ConvertPointersForWriteFromDll(expressions_list exprs) { for (int i = 0; i < exprs.Count; ++i) { if (exprs[i].type.IsPointer) { if (SystemLibrary.SystemLibInitializer.PointerOutputConstructor == null) { SymbolInfo si = (SystemLibrary.SystemLibInitializer.PointerOutputType.sym_info as compiled_type_node).find_in_type(compiler_string_consts.default_constructor_name); compiled_constructor_node cnode = null; do { cnode = si.sym_info as compiled_constructor_node; if (cnode.parameters.Count != 1) { cnode = null; si = si.Next; } } while (cnode == null); SystemLibrary.SystemLibInitializer.PointerOutputConstructor = cnode; } compiled_constructor_call cnc = new compiled_constructor_call(SystemLibrary.SystemLibInitializer.PointerOutputConstructor as compiled_constructor_node, exprs[i].location); //common_namespace_function_call cnfc = new common_namespace_function_call( // SystemLibrary.SystemLibInitializer.PointerToStringFunction.sym_info as common_namespace_function_node, // exprs[i].location); cnc.parameters.AddElement(exprs[i]); exprs[i] = cnc; } } }
private void make_attributes_for_declaration(SyntaxTree.unit_module un, common_unit_node cun) { if (cun.attributes != null) { Hashtable ht = new Hashtable(); foreach (SyntaxTree.simple_attribute_list sal in un.attributes.attributes) for (int j = 0; j < sal.attributes.Count; j++) { SyntaxTree.attribute attr = sal.attributes[j]; attribute_converted = true; type_node tn = convert_strong(attr.type); bool is_attr = false; type_node tmp = tn; while (tmp.base_type != null && !is_attr) { is_attr = tmp.base_type == SystemLibrary.SystemLibrary.attribute_type; tmp = tmp.base_type; } if (!is_attr) AddError(get_location(attr), "CLASS_{0}_NOT_ATTRIBUTE", tn.name); bool allowMultiple = false; AttributeTargets targets = get_usage_attrs(tn, out allowMultiple); if (ht.Contains(tn) && !allowMultiple) { AddError(get_location(attr), "DUPLICATE_ATTRIBUTE_{0}_APPLICATION", tn.name); } else ht[tn] = tn; SemanticTree.attribute_qualifier_kind qualifier = SemanticTree.attribute_qualifier_kind.none_kind; if (attr.qualifier != null) if (j == 0) { if (string.Compare(attr.qualifier.name, "return", true) == 0) { if (context.top_function == null) AddError(get_location(attr), "ATTRIBUTE_APPLICABLE_ONLY_TO_METHOD"); if (context.top_function.return_value_type == null || context.top_function.return_value_type == SystemLibrary.SystemLibrary.void_type) AddError(get_location(attr), "EXPECTED_RETURN_VALUE_FOR_ATTRIBUTE"); throw new NotSupportedError(get_location(attr.qualifier)); qualifier = SemanticTree.attribute_qualifier_kind.return_kind; } else throw new NotSupportedError(get_location(attr.qualifier)); } else AddError(get_location(attr.qualifier), "ATTRIBUTE_QUALIFIER_MUST_BE_FIRST"); check_for_usage_attribute(cun, targets, tn.name, get_location(attr), qualifier); attribute_converted = false; SyntaxTree.expression_list cnstr_args = new SyntaxTree.expression_list(); if (attr.arguments != null) { foreach (SyntaxTree.expression e in attr.arguments.expressions) { if (e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal && (e as SyntaxTree.bin_expr).left is SyntaxTree.ident) { break; } else { cnstr_args.expressions.Add(e); } } } expressions_list args = new expressions_list(); for (int i = 0; i < cnstr_args.expressions.Count; i++) { constant_node cn = convert_strong_to_constant_node(cnstr_args.expressions[i]); check_for_strong_constant(cn, get_location(cnstr_args.expressions[i])); args.AddElement(cn); } base_function_call bfc = create_constructor_call(tn, args, get_location(attr)); attribute_node attr_node = new attribute_node(bfc.simple_function_node, tn, get_location(un)); foreach (expression_node en in bfc.parameters) { constant_node cn = convert_strong_to_constant_node(en, en.type); check_for_strong_constant(cn, en.location); attr_node.args.Add(cn); } if (attr.arguments != null) { for (int i = cnstr_args.expressions.Count; i < attr.arguments.expressions.Count; i++) { SyntaxTree.expression e = attr.arguments.expressions[i]; if (!(e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal && (e as SyntaxTree.bin_expr).left is SyntaxTree.ident)) { AddError(get_location(e), "EXPECTED_ATTRIBUTE_INITIALIZER"); } else { SyntaxTree.ident id = (e as SyntaxTree.bin_expr).left as SyntaxTree.ident; SymbolInfo si = tn.find(id.name); definition_node dn = context.check_name_node_type(id.name, si, get_location(id), general_node_type.property_node, general_node_type.variable_node); type_node mem_tn = null; if (dn is property_node) { property_node pn = dn as property_node; attr_node.prop_names.Add(pn); if (pn.set_function == null) AddError(new ThisPropertyCanNotBeWrited(pn, get_location(id))); if (pn.set_function.parameters.Count != 1) AddError(get_location(id), "INDEX_PROPERTY_INITIALIZING_NOT_VALID"); mem_tn = pn.set_function.parameters[0].type; } else if (dn is var_definition_node) { attr_node.field_names.Add(dn as var_definition_node); mem_tn = (dn as var_definition_node).type; } else { throw new CompilerInternalError("Bad general node type for attribute initializer"); } //SyntaxTree.assign tmp_ass = new SyntaxTree.assign(id,(e as SyntaxTree.bin_expr).right,SyntaxTree.Operators.Assignment); //tmp_ass.source_context = e.source_context; //basic_function_call tmp_bfc = convert_strong(tmp_ass) as basic_function_call; constant_node cn = convert_strong_to_constant_node((e as SyntaxTree.bin_expr).right, mem_tn); check_for_strong_constant(cn, get_location((e as SyntaxTree.bin_expr).right)); if (dn is property_node) attr_node.prop_initializers.Add(cn); else attr_node.field_initializers.Add(cn); } } } attr_node.qualifier = qualifier; cun.attributes.AddElement(attr_node); if (cun.namespaces.Count > 0) cun.namespaces[0].attributes.AddElement(attr_node); } } }
public override void visit(SyntaxTree.format_expr _format_expr) { if (_format_expr.expr == null || _format_expr.format1 == null) AddError(get_location(_format_expr), "BAD_CONSTRUCTED_FORMAT_EXPRESSION"); //TODO: Добавить проверки. if (!SemanticRules.AllowUseFormatExprAnywhere && !is_format_allowed) AddError(get_location(_format_expr.expr), "FORMAT_EXPRESSION_CAN_USE_ONLY_IN_THESE_PROCEDURES"); expression_node expr = convert_strong(_format_expr.expr); if (expr is typed_expression) expr = convert_typed_expression_to_function_call(expr as typed_expression); expression_node par1 = convert_strong(_format_expr.format1); par1 = convertion_data_and_alghoritms.convert_type(par1, SystemLibrary.SystemLibrary.integer_type); expression_node par2 = convert_weak(_format_expr.format2); if (par2 != null) { if (expr.type != SystemLibrary.SystemLibrary.double_type && expr.type != SystemLibrary.SystemLibrary.float_type) { AddError(expr.location, "REAL_TYPE_IN_DOUBLE_COLON_EXPRESSION_EXPECTED"); } par2 = convertion_data_and_alghoritms.convert_type(par2, SystemLibrary.SystemLibrary.integer_type); } expressions_list exl = new expressions_list(); exl.AddElement(expr); exl.AddElement(par1); if (par2 != null) { exl.AddElement(par2); } location loc = get_location(_format_expr); if (!SystemUnitAssigned) AddError( new NotSupportedError(loc)); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.format_function.SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return_value(ret); }
/// <summary> /// Обрабатывает случай, когда левая часть присваивания свойство. /// </summary> /// <returns>True - обработка прошла, иначе False.</returns> private bool ProcessAssignToPropertyIfPossible(assign _assign, addressed_expression to, location loc, expression_node from) { //проверка на обращение к полю записи возвращенной из функции с целью присваивания //нужно чтобы пользователь не мог менять временный обьект if (to.semantic_node_type == semantic_node_type.static_property_reference || to.semantic_node_type == semantic_node_type.non_static_property_reference) { property_node pn; if (to.semantic_node_type == semantic_node_type.static_property_reference) { pn = (to as static_property_reference).property; } else { pn = (to as non_static_property_reference).property; } var ot = MapCompositeAssignmentOperatorToSameBinaryOperator(_assign); var oper_ass_in_prop = ot != Operators.Undefined; if (_assign.operator_type == Operators.Assignment || oper_ass_in_prop) { if (oper_ass_in_prop) { if (pn.get_function == null) { AddError(loc, "THIS_PROPERTY_{0}_CAN_NOT_BE_READED", pn.name); } base_function_call prop_expr; if (to.semantic_node_type == semantic_node_type.non_static_property_reference) { prop_expr = create_not_static_method_call(pn.get_function, (to as non_static_property_reference).expression, loc, false); prop_expr.parameters.AddRange((to as non_static_property_reference).fact_parametres); } else { prop_expr = create_static_method_call(pn.get_function, loc, pn.comprehensive_type, false); prop_expr.parameters.AddRange((to as static_property_reference).fact_parametres); } from = find_operator(ot, prop_expr, from, loc); } if (to.semantic_node_type == semantic_node_type.static_property_reference) { static_property_reference spr = (static_property_reference)to; if (spr.property.set_function == null) { AddError(loc, "THIS_PROPERTY_{0}_CAN_NOT_BE_WRITED", spr.property.name); } check_property_params(spr, loc); function_node set_func = spr.property.set_function; from = convertion_data_and_alghoritms.convert_type(from, spr.property.property_type); spr.fact_parametres.AddElement(from); base_function_call bfc = create_static_method_call(set_func, loc, spr.property.comprehensive_type, true); bfc.parameters.AddRange(spr.fact_parametres); return_value((statement_node)bfc); } else if (to.semantic_node_type == semantic_node_type.non_static_property_reference) { non_static_property_reference nspr = (non_static_property_reference)to; check_property_params(nspr, loc); from = convertion_data_and_alghoritms.convert_type(from, nspr.property.property_type); nspr.fact_parametres.AddElement(from); //Обработка s[i]:='c' if (SystemUnitAssigned) { if (nspr.property.comprehensive_type == SystemLibrary.SystemLibrary.string_type) { if (nspr.property == SystemLibrary.SystemLibrary.string_type.default_property_node) { if (SystemLibInitializer.StringDefaultPropertySetProcedure != null) { expressions_list exl = new expressions_list(); exl.AddElement(nspr.expression); exl.AddElement(nspr.fact_parametres[0]); exl.AddElement(from); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibInitializer.StringDefaultPropertySetProcedure .SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return_value((statement_node)ret); return(true); } } } } if (nspr.property.set_function == null) { AddError(loc, "THIS_PROPERTY_{0}_CAN_NOT_BE_WRITED", nspr.property.name); } function_node set_func = nspr.property.set_function; base_function_call bfc = create_not_static_method_call(set_func, nspr.expression, loc, true); bfc.parameters.AddRange(nspr.fact_parametres); return_value((statement_node)bfc); } return(true); } } return(false); }
public expression_node find_operator(string name, expression_node left, expression_node right, location loc) { //if (!CheckExpressionType(left)) // return SystemLibrary.SystemLibrary.get_empty_method_call(left.location); //if (!CheckExpressionType(right)) // return SystemLibrary.SystemLibrary.get_empty_method_call(right.location); //string name=name_reflector.get_name(ot); #if (DEBUG) if (name == null) { throw new CompilerInternalError("Invalid operator name"); } #endif if (right.semantic_node_type == semantic_node_type.null_const_node) { if ( !type_table.is_with_nil_allowed(left.type) && !left.type.IsPointer) AddError(right.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED"); right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right); } type_node left_type = left.type; type_node right_type = right.type; /*if (left.type == SystemLibrary.SystemLibrary.uint64_type || right.type == SystemLibrary.SystemLibrary.uint64_type) if (name == compiler_string_consts.plus_name || name == compiler_string_consts.minus_name || name == compiler_string_consts.mul_name || name == compiler_string_consts.idiv_name || name == compiler_string_consts.mod_name) { expression_node expr = right.type != SystemLibrary.SystemLibrary.uint64_type ? right : left; if (!(expr is constant_node)) { type_node tn = expr.type; if (tn == SystemLibrary.SystemLibrary.short_type || tn == SystemLibrary.SystemLibrary.sbyte_type || tn == SystemLibrary.SystemLibrary.integer_type || tn == SystemLibrary.SystemLibrary.int64_type) throw new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc); } } */ if (left_type.semantic_node_type == semantic_node_type.delegated_method) { delegated_methods dm1 = (delegated_methods)left_type; if (dm1.empty_param_method != null) { if (dm1.empty_param_method.simple_function_node.return_value_type != null) { left_type = dm1.empty_param_method.simple_function_node.return_value_type; } } } if (right_type.semantic_node_type == semantic_node_type.delegated_method && name != compiler_string_consts.plusassign_name && name != compiler_string_consts.minusassign_name) { delegated_methods dm2 = (delegated_methods)right_type; if (dm2.empty_param_method != null) { if (dm2.empty_param_method.simple_function_node.return_value_type != null) { right_type = dm2.empty_param_method.simple_function_node.return_value_type; } } } //zdes ne vse verno. += odnostoronnjaa operacija, a += b pochemu esli tipy ne ravny, += ishetsja v tipe b??? //TODO: Посмотреть. //TODO: Не find а find_in_type. //SymbolInfo si=left_type.find(name, context.CurrentScope); SymbolInfo si = left_type.find_in_type(name, left_type.Scope); SymbolInfo added_symbols = null; SymbolInfo si2 = null; if (left_type != right_type && !one_way_operation(name)) { //SymbolInfo si2 = right_type.find(name, context.CurrentScope); if (si != null) si = si.copy(); si2 = right_type.find_in_type(name, right_type.Scope); if ((si != null) && (si2 != null)) { //Важная проверка. Возможно один и тот же оператор с одними и теми же типами определен в двух разных классах. //Возможно она занимает много времени, но, наверное, от нее нельзя отказаться. function_node_list funcs = new function_node_list(); SymbolInfo sic = si; SymbolInfo sic_last = null; while (sic != null) { if (sic.sym_info.general_node_type != general_node_type.function_node) { BasePCUReader.RestoreSymbols(sic, name); } #if (DEBUG) if (sic.sym_info.general_node_type != general_node_type.function_node) { throw new CompilerInternalError("Expected operator."); } #endif function_node fn = ((function_node)(sic.sym_info)); if (convertion_data_and_alghoritms.is_exist_eq_method_in_list(fn, funcs) != null) { break; } funcs.AddElement(fn); sic_last = sic; sic = sic.Next; } sic = si2; //TODO: Разобраться с зацикливанием. function_node_list fnl = new function_node_list(); while (sic != null) { if (sic.sym_info.general_node_type != general_node_type.function_node) { BasePCUReader.RestoreSymbols(sic, name); } #if (DEBUG) if (sic.sym_info.general_node_type != general_node_type.function_node) { throw new CompilerInternalError("Expected operator."); } #endif fnl.AddElement(((function_node)(sic.sym_info))); sic = sic.Next; } added_symbols = sic_last; foreach (function_node fnode in fnl) { function_node eq_func = convertion_data_and_alghoritms.find_eq_method_in_list(fnode, funcs); if (eq_func != null) { //TODO: Проверить правильно ли это будет работать. if (eq_func != fnode) { basic_function_node bbfn1 = fnode as basic_function_node; basic_function_node bbfn2 = eq_func as basic_function_node; if ((bbfn1 != null) && (bbfn2 != null)) { if (bbfn1.basic_function_type != bbfn2.basic_function_type) { AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right)); } //sic = sic.Next; continue; } else { if (left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type || left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type || left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type || left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type && right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type || left.type == SystemLibrary.SystemLibrary.string_type && right.type.type_special_kind == SemanticTree.type_special_kind.short_string || right.type == SystemLibrary.SystemLibrary.string_type && left.type.type_special_kind == SemanticTree.type_special_kind.short_string || left.type.type_special_kind == SemanticTree.type_special_kind.short_string && right.type.type_special_kind == SemanticTree.type_special_kind.short_string) { //if (left.type.find_in_type(name) !=null) } else AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right)); } } } sic_last.Next = new SymbolInfo(fnode); sic_last = sic_last.Next; } /*while (sic!=null) { #if (DEBUG) if (sic.sym_info.general_node_type!=general_node_type.function_node) { throw new CompilerInternalError("Expected operator."); } #endif function_node fn=((function_node)(sic.sym_info)); function_node eq_func=convertion_data_and_alghoritms.find_eq_method_in_list(fn,funcs); if (eq_func!=null) { basic_function_node bbfn1=fn as basic_function_node; basic_function_node bbfn2=eq_func as basic_function_node; if ((bbfn1!=null)&&(bbfn2!=null)) { if (bbfn1.basic_function_type!=bbfn2.basic_function_type) { throw new TwoOperatorsCanBeCalled(eq_func,fn,left,right); } sic=sic.Next; continue; } else { throw new TwoOperatorsCanBeCalled(eq_func,fn,left,right); } } //TODO: Разобраться с зацикливанием. sic_last.Next = sic; sic_last = sic; sic=sic.Next; }*/ //sic_last.Next=si2; } else { if ((si == null) && (si2 != null)) { si = si2; } } } //if (si == null) { if (/*si2 == null && */left_type.semantic_node_type == semantic_node_type.delegated_method && right_type.semantic_node_type == semantic_node_type.delegated_method) { SymbolInfo saved_si = si; SymbolInfo saved_si2 = si2; base_function_call bfc = ((left as typed_expression).type as delegated_methods).proper_methods[0]; left = convertion_data_and_alghoritms.explicit_convert_type(left, CreateDelegate(bfc.simple_function_node)); si = left.type.find_in_type(name); bfc = ((right as typed_expression).type as delegated_methods).proper_methods[0]; right = convertion_data_and_alghoritms.explicit_convert_type(right, CreateDelegate(bfc.simple_function_node)); si2 = right.type.find_in_type(name); if (saved_si != null) si.Next = saved_si; else saved_si = si; if (saved_si2 != null) si2.Next = saved_si2; else saved_si2 = si2; if (saved_si == null) AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); } else if (si == null) AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); } expressions_list pars = null; function_node fnsel = null; SymbolInfo tmp_si = si; while (tmp_si != null) { if (tmp_si.sym_info is wrapped_definition_node) BasePCUReader.RestoreSymbols(tmp_si, name); tmp_si = tmp_si.Next; } pars = new expressions_list(); pars.AddElement(left); pars.AddElement(right); fnsel = convertion_data_and_alghoritms.select_function(pars, si, loc); //function_node fnsel=convertion_data_and_alghoritms.select_function(pars,si,loc); CheckSpecialFunctionCall(si, pars,loc); //TODO: А это зачем? Можно передать в create_simple_function_call pars. left = pars[0]; right = pars[1]; if (fnsel == null) { AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); } if (added_symbols != null) added_symbols.Next = null; if (SystemUnitAssigned && in_check_range_region() && name == compiler_string_consts.assign_name && is_range_checkable(left.type) && is_range_checkable(right.type)) { ordinal_type_interface oti = left.type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (left.type != SystemLibrary.SystemLibrary.char_type && left.type != SystemLibrary.SystemLibrary.uint64_type && !(oti.lower_value is ulong_const_node)) if(!(oti.lower_value is enum_const_node) && !(oti.lower_value is char_const_node)) right = convertion_data_and_alghoritms.convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.convert_type(right,SystemLibrary.SystemLibrary.int64_type), convertion_data_and_alghoritms.convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type); else if (oti.lower_value is enum_const_node) { right = convertion_data_and_alghoritms.explicit_convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.explicit_convert_type(right,SystemLibrary.SystemLibrary.int64_type), convertion_data_and_alghoritms.explicit_convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.explicit_convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type); } else if (oti.lower_value is char_const_node) right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckCharRangeFunction.sym_info as common_namespace_function_node, null, right, oti.lower_value,oti.upper_value); } expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fnsel, loc, left, right); return exp_node; }
/// <summary> /// Возвращает список преобразований типов для вызова метода. /// </summary> /// <param name="factparams">Список фактических параметров.</param> /// <param name="formalparams">Список формальных параметров.</param> /// <param name="is_alone_method_defined">Для единственного метода у которого типы параметров совпадают, но в качестве var параметра мы передаем константное значение мы можем сгенерировать более подробное сообщение об ошибке.</param> /// <returns>Список преобразований типов.</returns> internal possible_type_convertions_list get_conversions(expressions_list factparams, parameter_list formalparams,bool is_alone_method_defined, location locg) { //TODO:Явно указывать capacity при создании. possible_type_convertions_list tc = new possible_type_convertions_list(); possible_type_convertions ptc; if (factparams.Count>formalparams.Count) { if ( (formalparams.Count==0) || (!(formalparams[formalparams.Count-1].is_params)) ) { return null; } } type_node for_par_type = null; array_internal_interface aii=null; if (formalparams.Count > 0) { parameter pr=formalparams[formalparams.Count - 1]; if (pr.is_params && //это для возможности вызова сразу с массивом[], типа просто не обращаем внимаение на params !(factparams.Count == formalparams.Count && factparams[factparams.Count - 1].type == formalparams[formalparams.Count - 1].type)) { //TODO: Добавить проверку на правильность. aii = (array_internal_interface) pr.type.get_internal_interface(internal_interface_kind.unsized_array_interface); for_par_type = aii.element_type; tc.snl = new statement_node_list(); location loc=null; if (factparams.Count > 0) loc = factparams[factparams.Count-1].location; //var_definition_node vdn=syntax_tree_visitor.context.add_var_definition_in_entry_scope(get_temp_arr_name(),loc); var_definition_node vdn = null; if (syntax_tree_visitor.context.converted_func_stack.size > 0) { common_function_node cfn = syntax_tree_visitor.context.converted_func_stack.first(); if (cfn.is_generic_function) { vdn = syntax_tree_visitor.context.add_var_definition(get_temp_arr_name(), loc); } else vdn = syntax_tree_visitor.context.add_var_definition_in_entry_scope(get_temp_arr_name(), loc); } else if (syntax_tree_visitor.context.converted_type != null) vdn = syntax_tree_visitor.context.add_field(get_temp_arr_name(), loc, pr.type, polymorphic_state.ps_static); else vdn = syntax_tree_visitor.context.add_var_definition_in_entry_scope(get_temp_arr_name(), loc); syntax_tree_visitor.context.close_var_definition_list(pr.type,null); expression_node fst=null; /*switch (syntax_tree_visitor.context.converting_block()) { case block_type.function_block: { fst=new local_variable_reference((local_variable)vdn,0,loc); break; } case block_type.namespace_block: { fst=new namespace_variable_reference((namespace_variable)vdn,loc); break; } }*/ switch (vdn.semantic_node_type) { case semantic_node_type.local_variable: { fst = new local_variable_reference((local_variable)vdn, 0, loc); break; } case semantic_node_type.namespace_variable: { fst = new namespace_variable_reference((namespace_variable)vdn, loc); break; } case semantic_node_type.local_block_variable: { fst = new local_block_variable_reference((local_block_variable)vdn, loc); break; } case semantic_node_type.class_field: { class_field cf = vdn as class_field; cf.polymorphic_state = polymorphic_state.ps_static; fst = new static_class_field_reference(cf, loc); break; } default: throw new CompilerInternalError("Invalid node type"); } tc.var_ref = fst; int del=factparams.Count-formalparams.Count+1; int_const_node icn=new int_const_node(del,loc); expression_node bfc = create_simple_function_call(SystemLibrary.SystemLibrary.resize_func, loc, fst, icn); tc.snl.AddElement(bfc); /*if (factparams.Count == 0) { possible_type_convertions ptci=new possible_type_convertions(); ptci.first=null; ptci.second=null; ptci.from=null; ptci.to = for_par_type; tc.AddElement(ptci); }*/ } } for(int i=0;i<factparams.Count;i++) { type_node formal_param_type = null; if ((for_par_type!=null)&&(i >= formalparams.Count-1)) { formal_param_type = for_par_type; } else { formal_param_type = formalparams[i].type; } if (possible_equal_types(factparams[i].type, formal_param_type)) { if ((i<formalparams.Count)&&(formalparams[i].parameter_type==SemanticTree.parameter_type.var)) { bool is_pascal_array_ref = false; bool is_ok = false; if (factparams[i].is_addressed==false) { if (factparams[i].semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)factparams[i]; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value),cmc.location)); factparams[i] = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } } if (!is_pascal_array_ref) { //Если мы попали сюда, то мы пытаемся передать по ссылке значение, //которое не мохет быть передано по ссылке. Например, передать //по ссылки из одной функции в другую константный параметр. if (is_alone_method_defined) { if (syntax_tree_visitor.assign_is_converting) { AddError(factparams[i].location, "CAN_NOT_ASSIGN_TO_LEFT_PART"); } else { if (formalparams[i] is common_parameter && (formalparams[i] as common_parameter).concrete_parameter_type == concrete_parameter_type.cpt_const /*&& factparams[i] is common_parameter_reference*/) { is_ok = true; } else if (formalparams[i] is common_parameter && (formalparams[i] as common_parameter).concrete_parameter_type == concrete_parameter_type.cpt_const) ; //throw new ThisExpressionCanNotBePassedAsConstParameter(factparams[i].location); else if (is_string_getter(factparams[i])) { if (factparams[i] is compiled_function_call) factparams[i] = make_unmanaged_string_getter(factparams[i] as compiled_function_call); else factparams[i] = make_unmanaged_shortstring_getter(factparams[i] as base_function_call); is_ok = true; } else AddError(new ThisExpressionCanNotBePassedAsVarParameter(factparams[i])); } } else if (is_string_getter(factparams[i])) { if (factparams[i] is compiled_function_call) factparams[i] = make_unmanaged_string_getter(factparams[i] as compiled_function_call); else factparams[i] = make_unmanaged_shortstring_getter(factparams[i] as base_function_call); is_ok = true; } if (!is_ok) return null; } } } //Разобраться: может лучше добавлять null к списку. possible_type_convertions ptci=new possible_type_convertions(); ptci.first=null; ptci.second=null; ptci.from=factparams[i].type; ptci.to = formal_param_type; tc.AddElement(ptci); if ((for_par_type != null) && (i >= formalparams.Count - 1)) { expression_node to = new simple_array_indexing(tc.var_ref,//factparams[formalparams.Count - 1], new int_const_node(i - formalparams.Count + 1, factparams[i].location), aii.element_type, factparams[i].location); expression_node from = factparams[i]; statement_node stat = syntax_tree_visitor.find_operator(compiler_string_consts.assign_name, to, from, factparams[i].location); tc.snl.AddElement(stat); } continue; } if ((i<formalparams.Count)&&(formalparams[i].parameter_type==SemanticTree.parameter_type.var)) { return null; } else { ptc = type_table.get_convertions(factparams[i].type, formal_param_type); if (ptc.first==null) { if (type_table.is_derived(formal_param_type, factparams[i].type)) { possible_type_convertions ptci=new possible_type_convertions(); ptci.first=null; ptci.second=null; ptci.from=factparams[i].type; ptci.to = formal_param_type; tc.AddElement(ptci); if ((for_par_type != null) && (i >= formalparams.Count - 1)) { expression_node to = new simple_array_indexing(tc.var_ref,//factparams[formalparams.Count - 1], new int_const_node(i - formalparams.Count + 1, factparams[i].location), aii.element_type, factparams[i].location); expression_node from = factparams[i]; statement_node stat = syntax_tree_visitor.find_operator(compiler_string_consts.assign_name, to, from, factparams[i].location); tc.snl.AddElement(stat); } } else { if (is_alone_method_defined) { AddError(new CanNotConvertTypes(factparams[i], factparams[i].type, formal_param_type, locg)); } return null; } } else { tc.AddElement(ptc); if ((for_par_type != null) && (i >= formalparams.Count - 1)) { expression_node to = new simple_array_indexing(tc.var_ref,//factparams[formalparams.Count - 1], new int_const_node(i - formalparams.Count + 1, factparams[i].location), aii.element_type, factparams[i].location); expression_node from = create_simple_function_call(ptc.first.convertion_method, factparams[i].location, factparams[i]); statement_node stat = syntax_tree_visitor.find_operator(compiler_string_consts.assign_name, to, from, factparams[i].location); tc.snl.AddElement(stat); } } } } if (tc.snl != null) foreach (statement_node sn in tc.snl) sn.location = null; return tc; }
/// <summary> /// Этот метод вызывается если мы встречаем простой вызов функии, например f(1). /// Он определяет является ли эта функция методом класса, вложенной функцией и т.д. и создает соответствующее обращение. /// Например, для метода класса он добавляет this, а для вложенной функции вычисляет статическую глубину. /// </summary> /// <param name="exprs">Список параметров.</param> /// <param name="si">Список методов.</param> /// <param name="loc">Расположение вызова.</param> /// <param name="converted_type">Тип в котором мы находимся. null, если мы вне типа.</param> /// <param name="top_function">Функция в которой мы находимся.</param> /// <param name="allow_procedure">Может ли это быть вызов процедуры. false если вызов стоит в выражении или правой части опреатора присваивания.</param> /// <returns>Возвращает узел вызова метода.</returns> public expression_node create_full_function_call(expressions_list exprs,SymbolInfo si,location loc, common_type_node converted_type,common_function_node top_function,bool allow_procedure) { function_node fn=select_function(exprs,si,loc); /* if (fn.compile_time_executor != null) { expression_node ex = fn.compile_time_executor(loc, exprs.ToArray()); if (ex != null) { return ex; } } */ //allow_procedure = true; if ((!allow_procedure)&&(fn.return_value_type==null)) { throw new SimpleSemanticError(loc, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", fn.name); } expression_node expr_node=null; switch (fn.semantic_node_type) { case semantic_node_type.basic_function_node: case semantic_node_type.common_namespace_function_node: { expr_node=create_simple_function_call(fn,loc,exprs.ToArray()); break; } case semantic_node_type.common_method_node: case semantic_node_type.compiled_function_node: { SemanticTree.IClassMemberNode icmn=(SemanticTree.IClassMemberNode)fn; if (icmn.polymorphic_state==SemanticTree.polymorphic_state.ps_static) { expr_node=create_simple_function_call(fn,loc,exprs.ToArray()); break; } //expression_node tn = new this_node(converted_type,loc); base_function_call cmc=null; switch (fn.semantic_node_type) { case semantic_node_type.common_method_node: { //ssyy добавил if (((common_method_node)fn).is_constructor) { common_constructor_call ccc = new common_constructor_call((common_method_node)fn, loc); //(ssyy) По-видимому, здесь всегда можно присваивать false, так как при создании нового объекта мы сюда не заходим... ccc._new_obj_awaited = false; if (!syntax_tree_visitor.context.allow_inherited_ctor_call) { throw new SimpleSemanticError(loc, "INHERITED_CONSTRUCTOR_CALL_MUST_BE_FIRST"); } cmc = ccc; } else //\ssyy { cmc = new common_method_call((common_method_node)fn, syntax_tree_visitor.GetCurrentObjectReference(((common_method_node)fn).cont_type.Scope, fn, loc), loc); (cmc as common_method_call).virtual_call = !syntax_tree_visitor.inherited_ident_processing; } break; } case semantic_node_type.compiled_function_node: { cmc = new compiled_function_call((compiled_function_node)fn, syntax_tree_visitor.GetCurrentObjectReference(((compiled_function_node)fn).cont_type.Scope, fn, loc), loc); (cmc as compiled_function_call).virtual_call = !syntax_tree_visitor.inherited_ident_processing; break; } } cmc.parameters.AddRange(exprs); expr_node=cmc; break; } case semantic_node_type.common_in_function_function_node: { common_in_function_function_node cffn=(common_in_function_function_node)fn; common_in_function_function_call cffc=new common_in_function_function_call(cffn, symtab.GetRelativeScopeDepth(cffn.function.scope,top_function.scope),loc); cffc.parameters.AddRange(exprs); expr_node=cffc; break; } //ssyy добавил case semantic_node_type.compiled_constructor_node: { compiled_constructor_node ccn = fn as compiled_constructor_node; if (ccn == null) { throw new CompilerInternalError("compiled_constructor_node expected"); } compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc); ccc.parameters.AddRange(exprs); ccc._new_obj_awaited = false; if (!syntax_tree_visitor.context.allow_inherited_ctor_call) { throw new SimpleSemanticError(loc, "INHERITED_CONSTRUCTOR_CALL_MUST_BE_FIRST"); } expr_node = ccc; break; } case semantic_node_type.indefinite_definition_node: { indefinite_function_call ifc = new indefinite_function_call(fn, loc); ifc.parameters.AddRange(exprs); expr_node = ifc; break; } //\ssyy default: { throw new NotSupportedError(loc); } } return expr_node; }
//Первый параметр - выходной. Он содержит выражения с необходимыми преобразованиями типов. public function_node select_function(expressions_list parameters, SymbolInfo functions, location loc, List<SyntaxTree.expression> syntax_nodes_parameters = null) { if (functions==null) { AddError(new NoFunctionWithThisName(loc)); } function_node_list set_of_possible_functions = new function_node_list(); bool is_alone_method_defined = (functions.Next == null); function_node first_function = functions.sym_info as function_node; bool _is_assigment = first_function.name == compiler_string_consts.assign_name; basic_function_node _tmp_bfn = functions.sym_info as basic_function_node; List<function_node> indefinits = new List<function_node>(); while(functions!=null) { #if (DEBUG) if (functions.sym_info.general_node_type!=general_node_type.function_node && functions.sym_info.general_node_type != general_node_type.property_node) { throw new CompilerInternalError("Function name is used to define another kind of object."); } #endif function_node fn = null; if (functions.sym_info.general_node_type == general_node_type.property_node) { fn = (functions.sym_info as property_node).get_function; } else fn=(function_node)functions.sym_info; if (fn.node_kind == node_kind.indefinite) { indefinits.Add(fn); } else if (fn.node_kind==SemanticTree.node_kind.common) { common_function_node cfn=(common_function_node)fn; if ((parameters.Count>=cfn.parameters.Count-cfn.num_of_default_variables)&& (parameters.Count<=cfn.parameters.Count) || parameters.Count == 0 && cfn.parameters.Count == 1 && cfn.parameters[0].is_params) { if (is_exist_eq_method_in_list(fn,set_of_possible_functions) != null) { //!!!!!!!!!!!!! //DS TODO //Это нужно чтобы была возможность создавать операторы = := ..., т.к. всегда они добавляюся автоматом //Надо сначало просматривать заголовки и добавлять такие операторы только если нужно. if (set_of_possible_functions.Count > 0) if (set_of_possible_functions[0] is basic_function_node) { set_of_possible_functions.remove(set_of_possible_functions[0]); set_of_possible_functions.AddElement(fn); } //!!!!!!!!!!!!! functions=functions.Next; continue; } set_of_possible_functions.AddElement(fn); } } else { //TODO: Здесь нужно поправить, если создавать возможность вызова метода с параметрами по умолчанию из откомпилированной dll. if (parameters.Count==fn.parameters.Count) { function_node func = null; if ((func=is_exist_eq_method_in_list(fn,set_of_possible_functions)) != null) { if (!eq_type_nodes(fn.return_value_type, func.return_value_type)) { set_of_possible_functions[set_of_possible_functions.IndexOf(func)] = fn; } functions = functions.Next; continue; } set_of_possible_functions.AddElement(fn); } } if (parameters.Count > fn.parameters.Count) { if (fn.parameters.Count > 0) { if ((fn.parameters[fn.parameters.Count - 1]).is_params) { //+DS ms0105 if (is_exist_eq_method_in_list(fn, set_of_possible_functions) != null) { functions = functions.Next; continue; } //-DS set_of_possible_functions.AddElement(fn); } } } else if ((parameters.Count == 0 && fn.parameters.Count == 1) && fn.parameters[0].is_params && !set_of_possible_functions.Contains(fn)) set_of_possible_functions.AddElement(fn); else if (fn.num_of_default_parameters != 0 && parameters.Count >= fn.parameters.Count - fn.num_of_default_parameters) { if (!set_of_possible_functions.Contains(fn)) set_of_possible_functions.AddElement(fn); } else if (parameters.Count == 1 && fn is common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null && fn.parameters.Count == 2 && fn.parameters[1].is_params) set_of_possible_functions.AddElement(fn); functions=functions.Next; } if (set_of_possible_functions.Count==0 && indefinits.Count == 0) { AddError(new NoFunctionWithSameParametresNum(loc, is_alone_method_defined, first_function)); } //(ssyy) Инициализируем is_alone_defined FailedWhileTryingToCompileLambdaBodyWithGivenParametersException lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException = null; if (set_of_possible_functions.Count == 1 && indefinits.Count == 0) { is_alone_method_defined = true; } //(ssyy) Инстанцируем дженерики for (int i = set_of_possible_functions.Count - 1; i > -1; --i) { function_node func = set_of_possible_functions[i]; if (func.is_generic_function) { try { function_node inst = generic_convertions.DeduceFunction(func, parameters, is_alone_method_defined, loc, syntax_nodes_parameters); if (inst == null) { set_of_possible_functions.remove_at(i); } else { set_of_possible_functions[i] = inst; } } catch (FailedWhileTryingToCompileLambdaBodyWithGivenParametersException exc) //lroman Отлавливаем последнее исключение, которое возникло при попытке скомпилировать тело лямбды с заданными типами параметров { set_of_possible_functions.remove_at(i); lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException = exc; } } } if (lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException != null && set_of_possible_functions.Count == 0 && indefinits.Count == 0) { throw lastFailedWhileTryingToCompileLambdaBodyWithGivenParametersException.ExceptionOnCompileBody; // Если перебрали все, но ничто не подошло, то кидаем последнее исключение } if (set_of_possible_functions.Count == 0 && indefinits.Count == 0) { AddError(loc, "CAN_NOT_CALL_ANY_GENERIC_FUNCTION_{0}_WITH_THESE_PARAMETERS", first_function.name); } possible_type_convertions_list_list tcll = new possible_type_convertions_list_list(); for(int i=0;i<set_of_possible_functions.Count;i++) { possible_type_convertions_list tc=get_conversions(parameters,set_of_possible_functions[i].parameters, is_alone_method_defined,loc); tcll.AddElement(tc); } int j=0; while(j<set_of_possible_functions.Count) { if (tcll[j]==null && set_of_possible_functions[j].node_kind != node_kind.indefinite) { tcll.remove_at(j); set_of_possible_functions.remove_at(j); } else { j++; } } if (set_of_possible_functions.Count==0 && indefinits.Count == 0) { if (_is_assigment && parameters.Count == 2) AddError(new CanNotConvertTypes(parameters[1], parameters[1].type, parameters[0].type, parameters[1].location)); if (_tmp_bfn != null && parameters.Count == 2) AddError(new OperatorCanNotBeAppliedToThisTypes(_tmp_bfn.name, parameters[0], parameters[1],loc)); AddError(new NoFunctionWithSameArguments(loc,is_alone_method_defined)); } bool remove=true; while(remove) { if (set_of_possible_functions.Count==1) { check_single_possible_convertion(loc,tcll[0]); convert_function_call_expressions(set_of_possible_functions[0],parameters,tcll[0]); return set_of_possible_functions[0]; } remove=false; var i = 0; while (i < set_of_possible_functions.Count-1) { j = i+1; while (j < set_of_possible_functions.Count) { method_compare mc = compare_methods(set_of_possible_functions[i], set_of_possible_functions[j], tcll[i], tcll[j]); if (mc == method_compare.greater_method) { tcll.remove_at(j); set_of_possible_functions.remove_at(j); remove = true; } else if (mc == method_compare.less_method) { tcll[i] = tcll[j]; set_of_possible_functions[i] = set_of_possible_functions[j]; tcll.remove_at(j); set_of_possible_functions.remove_at(j); remove = true; } else { j++; } } i++; } } // TODO: Исправить этот алгоритм, сделав каждый с каждым - вроде исправил - см. выше /*j = 1; while(j<set_of_possible_functions.Count) { method_compare mc = compare_methods(set_of_possible_functions[0], set_of_possible_functions[j], tcll[0], tcll[j]); if (mc==method_compare.greater_method) { tcll.remove_at(j); set_of_possible_functions.remove_at(j); remove=true; } else if (mc==method_compare.less_method) { tcll[0]=tcll[j]; set_of_possible_functions[0]=set_of_possible_functions[j]; tcll.remove_at(j); set_of_possible_functions.remove_at(j); remove=true; } else { j++; } } }*/ /*remove=true; while (remove) { if (set_of_possible_functions.Count == 1) { check_single_possible_convertion(loc, tcll[0]); convert_function_call_expressions(set_of_possible_functions[0], parameters, tcll[0]); return set_of_possible_functions[0]; } remove = false; j = 1; while (j < set_of_possible_functions.Count) { } }*/ //Тут некоторое дублирование кода, но сюда программа не должна никогда зайти. //Должен быть выполнен if выше. //Но пусть пока повисит. Потом нужно разобраться и убрать. /*if (set_of_possible_functions.Count==1) { check_single_possible_conversion(func_call,tcll[0]); func_call.function=set_of_possible_functions[0]; convert_function_call_expressions(func_call,tcll[0]); func_call.type=func_call.function.return_value_type; return func_call; }*/ //Тупая заглушка для примитивных типов. иначе не работает +=, у нас лишком много неявных приведений //в дальнейшем может вызвать странное поведение, это надо проверить if (set_of_possible_functions.Count == 2 && indefinits.Count == 0) if (set_of_possible_functions[0] is basic_function_node && set_of_possible_functions[1] is basic_function_node) return set_of_possible_functions[0]; if (indefinits.Count > 0) { if (indefinits.Count == 1 && set_of_possible_functions.Count == 0) { return indefinits[0]; } indefinits.AddRange(set_of_possible_functions); return new indefinite_functions_set(indefinits); } bool exist_indefinite_parameter = false; foreach (expression_node par in parameters) { if (par.type.depended_from_indefinite) { exist_indefinite_parameter = true; break; } } if (exist_indefinite_parameter) { indefinits.AddRange(set_of_possible_functions); return new indefinite_functions_set(indefinits); } AddError(new SeveralFunctionsCanBeCalled(loc,set_of_possible_functions)); return null; }
private void convert_function_call_expressions(function_node fn,expressions_list exprs, possible_type_convertions_list ptcal) { /*if (SystemLibrary.SystemLibrary.syn_visitor.SystemUnitAssigned && fn.name != compiler_string_consts.assign_name && !SystemLibrary.SystemLibrary.syn_visitor.one_way_operation(fn.name) && SystemLibrary.SystemLibrary.syn_visitor.in_check_range_region()) { for (int i=0; i<exprs.Count; i++) { if (exprs[i] is statements_expression_node) break; expression_node right = exprs[i]; if (fn.parameters.Count <= i) break; if (fn.parameters[i].parameter_type == parameter_type.var) continue; type_node left_type = fn.parameters[i].type; if (SystemLibrary.SystemLibrary.syn_visitor.is_range_checkable(left_type) && SystemLibrary.SystemLibrary.syn_visitor.is_range_checkable(exprs[i].type)) { ordinal_type_interface oti = left_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (left_type != SystemLibrary.SystemLibrary.char_type) if(!(oti.lower_value is enum_const_node) && !(oti.lower_value is char_const_node)) right = SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.convert_type(SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.convert_type(right,SystemLibrary.SystemLibrary.int64_type), SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type); else if (oti.lower_value is enum_const_node) { right = SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.explicit_convert_type(SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.explicit_convert_type(right,SystemLibrary.SystemLibrary.int64_type), SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.explicit_convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.explicit_convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type); } else if (oti.lower_value is char_const_node) right = SystemLibrary.SystemLibrary.syn_visitor.convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckCharRangeFunction.sym_info as common_namespace_function_node, null, right, oti.lower_value,oti.upper_value); } exprs[i] = right; } }*/ for(int i=0;i<exprs.Count;i++) { if ((ptcal.snl != null) && (i >= fn.parameters.Count - 1)) { //statement_list_stack.top().statements.AddRange(ptcal.snl); statements_expression_node sre = new statements_expression_node(ptcal.snl, ptcal.var_ref, ptcal.var_ref.location); exprs.remove_range(fn.parameters.Count - 1, exprs.Count - fn.parameters.Count); //exprs.AddElement(ptcal.var_ref); //exprs[i] = ptcal.var_ref; exprs[i] = sre; break; } if ((ptcal[i]==null)||(ptcal[i].first==null)||exprs[i] is null_const_node) { continue; } expression_node[] temp_arr = new expression_node[1]; temp_arr[0] = exprs[i]; if (ptcal[i].first.convertion_method is compiled_constructor_node) exprs[i] = create_compiled_construcor_call(ptcal[i].first.convertion_method as compiled_constructor_node, get_location(exprs[i]), temp_arr); else exprs[i] = create_simple_function_call(ptcal[i].first.convertion_method, get_location(exprs[i]), temp_arr); } //TODO: Можно сделать параметры по умолчанию для откомпилированных функций. if ((exprs.Count < fn.parameters.Count) && (fn.node_kind == SemanticTree.node_kind.common)) { if (exprs.Count == 0 && fn.parameters != null && fn.parameters.Count == 1 && fn.parameters[0].is_params || exprs.Count == 1 && fn.parameters != null && fn is common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null && fn.parameters.Count == 2 && fn.parameters[1].is_params) { statements_expression_node sre = new statements_expression_node(ptcal.snl, ptcal.var_ref, ptcal.var_ref.location); //exprs.remove_range(fn.parameters.Count - 1, exprs.Count - fn.parameters.Count); //exprs.AddElement(ptcal.var_ref); //exprs[i] = ptcal.var_ref; exprs.AddElement(sre); } common_function_node cfn = (common_function_node)fn; for (int j = exprs.Count; j < cfn.parameters.Count; j++) { common_parameter cp = (common_parameter)cfn.parameters[j]; if (cp.default_value != null) exprs.AddElement(cp.default_value); } } else if ((exprs.Count < fn.parameters.Count) && (fn.node_kind == SemanticTree.node_kind.compiled)) { if (exprs.Count == 0 && fn.parameters != null && fn.parameters.Count == 1 && fn.parameters[0].is_params) { statements_expression_node sre = new statements_expression_node(ptcal.snl, ptcal.var_ref, ptcal.var_ref.location); exprs.AddElement(sre); } //compiled_function_node cfn = (compiled_function_node)fn; for (int j = exprs.Count; j < fn.parameters.Count; j++) { compiled_parameter cp = (compiled_parameter)fn.parameters[j]; if (cp.default_value != null) exprs.AddElement(cp.default_value); } } }
private base_function_call_list convert_functions_to_calls(expression_node obj, function_node_list fnl, location loc, bool is_static) { base_function_call_list ret = new base_function_call_list(); foreach (function_node fnode in fnl) { base_function_call bfc = null; switch (fnode.semantic_node_type) { case semantic_node_type.common_namespace_function_node: { common_namespace_function_node cmfn = fnode as common_namespace_function_node; common_namespace_function_call cnfc = new common_namespace_function_call(cmfn, loc); if (cmfn.ConnectedToType != null) cnfc.parameters.AddElement(obj); if (cmfn.is_generic_function && !cmfn.is_generic_function_instance && cmfn.ConnectedToType != null && cmfn.parameters.Count == 1) { expressions_list parameters = new expressions_list(); parameters.AddElement(obj); function_node inst = null; try { inst = generic_convertions.DeduceFunction(cmfn, parameters, true, loc); } catch { continue; } cnfc = new common_namespace_function_call((common_namespace_function_node)inst, loc); if (cmfn.ConnectedToType != null) cnfc.parameters.AddElement(obj); } /*if (cmfn.parameters.Count >= 1 && cmfn.parameters[cmfn.parameters.Count - 1].is_params) { convertion_data_and_alghoritms.select_function(cnfc.parameters, new SymbolInfo(cmfn), loc); }*/ bfc = cnfc; break; } case semantic_node_type.basic_function_node: { //Может здесь стоит и выругаться, но я не буду пока этого делать. break; } case semantic_node_type.common_in_function_function_node: { common_in_function_function_node ciffn = fnode as common_in_function_function_node; int depth = convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(ciffn.scope, context.top_function.scope); common_in_function_function_call ciffc = new common_in_function_function_call(ciffn, depth, loc); bfc = ciffc; break; } case semantic_node_type.common_method_node: { common_method_node cmn = fnode as common_method_node; //Если cmn конструктор - то плохо, но его не должно сюда попасть. if (cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { if (!is_static) { if (obj == null) obj = GetCurrentObjectReference(cmn.cont_type.Scope, cmn, loc);//new this_node(context.converted_type, loc); common_method_call cmc = new common_method_call(cmn, obj, loc); cmc.virtual_call = !inherited_ident_processing; bfc = cmc; } //ssyy!!! Мне сложно понять предназначение данного кода, но, по-видимому, //следует его переписать так. else if (cmn.is_constructor) { if (cmn.parameters.Count == 0) { if (cmn.cont_type.IsAbstract) AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", cmn.cont_type.name); ret.clear(); ret.AddElement(new common_constructor_call(cmn, loc)); return ret; } } } else { if (is_static) { common_static_method_call csmc = new common_static_method_call(cmn, loc); bfc = csmc; } } break; } case semantic_node_type.compiled_function_node: { compiled_function_node cfn = fnode as compiled_function_node; if (cfn.cont_type.Scope == null && cfn is compiled_function_node) (cfn.cont_type as compiled_type_node).init_scope(); if (cfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { //ispravleno ibond //if (is_static) { if (cfn.is_generic_function && !cfn.is_generic_function_instance && cfn.ConnectedToType != null && cfn.parameters.Count == 1) { expressions_list parameters = new expressions_list(); parameters.AddElement(obj); function_node inst = null; try { inst = generic_convertions.DeduceFunction(cfn, parameters, true, loc); } catch { continue; } if (inst is common_namespace_function_node) bfc = new common_namespace_function_call((common_namespace_function_node)inst, loc); else if (inst is compiled_function_node) bfc = new compiled_static_method_call((compiled_function_node)inst, loc); else bfc = new compiled_static_method_call(cfn, loc); } else { compiled_static_method_call csmc = new compiled_static_method_call(cfn, loc); bfc = csmc; } if (cfn.ConnectedToType != null) bfc.parameters.AddElement(obj); } } else { if (!is_static) { if (obj == null) obj = GetCurrentObjectReference(cfn.cont_type.Scope, cfn, loc);//new this_node(context.converted_type, loc); compiled_function_call cfc = new compiled_function_call(cfn, obj, loc); cfc.virtual_call = !inherited_ident_processing; bfc = cfc; } } break; } case semantic_node_type.compiled_constructor_node: { //Этот код мы вроде не должны вызывать, но если он все-же вызовется. compiled_constructor_node ccn = fnode as compiled_constructor_node; compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc); bfc = ccc; break; } default: { throw new CompilerInternalError("Undefined method type."); } } if (bfc != null) { ret.AddElement(bfc); } } return ret; }
internal expression_node get_init_call_for_short_string(var_definition_node vdn) { location loc = (vdn.type as short_string_type_node).loc; type_node tn = vdn.type; //vdn.type = SystemLibrary.SystemLibInitializer.ShortStringType.TypeNode; vdn.type = SystemLibrary.SystemLibrary.string_type; int Length = (tn as short_string_type_node).Length; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(var_ref); exl.AddElement(new int_const_node(Length, loc)); expression_node expr = null; //if (SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure != null) //convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure.SymbolInfo, null, context.converted_type, context.top_function, true); vdn.type = tn; return expr; }
private expression_node inherited_message_value_reciving(SyntaxTree.inherited_message _ident) { SymbolInfo si = find_in_base(_ident); bool constr = false; if (si != null) if (si.sym_info is common_method_node) { if ((si.sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD"); constr = (si.sym_info as common_method_node).is_constructor; } else if (si.sym_info is compiled_function_node) { if ((si.sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD"); } else if (si.sym_info is compiled_constructor_node) { constr = true; } location loc = get_location(_ident); function_node fn = si.sym_info as function_node; base_function_call bfc = null; common_function_node cfn = context.converted_func_stack.first(); int depth = context.converted_func_stack.size-1; if (!constr) { if (fn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { bfc = create_not_static_method_call(fn,new this_node(context.converted_type,loc),loc,true); if (bfc is common_method_call) (bfc as common_method_call).virtual_call = false; else (bfc as compiled_function_call).virtual_call = false; } else if (fn is common_method_node) bfc = create_static_method_call(fn,loc,(fn as common_method_node).cont_type,true); else if (fn is compiled_function_node) bfc = create_static_method_call(fn,loc,(fn as compiled_function_node).cont_type,true); else throw new NotSupportedError(loc); } else { if (!context.allow_inherited_ctor_call) AddError(loc, "INHERITED_CONSTRUCTOR_CALL_MUST_BE_FIRST"); expressions_list exprs = new expressions_list(); foreach (common_parameter cp in cfn.parameters) { exprs.AddElement(new common_parameter_reference(cp,depth,loc)); } if (fn is common_method_node) { common_constructor_call ccc = create_constructor_call((fn as common_method_node).cont_type,exprs,loc) as common_constructor_call; ccc._new_obj_awaited = false; return ccc; } else if (fn is compiled_constructor_node) { compiled_constructor_call ccc = create_constructor_call((fn as compiled_constructor_node).compiled_type,exprs,loc) as compiled_constructor_call; ccc._new_obj_awaited = false; return ccc; } else throw new NotSupportedError(loc); } foreach (common_parameter cp in cfn.parameters) { bfc.parameters.AddElement(new common_parameter_reference(cp,depth,loc)); } return bfc; }
private void add_set_initializer(expression_node cnfc, expressions_list exprs) { set_intls[cnfc] = exprs; }
public override void visit(SyntaxTree.assign _assign) { internal_is_assign = true; addressed_expression to = convert_address_strong(_assign.to); internal_is_assign = false; if (to == null) AddError(get_location(_assign.to), "CAN_NOT_ASSIGN_TO_LEFT_PART"); #region Вывод параметров лямбда-выражения var fld1 = _assign.from as SyntaxTree.function_lambda_definition; if (fld1 != null) { MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(fld1); LambdaHelper.InferTypesFromVarStmt(to.type, _assign.from as SyntaxTree.function_lambda_definition, this); //lroman// } #endregion //(ssyy) Вставляю проверки прямо сюда, т.к. запарился вылавливать другие случаи. bool flag=false; general_node_type node_type = general_node_type.constant_definition; if (convertion_data_and_alghoritms.check_for_constant_or_readonly(to, out flag, out node_type)) { if (flag) AddError(to.location, "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT"); else AddError(new CanNotAssignToReadOnlyElement(to.location,node_type)); } //expression_node from = convert_strong(_assign.from); /// SSM исправление Саушкина 10.03.16 expression_node from; var fromAsLambda = _assign.from as function_lambda_definition; if (fromAsLambda != null) { var lambdaVisitMode = fromAsLambda.lambda_visit_mode; fromAsLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; from = convert_strong(_assign.from); fromAsLambda.lambda_visit_mode = lambdaVisitMode; } else { from = convert_strong(_assign.from); } /// end //SSM 4.04.16 if (to.type is undefined_type) to.type = from.type; if (stflambda.Count>0) // мы находимся внутри лямбды - возможно, вложенной { var fld = stflambda.Peek(); if (_assign.to is ident && (_assign.to as ident).name.ToLower()=="result" && fld.RealSemTypeOfResExpr == null) // если это - первое присваивание Result { fld.RealSemTypeOfResExpr = from.type; fld.RealSemTypeOfResult = to.type; } } location loc = get_location(_assign); bool oper_ass_in_prop = false; //проверка на обращение к полю записи возвращенной из функции с целью присваивания //нужно чтобы пользователь не мог менять временный обьект if (to.semantic_node_type == semantic_node_type.static_property_reference || to.semantic_node_type == semantic_node_type.non_static_property_reference) { property_node pn = null; base_function_call prop_expr = null; if (to.semantic_node_type == semantic_node_type.static_property_reference) pn = (to as static_property_reference).property; else pn = (to as non_static_property_reference).property; PascalABCCompiler.SyntaxTree.Operators ot = PascalABCCompiler.SyntaxTree.Operators.Undefined; switch (_assign.operator_type) { case PascalABCCompiler.SyntaxTree.Operators.AssignmentAddition: ot = PascalABCCompiler.SyntaxTree.Operators.Plus; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseAND: ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseAND; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseLeftShift: ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseLeftShift; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseOR: ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseOR; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseRightShift: ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseRightShift; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentBitwiseXOR: ot = PascalABCCompiler.SyntaxTree.Operators.BitwiseXOR; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentDivision: ot = PascalABCCompiler.SyntaxTree.Operators.Division; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentModulus: ot = PascalABCCompiler.SyntaxTree.Operators.ModulusRemainder; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentMultiplication: ot = PascalABCCompiler.SyntaxTree.Operators.Multiplication; oper_ass_in_prop = true; break; case PascalABCCompiler.SyntaxTree.Operators.AssignmentSubtraction: ot = PascalABCCompiler.SyntaxTree.Operators.Minus; oper_ass_in_prop = true; break; } if (oper_ass_in_prop) { if (pn.get_function == null) AddError(new ThisPropertyCanNotBeReaded(pn,loc)); if (to.semantic_node_type == semantic_node_type.non_static_property_reference) { prop_expr = create_not_static_method_call(pn.get_function,(to as non_static_property_reference).expression,loc,false); prop_expr.parameters.AddRange((to as non_static_property_reference).fact_parametres); } else { prop_expr = create_static_method_call(pn.get_function,loc,pn.comprehensive_type,false); prop_expr.parameters.AddRange((to as static_property_reference).fact_parametres); } from = find_operator(ot,prop_expr,from,loc); } } else if (to is class_field_reference) { if ((to as class_field_reference).obj.type.type_special_kind == SemanticTree.type_special_kind.record && (to as class_field_reference).obj is base_function_call) { //исключим ситуацию обращения к массиву if (!(((to as class_field_reference).obj is common_method_call) && ((to as class_field_reference).obj as common_method_call).obj.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper)) AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); } //else check_field_reference_for_assign(to as class_field_reference,loc); } else if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable && to.semantic_node_type == semantic_node_type.namespace_variable_reference) { if (context.is_loop_variable((to as namespace_variable_reference).var)) AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } else if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable && to.semantic_node_type == semantic_node_type.local_variable_reference) { if (context.is_loop_variable((to as local_variable_reference).var)) AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } else if (context.is_in_cycle() && !SemanticRules.AllowChangeLoopVariable && to.semantic_node_type == semantic_node_type.local_block_variable_reference) { if (context.is_loop_variable((to as local_block_variable_reference).var)) AddError(to.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } else if (to is simple_array_indexing) if ((to as simple_array_indexing).simple_arr_expr is class_field_reference && ((to as simple_array_indexing).simple_arr_expr as class_field_reference).obj != null && ((to as simple_array_indexing).simple_arr_expr as class_field_reference).obj is constant_node) AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); if ((to.semantic_node_type == semantic_node_type.static_event_reference) || (to.semantic_node_type == semantic_node_type.nonstatic_event_reference)) { statement_node event_assign = null; if (_assign.operator_type == PascalABCCompiler.SyntaxTree.Operators.Assignment) { //throw new CanNotAssignToEvent(); } static_event_reference ser = (static_event_reference)to; expression_node right_del = convertion_data_and_alghoritms.convert_type(from, ser.en.delegate_type); switch (_assign.operator_type) { case PascalABCCompiler.SyntaxTree.Operators.AssignmentAddition: { if (to.semantic_node_type == semantic_node_type.static_event_reference) { event_assign = convertion_data_and_alghoritms.create_simple_function_call( ser.en.add_method, loc, right_del); } else { if (ser.en.semantic_node_type == semantic_node_type.compiled_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; compiled_function_node cfn = (compiled_function_node)ser.en.add_method; compiled_function_call tmp_event_assign = new compiled_function_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } else if (ser.en.semantic_node_type == semantic_node_type.common_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; common_method_node cfn = (common_method_node)ser.en.add_method; common_method_call tmp_event_assign = new common_method_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } } break; } case PascalABCCompiler.SyntaxTree.Operators.AssignmentSubtraction: { if (to.semantic_node_type == semantic_node_type.static_event_reference) { event_assign = convertion_data_and_alghoritms.create_simple_function_call( ser.en.remove_method, loc, right_del); } else { if (ser.en.semantic_node_type == semantic_node_type.compiled_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; compiled_function_node cfn = (compiled_function_node)ser.en.remove_method; compiled_function_call tmp_event_assign = new compiled_function_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } else if (ser.en.semantic_node_type == semantic_node_type.common_event) { nonstatic_event_reference nser = (nonstatic_event_reference)ser; common_method_node cfn = (common_method_node)ser.en.remove_method; common_method_call tmp_event_assign = new common_method_call(cfn, nser.obj, loc); tmp_event_assign.parameters.AddElement(right_del); event_assign = tmp_event_assign; } } break; } default: { AddError(loc, "ASSIGN_TO_EVENT"); //throw new CanNotApplyThisOperationToEvent break; } } return_value(event_assign); return; } if (_assign.operator_type == PascalABCCompiler.SyntaxTree.Operators.Assignment || oper_ass_in_prop) { if (to.semantic_node_type == semantic_node_type.static_property_reference) { static_property_reference spr = (static_property_reference)to; if (spr.property.set_function == null) { AddError(new ThisPropertyCanNotBeWrited(spr.property, loc)); } check_property_params(spr, loc); function_node set_func = spr.property.set_function; from = convertion_data_and_alghoritms.convert_type(from, spr.property.property_type); spr.fact_parametres.AddElement(from); base_function_call bfc = create_static_method_call(set_func, loc, spr.property.comprehensive_type, true); bfc.parameters.AddRange(spr.fact_parametres); return_value((statement_node)bfc); return; } else if (to.semantic_node_type == semantic_node_type.non_static_property_reference) { non_static_property_reference nspr = (non_static_property_reference)to; check_property_params(nspr, loc); from = convertion_data_and_alghoritms.convert_type(from, nspr.property.property_type); nspr.fact_parametres.AddElement(from); //Обработка s[i]:='c' if (SystemUnitAssigned) if (nspr.property.comprehensive_type == SystemLibrary.SystemLibrary.string_type) { if (nspr.property == SystemLibrary.SystemLibrary.string_type.default_property_node) { if (SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure != null) { expressions_list exl = new expressions_list(); exl.AddElement(nspr.expression); exl.AddElement(nspr.fact_parametres[0]); exl.AddElement(from); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return_value((statement_node)ret); return; } } } if (nspr.property.set_function == null) { AddError(new ThisPropertyCanNotBeWrited(nspr.property, loc)); } function_node set_func = nspr.property.set_function; base_function_call bfc = create_not_static_method_call(set_func, nspr.expression, loc, true); bfc.parameters.AddRange(nspr.fact_parametres); return_value((statement_node)bfc); return; } else if (to is simple_array_indexing && (to as simple_array_indexing).simple_arr_expr.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node expr = (to as simple_array_indexing).simple_arr_expr; expression_node ind_expr = (to as simple_array_indexing).ind_expr; from = convertion_data_and_alghoritms.convert_type(from,SystemLibrary.SystemLibrary.char_type); ind_expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null),from); return_value(find_operator(compiler_string_consts.assign_name, expr, ind_expr, get_location(_assign))); return; } else if (to.type.type_special_kind == SemanticTree.type_special_kind.short_string) { if (from.type is null_type_node) AddError(get_location(_assign), "NIL_WITH_VALUE_TYPES_NOT_ALLOWED"); expression_node clip_expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, loc, convertion_data_and_alghoritms.convert_type(from, SystemLibrary.SystemLibrary.string_type), new int_const_node((to.type as short_string_type_node).Length, null)); statement_node en = find_operator(compiler_string_consts.assign_name, to, clip_expr, get_location(_assign)); return_value(en); return; } else { assign_is_converting = true; statement_node en = find_operator(compiler_string_consts.assign_name, to, from, get_location(_assign)); assign_is_converting = false; return_value(en); return; } } else { assign_is_converting = true; statement_node en = find_operator(_assign.operator_type, to, from, get_location(_assign)); assign_is_converting = false; return_value(en); return; } //throw new CompilerInternalError("Undefined assign to type"); }
internal void visit_method_call(SyntaxTree.method_call _method_call) { // frninja 01/03/16 - for iterator capturing (yield) if (_method_call.dereferencing_value is yield_unknown_ident) { var nodeToVisit = new method_call(ProcessUnknownIdent(_method_call.dereferencing_value as yield_unknown_ident), _method_call.parameters); visit(nodeToVisit); return; } // end frninja //lroman if (_method_call.dereferencing_value is closure_substituting_node) { var nodeToVisit = new method_call(((closure_substituting_node) _method_call.dereferencing_value).substitution, _method_call.parameters); visit(nodeToVisit); return; } bool proc_wait = procedure_wait; bool lambdas_are_in_parameters = false; //lroman// var syntax_nodes_parameters = _method_call.parameters == null ? new List<expression>() : _method_call.parameters.expressions; if (procedure_wait) { procedure_wait = false; } //throw new ArgumentNullException("test"); motivation mot = motivation_keeper.motivation; expression_node expr_node = null; expressions_list exprs = new expressions_list(); SyntaxTree.ident id = null; SymbolInfo si = null; type_node to_type = null; SyntaxTree.addressed_value deref_value = _method_call.dereferencing_value; int templ_args_count = 0; //bool needs_generic_type_search = false; SyntaxTree.ident_with_templateparams iwt = deref_value as SyntaxTree.ident_with_templateparams; if (iwt != null) { deref_value = iwt.name; templ_args_count = iwt.template_params.params_list.Count; //needs_generic_type_search = _method_call.parameters.expressions.Count == 1; } SyntaxTree.inherited_ident inh_id = deref_value as SyntaxTree.inherited_ident; if (inh_id != null) { inherited_ident_processing = true; si = find_in_base(inh_id); if (si != null) if (si.sym_info is common_method_node) { if ((si.sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(inh_id), "CANNOT_CALL_ABSTRACT_METHOD"); } else if (si.sym_info is compiled_function_node) { if ((si.sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(inh_id), "CANNOT_CALL_ABSTRACT_METHOD"); } id = inh_id; } else { id = deref_value as SyntaxTree.ident; if (id != null) { if (templ_args_count != 0) { //Ищем generics si = context.find(id.name + compiler_string_consts.generic_params_infix + templ_args_count.ToString()); if (si != null) { si = new SymbolInfo(get_generic_instance(si, iwt.template_params.params_list)); iwt = null; } } if (si == null) { SyntaxTree.operator_name_ident oni = id as SyntaxTree.operator_name_ident; if (oni != null) { si = context.find(name_reflector.get_name(oni.operator_type)); } else { si = context.find(id.name); if (templ_args_count != 0) { SymbolInfo conv = ConvertTypeToInstance(si, iwt.template_params.params_list, get_location(id)); if (conv != null) { si = conv; iwt = null; } } } } } else { SyntaxTree.dot_node _dot_node = deref_value as SyntaxTree.dot_node; if (_dot_node != null) { bool skip_first_parameter = false; //lroman// bool has_extension_overload = false; semantic_node sn = convert_semantic_strong(_dot_node.left); //SyntaxTree.ident id_right = ConvertOperatorNameToIdent(_dot_node.right as SyntaxTree.ident); SyntaxTree.ident id_right = _dot_node.right as SyntaxTree.ident; switch (sn.general_node_type) { case general_node_type.expression: { expression_node exp = (expression_node)sn; if (exp is typed_expression) try_convert_typed_expression_to_function_call(ref exp); SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { si = exp.type.find_in_type(name_reflector.get_name(oni_right.operator_type), context.CurrentScope); } else { si = exp.type.find_in_type(id_right.name, context.CurrentScope); if (si != null && si.sym_info != null && si.sym_info.semantic_node_type == semantic_node_type.wrap_def) BasePCUReader.RestoreSymbols(si, id_right.name); } //definition_node ddn=check_name_node_type(id_right.name,si,get_location(id_right), // general_node_type.function_node,general_node_type.variable_node); location subloc = get_location(id_right); if (si == null) { AddError(new UndefinedNameReference(id_right.name, subloc)); } if (si.sym_info.general_node_type != general_node_type.function_node) { if (si.sym_info.general_node_type == general_node_type.type_node) { to_type = ((type_node)(si.sym_info)); } else { dot_node_as_expression_dot_ident(exp, id_right, motivation.expression_evaluation, _dot_node.left); exp = ret.get_expression(); internal_interface ii = exp.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(subloc, "EXPECTED_DELEGATE"); } delegate_internal_interface dii = ii as delegate_internal_interface; si = new SymbolInfo(dii.invoke_method); } } if (to_type != null) { if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1)) { AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED" ); } } SymbolInfo tmp_si = si; while (si != null) { if (si.sym_info is common_namespace_function_node) { common_namespace_function_node cnfn = si.sym_info as common_namespace_function_node; if (cnfn.ConnectedToType != null && !cnfn.IsOperator) { exprs.AddElementFirst(exp); skip_first_parameter = true; break; } } if (si.sym_info is compiled_function_node) { compiled_function_node cfn = si.sym_info as compiled_function_node; if (cfn.ConnectedToType != null) { exprs.AddElementFirst(exp); skip_first_parameter = true; if (cfn.is_generic_function) { //generic_convertions.DeduceFunction(cfn, exprs); //si.sym_info = cfn.get_instance(new List<type_node>(new type_node[] { exp.type }), true, get_location(_method_call)); } break; } } si = si.Next; } si = tmp_si; if (skip_first_parameter) { SymbolInfo new_si = null; bool has_obj_methods = false; List<SymbolInfo> si_list = new List<SymbolInfo>(); while (si != null) { if (si.sym_info is common_namespace_function_node) { common_namespace_function_node cnfn = si.sym_info as common_namespace_function_node; if (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static || cnfn.ConnectedToType != null) si_list.Add(si); if (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cnfn.ConnectedToType == null) has_obj_methods = true; } else if (si.sym_info is compiled_function_node) { compiled_function_node cfn = si.sym_info as compiled_function_node; if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static || cfn.ConnectedToType != null) si_list.Add(si); if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfn.ConnectedToType == null) has_obj_methods = true; } else if (si.sym_info is common_method_node) { common_method_node cfn = si.sym_info as common_method_node; if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) si_list.Add(si); if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) has_obj_methods = true; } si = si.Next; } for (int i = 0; i < si_list.Count; i++) { if (new_si == null) { new_si = si_list[i]; si = new_si; } else { si.Next = si_list[i]; si = si.Next; } } if (si != null) si.Next = null; si = new_si; } if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion var cen = convert_strong(en); exprs.AddElement(cen); } } expression_node subexpr1 = null; if (to_type != null) { subexpr1 = convertion_data_and_alghoritms.explicit_convert_type(exprs[0], to_type); } else { if (iwt != null) { si = get_generic_functions(si, true, subloc); si = get_function_instances(si, iwt.template_params.params_list, id_right.name, subloc, si.Next == null); } #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями function_node_list spf = null; try { ThrowCompilationError = false; function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); if (ffn == null) { if (skip_first_parameter) { expressions_list ex_list = new expressions_list(); ex_list.AddRange(exprs); ex_list.remove_at(0); ffn = convertion_data_and_alghoritms.select_function(ex_list, si, subloc, syntax_nodes_parameters); if (ffn == null) { ThrowCompilationError = true; throw LastError(); } RemoveLastError(); skip_first_parameter = false; exprs = ex_list; ThrowCompilationError = true; } else { ThrowCompilationError = true; throw LastError(); } } ThrowCompilationError = true; int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fnn = spf[i]; try { int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*compiled_type_node tt; tt = fnn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } // конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } int kk = 0; if (skip_first_parameter) kk++; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion function_node fn = null; if (!skip_first_parameter || si.Next == null) fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); else { try { ThrowCompilationError = false; fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); if (fn == null && skip_first_parameter) { if (si.Next == null) { ThrowCompilationError = true; throw LastError(); } RemoveLastError(); skip_first_parameter = false; si = tmp_si; exprs.remove_at(0); fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); if (fn == null) { ThrowCompilationError = true; throw LastError(); } // else // RemoveLastError(); // ошибка уже убрана чуть выше } } catch (Exception ex) { ThrowCompilationError = true; if (skip_first_parameter) { si = tmp_si; exprs.remove_at(0); fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); } else throw ex; } ThrowCompilationError = true; } SemanticTree.IGenericInstance igi = fn as SemanticTree.IGenericInstance; if (igi != null) { //проверяем на соответствие ограничителям int num_err; //CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list( } base_function_call bfc = create_not_static_method_call(fn, exp, get_location(id_right), proc_wait); bfc.parameters.AddRange(exprs); subexpr1 = bfc; } switch (mot) { case motivation.expression_evaluation: { return_value(subexpr1); return; } case motivation.semantic_node_reciving: { return_semantic_value(subexpr1); return; } default: { AddError(subexpr1.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } case general_node_type.namespace_node: { namespace_node nsn = (namespace_node)sn; if (templ_args_count != 0) { //Ищем generics si = context.find(id_right.name + compiler_string_consts.generic_params_infix + templ_args_count.ToString()); if (si != null) { si = new SymbolInfo(get_generic_instance(si, iwt.template_params.params_list)); iwt = null; } } if (si == null) { SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { si = nsn.find(name_reflector.get_name(oni_right.operator_type)); } else { si = nsn.find(id_right.name); if (templ_args_count != 0) { SymbolInfo conv = ConvertTypeToInstance(si, iwt.template_params.params_list, get_location(id_right)); if (conv != null) { si = conv; iwt = null; } } } } id = id_right; break; } case general_node_type.unit_node: { unit_node un = (unit_node)sn; SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { si = un.find_only_in_namespace(name_reflector.get_name(oni_right.operator_type)); } else { si = un.find_only_in_namespace(id_right.name); } id = id_right; break; } case general_node_type.type_node: { type_node tn = (type_node)sn; /*if (tn == SystemLibrary.SystemLibrary.void_type) { throw new VoidNotValid(get_location(id_right)); }*/ check_for_type_allowed(tn,get_location(id_right)); SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { si = tn.find_in_type(name_reflector.get_name(oni_right.operator_type), context.CurrentScope); } else { si = tn.find_in_type(id_right.name, context.CurrentScope);//CurrentScope delete_inherited_constructors(ref si, tn); delete_extension_methods(ref si, tn); // SSM 2.2.2016 Пока временно закомментировал - в старом коде этого не было. Из-за этого не работает System.Linq.Enumerable.Select } //definition_node ddn2=check_name_node_type(id_right.name,si,get_location(id_right), // general_node_type.function_node); expression_node exp = null; location subloc = get_location(id_right); if (si == null) { AddError( new UndefinedNameReference(id_right.name, subloc)); } if (si.sym_info.general_node_type != general_node_type.function_node) { if (si.sym_info.general_node_type == general_node_type.type_node) { to_type = ((type_node)(si.sym_info)); } else { dot_node_as_type_ident(tn, id_right, motivation.expression_evaluation); exp = ret.get_expression(); internal_interface ii = exp.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(subloc, "EXPECTED_DELEGATE"); } delegate_internal_interface dii = ii as delegate_internal_interface; si = new SymbolInfo(dii.invoke_method); } } if (to_type != null) { if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1)) { AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED" ); } } if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion exprs.AddElement(convert_strong(en)); } } expression_node subexpr2 = null; if (to_type != null) { subexpr2 = convertion_data_and_alghoritms.explicit_convert_type(exprs[0], to_type); } else { if (iwt != null) { si = get_generic_functions(si, true, subloc); si = get_function_instances(si, iwt.template_params.params_list, id_right.name, subloc, si.Next == null); } #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями function_node_list spf = null; try { function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fnn = spf[i]; try { int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*compiled_type_node tt; tt = fnn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } // конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } int kk = 0; if (skip_first_parameter) kk++; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); if (!debug && fn == SystemLibrary.SystemLibrary.assert_method) { // return_value(new empty_statement(null)); // return; } /*if ((proc_wait==false)&&(fn.return_value_type==null)) { throw new FunctionExpectedProcedureMeet(fn,get_location(id_right)); }*/ base_function_call bfc2 = null; if (exp == null) { bfc2 = create_static_method_call(fn, subloc, tn, proc_wait); } else { bfc2 = create_not_static_method_call(fn, exp, subloc, proc_wait); } bfc2.parameters.AddRange(exprs); subexpr2 = bfc2; } switch (mot) { case motivation.expression_evaluation: { return_value(subexpr2); return; } case motivation.semantic_node_reciving: { return_semantic_value(subexpr2); return; } default: { AddError(subexpr2.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } } } else { SyntaxTree.expression expr = deref_value as SyntaxTree.expression; if (expr != null) { //throw new CompilerInternalError("Not supported"); expression_node exp_int = convert_strong(expr); location sloc = get_location(expr); internal_interface ii = exp_int.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(sloc, "EXPECTED_DELEGATE"); } delegate_internal_interface dii = (delegate_internal_interface)ii; si = new SymbolInfo(dii.invoke_method); if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion exprs.AddElement(convert_strong(en)); } } location subloc = sloc; #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями function_node_list spf = null; try { function_node ffn = convertion_data_and_alghoritms.select_function(exprs, si, subloc, syntax_nodes_parameters); int exprCounter = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fnn = spf[i]; try { int exprCounter = 0; expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*compiled_type_node tt; tt = fnn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } // конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } int kk = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion function_node del_func = convertion_data_and_alghoritms.select_function(exprs, si, sloc, syntax_nodes_parameters); base_function_call bbfc = create_not_static_method_call(del_func, exp_int, sloc, proc_wait); bbfc.parameters.AddRange(exprs); switch (mot) { case motivation.expression_evaluation: { return_value(bbfc); return; } case motivation.semantic_node_reciving: { return_semantic_value(bbfc); return; } default: { AddError(bbfc.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } else { throw new CompilerInternalError("Unexpected method name kind"); } } } } //definition_node dn=check_name_node_type(id.name,si,get_location(_method_call),general_node_type.function_node); expression_node exp2 = null; location subloc2 = get_location(id); List<TreeConverter.SymbolInfo> sibak = new List<TreeConverter.SymbolInfo>(); TreeConverter.SymbolInfo ssi=si; while (ssi != null) { ssi = ssi.Next; sibak.Add(ssi); } if (si == null) { AddError(new UndefinedNameReference(id.name, subloc2)); } is_format_allowed = false; if (SystemUnitAssigned) if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(si) || SystemLibrary.SystemLibInitializer.readln_procedure.Equal(si)) { expression_node bfcint = make_read_call(si, _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (SystemLibrary.SystemLibInitializer.write_procedure.Equal(si) || SystemLibrary.SystemLibInitializer.writeln_procedure.Equal(si) || SystemLibrary.SystemLibInitializer.StrProcedure.Equal(si)) { is_format_allowed = true; } else if (SystemLibrary.SystemLibInitializer.ArrayCopyFunction.Equal(si)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_kind) { location loc = get_location(_method_call); expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ArrayCopyFunction.sym_info as function_node,loc,param0); function_node fn = convertion_data_and_alghoritms.get_empty_conversion(en.type, param0.type, false); en = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, en); return_value(en); return; } } } else if (SystemLibrary.SystemLibInitializer.SetLengthProcedure.Equal(si) || SystemLibrary.SystemLibrary.resize_func == si.sym_info as function_node) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count >= 2) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (!param0.is_addressed) AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); if (param0.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type); base_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info is common_namespace_function_node) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); cnfn.parameters.AddElement(new int_const_node((param0.type as short_string_type_node).Length,null)); switch (mot) { case motivation.expression_evaluation: { return_value(cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(cnfn); return; } default: { AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } else if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_kind) { int rank = 1; if (param0.type is compiled_type_node) rank = (param0.type as compiled_type_node).rank; else if (param0.type is common_type_node) rank = (param0.type as common_type_node).rank; if (_method_call.parameters.expressions.Count-1 != rank) AddError(get_location(_method_call), "{0}_PARAMETERS_EXPECTED", rank+1); if (rank > 1) { type_node tn = param0.type.element_type; location loc = get_location(_method_call); typeof_operator to = new typeof_operator(tn, loc); List<expression_node> lst = new List<expression_node>(); //размер for (int i=1; i<_method_call.parameters.expressions.Count; i++) { expression_node expr = convert_strong(_method_call.parameters.expressions[i]);; expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.integer_type); if (expr is int_const_node && (expr as int_const_node).constant_value < 0) AddError(expr.location,"NEGATIVE_ARRAY_LENGTH_({0})_NOT_ALLOWED", (expr as int_const_node).constant_value); lst.Add(expr); } //это вызов спецфункции expression_node retv = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, loc, to, new int_const_node(lst.Count,loc)); common_namespace_function_call cnfc = retv as common_namespace_function_call; foreach (expression_node e in lst) cnfc.parameters.AddElement(e); expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CopyWithSizeFunction.sym_info as function_node,loc,param0,cnfc); function_node fn = convertion_data_and_alghoritms.get_empty_conversion(en.type, retv.type, false); en = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, en); basic_function_call bfc = new basic_function_call(tn.find(compiler_string_consts.assign_name).sym_info as basic_function_node,loc,param0,en); return_value(bfc); return; } } } } else if (SystemLibrary.SystemLibInitializer.InsertProcedure.Equal(si)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 3) { //expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); //expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); if (param1.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); param0 = convertion_data_and_alghoritms.convert_type(param0,SystemLibrary.SystemLibrary.string_type); param2 = convertion_data_and_alghoritms.convert_type(param2,SystemLibrary.SystemLibrary.integer_type); base_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info is common_namespace_function_node) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); cnfn.parameters.AddElement(param2); cnfn.parameters.AddElement(new int_const_node((param1.type as short_string_type_node).Length,null)); switch (mot) { case motivation.expression_evaluation: { return_value(cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(cnfn); return; } default: { AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } } } else if (SystemLibrary.SystemLibInitializer.DeleteProcedure.Equal(si)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 3) { //expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); //expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type); param2 = convertion_data_and_alghoritms.convert_type(param2,SystemLibrary.SystemLibrary.integer_type); base_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info is common_namespace_function_node) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); cnfn.parameters.AddElement(param2); switch (mot) { case motivation.expression_evaluation: { return_value(cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(cnfn); return; } default: { AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } } } else if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si) || SystemLibrary.SystemLibInitializer.ExcludeProcedure.Equal(si)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 2) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); expressions_list args = new expressions_list(); args.AddElement(param0); args.AddElement(param1); CheckSpecialFunctionCall(si,args,get_location(_method_call)); expression_node en_cnfn = null; if (SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info is common_namespace_function_node) { common_namespace_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si)) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ExcludeProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); en_cnfn = cnfn; } else { compiled_static_method_call cnfn = null; if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si)) cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info as compiled_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ExcludeProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); en_cnfn = cnfn; } switch (mot) { case motivation.expression_evaluation: { return_value(en_cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(en_cnfn); return; } default: { AddError(en_cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } } else if (SystemLibrary.SystemLibInitializer.IncProcedure.Equal(si)) { expression_node bfcint = make_inc_call(si, _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (SystemLibrary.SystemLibInitializer.DecProcedure.Equal(si)) { expression_node bfcint = make_dec_call(si, _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (SystemLibrary.SystemLibInitializer.SuccFunction.Equal(si)) { expression_node bfcint = make_succ_call(si, _method_call.parameters, subloc2); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (SystemLibrary.SystemLibInitializer.PredFunction.Equal(si)) { expression_node bfcint = make_pred_call(si, _method_call.parameters, subloc2); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (SystemLibrary.SystemLibInitializer.OrdFunction.Equal(si)) { expression_node bfcint = make_ord_call(si, _method_call.parameters, subloc2); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (SystemLibrary.SystemLibInitializer.LowFunction.Equal(si)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { bounded_array_interface bai = param0.type.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface; expression_node en = new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value),get_location(_method_call)); switch (mot) { case motivation.expression_evaluation: { return_value(en); return; } case motivation.semantic_node_reciving: { return_semantic_value(en); return; } default: { AddError(en.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } } } else if (SystemLibrary.SystemLibInitializer.HighFunction.Equal(si)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { bounded_array_interface bai = param0.type.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface; expression_node en = new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.upper_value),get_location(_method_call)); switch (mot) { case motivation.expression_evaluation: { return_value(en); return; } case motivation.semantic_node_reciving: { return_semantic_value(en); return; } default: { AddError(en.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } } } else if (si == SystemLibrary.SystemLibInitializer.NewProcedure) { expression_node bfcint = make_new_call(si, _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; } else if (si == SystemLibrary.SystemLibInitializer.DisposeProcedure) { //if (convertion_data_and_alghoritms.select_function(convert_expression_list(_method_call.parameters.expressions), si, subloc2) == SystemLibrary.SystemLibInitializer.DisposeProcedure.sym_info) //{ expression_node bfcint = make_dispose_call(si, _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (si.sym_info as function_node).name); switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } return; // } } else if (!debug && SystemLibrary.SystemLibInitializer.AssertProcedure.Equal(si)) { // return_value(new empty_statement(null)); // return; } /*else if (SystemLibrary.SystemLibInitializer.IncProcedure != null && SystemLibrary.SystemLibInitializer.IncProcedure.Equal(si)) { expression_node bfcint = make_inc_call(si, _method_call.parameters, subloc2); }*/ if (si.sym_info.general_node_type != general_node_type.function_node) { if (si.sym_info.general_node_type == general_node_type.type_node) { to_type = ((type_node)(si.sym_info)); /*if (to_type == SystemLibrary.SystemLibrary.void_type) { throw new VoidNotValid(subloc2); }*/ check_for_type_allowed(to_type,subloc2); } else { exp2 = ident_value_reciving(si, id); internal_interface ii = exp2.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(subloc2, "EXPECTED_DELEGATE"); } if (exp2 is nonstatic_event_reference) { nonstatic_event_reference nser = exp2 as nonstatic_event_reference; common_event ce = nser.en as common_event; if (ce != null) exp2 = new class_field_reference(ce.field,new this_node(ce.cont_type,null),null); else AddError(get_location(_method_call), "EVENT_{0}_MUST_BE_IN_LEFT_PART", nser.en.name); } else if (exp2 is static_event_reference) { static_event_reference nser = exp2 as static_event_reference; common_event ce = nser.en as common_event; if (ce != null) exp2 = new static_class_field_reference(ce.field, null); else if (nser.en is common_namespace_event && _compiled_unit.namespaces.IndexOf((nser.en as common_namespace_event).namespace_node) != -1) exp2 = new namespace_variable_reference((nser.en as common_namespace_event).field, null); else AddError(get_location(_method_call), "EVENT_{0}_MUST_BE_IN_LEFT_PART", nser.en.name); } delegate_internal_interface dii = ii as delegate_internal_interface; si = new SymbolInfo(dii.invoke_method); } } if (to_type != null) { if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1)) { AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED"); } } if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { bool tmp = is_format_allowed; #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion exprs.AddElement(convert_strong(en)); is_format_allowed = tmp; } } is_format_allowed = false; CheckSpecialFunctionCall(si, exprs,get_location(_method_call)); ssi=si; foreach (SymbolInfo sii in sibak) { ssi.Next = sii; ssi = sii; } if (to_type != null) { //(ssyy) К вызову функции здесь явно не приводим, т.к. это излишне. expression_node ee = exprs[0]; bool del = to_type is common_type_node && (to_type as common_type_node).IsDelegate; if (!del) try_convert_typed_expression_to_function_call(ref ee); else ee = convert_strong(_method_call.parameters.expressions[0]); expr_node = convertion_data_and_alghoritms.explicit_convert_type(ee, to_type); //expression_node expr = convert_if_typed_expression_to_function_call(exprs[0]); //expr_node = convertion_data_and_alghoritms.explicit_convert_type(expr, to_type); } else { if (exp2 == null) { location mcloc = get_location(_method_call); if (iwt != null) { si = get_generic_functions(si, true, mcloc); si = get_function_instances(si, iwt.template_params.params_list, id.name, mcloc, si.Next == null); } #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями function_node_list spf = null; try { function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc2, syntax_nodes_parameters); int exprCounter = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition) en; LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! И еще выше по коду!!! кошмар!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fn = spf[i]; try // внутренний try регенерирует исключение, а этот гасит { int exprCounter = 0; expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); // SSM 7/08/15 type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*var tt = fn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType==0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } //--------------- конец цикла по версиям if (GoodVersionsCount>1 && GoodVersionsCountWithSameResType!=1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc2, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } var kk = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion expr_node = convertion_data_and_alghoritms.create_full_function_call(exprs, si, mcloc, context.converted_type, context.top_function, proc_wait); } else { function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, subloc2, syntax_nodes_parameters); base_function_call bbffcc = create_not_static_method_call(fn, exp2, subloc2, proc_wait); bbffcc.parameters.AddRange(exprs); expr_node = bbffcc; } } /*if ((proc_wait==false)&&(expr_node.type==null)) { throw new FunctionExpectedProcedureMeet((function_node)dn,get_location(_method_call)); }*/ switch (mot) { case motivation.expression_evaluation: { return_value(expr_node); return; } case motivation.semantic_node_reciving: { return_semantic_value(expr_node); return; } case motivation.address_reciving: { AddError(get_location(_method_call), "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); return; } default: { //throw new CompilerInternalError("Can not recive address from method call");//! AddError(get_location(_method_call), "EXPECTED_VARIABLE"); return; } } //throw new CompilerInternalError("Error in creation method call"); }
private base_function_call create_constructor_call(type_node tn, expressions_list exprs, location loc, Tuple<bool, List<SyntaxTree.expression>> lambdas_info = null) { if (tn.IsInterface) { AddError(loc, "INTERFACE_{0}_CONSTRUCTOR_CALL", tn.name); } if (tn.IsAbstract) { AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", tn.name); } SymbolInfo si = tn.find_in_type(TreeConverter.compiler_string_consts.default_constructor_name, context.CurrentScope); //tn.Scope); delete_inherited_constructors(ref si, tn); if (si == null) AddError(loc, "CONSTRUCTOR_NOT_FOUND"); function_node fnn = null; try { #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_info != null && lambdas_info.Item1) { LambdaHelper.processingLambdaParametersForTypeInference++; var syntax_nodes_parameters = lambdas_info.Item2; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями function_node_list spf = null; try { function_node fn = convertion_data_and_alghoritms.select_function(exprs, si, loc, syntax_nodes_parameters); int exprCounter = 0; foreach (SyntaxTree.expression en in syntax_nodes_parameters) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // spfnum - первый номер правильно инстанцированной. Пока -1. Если потом встретился второй, то тоже ошибка int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) { function_node fn = spf[i]; try { int exprCounter = 0; expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in syntax_nodes_parameters) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*var tt = fn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func<T,T1,...TN> - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(loc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } var kk = 0; foreach (SyntaxTree.expression en in syntax_nodes_parameters) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; fnn = convertion_data_and_alghoritms.select_function(exprs, si, loc); } //lroman// #endregion else { fnn = convertion_data_and_alghoritms.select_function(exprs, si, loc); } } catch (NoFunctionWithSameParametresNum e) { e.is_constructor = true; throw; } return create_static_method_call_with_params(fnn, loc, tn, false, exprs); }
private void CheckSpecialFunctionCall(SymbolInfo si, expressions_list exprs, location loc) { if (SystemUnitAssigned) { bool write_proc = SystemLibrary.SystemLibInitializer.write_procedure.Equal(si); if (write_proc && exprs.Count > 1) { //возможно это запись в типизированый файл if (exprs[0].type.type_special_kind == SemanticTree.type_special_kind.typed_file) //да, точно это типизированый файл! { //Проверим типы параметров вызова на совпадение с типом элементов файла type_node element_type = exprs[0].type.element_type; for (int i = 1; i < exprs.Count; i++) convertion_data_and_alghoritms.check_convert_type(exprs[i], element_type, exprs[i].location); if (element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { for (int i=1; i<exprs.Count; i++) { //common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null); //cmc.parameters.AddElement(exprs[i]); //cmc.parameters.AddElement(new int_const_node((element_type as short_string_type_node).Length,null)); expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(exprs[i],SystemLibrary.SystemLibrary.string_type),new int_const_node((element_type as short_string_type_node).Length,null)); exprs[i] = cmc; } } //if (exprs[i].type != element_type) // throw new ExpectedExprHaveTypeTypedFile(element_type, exprs[i].type, false, get_location(_method_call.parameters.expressions[i])); } else //(ssyy) а может быть, в бинарный! if (exprs[0].type.type_special_kind == SemanticTree.type_special_kind.binary_file) { //(ssyy) действительно, бинарный for (int i = 1; i < exprs.Count; i++) { if (!CanUseThisTypeForBinaryFiles(exprs[i].type)) { AddError(exprs[i].location, "CAN_NOT_WRITE_REFERENCE_DATA_TO_BINARY_FILE"); } } } else { if (SystemLibrary.SystemLibInitializer.write_procedure.sym_info is common_namespace_function_node) ConvertPointersForWrite(exprs); else ConvertPointersForWriteFromDll(exprs); } } else if (write_proc || SystemLibrary.SystemLibInitializer.writeln_procedure.Equal(si)) { //(ssyy) Преобразуем указатели в строки для вывода write/writeln if (SystemLibrary.SystemLibInitializer.writeln_procedure.sym_info is common_namespace_function_node) ConvertPointersForWrite(exprs); else ConvertPointersForWriteFromDll(exprs); } else if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(si) || SystemLibrary.SystemLibInitializer.ExcludeProcedure.Equal(si)) { if (exprs.Count != 2) AddError( new NoFunctionWithSameArguments(loc, true)); type_node element_type = exprs[0].type.element_type; if (exprs[0].type.type_special_kind != SemanticTree.type_special_kind.base_set_type && exprs[0].type.type_special_kind != SemanticTree.type_special_kind.set_type) { AddError( new NoFunctionWithSameArguments(loc, true)); } if (element_type != null) convertion_data_and_alghoritms.check_convert_type(exprs[1], element_type, exprs[1].location); else convertion_data_and_alghoritms.check_convert_type(exprs[1], exprs[0].type, exprs[0].location); if (!exprs[0].is_addressed) AddError( new ThisExpressionCanNotBePassedAsVarParameter(exprs[0])); } else if (SystemLibrary.SystemLibInitializer.InSetProcedure.Equal(si)) { if (exprs.Count != 2) AddError( new NoFunctionWithSameArguments(loc, true)); type_node element_type = exprs[1].type.element_type; if (element_type != null) { //exprs[0] = convertion_data_and_alghoritms.convert_type(exprs[0], element_type, exprs[0].location); convertion_data_and_alghoritms.check_convert_type(exprs[0], element_type, exprs[0].location); } else convertion_data_and_alghoritms.check_convert_type(exprs[0], exprs[1].type, exprs[0].location); } else if (SystemLibrary.SystemLibInitializer.SetUnionProcedure.Equal(si) || SystemLibrary.SystemLibInitializer.SetIntersectProcedure.Equal(si) || SystemLibrary.SystemLibInitializer.SetSubtractProcedure.Equal(si)) { if (exprs.Count != 2) AddError( new NoFunctionWithSameArguments(loc, true)); convertion_data_and_alghoritms.check_convert_type(exprs[1], exprs[0].type, exprs[1].location); } if (si == SystemLibrary.SystemLibInitializer.NewProcedure || si == SystemLibrary.SystemLibInitializer.DisposeProcedure) { if (exprs[0].type == SystemLibrary.SystemLibrary.pointer_type) AddError(exprs[0].location, "EXPECTED_TYPED_POINTER_IN_PROCEDURE{0}", (si.sym_info as function_node).name); } } }
public override void visit(SyntaxTree.new_expr _new_expr) { type_node tn = ret.visit(_new_expr.type); //if (tn == SystemLibrary.SystemLibrary.void_type) // AddError(new VoidNotValid(get_location(_new_expr.type))); check_for_type_allowed(tn,get_location(_new_expr.type)); location loc = get_location(_new_expr); expressions_list exprs = null; var lambdas_are_in_parameters = false; var syntax_nodes_parameters = _new_expr.params_list == null ? new List<expression>() : _new_expr.params_list.expressions; if (_new_expr.params_list != null) { exprs = new expressions_list(); foreach (SyntaxTree.expression en in _new_expr.params_list.expressions) { if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } exprs.AddElement(convert_strong(en)); } } else exprs = new expressions_list(); if (_new_expr.new_array) { //if (exprs.Count == 1) { //new typename[size] type_node atn = convertion_data_and_alghoritms.type_constructor.create_unsized_array(tn, context.converted_namespace, exprs.Count, loc); //тип элементов typeof_operator to = new typeof_operator(tn, loc); List<expression_node> lst = new List<expression_node>(); //размер for (int i=0; i<exprs.Count; i++) { expression_node expr = exprs[i]; expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.integer_type); if (expr is int_const_node && (expr as int_const_node).constant_value < 0) AddError(expr.location, "NEGATIVE_ARRAY_LENGTH_({0})_NOT_ALLOWED", (expr as int_const_node).constant_value); lst.Add(expr); } //это вызов спецфункции expression_node retv = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, loc, to, new int_const_node(exprs.Count,loc)); base_function_call cnfc = retv as base_function_call; foreach (expression_node e in lst) cnfc.parameters.AddElement(e); if (_new_expr.array_init_expr != null) { if (exprs.Count > 1) { foreach (expression_node expr in lst) if (!(expr is int_const_node)) AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED"); if (_new_expr.array_init_expr.elements == null) AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_EXPECTED"); _new_expr.array_init_expr = get_possible_array_const(_new_expr.array_init_expr,atn) as SyntaxTree.array_const; expression_node e = convert_strong(_new_expr.array_init_expr); if (e is array_initializer) { array_initializer tmp = e as array_initializer; for (int i=0; i<exprs.Count; i++) { int len = (exprs[i] as int_const_node).constant_value; if (!(e is array_initializer) || (e as array_initializer).element_values.Count != len) AddError(e.location, "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", len); e = (e as array_initializer).element_values[0]; } cnfc.parameters.AddElement(ConvertArrayInitializer(atn,tmp)); } } else { expression_node expr = lst[0]; if (!(expr is int_const_node)) AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED"); int len = (expr as int_const_node).constant_value; if (_new_expr.array_init_expr.elements == null) { if (len != 0) AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", len); } else if (_new_expr.array_init_expr.elements.expressions.Count != len) AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", len); _new_expr.array_init_expr = get_possible_array_const(_new_expr.array_init_expr,atn) as SyntaxTree.array_const; if (_new_expr.array_init_expr.elements != null) foreach (SyntaxTree.expression e in _new_expr.array_init_expr.elements.expressions) cnfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(clip_expression_if_need(convert_strong(e),tn),tn)); } } //явное преобразования для того чтобы тип задать function_node fn = convertion_data_and_alghoritms.get_empty_conversion(retv.type, atn, false); retv = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, retv); return_value(retv); return; } } return_value(create_constructor_call(tn, exprs, get_location(_new_expr.type), new Tuple<bool, List<expression>>(lambdas_are_in_parameters, syntax_nodes_parameters))); }
private expression_node make_dec_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) throw new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node); if (parameters.expressions.Count == 1 || parameters.expressions.Count == 2) { expression_node param0 = convert_strong(parameters.expressions[0]); if (!param0.is_addressed) { bool is_pascal_array_ref = false; if (param0.semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)param0; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == compiler_string_consts.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); param0 = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } if (!is_pascal_array_ref) { throw new ThisExpressionCanNotBePassedAsVarParameter(param0); } } else if (param0 is compiled_function_call) { compiled_function_call cfc = param0 as compiled_function_call; if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type && cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function)) { expressions_list exl = new expressions_list(); exl.AddElement(cfc.obj); exl.AddElement(cfc.parameters[0]); basic_function_call bfc2 = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); bfc2.parameters.AddElement(param0); expression_node _param1 = null; if (parameters.expressions.Count == 2) { _param1 = convert_strong(parameters.expressions[1]); } if (_param1 != null) bfc2.parameters.AddElement(convertion_data_and_alghoritms.convert_type(_param1,SystemLibrary.SystemLibrary.integer_type)); else bfc2.parameters.AddElement(new int_const_node(1,null)); expressions_list el = new expressions_list(); el.AddElement(convertion_data_and_alghoritms.convert_type(bfc2,SystemLibrary.SystemLibrary.ushort_type)); function_node chr_func = convertion_data_and_alghoritms.select_function(el, SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc); exl.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray())); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return ret; } else { throw new ThisExpressionCanNotBePassedAsVarParameter(param0); } } else throw new ThisExpressionCanNotBePassedAsVarParameter(param0); } else check_on_loop_variable(param0); expression_node param1 = null; int type_flag = 0; bool is_uint=false; bool is_enum=false; if (parameters.expressions.Count == 2) { param1 = convert_strong(parameters.expressions[1]); param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type); } basic_function_call ass = null; basic_function_call bfc = null; if (param0.type == SystemLibrary.SystemLibrary.integer_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.char_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.char_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.byte_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.byte_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.sbyte_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.sbyte_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.short_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.short_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.ushort_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.ushort_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.uint_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.uint_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.uint_sub as basic_function_node,loc); type_flag = 2; is_uint = true; } else if (param0.type == SystemLibrary.SystemLibrary.int64_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.long_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.long_sub as basic_function_node,loc); type_flag = 1; } else if (param0.type == SystemLibrary.SystemLibrary.uint64_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.ulong_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.ulong_sub as basic_function_node,loc); type_flag = 2; } else if (param0.type == SystemLibrary.SystemLibrary.bool_type) { if (param1 == null) { ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc); type_flag = 4; } else { basic_function_call mod_expr = new basic_function_call(SystemLibrary.SystemLibrary.int_mod as basic_function_node,loc); mod_expr.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type)); mod_expr.parameters.AddElement(new int_const_node(2,loc)); basic_function_call condition = new basic_function_call(SystemLibrary.SystemLibrary.int_eq as basic_function_node,loc); condition.parameters.AddElement(mod_expr); condition.parameters.AddElement(new int_const_node(0,loc)); basic_function_call not_expr = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc); not_expr.parameters.AddElement(param0); question_colon_expression qce = new question_colon_expression(condition, param0, not_expr, loc); ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc); ass.parameters.AddElement(param0); ass.parameters.AddElement(qce); type_flag = 5; } } else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum) { ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type) { type_node bt = param0.type.base_type; if (bt == SystemLibrary.SystemLibrary.int64_type) type_flag = 1; else if (bt == SystemLibrary.SystemLibrary.uint64_type) type_flag = 2; else if (bt == SystemLibrary.SystemLibrary.uint_type) { type_flag =2; is_uint = true; } else if (bt.IsEnum) is_enum = true; } else if (param0.type.IsEnum) is_enum = true; } else throw new NoFunctionWithSameArguments(loc,false); if (type_flag != 5) { if (param1 != null) switch (type_flag) { case 0: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); break; case 3: case 1: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.int64_type); break; case 2: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.uint64_type); break; } //bfc.parameters.AddElement(param0); if (param0.type != SystemLibrary.SystemLibrary.char_type && !is_enum && param0.type != SystemLibrary.SystemLibrary.bool_type) switch (type_flag) { case 0: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.integer_type)); break; case 3: case 1: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.int64_type)); break; case 2: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.uint64_type)); break; } else bfc.parameters.AddElement(param0); if (param1 == null) { if (type_flag == 0 || type_flag == 3) bfc.parameters.AddElement(new int_const_node(1, null)); else if (type_flag == 1) bfc.parameters.AddElement(new long_const_node(1, null)); else if (type_flag == 2) bfc.parameters.AddElement(new ulong_const_node(1, null)); } else bfc.parameters.AddElement(param1); ass.parameters.AddElement(param0); if (is_uint) ass.parameters.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.uint_type)); else ass.parameters.AddElement(bfc); } return ass; } throw new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node); }
internal expression_node get_init_call_for_typed_file(var_definition_node vdn, type_node element_type) { location loc = (vdn.type as common_type_node).loc; if (!SystemUnitAssigned) AddError(new NotSupportedError(loc)); //Когда заработает наследование конструкторов надо вставить это /* expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(new typeof_operator(element_type, loc)); base_function_call bfc = create_constructor_call(vdn.type, exl, loc); expression_node expr = find_operator(compiler_string_consts.assign_name, var_ref, bfc, loc); */ type_node tn = vdn.type; vdn.type = SystemLibrary.SystemLibInitializer.TypedFileType.sym_info as type_node; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(var_ref); exl.AddElement(new typeof_operator(element_type, loc)); List<int> lens = get_short_string_lens(element_type); int sz = get_short_string_size(element_type); if (sz > 0) { exl.AddElement(new int_const_node(get_short_string_size(element_type),null)); for (int i=0; i<lens.Count; i++) exl.AddElement(new int_const_node(lens[i],null)); } this.context.save_var_definitions(); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedFileInitProcedure.SymbolInfo, loc); this.context.restore_var_definitions(); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray()); vdn.type = tn; return expr; }
private expressions_list convert_expression_list(List<SyntaxTree.expression> expr_list) { expressions_list exprs = new expressions_list(); foreach (SyntaxTree.expression en in expr_list) exprs.AddElement(convert_strong(en)); return exprs; }
internal expression_node get_init_call_for_binary_file(var_definition_node vdn) { location loc = null; if (vdn.type is common_type_node) loc = (vdn.type as common_type_node).loc; if (!SystemUnitAssigned) AddError(new NotSupportedError(loc)); type_node tn = vdn.type; vdn.type = SystemLibrary.SystemLibInitializer.BinaryFileType.sym_info as type_node; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(var_ref); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure.SymbolInfo, loc); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray()); vdn.type = tn; return expr; }
//TODO: Обратить внимание на эту функцию. Ее вызовы не приводят к созданиям узлов преобразования типов. private function_node find_function(string name, location loc, params expression_node[] exprs) { expressions_list exprs_list = new expressions_list(); exprs_list.AddRange(exprs); return find_function(name, loc, exprs_list); }
internal expression_node get_init_call_for_set_as_constr(var_definition_node vdn, expression_node init_value) { location loc = (vdn.type as common_type_node).loc; if (!SystemUnitAssigned) AddError(new NotSupportedError(loc)); //Когда заработает наследование конструкторов надо вставить это /* expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(new typeof_operator(element_type, loc)); base_function_call bfc = create_constructor_call(vdn.type, exl, loc); expression_node expr = find_operator(compiler_string_consts.assign_name, var_ref, bfc, loc); */ type_node tn = vdn.type; vdn.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); //exl.AddElement(var_ref); //exl.AddElement(new typeof_operator(element_type, loc)); if (tn.element_type == SystemLibrary.SystemLibrary.byte_type) { exl.AddElement(new byte_const_node(byte.MinValue,null)); exl.AddElement(new byte_const_node(byte.MaxValue,null)); } else if (tn.element_type == SystemLibrary.SystemLibrary.sbyte_type) { exl.AddElement(new sbyte_const_node(sbyte.MinValue,null)); exl.AddElement(new sbyte_const_node(sbyte.MaxValue,null)); } else if (tn.element_type == SystemLibrary.SystemLibrary.short_type) { exl.AddElement(new short_const_node(short.MinValue,null)); exl.AddElement(new short_const_node(short.MaxValue,null)); } else if (tn.element_type == SystemLibrary.SystemLibrary.ushort_type) { exl.AddElement(new ushort_const_node(ushort.MinValue,null)); exl.AddElement(new ushort_const_node(ushort.MaxValue,null)); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.diap_type || tn.element_type.type_special_kind == SemanticTree.type_special_kind.enum_kind) { ordinal_type_interface ii = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; exl.AddElement(ii.lower_value); exl.AddElement(ii.upper_value); } exl.AddElement(init_value); function_node fn = null; if (exl.Count > 1) { fn = convertion_data_and_alghoritms.select_function(exl, (SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node).find_in_type(compiler_string_consts.default_constructor_name), loc); } else { fn = convertion_data_and_alghoritms.select_function(exl, (SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node).find_in_type(compiler_string_consts.default_constructor_name), loc); } //expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray()); expression_node expr = create_static_method_call_with_params(fn, loc, tn, false, exl); vdn.type = tn; return expr; }
/*public function_lambda_call_node(type_node ret_type) { _ret_type = ret_type; }*/ /// <summary> /// Конструктор узла. /// </summary> /// <param name="ret_type">Тип возвращаемого значения функции.</param> public function_lambda_call_node(expressions_list parameters, function_lambda_node fln) { _parameters = parameters; _fln = fln; }
public static function_node DeduceFunction(function_node func, expressions_list fact, bool alone, location loc, List<SyntaxTree.expression> syntax_nodes_parameters = null) { parameter_list formal = func.parameters; int formal_count = formal.Count; int fact_count = fact.Count; int generic_type_params_count = func.generic_parameters_count; type_node[] deduced = new type_node[generic_type_params_count]; List<int> nils = new List<int>(); int count_params_to_see = fact_count; var lambda_syntax_nodes = new Dictionary<string, function_lambda_definition>(); //lroman Получим список фактических параметров-лямбд текущей вызываемой подпрограммы if (syntax_nodes_parameters != null && syntax_nodes_parameters.Count > 0) //lroman { lambda_syntax_nodes = syntax_nodes_parameters .OfType<function_lambda_definition>() .ToDictionary(f => f.lambda_name, f => f); } var lambda_in_parameters = lambda_syntax_nodes.Count > 0; var saved_lambdas_states = SaveLambdasStates(lambda_syntax_nodes.Select(ld => ld.Value)); // Сохраним типы лямбды перед вычислениями if (fact_count < formal_count) { //Сравниваем количества параметров parameter par = formal[fact_count]; if (par.default_value == null && !par.is_params) { if (alone) throw new NoFunctionWithSameParametresNum(loc, alone, func); return null; } } else { type_node last_params_type = null; bool last_is_params = false; parameter par = null; if (formal_count > 0) { par = formal[formal_count - 1]; last_is_params = par.is_params; } if (last_is_params) { array_internal_interface aii = par.type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; last_params_type = aii.element_type; } if (fact_count > formal_count) { //Фактических больше, чем формальных. Последний формальный должен быть params... if (last_is_params) { for (int i = formal_count - 1; i < fact_count; ++i) { //Проверяем фактические, попадающие под params... if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils)) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); return null; } } count_params_to_see = formal_count - 1; } else { if (alone) throw new NoFunctionWithSameParametresNum(loc, alone, func); return null; } } } bool need_params_work = (count_params_to_see > 0 && formal[count_params_to_see - 1].is_params); if (need_params_work) { count_params_to_see -= 1; } var continue_trying_to_infer_types = true; Dictionary<string, delegate_internal_interface> formal_delegates = null; while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации { var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced .Select((t, i) => new { Type = t, Index = i }) .Where(t => t.Type != null) .Select(t => t.Index) .ToArray(); for (int i = 0; i < count_params_to_see; ++i) { if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils)) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); return null; } } if (lambda_in_parameters) { if (formal_delegates == null) { formal_delegates = new Dictionary<string, delegate_internal_interface>(); for (int i = 0; i < count_params_to_see; ++i) //Выделим из формальных параметров те, которые соотвтествуют фактическим параметрам-лямбдам { var lambda_func = fact[i].type as delegated_methods; if (lambda_func != null && lambda_func.proper_methods.Count == 1 && LambdaHelper.IsLambdaName(lambda_func.proper_methods[0].simple_function_node.name)) { formal_delegates.Add(LambdaHelper.GetLambdaNamePartWithoutGenerics(lambda_func.proper_methods[0].simple_function_node.name), formal[i].type.get_internal_interface( internal_interface_kind.delegate_interface) as delegate_internal_interface); } } } foreach (var formal_delegate in formal_delegates) //Перебираем все полученные формальные параемтры, соотвтетсвующие фактическим лямбдам { var lambda_syntax_node = lambda_syntax_nodes[formal_delegate.Key]; Exception on_lambda_body_compile_exception; // Исключение которое может возникунть в результате компиляции тела лямбды если мы выберем неправильные типы параметров if (!TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils, out on_lambda_body_compile_exception)) //Пробуем вычислить типы из лямбд { RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); if (on_lambda_body_compile_exception != null) { if (alone) { throw on_lambda_body_compile_exception; } throw new FailedWhileTryingToCompileLambdaBodyWithGivenParametersException( on_lambda_body_compile_exception); } if (alone) { throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); } return null; } } } var current_deduce_state = deduced //текущее состояние выведенных типов .Select((t, ii) => new {Type = t, Index = ii}) .Where(t => t.Type != null) .Select(t => t.Index) .ToArray(); if (previous_deduce_state.SequenceEqual(current_deduce_state)) // Если ничего с прошлой итерации не изменилось, то дальше нет смысла пробовать выводить. Выходим из цикла { continue_trying_to_infer_types = false; } } RestoreLambdasStates(lambda_syntax_nodes.Values.ToList(), saved_lambdas_states); if (need_params_work) { type_node[] tmp_deduced = (type_node[])deduced.Clone(); List<int> tmp_nils = new List<int>(); tmp_nils.AddRange(nils); if (!DeduceInstanceTypes(formal[count_params_to_see].type, fact[count_params_to_see].type, deduced, nils)) { //Второй шанс. Учитываем слово params. deduced = tmp_deduced; nils = tmp_nils; if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils)) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); return null; } } } //Вывели всё, что могли. Теперь проверяем. for (int i = 0; i < generic_type_params_count; ++i) { if (deduced[i] == null) { if (alone) throw new SimpleSemanticError(loc, "CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}", func.name); return null; } } foreach (int num in nils) { if (!type_table.is_with_nil_allowed(deduced[num])) { if (alone) throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name); return null; } } foreach (type_node tt in deduced) { CompilationErrorWithLocation check_err = generic_parameter_eliminations.check_type_generic_useful(tt, loc); if (check_err != null) { if (alone) throw check_err; return null; } } //Итак, вывели все параметры. Теперь инстанцируем. List<type_node> deduced_list = new List<type_node>(generic_type_params_count); deduced_list.AddRange(deduced); return func.get_instance(deduced_list, alone, loc); }