diff --git a/TestSuite/delegates23.pas b/TestSuite/delegates23.pas new file mode 100644 index 000000000..c5854ab41 --- /dev/null +++ b/TestSuite/delegates23.pas @@ -0,0 +1,17 @@ +var i: integer; + +procedure p0(p: byte->()); +begin + Inc(i); +end; +procedure p1(o: T); +begin + Inc(i); +end; + +begin + p0(p1&); + //Ошибка: Нельзя преобразовать тип procedure(o: T) к Action + p0(p1); + assert(i = 2); +end. \ No newline at end of file diff --git a/TestSuite/delegates24.pas b/TestSuite/delegates24.pas new file mode 100644 index 000000000..c79d682f1 --- /dev/null +++ b/TestSuite/delegates24.pas @@ -0,0 +1,12 @@ +begin + var i := 0; + //Ошибка: Неизвестное имя 'procedure()' + var d: procedure(p: procedure); + // Если убрать присваивание, ошибка выше пропадает + d := p -> + begin + p; + end; + d(() -> begin Inc(i) end); + assert(i = 1); +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs index 9ce0f8d65..60de9d326 100644 --- a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs +++ b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs @@ -1204,13 +1204,44 @@ namespace PascalABCCompiler.TreeConverter { //issue #2161 - SSM 12.03.2020 //issue #348 - if (formal_param_type == SystemLibrary.SystemLibrary.object_type && factparams[i].type is delegated_methods) + if ((formal_param_type == SystemLibrary.SystemLibrary.object_type || formal_param_type.IsDelegate) && factparams[i].type is delegated_methods) { possible_type_convertions ptci = new possible_type_convertions(); ptci.first = null; ptci.second = null; + if (formal_param_type.instance_params != null && formal_param_type.instance_params.Count > 0) + { + var fn = (factparams[i].type as delegated_methods).proper_methods[0].simple_function_node; + if (fn.is_generic_function) + { + var fn_instance = fn.get_instance(formal_param_type.instance_params, true, factparams[i].location); + delegated_methods dm = new delegated_methods(); + if (fn is common_namespace_function_node) + dm.proper_methods.AddElement(new common_namespace_function_call(fn_instance as common_namespace_function_node, factparams[i].location)); + factparams[i].type = dm; + } + else if (!is_alone_method_defined) + return null; + } + else if (!is_alone_method_defined && formal_param_type.IsDelegate) + return null; ptci.from = factparams[i].type; ptci.to = formal_param_type; + if (formal_param_type.IsDelegate) + { + var ttc = type_table.get_convertions(formal_param_type, factparams[i].type); + if (ttc.first == null) + { + if (is_alone_method_defined) // если мы сюда попали, то ошибка более явная + { + error = new CanNotConvertTypes(factparams[i], factparams[i].type, formal_param_type, locg); + return null; + } + else + return null; + } + } + tc.AddElement(ptci); factparams[i] = syntax_tree_visitor.CreateDelegateCall((factparams[i].type as delegated_methods).proper_methods[0]); //return tc; diff --git a/TreeConverter/TreeRealization/type_table.cs b/TreeConverter/TreeRealization/type_table.cs index 5bfdedd3f..953851b36 100644 --- a/TreeConverter/TreeRealization/type_table.cs +++ b/TreeConverter/TreeRealization/type_table.cs @@ -1144,6 +1144,20 @@ namespace PascalABCCompiler.TreeRealization } } } + else if (to is delegated_methods) + { + var proper_meth = (to as delegated_methods).proper_methods[0].simple_function_node; + if (dii.parameters.Count == proper_meth.parameters.Count) + { + //ms100 error fixed (DS) + bool eq = TreeConverter.convertion_data_and_alghoritms.function_eq_params_and_result(dii.invoke_method, proper_meth); + 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) {