Refactor Typeclasses semantics

This commit is contained in:
Voloshin Bogdan 2019-02-27 02:56:23 +03:00
parent cdcf5af995
commit e0cf9f4a8f
5 changed files with 84 additions and 36 deletions

View 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;
}
}
}

View file

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

View file

@ -1087,15 +1087,13 @@ namespace PascalABCCompiler.TreeConverter
}
// 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);
@ -1106,16 +1104,14 @@ 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;

View file

@ -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" />

View file

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