Refactor Typeclasses semantics
This commit is contained in:
parent
cdcf5af995
commit
e0cf9f4a8f
60
TreeConverter/TreeConversion/TypeclassesHelper.cs
Normal file
60
TreeConverter/TreeConversion/TypeclassesHelper.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using PascalABCCompiler.TreeRealization;
|
||||||
|
using PascalABCCompiler.SemanticTree;
|
||||||
|
|
||||||
|
namespace PascalABCCompiler.TreeConverter
|
||||||
|
{
|
||||||
|
public static class TypeclassHelper
|
||||||
|
{
|
||||||
|
public static bool HasRestrictions(function_node fn)
|
||||||
|
{
|
||||||
|
var hasRestriction = fn?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
||||||
|
return hasRestriction.HasValue && hasRestriction.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<type_node> GetRestrictedGenerics(function_node fn)
|
||||||
|
{
|
||||||
|
return fn.get_generic_params_list().Where(x => x.Attributes != null && x.Attributes.Any(attr => attr.AttributeType.name == "__TypeclassGenericParameterAttribute"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsInstance(type_node ctn)
|
||||||
|
{
|
||||||
|
var isInstance = ctn?.attributes?.Any(x => x.AttributeType.name == "__TypeclassInstanceAttribute");
|
||||||
|
return isInstance.HasValue && isInstance.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsTypeclass(type_node ctn)
|
||||||
|
{
|
||||||
|
var isTypeclass = ctn?.attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
||||||
|
return isTypeclass.HasValue && isTypeclass.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string OperatorName(string op)
|
||||||
|
{
|
||||||
|
return "$typeclass" + op;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetInstanceName(type_node ctn)
|
||||||
|
{
|
||||||
|
return ctn?.attributes?.First(x => x.AttributeType.name == "__TypeclassInstanceAttribute")?.Arguments[0]?.value?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetTypeclassName(type_node ctn)
|
||||||
|
{
|
||||||
|
return ctn?.attributes?.First(x => x.AttributeType.name == "__TypeclassAttribute")?.Arguments[0]?.value?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ResugarMethodName(string name)
|
||||||
|
{
|
||||||
|
string newName = name;
|
||||||
|
if(name.StartsWith("$typeclass"))
|
||||||
|
{
|
||||||
|
newName = name.Replace("$typeclass", "operator");
|
||||||
|
}
|
||||||
|
return newName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2731,15 +2731,14 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var testIsInstance = _ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassInstanceAttribute");
|
if (TypeclassHelper.IsInstance(_ctn))
|
||||||
if (testIsInstance is true)
|
|
||||||
{
|
{
|
||||||
if (find_method == null || (find_method.sym_info as function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
if (find_method == null || (find_method.sym_info as function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract)
|
||||||
{
|
{
|
||||||
var instanceName = _ctn.Attributes.First(x => x.AttributeType.name == "__TypeclassInstanceAttribute").Arguments[0].value;
|
var instanceName = TypeclassHelper.GetInstanceName(_ctn);
|
||||||
var typeclassName = _ctn.Attributes.First(x => x.AttributeType.name == "__TypeclassAttribute").Arguments[0].value;
|
var typeclassName = TypeclassHelper.GetTypeclassName(_ctn);
|
||||||
AddError(_ctn.location, "INSTANCE_{0}_DOES_NOT_IMPLEMENT_REQUIREMENT_{1}_OF_TYPECLASS_{2}",
|
AddError(_ctn.location, "INSTANCE_{0}_DOES_NOT_IMPLEMENT_REQUIREMENT_{1}_OF_TYPECLASS_{2}",
|
||||||
instanceName.ToString(), Tools.GetFullMethodHeaderString(meth), typeclassName.ToString());
|
instanceName, TypeclassHelper.ResugarMethodName(Tools.GetFullMethodHeaderString(meth)), typeclassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1085,17 +1085,15 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
AddError(right.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED");
|
AddError(right.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED");
|
||||||
right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right);
|
right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right);
|
||||||
}
|
}
|
||||||
|
|
||||||
// voloshinbogdan Typeclasses 21.05.2018
|
// voloshinbogdan Typeclasses 21.05.2018
|
||||||
var testTopFunctionForTypeclassRestriction = context.func_stack.top()?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
if (TypeclassHelper.HasRestrictions(context.func_stack.top()))
|
||||||
if (testTopFunctionForTypeclassRestriction.HasValue && testTopFunctionForTypeclassRestriction.Value)
|
|
||||||
{
|
{
|
||||||
var func = context.func_stack.top();
|
var func = context.func_stack.top();
|
||||||
var typeclasses = func.generic_params.Where(x => x.Attributes != null && x.Attributes.Any(attr => attr.AttributeType.name == "__TypeclassGenericParameterAttribute"));
|
foreach (var item in TypeclassHelper.GetRestrictedGenerics(func))
|
||||||
foreach (var item in typeclasses)
|
|
||||||
{
|
{
|
||||||
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
|
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
|
||||||
var silTmp = (item as type_node)?.find_in_type("$typeclass" + name, context.CurrentScope);
|
var silTmp = (item as type_node)?.find_in_type(TypeclassHelper.OperatorName(name), context.CurrentScope);
|
||||||
if (silTmp != null)
|
if (silTmp != null)
|
||||||
{
|
{
|
||||||
var dn = new ident((args.First() as string_const_node).constant_value);
|
var dn = new ident((args.First() as string_const_node).constant_value);
|
||||||
|
|
@ -1105,17 +1103,15 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
if (TypeclassHelper.IsTypeclass(context._ctn) && !TypeclassHelper.IsInstance(context._ctn))
|
||||||
var testIsInstance = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassInstanceAttribute");
|
|
||||||
if (testIsTypeclass.HasValue && testIsTypeclass.Value && !(testIsInstance.HasValue && testIsInstance.Value))
|
|
||||||
{
|
{
|
||||||
var type = context._ctn;
|
var type = context._ctn;
|
||||||
|
|
||||||
var silTmp = (type.ImplementingInterfaces[0] as type_node)?.find_in_type("$typeclass" + name, context.CurrentScope);
|
var silTmp = (type.ImplementingInterfaces[0] as type_node)?.find_in_type(TypeclassHelper.OperatorName(name), context.CurrentScope);
|
||||||
if (silTmp != null)
|
if (silTmp != null)
|
||||||
{
|
{
|
||||||
var methodName = convert_strong(new ident("$typeclass" + name));
|
var methodName = convert_strong(new ident(TypeclassHelper.OperatorName(name)));
|
||||||
var thisNode = convert_strong(new ident("self"));
|
var thisNode = convert_strong(new ident("self"));
|
||||||
var exp = convertion_data_and_alghoritms.create_method_call(silTmp[0].sym_info as function_node, null, thisNode, left, right);
|
var exp = convertion_data_and_alghoritms.create_method_call(silTmp[0].sym_info as function_node, null, thisNode, left, right);
|
||||||
|
|
||||||
|
|
@ -3559,8 +3555,7 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
|
|
||||||
public override void visit(SyntaxTree.class_definition _class_definition)
|
public override void visit(SyntaxTree.class_definition _class_definition)
|
||||||
{
|
{
|
||||||
var testIsTypeclassInstance = context._ctn?.Attributes?.Any(a => a.AttributeType.name == "__TypeclassInstanceAttribute");
|
if (TypeclassHelper.IsInstance(context._ctn))
|
||||||
if (testIsTypeclassInstance.HasValue && testIsTypeclassInstance.Value)
|
|
||||||
{
|
{
|
||||||
context.typeclassInstances.Add(context._ctn);
|
context.typeclassInstances.Add(context._ctn);
|
||||||
}
|
}
|
||||||
|
|
@ -5147,12 +5142,10 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
// Typeclasses voloshinbogdan 2018.21.05 - search methods at typeclasses
|
// Typeclasses voloshinbogdan 2018.21.05 - search methods at typeclasses
|
||||||
if (sil == null)
|
if (sil == null)
|
||||||
{
|
{
|
||||||
var testTopFunctionForTypeclassRestriction = context.func_stack.top()?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
if (TypeclassHelper.HasRestrictions(context.func_stack.top()) && sil == null)
|
||||||
if (testTopFunctionForTypeclassRestriction.HasValue && testTopFunctionForTypeclassRestriction.Value && sil == null)
|
|
||||||
{
|
{
|
||||||
var func = context.func_stack.top();
|
var func = context.func_stack.top();
|
||||||
var typeclasses = func.generic_params.Where(x => x.Attributes != null && x.Attributes.Any(attr => attr.AttributeType.name == "__TypeclassGenericParameterAttribute"));
|
foreach (var item in TypeclassHelper.GetRestrictedGenerics(func))
|
||||||
foreach (var item in typeclasses)
|
|
||||||
{
|
{
|
||||||
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
|
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
|
||||||
var silTmp = (item as type_node)?.find_in_type(id.name, context.CurrentScope);
|
var silTmp = (item as type_node)?.find_in_type(id.name, context.CurrentScope);
|
||||||
|
|
@ -13057,8 +13050,8 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
if (context.top_function is common_method_node)
|
if (context.top_function is common_method_node)
|
||||||
{
|
{
|
||||||
common_method_node cmmn = context.top_function as common_method_node;
|
common_method_node cmmn = context.top_function as common_method_node;
|
||||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
var isTypeclass = TypeclassHelper.IsTypeclass(context._ctn);
|
||||||
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && !isTypeclass)
|
||||||
{
|
{
|
||||||
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
||||||
}
|
}
|
||||||
|
|
@ -13103,7 +13096,7 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
if (ptn == cmmn.cont_type)
|
if (ptn == cmmn.cont_type)
|
||||||
has_types = true;
|
has_types = true;
|
||||||
}
|
}
|
||||||
if (!has_types && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
if (!has_types && !isTypeclass)
|
||||||
AddError(new SimpleSemanticError(cmmn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cmmn.cont_type.name));
|
AddError(new SimpleSemanticError(cmmn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cmmn.cont_type.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13741,8 +13734,7 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
first_param = false;
|
first_param = false;
|
||||||
common_method_node cnode = context.top_function as common_method_node;
|
common_method_node cnode = context.top_function as common_method_node;
|
||||||
// Typeclasses voloshinbogdan 2018.05.21
|
// Typeclasses voloshinbogdan 2018.05.21
|
||||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
if (cnode != null && cnode.IsOperator && !TypeclassHelper.IsTypeclass(context._ctn))
|
||||||
if (cnode != null && cnode.IsOperator && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
|
||||||
{
|
{
|
||||||
parameter_list pars = context.top_function.parameters;
|
parameter_list pars = context.top_function.parameters;
|
||||||
if (cnode.name != compiler_string_consts.implicit_operator_name && cnode.name != compiler_string_consts.explicit_operator_name)
|
if (cnode.name != compiler_string_consts.implicit_operator_name && cnode.name != compiler_string_consts.explicit_operator_name)
|
||||||
|
|
@ -16943,11 +16935,8 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
expression_node right = convert_strong(_bin_expr.right);
|
expression_node right = convert_strong(_bin_expr.right);
|
||||||
expression_node res = find_operator(_bin_expr.operation_type, left, right, get_location(_bin_expr));
|
expression_node res = find_operator(_bin_expr.operation_type, left, right, get_location(_bin_expr));
|
||||||
// voloshinbogdan 22.05.2018 Typeclasses
|
// voloshinbogdan 22.05.2018 Typeclasses
|
||||||
var testTopFunctionForTypeclassRestriction = context.func_stack.top()?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
if (TypeclassHelper.HasRestrictions(context.func_stack.top()) ||
|
||||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
TypeclassHelper.IsTypeclass(context._ctn))
|
||||||
if (
|
|
||||||
(testTopFunctionForTypeclassRestriction.HasValue && testTopFunctionForTypeclassRestriction.Value) ||
|
|
||||||
(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
|
||||||
{
|
{
|
||||||
return_value(res);
|
return_value(res);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@
|
||||||
<Compile Include="TreeConversion\syntax_tree_visitor.cs">
|
<Compile Include="TreeConversion\syntax_tree_visitor.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="TreeConversion\TypeclassesHelper.cs" />
|
||||||
<Compile Include="TreeConversion\type_constructor.cs" />
|
<Compile Include="TreeConversion\type_constructor.cs" />
|
||||||
<Compile Include="TreeRealization\attributes.cs" />
|
<Compile Include="TreeRealization\attributes.cs" />
|
||||||
<Compile Include="TreeRealization\events.cs" />
|
<Compile Include="TreeRealization\events.cs" />
|
||||||
|
|
|
||||||
|
|
@ -837,9 +837,8 @@ namespace PascalABCCompiler.TreeRealization
|
||||||
var continue_trying_to_infer_types = true;
|
var continue_trying_to_infer_types = true;
|
||||||
Dictionary<string, delegate_internal_interface> formal_delegates = null;
|
Dictionary<string, delegate_internal_interface> formal_delegates = null;
|
||||||
|
|
||||||
var testIsTypeclassRestricted = func.Attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
var isTypeclassRestricted = TypeclassHelper.HasRestrictions(func);
|
||||||
var isTypeclassRestricted = testIsTypeclassRestricted.HasValue && testIsTypeclassRestricted.Value;
|
var typeclasses = TypeclassHelper.GetRestrictedGenerics(func);
|
||||||
var typeclasses = func.get_generic_params_list().Where(t => t.Attributes != null && t.Attributes.Any(a => a.AttributeType != null && a.AttributeType.name == "__TypeclassGenericParameterAttribute")); // Typeclasses
|
|
||||||
while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
|
while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
|
||||||
{
|
{
|
||||||
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
|
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue