Add deducing template type for not inherited typeclasses

This commit is contained in:
Voloshin Bogdan 2018-05-25 00:39:18 +03:00
parent 32b86ece99
commit 9c416f3855
6 changed files with 47 additions and 6 deletions

View file

@ -193,7 +193,7 @@ begin
var l1 := Arr(1,3,5,7,8);
var l2 := Arr(1,3,5,1,8);
writeln(ArrayEq&[integer](l1, l2));
writeln(ArrayEq(l1, l2));
end;
end;
@ -202,8 +202,8 @@ end;
procedure TestShow();
begin
writeln('TestShow');
ShowNTimes&[boolean](false, 2);
ShowNTimes&[boolean](true, 4);
ShowNTimes(false, 2);
ShowNTimes(true, 4);
end;
@ -235,7 +235,7 @@ begin
var res := Arr(a);
Sort(res);
MySort&[integer](a);
MySort(a);
var isCorrect := a.SequenceEqual(res);

View file

@ -109,6 +109,7 @@ namespace SyntaxVisitors.TypeclassVisitors
var instanceDeclTranslated = new type_declaration(typeName, instanceDefTranslated, instanceDeclaration.source_context);
instanceDeclTranslated.attributes = instanceDeclaration.attributes;
AddAttribute(instanceDeclTranslated, "__TypeclassInstanceAttribute");
AddAttribute(instanceDeclTranslated, "__TypeclassAttribute");
Replace(instanceDeclaration, instanceDeclTranslated);

View file

@ -200,6 +200,8 @@ namespace PascalABCCompiler.TreeConverter
internal List<var_definition_node> var_defs =
new List<var_definition_node>();
public List<type_node> typeclassInstances = new List<type_node>();
internal Stack<System.Collections.Generic.List<var_definition_node>> var_defs_stack =
new Stack<System.Collections.Generic.List<var_definition_node>>();
@ -331,6 +333,7 @@ namespace PascalABCCompiler.TreeConverter
in_parameters_block = false;
is_order_independed_method_description = false;
_has_nested_functions = false;
typeclassInstances.Clear();
}
public void clear_type_prededinitions()

View file

@ -3520,6 +3520,12 @@ namespace PascalABCCompiler.TreeConverter
public override void visit(SyntaxTree.class_definition _class_definition)
{
var testIsTypeclassInstance = context._ctn?.Attributes?.Any(a => a.AttributeType.name == "__TypeclassInstanceAttribute");
if (testIsTypeclassInstance.HasValue && testIsTypeclassInstance.Value)
{
context.typeclassInstances.Add(context._ctn);
}
if (_class_definition.attribute != class_attribute.None && _class_definition.body == null)
ErrorsList.Add(new SimpleSemanticError(get_location(_class_definition), "CLASS_ATTRIBUTE_NOT_ALLOWED_IN_CLASS_PREDEFINTIONS"));
if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Sealed) == SyntaxTree.class_attribute.Sealed)
@ -11072,6 +11078,7 @@ namespace PascalABCCompiler.TreeConverter
{
//bool is_template_synonym = false;
//SyntaxTree.array_type at=_type_declaration.type_def as SyntaxTree.array_type;
template_class tc = null;
SyntaxTree.template_type_name ttn = _type_declaration.type_name as SyntaxTree.template_type_name;
SyntaxTree.class_definition cl_def = _type_declaration.type_def as SyntaxTree.class_definition;

View file

@ -836,7 +836,7 @@ namespace PascalABCCompiler.TreeRealization
var testIsTypeclassRestricted = func.Attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
var isTypeclassRestricted = testIsTypeclassRestricted.HasValue && testIsTypeclassRestricted.Value;
var typeclasses = func.get_generic_params_list().Where(t => t.Attributes != null && t.Attributes.Any(a => a.AttributeType != null && a.AttributeType.name == "__TypeclassGenericParameter"));
var typeclasses = func.get_generic_params_list().Where(t => t.Attributes != null && t.Attributes.Any(a => a.AttributeType != null && a.AttributeType.name == "__TypeclassGenericParameterAttribute"));
while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
{
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
@ -922,7 +922,28 @@ namespace PascalABCCompiler.TreeRealization
if (isTypeclassRestricted)
{
//context.CurrentScope.SymbolTable
//func.wh
foreach (var tc in typeclasses)
{
var instances = context.typeclassInstances.Where(ti =>
(ti.ImplementingInterfaces[0] as common_generic_instance_type_node).original_generic ==
(tc.ImplementingInterfaces[0] as common_generic_instance_type_node).original_generic);
var appropriateInstances = instances.Where(ti =>
(ti.ImplementingInterfaces[0] as common_generic_instance_type_node).instance_params.SequenceEqual(
(tc.ImplementingInterfaces[0] as common_generic_instance_type_node).instance_params.Select(ip => deduced[ip.generic_param_index])));
if (appropriateInstances.Count() == 1)
{
var foundInstance = appropriateInstances.First() as common_type_node;
if (foundInstance.generic_params.Count > 0)
{
throw new NotImplementedException("Can't deduce type for typeclass inheritance");
}
deduced[tc.generic_param_index] = appropriateInstances.First();
}
}
//context.typeclassInstances.Where(ti => ti.ImplementingInterfaces[0].)
}
var current_deduce_state = deduced //текущее состояние выведенных типов

View file

@ -2107,6 +2107,15 @@ type
begin
end;
end;
///--
__TypeclassInstanceAttribute = class(Attribute)
public
constructor;
begin
end;
end;
// -----------------------------------------------------
// Internal procedures for PABCRTL.dll
// -----------------------------------------------------