commit
6dc9a7ed1c
Binary file not shown.
|
|
@ -1,11 +1,10 @@
|
|||
type
|
||||
t1=abstract class
|
||||
//!Класс t2 абстрактный и не может иметь атрибут sealed, потому что метод test не реализован
|
||||
type
|
||||
t1 = abstract class
|
||||
procedure test; abstract;
|
||||
end;
|
||||
t2=sealed class(t1)
|
||||
t2 = sealed class(t1)
|
||||
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
end.
|
||||
|
||||
begin end.
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
type
|
||||
//!Предописание I2<T> не может быть использовано в качестве базового типа
|
||||
type
|
||||
I1<T> = interface;
|
||||
I2<T> = interface;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
type
|
||||
t0<T> = class end;
|
||||
|
||||
A = class;
|
||||
B = class(t0<A>)
|
||||
|
||||
end;
|
||||
A = class
|
||||
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
type
|
||||
TErr<T3> = class;
|
||||
|
||||
TDer<T4> = class(List<TErr<T4>>)
|
||||
end;
|
||||
|
||||
TErr<T3> = class end;
|
||||
|
||||
begin
|
||||
|
||||
end.
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
type
|
||||
//!Невозможно инстанцировать, так как тип T не наследован от List<integer>
|
||||
type
|
||||
t1<T> = class
|
||||
where T: List<integer>;
|
||||
|
||||
|
|
|
|||
11
TestSuite/errors/err0512_recursive_inh.pas
Normal file
11
TestSuite/errors/err0512_recursive_inh.pas
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//!Тип 't1<T>' наследует от самого себя
|
||||
type
|
||||
t1<T> = partial class
|
||||
|
||||
end;
|
||||
t2<T> = class(t1<T>) end;
|
||||
t1<T> = partial class(t2<byte>)
|
||||
|
||||
end;
|
||||
|
||||
begin end.
|
||||
32
TestSuite/recursive_where.pas
Normal file
32
TestSuite/recursive_where.pas
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// issue#2725
|
||||
|
||||
type
|
||||
i0 = interface end;
|
||||
|
||||
base_i<TSelf> = interface
|
||||
where TSelf: base_i<TSelf>;
|
||||
function fi(a: TSelf): TSelf;
|
||||
end;
|
||||
|
||||
base_c<TSelf> = abstract class
|
||||
where TSelf: base_c<TSelf>;
|
||||
function fc(a: TSelf): TSelf; abstract;
|
||||
end;
|
||||
|
||||
class1 = class(i0, base_i<class1>)
|
||||
public function fi(a: class1) := a;
|
||||
end;
|
||||
class2 = class(base_c<class2>, base_i<class2>)
|
||||
public function fi(a: class2) := self;
|
||||
public function fc(a: class2): class2; override := self;
|
||||
end;
|
||||
|
||||
record1 = record(i0, base_i<record1>)
|
||||
public function fi(a: record1) := self;
|
||||
end;
|
||||
|
||||
interface1 = interface(i0, base_i<interface1>)
|
||||
|
||||
end;
|
||||
|
||||
begin end.
|
||||
|
|
@ -3058,19 +3058,6 @@ namespace PascalABCCompiler.TreeConverter
|
|||
return null; // это вхолостую
|
||||
}
|
||||
|
||||
public bool ContainsForward(type_node tn)
|
||||
{
|
||||
if (tn.ForwardDeclarationOnly || tn.original_generic != null && tn.original_generic.ForwardDeclarationOnly)
|
||||
return true;
|
||||
if (tn is generic_instance_type_node tni)
|
||||
foreach (var t in tn.instance_params)
|
||||
{
|
||||
var r = ContainsForward(t);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3756,121 +3756,160 @@ namespace PascalABCCompiler.TreeConverter
|
|||
context.converted_type.SetIsSealed(true);
|
||||
context.converted_type.SetIsAbstract(true, null); // Причина null, потому что причины нет, класс статический а не абстрактный
|
||||
}
|
||||
|
||||
common_type_node converted_type;
|
||||
//TODO Выглядит странно - в каком это случае семантический узел записи создаётся с задержкой?
|
||||
if (_class_definition.keyword==PascalABCCompiler.SyntaxTree.class_keyword.Record)
|
||||
{
|
||||
if (_record_created)
|
||||
{
|
||||
_record_created = false;
|
||||
converted_type = context.converted_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
converted_type = context.create_record_type(get_location(_class_definition), record_type_name);
|
||||
if (record_is_generic)
|
||||
{
|
||||
context.create_generic_indicator(converted_type);
|
||||
visit_generic_params(converted_type, _class_definition.template_args.idents);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_class_definition.template_args != null && _class_definition.template_args.idents != null)
|
||||
{
|
||||
AddError(get_location(_class_definition.template_args), "GENERIC_TYPE_NOT_ALLOWED_HERE");
|
||||
}
|
||||
}
|
||||
visit_where_list(_class_definition.where_section);
|
||||
}
|
||||
}
|
||||
else
|
||||
converted_type = context.converted_type;
|
||||
|
||||
// Для записей базовый класс устанавливает на SemanticRules.StructBaseType ещё в context.create_record_type
|
||||
var need_set_base = _class_definition.keyword != PascalABCCompiler.SyntaxTree.class_keyword.Record;
|
||||
if (_class_definition.class_parents != null)
|
||||
{
|
||||
// Ограничение шаблонов предка и интерфейсов нельзя проверять
|
||||
// на первом проходе, когда они не добавлены в converted_type
|
||||
var need_recheck_where = new List<syntax_tree_node>(_class_definition.class_parents.Count);
|
||||
|
||||
// В случае partial классов можно (и желательно) указывать интерфейсы, которые уже были в предыдущем описании
|
||||
// Поэтому проверять нужно только уникальное среди списка интерфейсов в этом описании
|
||||
var curr_def_interfaces = new List<type_node>(need_recheck_where.Capacity);
|
||||
|
||||
// Отключаем проверки where для случая
|
||||
// t1 = ...(t0<t1>)
|
||||
context.skip_check_where_sections = true;
|
||||
for (int i = 0; i < _class_definition.class_parents.Count; i++)
|
||||
{
|
||||
var syntax_tn = _class_definition.class_parents[i];
|
||||
location loc = get_location(syntax_tn);
|
||||
|
||||
var tn = (type_node)ret.visit(syntax_tn);
|
||||
if (tn.is_generic_type_definition || tn.is_generic_type_instance) need_recheck_where.Add(syntax_tn);
|
||||
|
||||
if ((tn.original_generic??tn).ForwardDeclarationOnly)
|
||||
AddError(loc, "FORWARD_DECLARATION_{0}_AS_BASE_TYPE", tn.PrintableName);
|
||||
if (tn.is_generic_parameter)
|
||||
AddError(loc, "CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER");
|
||||
|
||||
for (var curr = tn; curr!=null; curr=curr.base_type)
|
||||
{
|
||||
curr = curr.original_generic ?? curr;
|
||||
if (curr == converted_type)
|
||||
AddError(loc, "TYPE_{0}_INHERITS_SELF", converted_type.PrintableName);
|
||||
}
|
||||
|
||||
// Если первый тип в списке - класс-предок
|
||||
if (i==0 && !tn.IsInterface && _class_definition.keyword==PascalABCCompiler.SyntaxTree.class_keyword.Class)
|
||||
{
|
||||
if (tn.IsSealed)
|
||||
AddError(loc, "PARENT_TYPE_IS_SEALED{0}", tn.PrintableName);
|
||||
if (tn == SystemLibrary.SystemLibrary.value_type)
|
||||
AddError(loc, "CAN_NOT_INHERIT_FROM_VALUE_TYPE");
|
||||
if (tn.IsPointer)
|
||||
AddError(loc, "CAN_NOT_INHERIT_FROM_POINTER");
|
||||
if (tn.IsDelegate)
|
||||
AddError(loc, "CAN_NOT_INHERIT_FROM_FUNCTION_TYPE");
|
||||
if (tn == SystemLibrary.SystemLibrary.delegate_base_type || tn == SystemLibrary.SystemLibrary.system_delegate_type)
|
||||
AddError(loc, "CAN_NOT_INHERIT_FROM_DELEGATE_TYPE");
|
||||
|
||||
converted_type.SetBaseType(tn);
|
||||
need_set_base = false;
|
||||
|
||||
if (tn is common_type_node ctn && ctn.IsPartial)
|
||||
inherited_from_partials_list.Add(converted_type);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// type_table.AddInterface проверяет что tn это интерфейс
|
||||
type_table.AddInterface(converted_type, tn, loc);
|
||||
if (curr_def_interfaces.Contains(tn))
|
||||
AddError(loc, "INTERFACE_{0}_ALREADY_ADDED_TO_IMPLEMENTING_LIST", tn.PrintableName);
|
||||
else
|
||||
curr_def_interfaces.Add(tn);
|
||||
|
||||
}
|
||||
context.skip_check_where_sections = false;
|
||||
|
||||
// Проверяем секции where предка/интерфейсов
|
||||
// В самом конце, когда converted_type
|
||||
// уже содержит всю информацию о предке и интерфейсах
|
||||
foreach (var syntax_tn in need_recheck_where)
|
||||
ret.visit(syntax_tn);
|
||||
|
||||
}
|
||||
|
||||
if (need_set_base)
|
||||
{
|
||||
var bt =
|
||||
(converted_type.IsPartial ? converted_type.base_type : null) ??
|
||||
SemanticRules.ClassBaseType;
|
||||
converted_type.SetBaseType(bt);
|
||||
}
|
||||
|
||||
if (_class_definition.keyword==PascalABCCompiler.SyntaxTree.class_keyword.Class)
|
||||
foreach (generic_type_instance_info gti in generic_convertions.get_type_instances(converted_type))
|
||||
{
|
||||
if (!(gti.pseudo_instance.base_type != null && gti.pseudo_instance.base_type.is_generic_type_instance && converted_type.IsPartial))
|
||||
gti.pseudo_instance.SetBaseType(converted_type.base_type);
|
||||
}
|
||||
|
||||
switch (_class_definition.keyword)
|
||||
{
|
||||
case PascalABCCompiler.SyntaxTree.class_keyword.Class:
|
||||
//if (context.converted_type.IsPartial)
|
||||
// generic_convertions.remove_type_instances(context.converted_type);
|
||||
if (context.converted_type.is_value || context.converted_type.IsInterface)
|
||||
{
|
||||
AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", context.converted_type.name);
|
||||
}
|
||||
if ((_class_definition.class_parents != null) && (_class_definition.class_parents.types.Count > 0))
|
||||
{
|
||||
if (context.converted_type.IsStatic)
|
||||
AddError(get_location(_class_definition), "STATIC_CLASS_CANNOT_HAVE_PARENT");
|
||||
context.skip_check_where_sections = true;
|
||||
type_node tn = ret.visit(_class_definition.class_parents.types[0]);
|
||||
context.skip_check_where_sections = false;
|
||||
//if (tn == context.converted_type)
|
||||
if (type_table.original_types_equals(tn, context.converted_type))
|
||||
AddError(new UndefinedNameReference(tn.name, get_location(_class_definition.class_parents.types[0])));
|
||||
if (tn.IsSealed)
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "PARENT_TYPE_IS_SEALED{0}", tn.name);
|
||||
if (tn == SystemLibrary.SystemLibrary.value_type)
|
||||
{
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_VALUE_TYPE");
|
||||
}
|
||||
if (tn.IsPointer)
|
||||
{
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_POINTER");
|
||||
}
|
||||
if (tn.IsDelegate)
|
||||
{
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_FUNCTION_TYPE");
|
||||
}
|
||||
if (tn == SystemLibrary.SystemLibrary.delegate_base_type || tn == SystemLibrary.SystemLibrary.system_delegate_type)
|
||||
{
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_DELEGATE_TYPE");
|
||||
}
|
||||
Hashtable used_interfs = new Hashtable();
|
||||
if (tn is common_type_node && (tn as common_type_node).IsPartial)
|
||||
inherited_from_partials_list.Add(context.converted_type);
|
||||
//Если tn - это интерфейс
|
||||
if (tn.IsInterface)
|
||||
{
|
||||
//Первым в списке предков идёт интерфейс, поэтому базовым будет object.
|
||||
context.converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||||
//if (converted_type.IsPartial)
|
||||
// generic_convertions.remove_type_instances(converted_type);
|
||||
|
||||
if (converted_type.is_value || converted_type.IsInterface)
|
||||
AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", converted_type.name);
|
||||
converted_type.is_class = true;
|
||||
|
||||
//Добавляем интерфейс
|
||||
used_interfs.Add(tn, tn);
|
||||
type_table.AddInterface(context.converted_type, tn, get_location(_class_definition.class_parents.types[0]));
|
||||
if (tn.is_generic_type_instance)
|
||||
ret.visit(_class_definition.class_parents.types[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (convertion_data_and_alghoritms.ContainsForward(tn)) // SSM 20/05/2020 #2140
|
||||
{
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "FORWARD_DECLARATION_{0}_AS_BASE_TYPE", tn.name);
|
||||
}
|
||||
if (tn.is_generic_parameter)
|
||||
{
|
||||
AddError(get_location(_class_definition.class_parents.types[0]), "CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER");
|
||||
}
|
||||
context.converted_type.SetBaseType(tn);
|
||||
if (tn.is_generic_type_instance)
|
||||
ret.visit(_class_definition.class_parents.types[0]);
|
||||
var type_instances = generic_convertions.get_type_instances(context.converted_type);
|
||||
if (type_instances != null)
|
||||
foreach (generic_type_instance_info gti in type_instances)
|
||||
{
|
||||
if (!(gti.pseudo_instance.base_type != null && gti.pseudo_instance.base_type.is_generic_type_instance && context.converted_type.IsPartial))
|
||||
gti.pseudo_instance.SetBaseType(tn);
|
||||
}
|
||||
}
|
||||
//Теперь добавляем интерфейсы.
|
||||
//Цикл с единицы, т.к. нулевой элемент уже был рассмотрен.
|
||||
VisitAndAddInterfaces(context.converted_type, _class_definition.class_parents.types, 1, used_interfs);
|
||||
//for (int i = 1; i < _class_definition.class_parents.types.Count; i++)
|
||||
//{
|
||||
// type_node interf = ret.visit(_class_definition.class_parents.types[i]);
|
||||
// AddInterface(context.converted_type, interf, get_location(_class_definition.class_parents.types[i]));
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(context.converted_type.IsPartial && context.converted_type.base_type != null && context.converted_type.base_type != SemanticRules.ClassBaseType))
|
||||
context.converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||||
else if (context.converted_type.IsPartial && context.converted_type.base_type != null)
|
||||
context.converted_type.SetBaseType(context.converted_type.base_type);
|
||||
}
|
||||
|
||||
context.converted_type.is_class = true;
|
||||
if (_class_definition.body == null &&
|
||||
(_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0))
|
||||
{
|
||||
if (context.converted_type.ForwardDeclarationOnly)
|
||||
{
|
||||
AddError(new NameRedefinition(context.converted_type.name, context.converted_type.Location, get_location(_class_definition)));
|
||||
}
|
||||
context.types_predefined.Add(context.converted_type);
|
||||
context.converted_type.ForwardDeclarationOnly = true;
|
||||
if (converted_type.ForwardDeclarationOnly)
|
||||
AddError(new NameRedefinition(converted_type.name, converted_type.Location, get_location(_class_definition)));
|
||||
converted_type.ForwardDeclarationOnly = true;
|
||||
|
||||
context.types_predefined.Add(converted_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.converted_type.ForwardDeclarationOnly = false;
|
||||
converted_type.ForwardDeclarationOnly = false;
|
||||
if (_class_definition.body == null)
|
||||
{
|
||||
generate_inherit_constructors();
|
||||
if (!context.converted_type.has_default_constructor)
|
||||
if (!converted_type.has_default_constructor)
|
||||
{
|
||||
generate_default_constructor();
|
||||
}
|
||||
}
|
||||
List<SyntaxTree.ident> names = new List<SyntaxTree.ident>();
|
||||
List<SyntaxTree.type_definition> types = new List<SyntaxTree.type_definition>();
|
||||
if ((_class_definition.IsAutoClass()))
|
||||
|
||||
if (_class_definition.IsAutoClass())
|
||||
{
|
||||
// Если снова возникнет ошибка с предками в автоклассах, то не раскомментировать эти строки, а подумать, как разрешить
|
||||
//if (_class_definition.class_parents!=null)
|
||||
|
|
@ -3888,6 +3927,8 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
}
|
||||
|
||||
List<SyntaxTree.ident> names = new List<SyntaxTree.ident>();
|
||||
List<SyntaxTree.type_definition> types = new List<SyntaxTree.type_definition>();
|
||||
SyntaxTreeBuilder.AddMembersForAutoClass(_class_definition,ref names,ref types);
|
||||
|
||||
//if (names.Select(s => s.name.ToLower()).Distinct().Count() != names.Count)
|
||||
|
|
@ -3928,92 +3969,61 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
}
|
||||
}
|
||||
//if (!SemanticRules.OrderIndependedNames)
|
||||
|
||||
weak_node_test_and_visit(_class_definition.body);
|
||||
|
||||
|
||||
//if (!SemanticRules.OrderIndependedNames)
|
||||
weak_node_test_and_visit(_class_definition.body);
|
||||
}
|
||||
common_type_node converted_type = context.converted_type;
|
||||
context.leave_block();
|
||||
|
||||
// Обязательно после context.leave_block, потому что там неявно-абстрактные методы помечают свой IsAbstract
|
||||
if (converted_type.IsSealed && converted_type.IsAbstract && !converted_type.IsStatic)
|
||||
{
|
||||
if (converted_type.AbstractReason == null)
|
||||
AddError(get_location(_class_definition), "ABSTRACT_CLASS_CANNOT_BE_SEALED");
|
||||
else
|
||||
AddError(get_location(_class_definition), converted_type.AbstractReason.Explanation, converted_type.name, converted_type.AbstractReason.ObjName);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case PascalABCCompiler.SyntaxTree.class_keyword.Record:
|
||||
common_type_node ctn;
|
||||
if (_record_created)
|
||||
{
|
||||
_record_created = false;
|
||||
ctn = context.converted_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctn = context.create_record_type(get_location(_class_definition), record_type_name);
|
||||
if (record_is_generic)
|
||||
{
|
||||
context.create_generic_indicator(ctn);
|
||||
visit_generic_params(ctn, _class_definition.template_args.idents);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_class_definition.template_args != null && _class_definition.template_args.idents != null)
|
||||
{
|
||||
AddError(get_location(_class_definition.template_args), "GENERIC_TYPE_NOT_ALLOWED_HERE");
|
||||
}
|
||||
}
|
||||
visit_where_list(_class_definition.where_section);
|
||||
}
|
||||
|
||||
if (context.CurrentScope is SymbolTable.BlockScope)
|
||||
{
|
||||
AddError(get_location(_class_definition), "RECORD_CANNOT_BE_DECLARED_IN_BLOCK");
|
||||
ctn.internal_is_value = true;
|
||||
converted_type.internal_is_value = true;
|
||||
context.leave_record();
|
||||
return_value(ctn);
|
||||
return_value(converted_type);
|
||||
return;
|
||||
}
|
||||
|
||||
//Добавляем интерфейсы - предки.
|
||||
if (_class_definition.class_parents != null)
|
||||
{
|
||||
VisitAndAddInterfaces(context.converted_type, _class_definition.class_parents.types, 0, new Hashtable());
|
||||
//for (int i = 0; i < _class_definition.class_parents.types.Count; i++)
|
||||
//{
|
||||
// type_node interf = ret.visit(_class_definition.class_parents.types[i]);
|
||||
// AddInterface(context.converted_type, interf, get_location(_class_definition.class_parents.types[i]));
|
||||
//}
|
||||
}
|
||||
CheckWaitedRefTypes(ctn);
|
||||
// "PMyRec = ^MyRec" перед описанием "MyRec"
|
||||
CheckWaitedRefTypes(converted_type);
|
||||
|
||||
record_type_name = null;
|
||||
record_is_generic = false;
|
||||
context.converted_type.internal_is_value = true;
|
||||
converted_type.internal_is_value = true;
|
||||
|
||||
if (_class_definition.body == null &&
|
||||
(_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0))
|
||||
{
|
||||
if (context.converted_type.ForwardDeclarationOnly)
|
||||
{
|
||||
AddError(new NameRedefinition(context.converted_type.name, context.converted_type.Location, get_location(_class_definition)));
|
||||
}
|
||||
context.types_predefined.Add(context.converted_type);
|
||||
context.converted_type.ForwardDeclarationOnly = true;
|
||||
if (converted_type.ForwardDeclarationOnly)
|
||||
AddError(new NameRedefinition(converted_type.name, converted_type.Location, get_location(_class_definition)));
|
||||
context.types_predefined.Add(converted_type);
|
||||
|
||||
converted_type.ForwardDeclarationOnly = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
context.converted_type.ForwardDeclarationOnly = false;
|
||||
converted_type.ForwardDeclarationOnly = false;
|
||||
weak_node_test_and_visit(_class_definition.body);
|
||||
|
||||
|
||||
|
||||
}
|
||||
/*if (_class_definition.body != null)
|
||||
hard_node_test_and_visit(_class_definition.body);
|
||||
else
|
||||
{
|
||||
context.converted_type.ForwardDeclarationOnly = true;
|
||||
converted_type.ForwardDeclarationOnly = true;
|
||||
}*/
|
||||
/*if (_class_definition.body != null)
|
||||
foreach (SyntaxTree.var_def_statement var in (_class_definition.body.class_def_blocks[0].members))
|
||||
|
|
@ -4021,32 +4031,22 @@ namespace PascalABCCompiler.TreeConverter
|
|||
hard_node_test_and_visit(var);
|
||||
}*/
|
||||
context.leave_record();
|
||||
return_value(ctn);
|
||||
return;
|
||||
return_value(converted_type);
|
||||
break;
|
||||
//ssyy owns
|
||||
case PascalABCCompiler.SyntaxTree.class_keyword.Interface:
|
||||
if (context.converted_type.is_value || !context.converted_type.IsInterface)
|
||||
if (converted_type.is_value || !converted_type.IsInterface)
|
||||
{
|
||||
AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", context.converted_type.name);
|
||||
AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", converted_type.name);
|
||||
}
|
||||
if (SemanticRules.GenerateNativeCode)
|
||||
context.converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||||
converted_type.SetBaseType(SemanticRules.ClassBaseType);
|
||||
else
|
||||
context.converted_type.SetBaseType(SystemLibrary.SystemLibrary.object_type);
|
||||
context.converted_type.IsInterface = true;
|
||||
context.converted_type.is_class = true;
|
||||
//Добавляем интерфейсы - предки.
|
||||
if (_class_definition.class_parents != null)
|
||||
{
|
||||
VisitAndAddInterfaces(context.converted_type, _class_definition.class_parents.types, 0, new Hashtable());
|
||||
//for (int i = 0; i < _class_definition.class_parents.types.Count; i++)
|
||||
//{
|
||||
// type_node interf = ret.visit(_class_definition.class_parents.types[i]);
|
||||
// AddInterface(context.converted_type, interf, get_location(_class_definition.class_parents.types[i]));
|
||||
//}
|
||||
}
|
||||
converted_type.SetBaseType(SystemLibrary.SystemLibrary.object_type);
|
||||
converted_type.IsInterface = true;
|
||||
converted_type.is_class = true;
|
||||
|
||||
InitInterfaceScope(context.converted_type);
|
||||
InitInterfaceScope(converted_type);
|
||||
|
||||
//if (_class_definition.body == null)
|
||||
//{
|
||||
|
|
@ -4056,43 +4056,27 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if (_class_definition.body == null &&
|
||||
(_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0))
|
||||
{
|
||||
if (context.converted_type.ForwardDeclarationOnly)
|
||||
if (converted_type.ForwardDeclarationOnly)
|
||||
{
|
||||
AddError(new NameRedefinition(context.converted_type.name, context.converted_type.Location, get_location(_class_definition)));
|
||||
AddError(new NameRedefinition(converted_type.name, converted_type.Location, get_location(_class_definition)));
|
||||
}
|
||||
context.types_predefined.Add(context.converted_type);
|
||||
context.converted_type.ForwardDeclarationOnly = true;
|
||||
context.types_predefined.Add(converted_type);
|
||||
converted_type.ForwardDeclarationOnly = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.converted_type.ForwardDeclarationOnly = false;
|
||||
converted_type.ForwardDeclarationOnly = false;
|
||||
weak_node_test_and_visit(_class_definition.body);
|
||||
}
|
||||
//hard_node_test_and_visit(_class_definition.body);
|
||||
context.leave_block();
|
||||
return;
|
||||
break;
|
||||
//\ssyy owns
|
||||
default:
|
||||
throw new NotSupportedError(get_location(_class_definition));
|
||||
}
|
||||
}
|
||||
|
||||
private void VisitAndAddInterfaces(common_type_node t, List<SyntaxTree.named_type_reference> types, int start, Hashtable used_interfaces)
|
||||
{
|
||||
for (int i = start; i < types.Count; i++)
|
||||
{
|
||||
type_node interf = ret.visit(types[i]);
|
||||
location loc = get_location(types[i]);
|
||||
if (used_interfaces[interf] != null)
|
||||
{
|
||||
AddError(loc, "INTERFACE_{0}_ALREADY_ADDED_TO_IMPLEMENTING_LIST", interf.PrintableName);
|
||||
}
|
||||
used_interfaces.Add(interf, interf);
|
||||
check_cycle_interface_inheritance(t, interf, new List<common_type_node>());
|
||||
type_table.AddInterface(t, interf, loc);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitInterfaceScope(common_type_node ctn)
|
||||
{
|
||||
List<SymbolTable.Scope> interf_scopes = new List<SymbolTable.Scope>(ctn.ImplementingInterfaces.Count);
|
||||
|
|
@ -12782,30 +12766,6 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
}
|
||||
|
||||
private void check_cycle_interface_inheritance(common_type_node cnode, type_node base_of_cnode, List<common_type_node> interfaces)
|
||||
{
|
||||
// Для интерфейсов всё это излишне. Поскольку нельзя использовать предописанные интерфейсы в списке наследования, то
|
||||
// циклически интерфейс может наследовать только от себя. Поэтому достаточно проверять нерекурсивно свой список ImplementingInterfaces и если там есть этот интерфейс, то ошибка
|
||||
if (!cnode.IsInterface)
|
||||
return;
|
||||
interfaces.Add(cnode);
|
||||
common_type_node bt = base_of_cnode as common_type_node;
|
||||
if (bt != null && bt.original_generic != null)
|
||||
bt = bt.original_generic as common_type_node;
|
||||
if (bt != null)
|
||||
{
|
||||
if (interfaces.Contains(bt))
|
||||
{
|
||||
AddError(bt.loc, "TYPE_{0}_DERIVED_FROM_ITSELF", bt.PrintableName);
|
||||
}
|
||||
interfaces.Add(bt);
|
||||
foreach (var tn in bt.ImplementingInterfaces)
|
||||
{
|
||||
check_cycle_interface_inheritance(bt, tn as type_node, interfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void check_where_from_base_class(common_type_node ctn)
|
||||
{
|
||||
if (ctn.base_type != null && ctn.base_type.is_generic_type_instance && ctn.is_generic_type_definition)
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
// tn - не generic параметр - закомментировал
|
||||
if (base_type != tn && !type_table.is_derived(base_type, tn) /*&& !tn.is_generic_parameter*/)
|
||||
{
|
||||
return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.name);
|
||||
return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_BE_DERIVED_FROM_{1}", tn.PrintableName, base_type.PrintableName);
|
||||
}
|
||||
}
|
||||
if (gpe.is_class && !tn.is_class)
|
||||
|
|
@ -186,7 +186,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
(tn.ImplementingInterfaces == null ||
|
||||
!type_table.is_derived(di, tn)))
|
||||
{
|
||||
return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}", tn.PrintableName, di.name);
|
||||
return new SimpleSemanticError(null, "PARAMETER_{0}_MUST_IMPLEMENT_INTERFACE_{1}", tn.PrintableName, di.PrintableName);
|
||||
}
|
||||
}
|
||||
if (tn.IsStatic)
|
||||
|
|
|
|||
|
|
@ -352,16 +352,15 @@ namespace PascalABCCompiler.TreeRealization
|
|||
{
|
||||
throw new TreeConverter.SimpleSemanticError(loc, "FORWARD_DECLARATION_{0}_AS_IMPLEMENTING_INTERFACE", _interface.name);
|
||||
}
|
||||
if (!cnode.ImplementingInterfaces.Contains(_interface))
|
||||
|
||||
if (cnode.ImplementingInterfaces.Contains(_interface))
|
||||
return;
|
||||
cnode.ImplementingInterfaces.Add(_interface);
|
||||
foreach (type_node tn in _interface.ImplementingInterfaces)
|
||||
{
|
||||
cnode.ImplementingInterfaces.Add(_interface);
|
||||
foreach (type_node tn in _interface.ImplementingInterfaces)
|
||||
{
|
||||
if (!cnode.ImplementingInterfaces.Contains(tn))
|
||||
{
|
||||
cnode.ImplementingInterfaces.Add(tn);
|
||||
}
|
||||
}
|
||||
if (cnode.ImplementingInterfaces.Contains(tn))
|
||||
continue;
|
||||
cnode.ImplementingInterfaces.Add(tn);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,8 +139,8 @@ OPERATOR_RETURN_TYPE_UNDEFINED_{0}=Return type of operator {0} is not defined an
|
|||
STRUCT_TYPE_DEFINITION_IN_AUTO_CLASS=Field types in auto classes cannot be record or array definition
|
||||
EXTERNAL_METHOD_SHOULD_BE_STATIC=external-methods should be static
|
||||
ABSTRACT_CLASS_CANNOT_BE_SEALED=Abstract classes can not be sealed
|
||||
ABSTRACT_CLASS_CANNOT_BE_SEALED_BECAUSE_METHOD_NOT_IMPLEMENTED=Class {0} is abstract and connot be sealed, because method {1} not implement
|
||||
ABSTRACT_CLASS_CANNOT_BE_SEALED_BECAUSE_PROPERTIE_NOT_IMPLEMENTED=Class {0} is abstract and connot be sealed, because propertie {1} not implement
|
||||
ABSTRACT_CLASS_CANNOT_BE_SEALED_BECAUSE_METHOD_NOT_IMPLEMENTED=Class {0} is abstract and connot be sealed, because method {1} not implemented
|
||||
ABSTRACT_CLASS_CANNOT_BE_SEALED_BECAUSE_PROPERTIE_NOT_IMPLEMENTED=Class {0} is abstract and connot be sealed, because propertie {1} not implemented
|
||||
ABSTRACT_CLASS_CANNOT_BE_SEALED_BECAUSE_ABSTRACT_PROPERTIE=Class {0} is abstract and connot be sealed, because propertie {1} is abstract
|
||||
EXPRESSION_EXPECTED=Expression expected
|
||||
CLASS_ATTRIBUTE_NOT_ALLOWED_IN_CLASS_PREDEFINTIONS=Can not declare class attributes in class predefintions
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS=Non-generic methods cannot b
|
|||
FUNCTION_{0}_DEPEND_FROM_{1}_TYPE_PARAMS=The number of type parameters in generic subprogramm '{0}' must be {1}
|
||||
WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION=where-section is not valid in this context
|
||||
CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER=Cannot derive from generic parameter
|
||||
TYPE_{0}_INHERITS_SELF=Type '{0}' inherits from itself
|
||||
GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS=Cannot call the generic function '{0}' with these arguments
|
||||
CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}=The type arguments for method '{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly
|
||||
CAN_NOT_CALL_ANY_GENERIC_FUNCTION_{0}_WITH_THESE_PARAMETERS=The best overloaded method match for '{0}' has some invalid arguments
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS=Спецификация п
|
|||
FUNCTION_{0}_DEPEND_FROM_{1}_TYPE_PARAMS=Число типов-параметров в спецификации обобщённой подпрограммы {0} должно быть равно {1}
|
||||
WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION=Секцию where следует указывать только в предописании (предописание найдено)
|
||||
CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER=Нельзя наследовать от generic-параметра
|
||||
TYPE_{0}_INHERITS_SELF=Тип '{0}' наследует от самого себя
|
||||
GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS=Обобщённая функция {0} не может быть вызвана с данным набором фактических параметров
|
||||
CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}=Невозможно вывести типы-параметры обобщённой подпрограммы {0} (укажите типы-параметры явно)
|
||||
CAN_NOT_CALL_ANY_GENERIC_FUNCTION_{0}_WITH_THESE_PARAMETERS=С данным списком формальных параметров невозможно вызвать ни одну из перегруженных generic-подпрограмм {0}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS=Специфікація з
|
|||
FUNCTION_{0}_DEPEND_FROM_{1}_TYPE_PARAMS=Число типів-параметрів у специфікації generic-підпрограми {0} має дорівнювати {1}
|
||||
WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION=Секцію where слід вказувати тільки в передопису (предопис знайдено)
|
||||
CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER=Не можна успадкувати від generic-параметру
|
||||
TYPE_{0}_INHERITS_SELF=Тип '{0}' успадковує від себе
|
||||
GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS=Generic-функція {0} не може бути викликана з даними набором фактичних параметрів
|
||||
CAN_NOT_DEDUCE_TYPE_PARAMS_FROM_CALL_{0}=Неможливо вивести типи-параметри generic-підпрограми {0} (вкажіть типи-параметри явно)
|
||||
CAN_NOT_CALL_ANY_GENERIC_FUNCTION_{0}_WITH_THESE_PARAMETERS=З даним списком формальних параметрів неможливо викликати жодну з перевантажених generic-підпрограм {0}
|
||||
|
|
|
|||
Loading…
Reference in a new issue