private static void add_conversion(possible_type_convertions ptc, function_node fn, type_node from, type_node to) { if (fn == null) { return; } if (ptc.first == null) { ptc.first = new type_conversion(fn); } else { ptc.second = new type_conversion(fn); } ptc.from = from; ptc.to = to; }
/// <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; }
private type_conversion_compare compare_type_conversions(possible_type_convertions left,possible_type_convertions right) { if ((left.first==null)&&(right.first!=null)) { return type_conversion_compare.greater_type_conversion; } if ((left.first!=null)&&(right.first==null)) { return type_conversion_compare.less_type_conversion; } if ((left.first != null) && (right.first != null)) { convert_types_function_node cleft = left.first.convertion_method as convert_types_function_node; convert_types_function_node cright = right.first.convertion_method as convert_types_function_node; if ((cleft != null) && (cright != null)) { if ((cleft.Good) && (!cright.Good)) { return type_conversion_compare.greater_type_conversion; } if ((!cleft.Good) && (cright.Good)) { return type_conversion_compare.less_type_conversion; } } } /*if ((left.first==null)&&(right.first==null)) { return type_conversion_compare.equal_type_conversions; }*/ //type_compare tc=type_table.compare_types(left.first.to,right.first.to); type_compare tc=type_table.compare_types(left.to,right.to); if (tc==type_compare.greater_type) { if (left.to.type_special_kind == type_special_kind.diap_type && left.to is common_type_node && right.to.type_special_kind == type_special_kind.diap_type && right.to is common_type_node) { tc = type_table.compare_types(left.to.base_type,right.to.base_type); if (tc == type_compare.greater_type) return type_conversion_compare.less_type_conversion; } else return type_conversion_compare.less_type_conversion; //return type_conversion_compare.greater_type_conversion; } if (tc==type_compare.less_type) { if (left.to.type_special_kind == type_special_kind.diap_type && left.to is common_type_node && right.to.type_special_kind == type_special_kind.diap_type && right.to is common_type_node) { tc = type_table.compare_types(left.to.base_type,right.to.base_type); if (tc == type_compare.less_type) return type_conversion_compare.greater_type_conversion; } else return type_conversion_compare.greater_type_conversion; //return type_conversion_compare.less_type_conversion; } internal_interface left_del = left.to.get_internal_interface(internal_interface_kind.delegate_interface); internal_interface right_del = right.to.get_internal_interface(internal_interface_kind.delegate_interface); if ((left_del == null) && (right_del == null)) { return type_conversion_compare.equal_type_conversions; } if ((left_del == null) && (right_del != null)) { return type_conversion_compare.less_type_conversion; } if ((left_del != null) && (right_del == null)) { return type_conversion_compare.greater_type_conversion; } return type_conversion_compare.equal_type_conversions; }
//TODO: Возможно стоит если пересечение типов найдено в откомпилированных типах, добавлять к нашим структурам и не искать повторно. public static possible_type_convertions get_convertions(type_node from, type_node to, bool is_implicit) { possible_type_convertions ret = new possible_type_convertions(); ret.first = null; ret.second = null; if ((from == null) || (to == null)) { return(ret); } type_intersection_node tin_from = from.get_type_intersection(to); type_intersection_node tin_to = to.get_type_intersection(from); if (tin_from != null) { if (tin_from.this_to_another != null) { if ((!is_implicit) || (!(tin_from.this_to_another.is_explicit))) { add_conversion(ret, tin_from.this_to_another.convertion_method, from, to); } } } if (tin_to != null) { if (tin_to.another_to_this != null) { if ((!is_implicit) || (!(tin_to.another_to_this.is_explicit))) { add_conversion(ret, tin_to.another_to_this.convertion_method, from, to); } } } if (ret.second != null) { return(ret); } if (is_derived(to, from) || (from.IsInterface && to == SystemLibrary.SystemLibrary.object_type) || from.is_generic_type_instance && to == SystemLibrary.SystemLibrary.object_type) { add_conversion(ret, TreeConverter.convertion_data_and_alghoritms.get_empty_conversion(from, to, true), from, to); //add_conversion(ret, SystemLibrary.SystemLibrary.empty_method, from, to); } if (ret.second != null) { return(ret); } wrapped_type ctn_to = to as wrapped_type; wrapped_type ctn_from = from as wrapped_type; if (ctn_to != null) { function_node fnode1 = null; fnode1 = ctn_to.get_implicit_conversion_from(from); add_conversion(ret, fnode1, from, to); if (ret.second != null) { return(ret); } fnode1 = null; if (!is_implicit) { fnode1 = ctn_to.get_explicit_conversion_from(from); } add_conversion(ret, fnode1, from, to); if (ret.second != null) { return(ret); } } if (ctn_from != null) { function_node fnode2 = null; fnode2 = ctn_from.get_implicit_conversion_to(to); add_conversion(ret, fnode2, from, to); if (ret.second != null) { return(ret); } fnode2 = null; if (!is_implicit) { fnode2 = ctn_from.get_explicit_conversion_to(to); } add_conversion(ret, fnode2, from, to); if (ret.second != null) { return(ret); } } //TODO: Вот это должно быть в каком нибудь другом месте. internal_interface ii = from.get_internal_interface(internal_interface_kind.delegate_interface); if (ii != null) { delegate_internal_interface dii = (delegate_internal_interface)ii; internal_interface to_ii = to.get_internal_interface(internal_interface_kind.delegate_interface); if (to_ii != null) { delegate_internal_interface to_dii = (delegate_internal_interface)to_ii; if (dii.parameters.Count == to_dii.parameters.Count) { //ms100 error fixed (DS) bool eq = TreeConverter.convertion_data_and_alghoritms.function_eq_params_and_result(dii.invoke_method, to_dii.invoke_method); if (eq) { delegate_to_delegate_type_converter dtdtc = new delegate_to_delegate_type_converter(to); add_conversion(ret, new convert_types_function_node(dtdtc.convert_delegates_to_delegates, false), from, to); } } } if (dii.parameters.Count == 0) { if (dii.return_value_type == to) { add_conversion(ret, new convert_types_function_node(convert_delegate_to_return_value_type, true), from, to); } else { possible_type_convertions ptcc = get_convertions(dii.return_value_type, to); if ((ptcc.first != null) && (ptcc.first.convertion_method != null)) { delegate_type_converter dtc = new delegate_type_converter(ptcc.first.convertion_method); add_conversion(ret, new convert_types_function_node(dtc.convert_delegate_to_return_value_type_with_convertion, false), from, to); } if ((ptcc.second != null) && (ptcc.second.convertion_method != null)) { delegate_type_converter dtc = new delegate_type_converter(ptcc.second.convertion_method); add_conversion(ret, new convert_types_function_node(dtc.convert_delegate_to_return_value_type_with_convertion, false), from, to); } } } } return(ret); }
//TODO: Возможно стоит если пересечение типов найдено в откомпилированных типах, добавлять к нашим структурам и не искать повторно. public static possible_type_convertions get_convertions(type_node from,type_node to, bool is_implicit) { possible_type_convertions ret = new possible_type_convertions(); ret.first = null; ret.second = null; if ((from == null) || (to == null)) { return ret; } type_intersection_node tin_from=from.get_type_intersection(to); type_intersection_node tin_to=to.get_type_intersection(from); if (tin_from != null) { if (tin_from.this_to_another != null) { if ((!is_implicit) || (!(tin_from.this_to_another.is_explicit))) { add_conversion(ret, tin_from.this_to_another.convertion_method, from, to); } } } if (tin_to != null) { if (tin_to.another_to_this != null) { if ((!is_implicit) || (!(tin_to.another_to_this.is_explicit))) { add_conversion(ret, tin_to.another_to_this.convertion_method, from, to); } } } if (ret.second != null) { return ret; } if (is_derived(to, from) || (from.IsInterface && to == SystemLibrary.SystemLibrary.object_type)) { add_conversion(ret, TreeConverter.convertion_data_and_alghoritms.get_empty_conversion(from, to, true), from, to); //add_conversion(ret, SystemLibrary.SystemLibrary.empty_method, from, to); } if (ret.second != null) { return ret; } wrapped_type ctn_to=to as wrapped_type; wrapped_type ctn_from=from as wrapped_type; if (ctn_to != null) { function_node fnode1 = null; fnode1 = ctn_to.get_implicit_conversion_from(from); add_conversion(ret, fnode1, from, to); if (ret.second != null) { return ret; } fnode1 = null; if (!is_implicit) { fnode1 = ctn_to.get_explicit_conversion_from(from); } add_conversion(ret, fnode1, from, to); if (ret.second != null) { return ret; } } if (ctn_from != null) { function_node fnode2 = null; fnode2 = ctn_from.get_implicit_conversion_to(to); add_conversion(ret, fnode2, from, to); if (ret.second != null) { return ret; } fnode2 = null; if (!is_implicit) { fnode2 = ctn_from.get_explicit_conversion_to(to); } add_conversion(ret, fnode2, from, to); if (ret.second != null) { return ret; } } //TODO: Вот это должно быть в каком нибудь другом месте. internal_interface ii = from.get_internal_interface(internal_interface_kind.delegate_interface); if (ii != null) { delegate_internal_interface dii = (delegate_internal_interface)ii; internal_interface to_ii = to.get_internal_interface(internal_interface_kind.delegate_interface); if (to_ii != null) { delegate_internal_interface to_dii = (delegate_internal_interface)to_ii; if (dii.parameters.Count == to_dii.parameters.Count) { //ms100 error fixed (DS) bool eq = TreeConverter.convertion_data_and_alghoritms.function_eq_params_and_result(dii.invoke_method, to_dii.invoke_method); if (eq) { delegate_to_delegate_type_converter dtdtc = new delegate_to_delegate_type_converter(to); add_conversion(ret, new convert_types_function_node(dtdtc.convert_delegates_to_delegates, false), from, to); } } } if (dii.parameters.Count == 0) { if (dii.return_value_type == to) { add_conversion(ret, new convert_types_function_node(convert_delegate_to_return_value_type, true), from, to); } else { possible_type_convertions ptcc = get_convertions(dii.return_value_type, to); if ((ptcc.first != null) && (ptcc.first.convertion_method != null)) { delegate_type_converter dtc = new delegate_type_converter(ptcc.first.convertion_method); add_conversion(ret, new convert_types_function_node(dtc.convert_delegate_to_return_value_type_with_convertion, false), from, to); } if ((ptcc.second != null) && (ptcc.second.convertion_method != null)) { delegate_type_converter dtc = new delegate_type_converter(ptcc.second.convertion_method); add_conversion(ret, new convert_types_function_node(dtc.convert_delegate_to_return_value_type_with_convertion, false), from, to); } } } } return ret; }
private static void add_conversion(possible_type_convertions ptc, function_node fn,type_node from,type_node to) { if (fn==null) { return; } if (ptc.first == null) { ptc.first = new type_conversion(fn); } else { ptc.second = new type_conversion(fn); } ptc.from = from; ptc.to = to; }