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 (testIsInstance is true)
|
||||
if (TypeclassHelper.IsInstance(_ctn))
|
||||
{
|
||||
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 typeclassName = _ctn.Attributes.First(x => x.AttributeType.name == "__TypeclassAttribute").Arguments[0].value;
|
||||
var instanceName = TypeclassHelper.GetInstanceName(_ctn);
|
||||
var typeclassName = TypeclassHelper.GetTypeclassName(_ctn);
|
||||
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");
|
||||
right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right);
|
||||
}
|
||||
|
||||
|
||||
// voloshinbogdan Typeclasses 21.05.2018
|
||||
var testTopFunctionForTypeclassRestriction = context.func_stack.top()?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
||||
if (testTopFunctionForTypeclassRestriction.HasValue && testTopFunctionForTypeclassRestriction.Value)
|
||||
if (TypeclassHelper.HasRestrictions(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 typeclasses)
|
||||
foreach (var item in TypeclassHelper.GetRestrictedGenerics(func))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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");
|
||||
var testIsInstance = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassInstanceAttribute");
|
||||
if (testIsTypeclass.HasValue && testIsTypeclass.Value && !(testIsInstance.HasValue && testIsInstance.Value))
|
||||
|
||||
if (TypeclassHelper.IsTypeclass(context._ctn) && !TypeclassHelper.IsInstance(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)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
var testIsTypeclassInstance = context._ctn?.Attributes?.Any(a => a.AttributeType.name == "__TypeclassInstanceAttribute");
|
||||
if (testIsTypeclassInstance.HasValue && testIsTypeclassInstance.Value)
|
||||
if (TypeclassHelper.IsInstance(context._ctn))
|
||||
{
|
||||
context.typeclassInstances.Add(context._ctn);
|
||||
}
|
||||
|
|
@ -5147,12 +5142,10 @@ namespace PascalABCCompiler.TreeConverter
|
|||
// Typeclasses voloshinbogdan 2018.21.05 - search methods at typeclasses
|
||||
if (sil == null)
|
||||
{
|
||||
var testTopFunctionForTypeclassRestriction = context.func_stack.top()?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
||||
if (testTopFunctionForTypeclassRestriction.HasValue && testTopFunctionForTypeclassRestriction.Value && sil == null)
|
||||
if (TypeclassHelper.HasRestrictions(context.func_stack.top()) && sil == null)
|
||||
{
|
||||
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 typeclasses)
|
||||
foreach (var item in TypeclassHelper.GetRestrictedGenerics(func))
|
||||
{
|
||||
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
|
||||
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)
|
||||
{
|
||||
common_method_node cmmn = context.top_function as common_method_node;
|
||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
||||
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
||||
var isTypeclass = TypeclassHelper.IsTypeclass(context._ctn);
|
||||
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && !isTypeclass)
|
||||
{
|
||||
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
|
||||
}
|
||||
|
|
@ -13103,7 +13096,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if (ptn == cmmn.cont_type)
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
@ -13741,8 +13734,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
first_param = false;
|
||||
common_method_node cnode = context.top_function as common_method_node;
|
||||
// Typeclasses voloshinbogdan 2018.05.21
|
||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
||||
if (cnode != null && cnode.IsOperator && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
||||
if (cnode != null && cnode.IsOperator && !TypeclassHelper.IsTypeclass(context._ctn))
|
||||
{
|
||||
parameter_list pars = context.top_function.parameters;
|
||||
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 res = find_operator(_bin_expr.operation_type, left, right, get_location(_bin_expr));
|
||||
// voloshinbogdan 22.05.2018 Typeclasses
|
||||
var testTopFunctionForTypeclassRestriction = context.func_stack.top()?.attributes?.Any(x => x.AttributeType.name == "__TypeclassRestrictedFunctionAttribute");
|
||||
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
|
||||
if (
|
||||
(testTopFunctionForTypeclassRestriction.HasValue && testTopFunctionForTypeclassRestriction.Value) ||
|
||||
(testIsTypeclass.HasValue && testIsTypeclass.Value))
|
||||
if (TypeclassHelper.HasRestrictions(context.func_stack.top()) ||
|
||||
TypeclassHelper.IsTypeclass(context._ctn))
|
||||
{
|
||||
return_value(res);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@
|
|||
<Compile Include="TreeConversion\syntax_tree_visitor.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TreeConversion\TypeclassesHelper.cs" />
|
||||
<Compile Include="TreeConversion\type_constructor.cs" />
|
||||
<Compile Include="TreeRealization\attributes.cs" />
|
||||
<Compile Include="TreeRealization\events.cs" />
|
||||
|
|
|
|||
|
|
@ -837,9 +837,8 @@ namespace PascalABCCompiler.TreeRealization
|
|||
var continue_trying_to_infer_types = true;
|
||||
Dictionary<string, delegate_internal_interface> formal_delegates = null;
|
||||
|
||||
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 == "__TypeclassGenericParameterAttribute")); // Typeclasses
|
||||
var isTypeclassRestricted = TypeclassHelper.HasRestrictions(func);
|
||||
var typeclasses = TypeclassHelper.GetRestrictedGenerics(func);
|
||||
while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
|
||||
{
|
||||
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
|
||||
|
|
|
|||
Loading…
Reference in a new issue