From 7a5d113c775436e80eb06ac803483d1b95fd9a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=BD=D0=B4=D0=B0=D1=80=D0=B5=D0=B2=20=D0=98?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD?= Date: Sun, 13 Mar 2016 18:50:38 +0100 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D1=8F=D0=B2=D0=BD=D1=83=D1=8E=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8E=20generic-=D0=B8=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TestSuite/interface3.pas | 14 ++++++ TestSuite/interface4.pas | 30 ++++++++++++ .../TreeConversion/compilation_context.cs | 4 +- .../convertion_data_and_alghoritms.cs | 18 ++----- .../TreeConversion/syntax_tree_visitor.cs | 47 +++++++++++++------ bin/Lng/Eng/SemanticErrors_ib.dat | 2 + bin/Lng/Rus/SemanticErrors_ib.dat | 2 + 7 files changed, 86 insertions(+), 31 deletions(-) create mode 100644 TestSuite/interface3.pas create mode 100644 TestSuite/interface4.pas diff --git a/TestSuite/interface3.pas b/TestSuite/interface3.pas new file mode 100644 index 000000000..1adf2c1fc --- /dev/null +++ b/TestSuite/interface3.pas @@ -0,0 +1,14 @@ +type TClass = class(IEnumerable) +public function System.Collections.Generic.IEnumerable.GetEnumerator: IEnumerator; +begin + +end; + +public function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator; +begin + +end; +end; +begin + +end. \ No newline at end of file diff --git a/TestSuite/interface4.pas b/TestSuite/interface4.pas new file mode 100644 index 000000000..4d4995c71 --- /dev/null +++ b/TestSuite/interface4.pas @@ -0,0 +1,30 @@ +type + IEnr = System.Collections.IEnumerator; + IEnb = System.Collections.IEnumerable; + + var a : integer; + type My = class(IEnumerable) + public + function IEnb.GetEnumerator(): IEnr; + begin + a := 1; + end; + function System.Collections.Generic.IEnumerable.GetEnumerator(): IEnumerator; + begin + a := 2; + end; + + end; + +begin +var ien: IEnb := new My; +ien.GetEnumerator; +assert(a=1); +var ien2: IEnumerable := new My; +ien2.GetEnumerator; +assert(a=2); +a := 0; +var mc := new My; +mc.GetEnumerator(); +assert(a=2); +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/compilation_context.cs b/TreeConverter/TreeConversion/compilation_context.cs index f8235e3fe..2850686c4 100644 --- a/TreeConverter/TreeConversion/compilation_context.cs +++ b/TreeConverter/TreeConversion/compilation_context.cs @@ -917,7 +917,7 @@ namespace PascalABCCompiler.TreeConverter while (si != null) { compar = si.sym_info as function_node; - if (fn != compar && convertion_data_and_alghoritms.function_eq_params(fn, compar, false)) + if (fn != compar && convertion_data_and_alghoritms.function_eq_params(fn, compar)) //if (fn is common_namespace_function_node && compar is common_namespace_function_node && (fn as common_namespace_function_node).comprehensive_namespace == (compar as common_namespace_function_node).comprehensive_namespace) AddError(new FunctionDuplicateDefinition(compar, fn)); @@ -2760,7 +2760,7 @@ _cmn.types.AddElement(tctn);*/ { fn = si.sym_info as function_node; //Сверяем параметры и тип возвращаемого значения - if (convertion_data_and_alghoritms.function_eq_params_and_result(meth, fn) && fn.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract) + if (convertion_data_and_alghoritms.function_eq_params_and_result(meth, fn, true) && fn.polymorphic_state != SemanticTree.polymorphic_state.ps_virtual_abstract) { //Нашли нужную функцию common_method_node fn_common = fn as common_method_node; diff --git a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs index 3a27be3f6..d7c3c46bf 100644 --- a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs +++ b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs @@ -1467,9 +1467,9 @@ namespace PascalABCCompiler.TreeConverter } //Этот метод сверяет не только параметры, но и возвращаемое значение - public static bool function_eq_params_and_result(function_node left, function_node right) + public static bool function_eq_params_and_result(function_node left, function_node right, bool weak=false) { - if (!function_eq_params(left, right)) + if (!function_eq_params(left, right, weak)) { return false; } @@ -1482,18 +1482,8 @@ namespace PascalABCCompiler.TreeConverter //Сравниваем типы-параметры generic-функций public static bool function_eq_generic_params(function_node left, function_node right) { - common_function_node cleft = left as common_function_node; - common_function_node cright = right as common_function_node; - List left_type_params = null; - List right_type_params = null; - if (cleft != null) - { - left_type_params = cleft.generic_params; - } - if (cright != null) - { - right_type_params = cright.generic_params; - } + List left_type_params = left.get_generic_params_list(); + List right_type_params = right.get_generic_params_list(); if (left_type_params == null && right_type_params == null) { return true; diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 1743ae590..7b895d327 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -9100,12 +9100,6 @@ namespace PascalABCCompiler.TreeConverter common_type_node tp = null; definition_node def_temp = null; SyntaxTree.template_type_name ttn = null; - /*SyntaxTree.operator_name_ident on = _method_name as SyntaxTree.operator_name; - if (on != null) - { - _method_name.meth_name = new SyntaxTree.ident(name_reflector.get_name(on.operator_type.type)); - } - */ bool is_operator = _method_name.meth_name is SyntaxTree.operator_name_ident; SyntaxTree.Operators op = PascalABCCompiler.SyntaxTree.Operators.Undefined; if(is_operator) @@ -9114,8 +9108,6 @@ namespace PascalABCCompiler.TreeConverter bool explicit_impl = false; if ((context.converting_block() != block_type.namespace_block) && (_method_name.class_name != null)) { - /*AddError(new OnlyProcedureNameAllowedInClassFunctionDefinition(_method_name.class_name.name, - get_location(_method_name.class_name)));*/ explicit_impl = true; } if (is_operator && op==SyntaxTree.Operators.AddressOf && SemanticRules.AddressOfOperatorNonOverloaded) @@ -9245,12 +9237,6 @@ namespace PascalABCCompiler.TreeConverter } else if (def_temp as compiled_type_node == SystemLibrary.SystemLibrary.void_type) AddError(get_location(_method_name.class_name), "VOID_NOT_VALID"); - //else if ((def_temp as compiled_type_node).IsInterface) - // AddError(new ExtensionMethodForInterfaceNotAllowed(get_location(_method_name.class_name))); - //else - //{ - // throw new CanNotDefineMethodOfCompiledType(get_location(_method_name)); - //} } else { @@ -9292,7 +9278,38 @@ namespace PascalABCCompiler.TreeConverter context.top_function.IsOperator = is_operator; if (ttn != null && def_temp is compiled_type_node) { - visit_generic_params(context.top_function, ttn.template_args.idents); + if (!explicit_impl) + visit_generic_params(context.top_function, ttn.template_args.idents); + else + { + List instance_params = new List(); + foreach (ident id in ttn.template_args.idents) + { + SymbolInfo si = context.find(id.name); + if (si == null) + AddError(new UndefinedNameReference(id.name, get_location(id))); + if (!(si.sym_info is type_node)) + AddError(new ExpectedType(get_location(id))); + instance_params.Add(si.sym_info as type_node); + } + if (!context.converted_explicit_interface_type.IsInterface) + AddError(get_location(ttn), "INTERFACE_EXPECTED"); + type_node inst_tn = context.converted_explicit_interface_type.get_instance(instance_params); + bool found = false; + if (context.converted_type.ImplementingInterfaces.Count > 0) + { + foreach (type_node interf in context.converted_type.ImplementingInterfaces) + { + if (interf == inst_tn) + { + found = true; + break; + } + } + } + if (!found) + AddError(get_location(ttn),"CLASS_NOT_IMPLEMENT_THIS_INTERFACE"); + } } //context.top_function.IsOperator = _method_name.meth_name is SyntaxTree.operator_name_ident; diff --git a/bin/Lng/Eng/SemanticErrors_ib.dat b/bin/Lng/Eng/SemanticErrors_ib.dat index 586058ee6..9f879fc25 100644 --- a/bin/Lng/Eng/SemanticErrors_ib.dat +++ b/bin/Lng/Eng/SemanticErrors_ib.dat @@ -114,6 +114,8 @@ CANNOT_EVALUATE_FUNCTION_TYPE=Cannot infer the return type of function TYPE_NAME_EXPECTED=Type name expected EXPLICIT_IMPLEMENTATION_EXPECTED=Method implementation expected ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS=Anonymous delegates can not use generic parameters +CLASS_NOT_IMPLEMENT_THIS_INTERFACE=Class doesn't implement this interface +INTERFACE_EXPECTED=Interface expected %PREFIX%=COMPILATIONERROR_ UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Unit expected, library found ASSEMBLY_{0}_READING_ERROR=Error by reading assembly '{0}' diff --git a/bin/Lng/Rus/SemanticErrors_ib.dat b/bin/Lng/Rus/SemanticErrors_ib.dat index 5664f98bc..71c1cdb8c 100644 --- a/bin/Lng/Rus/SemanticErrors_ib.dat +++ b/bin/Lng/Rus/SemanticErrors_ib.dat @@ -109,6 +109,8 @@ CANNOT_EVALUATE_FUNCTION_TYPE=Невозможно вывести тип фун TYPE_NAME_EXPECTED=Ожидался тип EXPLICIT_IMPLEMENTATION_EXPECTED=Метод, явно реализующий интерфейс, должен быть реализован в определении класса ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS=Недопустимо описание анонимных делегатов, использующих generic-параметры +CLASS_NOT_IMPLEMENT_THIS_INTERFACE=Класс не реализует данный интерфейс +INTERFACE_EXPECTED=Ожидался интерфейс %PREFIX%=COMPILATIONERROR_ UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Ожидался модуль, а встречена библиотека ASSEMBLY_{0}_READING_ERROR=Ошибка при чтении сборки '{0}'