доделал явную реализацию generic-интерфейсов

This commit is contained in:
Бондарев Иван 2016-03-13 18:50:38 +01:00
parent 893e4d9d16
commit 7a5d113c77
7 changed files with 86 additions and 31 deletions

14
TestSuite/interface3.pas Normal file
View file

@ -0,0 +1,14 @@
type TClass<T> = class(IEnumerable<T>)
public function System.Collections.Generic.IEnumerable<T>.GetEnumerator: IEnumerator<T>;
begin
end;
public function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator;
begin
end;
end;
begin
end.

30
TestSuite/interface4.pas Normal file
View file

@ -0,0 +1,30 @@
type
IEnr = System.Collections.IEnumerator;
IEnb = System.Collections.IEnumerable;
var a : integer;
type My = class(IEnumerable<integer>)
public
function IEnb.GetEnumerator(): IEnr;
begin
a := 1;
end;
function System.Collections.Generic.IEnumerable<integer>.GetEnumerator(): IEnumerator<integer>;
begin
a := 2;
end;
end;
begin
var ien: IEnb := new My;
ien.GetEnumerator;
assert(a=1);
var ien2: IEnumerable<integer> := new My;
ien2.GetEnumerator;
assert(a=2);
a := 0;
var mc := new My;
mc.GetEnumerator();
assert(a=2);
end.

View file

@ -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;

View file

@ -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<ICommonTypeNode> left_type_params = null;
List<ICommonTypeNode> right_type_params = null;
if (cleft != null)
{
left_type_params = cleft.generic_params;
}
if (cright != null)
{
right_type_params = cright.generic_params;
}
List<type_node> left_type_params = left.get_generic_params_list();
List<type_node> right_type_params = right.get_generic_params_list();
if (left_type_params == null && right_type_params == null)
{
return true;

View file

@ -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<type_node> instance_params = new List<type_node>();
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;

View file

@ -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}'

View file

@ -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}'