Restore typeclasses

This commit is contained in:
Voloshin Bogdan 2018-12-26 02:06:19 +03:00
parent 32fd1a38b0
commit e53c926d2a
18 changed files with 2737 additions and 219 deletions

View file

@ -2,7 +2,7 @@
// This CSharp output file generated by Gardens Point LEX
// Version: 1.1.3.301
// Machine: DESKTOP-7B4K9VB
// DateTime: 26.12.2018 0:32:41
// DateTime: 26.12.2018 1:39:51
// UserName: Bogdan
// GPLEX input file <ABCPascal.lex>
// GPLEX frame file <embedded resource>

View file

@ -3,9 +3,9 @@
// GPPG error listing for yacc source file <ABCPascal.y>
// ==========================================================================
// Version: 1.3.6
// Machine: DESKTOP-A6LT9RI
// DateTime: 10.11.2018 23:09:24
// UserName: Станислав
// Machine: DESKTOP-7B4K9VB
// DateTime: 26.12.2018 1:31:13
// UserName: Bogdan
// ==========================================================================
@ -35,6 +35,7 @@
%using PascalABCCompiler.ParserTools;
%using PascalABCCompiler.Errors;
%using System.Linq;
%using SyntaxVisitors;
%namespace GPPGParserScanner
@ -44,7 +45,7 @@
%token <ti> tkDirectiveName tkAmpersend tkColon tkDotDot tkPoint tkRoundOpen tkRoundClose tkSemiColon tkSquareOpen tkSquareClose tkQuestion tkQuestionPoint tkDoubleQuestion tkQuestionSquareOpen
%token <ti> tkSizeOf tkTypeOf tkWhere tkArray tkCase tkClass tkAuto tkStatic tkConst tkConstructor tkDestructor tkElse tkExcept tkFile tkFor tkForeach tkFunction tkMatch tkWhen
%token <ti> tkIf tkImplementation tkInherited tkInterface /* tkTypeclass tkInstance */ tkProcedure tkOperator tkProperty tkRaise tkRecord tkSet tkType tkThen tkUses tkVar tkWhile tkWith tkNil
%token <ti> tkIf tkImplementation tkInherited tkInterface tkTypeclass tkInstance tkProcedure tkOperator tkProperty tkRaise tkRecord tkSet tkType tkThen tkUses tkVar tkWhile tkWith tkNil
%token <ti> tkGoto tkOf tkLabel tkLock tkProgram tkEvent tkDefault tkTemplate tkPacked tkExports tkResourceString tkThreadvar tkSealed tkPartial tkTo tkDownto
%token <ti> tkLoop
%token <ti> tkSequence tkYield
@ -88,7 +89,7 @@
%type <stn> exception_handler
%type <stn> exception_handler_list
%type <stn> exception_identifier
%type <stn> typed_const_list1 typed_const_list optional_expr_list elem_list optional_expr_list_with_bracket expr_list const_elem_list1 const_func_expr_list case_label_list const_elem_list optional_const_func_expr_list elem_list1
%type <stn> typed_const_list1 typed_const_list optional_expr_list elem_list optional_expr_list_with_bracket expr_list const_elem_list1 /*const_func_expr_list*/ case_label_list const_elem_list optional_const_func_expr_list elem_list1
%type <stn> enumeration_id expr_l1_list
%type <stn> enumeration_id_list
%type <ex> const_simple_expr term simple_term typed_const typed_const_plus typed_var_init_expression expr expr_with_func_decl_lambda const_expr elem range_expr const_elem array_const factor relop_expr expr_dq expr_l1 expr_l1_func_decl_lambda simple_expr range_term range_factor
@ -104,7 +105,7 @@
%type <id> func_name_ident param_name const_field_name func_name_with_template_args identifier_or_keyword unit_name exception_variable const_name func_meth_name_ident label_name type_decl_identifier template_identifier_with_equal
%type <id> program_param identifier identifier_keyword_operatorname func_class_name_ident /*optional_identifier*/ visibility_specifier
%type <id> property_specifier_directives non_reserved
//%type <id> typeclass_restriction
%type <id> typeclass_restriction
%type <stn> if_stmt
%type <stn> initialization_part
%type <stn> template_arguments label_list ident_or_keyword_pointseparator_list ident_list param_name_list
@ -166,7 +167,7 @@
%type <ex> typeof_expr
%type <stn> simple_fp_sect
%type <stn> template_param_list template_empty_param_list template_type_params template_type_empty_params
//%type <stn> template_type_or_typeclass_params typeclass_params
%type <stn> template_type_or_typeclass_params typeclass_params
%type <td> template_type
%type <stn> try_stmt
%type <stn> uses_clause used_units_list
@ -174,7 +175,7 @@
%type <stn> used_unit_name
%type <stn> unit_header
%type <stn> var_decl_sect
%type <stn> var_decl var_decl_part /*var_decl_internal*/ field_definition
%type <stn> var_decl var_decl_part /*var_decl_internal*/ field_definition var_decl_with_assign_var_tuple
%type <stn> var_stmt
%type <stn> where_part
%type <stn> where_part_list optional_where_section
@ -183,14 +184,12 @@
%type <ex> variable_as_type dotted_identifier
%type <ex> func_decl_lambda expl_func_decl_lambda
%type <td> lambda_type_ref lambda_type_ref_noproctype
%type <stn> full_lambda_fp_list lambda_simple_fp_sect lambda_function_body lambda_procedure_body optional_full_lambda_fp_list
%type <stn> full_lambda_fp_list lambda_simple_fp_sect lambda_function_body lambda_procedure_body common_lambda_body optional_full_lambda_fp_list
%type <ob> field_in_unnamed_object list_fields_in_unnamed_object func_class_name_ident_list rem_lambda variable_list var_ident_list
%type <ti> tkAssignOrEqual
%type <stn> pattern pattern_optional_var match_with pattern_case pattern_cases pattern_out_param pattern_out_param_optional_var
%type <ob> pattern_out_param_list pattern_out_param_list_optional_var
%%
// Warning: NonTerminal symbol "const_func_expr_list" is unreachable
// -----------------------------------------------------------------
parse_goal
: program_file
@ -666,26 +665,39 @@ type_decl_sect
}
;
var_decl_with_assign_var_tuple
: var_decl
{
$$ = $1;
}
| tkRoundOpen identifier tkComma ident_list tkRoundClose tkAssign expr_l1 tkSemiColon
{
($4 as ident_list).Insert(0,$2);
$4.source_context = LexLocation.MergeAll(@1,@2,@3,@4,@5);
$$ = new var_tuple_def_statement($4 as ident_list, $7, @$);
}
;
var_decl_sect
: tkVar var_decl
: tkVar var_decl_with_assign_var_tuple
{
$$ = new variable_definitions($2 as var_def_statement, @$);
}
| tkEvent var_decl
| tkEvent var_decl_with_assign_var_tuple
{
$$ = new variable_definitions($2 as var_def_statement, @$);
($2 as var_def_statement).is_event = true;
}
| var_decl_sect var_decl
| var_decl_sect var_decl_with_assign_var_tuple
{
$$ = ($1 as variable_definitions).Add($2 as var_def_statement, @$);
}
| tkVar tkRoundOpen identifier tkComma ident_list tkRoundClose tkAssign expr_l1 tkSemiColon
/*| tkVar tkRoundOpen identifier tkComma ident_list tkRoundClose tkAssign expr_l1 tkSemiColon
{
($5 as ident_list).Insert(0,$3);
$5.source_context = LexLocation.MergeAll(@1,@2,@3,@4,@5,@6);
$$ = new assign_var_tuple($5 as ident_list, $8, @$);
}
}*/
;
const_decl
@ -921,7 +933,7 @@ const_variable
{
$$ = NewConstVariable($1, $2, @$);
}
| const_variable tkAmpersend template_type_params
| const_variable tkAmpersend template_type_or_typeclass_params
{
$$ = new ident_with_templateparams($1 as addressed_value, $3 as template_param_list, @$);
}
@ -966,7 +978,7 @@ optional_const_func_expr_list
{ $$ = null; }
;
const_func_expr_list
/*const_func_expr_list
: const_expr
{
$$ = new expression_list($1, @$);
@ -975,7 +987,7 @@ const_func_expr_list
{
$$ = ($1 as expression_list).Add($3, @$);
}
;
;*/
const_elem_list
: const_elem_list1
@ -1146,17 +1158,19 @@ simple_type_decl
| template_identifier_with_equal type_decl_type tkSemiColon
{
$$ = new type_declaration($1, $2, @$);
}/*
}
| typeclass_restriction tkEqual tkTypeclass optional_base_classes optional_component_list_seq_end tkSemiColon
{
s {
// Error: Syntax error, unexpected anchoredSymbol
// ----------------------------------------------
$$ = new type_declaration($1 as typeclass_restriction, new typeclass_definition($4 as named_type_reference_list, $5 as class_body_list, @$), @$);
}
| typeclass_restriction tkEqual tkInstance optional_component_list_seq_end tkSemiColon
{
$$ = new type_declaration($1 as typeclass_restriction, new instance_definition($4 as class_body_list, @$), @$);
}*/
}
;
/*
typeclass_restriction
: simple_type_identifier typeclass_params
{
@ -1180,7 +1194,7 @@ template_type_or_typeclass_params
{
$$ = $1;
}
;*/
;
type_decl_identifier
: identifier
@ -1563,108 +1577,31 @@ proc_type_decl
object_type
: class_attributes class_or_interface_keyword optional_base_classes optional_where_section optional_component_list_seq_end
{
$$ = NewObjectType((class_attribute)$1, $2, $3 as named_type_reference_list, $4 as where_definition_list, $5 as class_body_list, @$);
class_definition cd = $$ as class_definition;
if (cd == null || cd.body == null)
break;
var ccnt = cd.body.DescendantNodes().OfType<simple_property>().ToArray();
var cm = new class_members(access_modifer.private_modifer);
foreach (var prop in ccnt)
var cd = NewObjectType((class_attribute)$1, $2, $3 as named_type_reference_list, $4 as where_definition_list, $5 as class_body_list, @$);
$$ = cd;
var tt = cd.DescendantNodes().OfType<class_definition>().Where(cld => cld.keyword == class_keyword.Record);
if (tt.Count()>0)
{
var td = prop.property_type;
var ra = prop.accessors?.read_accessor;
if ($2.text.ToLower() == "interface" && ra != null && (ra.pr != null || ra.accessor_name != null))
parsertools.AddErrorFromResource("INVALID_INTERFACE_MEMBER",ra.source_context);
if (ra != null && ra.pr != null)
foreach (var ttt in tt)
{
if (prop.parameter_list != null)
parsertools.AddErrorFromResource("EXTENDED_INDEXED_PROPERTIES",ra.source_context);
var rapr = ra.pr as procedure_definition;
(rapr.proc_header as function_header).return_type = td;
cm.Add(rapr);
if (prop.attr == definition_attribute.Static)
{
rapr.proc_header.class_keyword = true;
procedure_attribute pa = new procedure_attribute(proc_attribute.attr_static);
pa.source_context = rapr.proc_header.source_context;
rapr.proc_header.proc_attributes = new procedure_attributes_list(pa);
}
}
var wa = prop.accessors?.write_accessor;
if ($2.text.ToLower() == "interface" && wa != null && (wa.pr != null || wa.accessor_name != null))
parsertools.AddErrorFromResource("INVALID_INTERFACE_MEMBER",wa.source_context);
if (wa != null && wa.pr != null)
{
if (prop.parameter_list != null)
parsertools.AddErrorFromResource("EXTENDED_INDEXED_PROPERTIES",ra.source_context);
var wapr = wa.pr as procedure_definition;
wapr.proc_header.parameters.params_list[0].vars_type = td;
cm.Add(wapr);
if (prop.attr == definition_attribute.Static)
{
wapr.proc_header.class_keyword = true;
procedure_attribute pa = new procedure_attribute(proc_attribute.attr_static);
pa.source_context = wapr.proc_header.source_context;
wapr.proc_header.proc_attributes = new procedure_attributes_list(pa);
}
var sc = ttt.source_context;
parsertools.AddErrorFromResource("NESTED_RECORD_DEFINITIONS_ARE_FORBIDDEN", new LexLocation(sc.begin_position.line_num, sc.begin_position.column_num-1, sc.end_position.line_num, sc.end_position.column_num, sc.FileName));
}
}
if (cm.Count>0)
cd.body.Insert(0, cm);
}
;
record_type
: tkRecord optional_base_classes optional_where_section member_list_section tkEnd
{
$$ = NewRecordType($2 as named_type_reference_list, $3 as where_definition_list, $4 as class_body_list, @$);
class_definition cd = $$ as class_definition;
if (cd == null || cd.body == null)
break;
var ccnt = cd.body.DescendantNodes().OfType<simple_property>().ToArray();
var cm = new class_members(access_modifer.private_modifer);
foreach (var prop in ccnt)
{
var td = prop.property_type;
var ra = prop.accessors?.read_accessor;
if (ra != null && ra.pr != null)
{
if (prop.parameter_list != null)
parsertools.AddErrorFromResource("EXTENDED_INDEXED_PROPERTIES",ra.source_context);
var rapr = ra.pr as procedure_definition;
(rapr.proc_header as function_header).return_type = td;
cm.Add(rapr);
if (prop.attr == definition_attribute.Static)
{
rapr.proc_header.class_keyword = true;
procedure_attribute pa = new procedure_attribute(proc_attribute.attr_static);
pa.source_context = rapr.proc_header.source_context;
rapr.proc_header.proc_attributes = new procedure_attributes_list(pa);
}
}
var wa = prop.accessors?.write_accessor;
if (wa != null && wa.pr != null && prop.parameter_list == null)
{
if (prop.parameter_list != null)
parsertools.AddErrorFromResource("EXTENDED_INDEXED_PROPERTIES",ra.source_context);
var wapr = wa.pr as procedure_definition;
wapr.proc_header.parameters.params_list[0].vars_type = td;
cm.Add(wapr);
if (prop.attr == definition_attribute.Static)
{
wapr.proc_header.class_keyword = true;
procedure_attribute pa = new procedure_attribute(proc_attribute.attr_static);
pa.source_context = wapr.proc_header.source_context;
wapr.proc_header.proc_attributes = new procedure_attributes_list(pa);
}
}
}
if (cm.Count>0)
cd.body.Insert(0, cm);
var nnrt = new class_definition($2 as named_type_reference_list, $4 as class_body_list, class_keyword.Record, null, $3 as where_definition_list, class_attribute.None, false, @$);
if (/*nnrt.body!=null && nnrt.body.class_def_blocks!=null &&
nnrt.body.class_def_blocks.Count>0 &&*/
nnrt.body.class_def_blocks[0].access_mod==null)
{
nnrt.body.class_def_blocks[0].access_mod = new access_modifer_node(access_modifer.public_modifer);
}
$$ = nnrt;
}
;
@ -1760,12 +1697,12 @@ base_class_name
: simple_type_identifier
{ $$ = $1; }
| template_type
{ $$ = $1; }/*
{ $$ = $1; }
| typeclass_restriction
{
var names = new List<ident>();
names.Add(($1 as typeclass_restriction).name);
$$ = new typeclass_reference(null, names, ($1 as typeclass_restriction).restriction_args); }*/
$$ = new typeclass_reference(null, names, ($1 as typeclass_restriction).restriction_args); }
;
template_arguments
@ -1798,11 +1735,11 @@ where_part
: tkWhere ident_list tkColon type_ref_and_secific_list tkSemiColon
{
$$ = new where_definition($2 as ident_list, $4 as where_type_specificator_list, @$);
}/*
}
| tkWhere typeclass_restriction tkSemiColon
{
$$ = new where_typeclass_constraint($2 as typeclass_restriction);
}*/
}
;
type_ref_and_secific_list
@ -2080,12 +2017,23 @@ simple_property_definition
{
parsertools.AddErrorFromResource("STATIC_PROPERTIES_CANNOT_HAVE_ATTRBUTE_{0}",@7,$7.name);
}
| tkAuto tkProperty qualified_identifier property_interface tkSemiColon
{
$$ = NewSimplePropertyDefinition($3 as method_name, $4 as property_interface, null, proc_attribute.attr_none, null, @$);
($$ as simple_property).is_auto = true;
}
| class_or_static tkAuto tkProperty qualified_identifier property_interface tkSemiColon
{
$$ = NewSimplePropertyDefinition($4 as method_name, $5 as property_interface, null, proc_attribute.attr_none, null, @$);
($$ as simple_property).is_auto = true;
($$ as simple_property).attr = definition_attribute.Static;
}
;
array_defaultproperty
:
{ $$ = null; }
| tkDefault tkSemiColon
| tkDefault tkSemiColon
{
$$ = new property_array_default();
$$.source_context = @$;
@ -2182,7 +2130,9 @@ property_specifiers
procedure_definition pr = null;
if (!parsertools.build_tree_for_formatter)
pr = CreateAndAddToClassWriteProc($2 as statement,id,@2);
$$ = NewPropertySpecifiersWrite($1, id, pr, $2 as statement, $3 as property_accessors, @$); // $2 ïåðåäà¸òñÿ äëÿ ôîðìàòèðîâàíèÿ
if (parsertools.build_tree_for_formatter)
$$ = NewPropertySpecifiersWrite($1, id, pr, $2 as statement, $3 as property_accessors, @$); // $2 ïåðåäà¸òñÿ äëÿ ôîðìàòèðîâàíèÿ
else $$ = NewPropertySpecifiersWrite($1, id, pr, null, $3 as property_accessors, @$);
}
}
;
@ -2205,7 +2155,9 @@ write_property_specifiers
procedure_definition pr = null;
if (!parsertools.build_tree_for_formatter)
pr = CreateAndAddToClassWriteProc($2 as statement,id,@2);
$$ = NewPropertySpecifiersWrite($1, id, pr, $2 as statement, null, @$);
if (parsertools.build_tree_for_formatter)
$$ = NewPropertySpecifiersWrite($1, id, pr, $2 as statement, null, @$);
else $$ = NewPropertySpecifiersWrite($1, id, pr, null, null, @$);
}
}
;
@ -2267,12 +2219,6 @@ var_decl_part
{
$$ = new var_def_statement($1 as ident_list, $3, $5, definition_attribute.None, false, @$);
}
/*| tkRoundOpen identifier tkComma ident_list tkRoundClose tkAssign expr_l1
{
($4 as ident_list).Insert(0,$2);
$4.source_context = LexLocation.MergeAll(@1,@2,@3,@4,@5,@6);
$$ = new assign_var_tuple($4 as ident_list, $7, @$);
}*/
;
typed_var_init_expression
@ -3261,7 +3207,7 @@ simple_or_template_type_reference
{
$$ = new template_type_reference((named_type_reference)$1, (template_param_list)$2, @$);
}
| simple_type_identifier tkAmpersend template_type_params
| simple_type_identifier tkAmpersend template_type_or_typeclass_params
{
$$ = new template_type_reference((named_type_reference)$1, (template_param_list)$3, @$);
}
@ -3867,7 +3813,7 @@ variable
{
$$ = new roof_dereference($1 as addressed_value,@$);
}
| variable tkAmpersend template_type_params
| variable tkAmpersend template_type_or_typeclass_params
{
$$ = new ident_with_templateparams($1 as addressed_value, $3 as template_param_list, @$);
}
@ -4211,9 +4157,9 @@ keyword
| tkMatch
{ $$ = $1; }
| tkWhen
{ $$ = $1; }/*
{ $$ = $1; }
| tkInstance
{ $$ = $1; }*/
{ $$ = $1; }
;
reserved_keyword
@ -4482,15 +4428,8 @@ lambda_type_ref_noproctype
}
;
lambda_function_body
: expr_l1
{
//$$ = NewLambdaBody($1, @$);
var sl = new statement_list(new assign("result",$1,@$),@$); // íàäî ïîìå÷àòü åù¸ è assign êàê àâòîñãåíåðèðîâàííûé äëÿ ëÿìáäû
sl.expr_lambda_body = true;
$$ = sl;
}
| compound_stmt
common_lambda_body
: compound_stmt
{
$$ = $1;
}
@ -4514,6 +4453,10 @@ lambda_function_body
{
$$ = new statement_list($1 as statement, @$);
}
| loop_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| case_stmt
{
$$ = new statement_list($1 as statement, @$);
@ -4534,6 +4477,25 @@ lambda_function_body
{
$$ = new statement_list($1 as statement, @$);
}
;
lambda_function_body
: expr_l1
{
var id = SyntaxVisitors.ExprHasNameVisitor.HasName($1, "Result");
if (id != null)
{
parsertools.AddErrorFromResource("RESULT_IDENT_NOT_EXPECTED_IN_THIS_CONTEXT", id.source_context);
}
var sl = new statement_list(new assign("result",$1,@$),@$); // íàäî ïîìå÷àòü åù¸ è assign êàê àâòîñãåíåðèðîâàííûé äëÿ ëÿìáäû - ÷òîáû çàïðåòèòü ÿâíûé Result
sl.expr_lambda_body = true;
$$ = sl;
}
| common_lambda_body
{
$$ = $1;
}
;
lambda_procedure_body
@ -4541,54 +4503,14 @@ lambda_procedure_body
{
$$ = new statement_list($1 as statement, @$);
}
| compound_stmt
{
$$ = $1;
}
| if_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| while_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| repeat_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| for_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| foreach_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| case_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| try_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| lock_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| yield_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| raise_stmt
{
$$ = new statement_list($1 as statement, @$);
}
| assignment
{
$$ = new statement_list($1 as statement, @$);
}
| common_lambda_body
{
$$ = $1;
}
;
%%// ==========================================================================

View file

@ -2,7 +2,7 @@
// GPPG version 1.3.6
// Machine: DESKTOP-7B4K9VB
// DateTime: 26.12.2018 0:32:42
// DateTime: 26.12.2018 1:39:52
// UserName: Bogdan
// Input file <ABCPascal.y>

View file

@ -1118,6 +1118,36 @@ namespace PascalABCCompiler.SyntaxTree
DefaultVisit(_double_question_node);
}
public virtual void visit(typeclass_restriction _typeclass_restriction)
{
DefaultVisit(_typeclass_restriction);
}
public virtual void visit(instance_definition _instance_definition)
{
DefaultVisit(_instance_definition);
}
public virtual void visit(typeclass_definition _typeclass_definition)
{
DefaultVisit(_typeclass_definition);
}
public virtual void visit(where_typeclass_constraint _where_typeclass_constraint)
{
DefaultVisit(_where_typeclass_constraint);
}
public virtual void visit(typeclass_param_list _typeclass_param_list)
{
DefaultVisit(_typeclass_param_list);
}
public virtual void visit(typeclass_reference _typeclass_reference)
{
DefaultVisit(_typeclass_reference);
}
public virtual void visit(pattern_node _pattern_node)
{
DefaultVisit(_pattern_node);

View file

@ -1781,6 +1781,54 @@ namespace PascalABCCompiler.SyntaxTree
{
}
public virtual void pre_do_visit(typeclass_restriction _typeclass_restriction)
{
}
public virtual void post_do_visit(typeclass_restriction _typeclass_restriction)
{
}
public virtual void pre_do_visit(instance_definition _instance_definition)
{
}
public virtual void post_do_visit(instance_definition _instance_definition)
{
}
public virtual void pre_do_visit(typeclass_definition _typeclass_definition)
{
}
public virtual void post_do_visit(typeclass_definition _typeclass_definition)
{
}
public virtual void pre_do_visit(where_typeclass_constraint _where_typeclass_constraint)
{
}
public virtual void post_do_visit(where_typeclass_constraint _where_typeclass_constraint)
{
}
public virtual void pre_do_visit(typeclass_param_list _typeclass_param_list)
{
}
public virtual void post_do_visit(typeclass_param_list _typeclass_param_list)
{
}
public virtual void pre_do_visit(typeclass_reference _typeclass_reference)
{
}
public virtual void post_do_visit(typeclass_reference _typeclass_reference)
{
}
public virtual void pre_do_visit(pattern_node _pattern_node)
{
}
@ -3800,6 +3848,54 @@ namespace PascalABCCompiler.SyntaxTree
post_do_visit(_double_question_node);
}
public override void visit(typeclass_restriction _typeclass_restriction)
{
DefaultVisit(_typeclass_restriction);
pre_do_visit(_typeclass_restriction);
visit(typeclass_restriction.restriction_args);
post_do_visit(_typeclass_restriction);
}
public override void visit(instance_definition _instance_definition)
{
DefaultVisit(_instance_definition);
pre_do_visit(_instance_definition);
visit(instance_definition.body);
post_do_visit(_instance_definition);
}
public override void visit(typeclass_definition _typeclass_definition)
{
DefaultVisit(_typeclass_definition);
pre_do_visit(_typeclass_definition);
visit(typeclass_definition.additional_restrictions);
visit(typeclass_definition.body);
post_do_visit(_typeclass_definition);
}
public override void visit(where_typeclass_constraint _where_typeclass_constraint)
{
DefaultVisit(_where_typeclass_constraint);
pre_do_visit(_where_typeclass_constraint);
visit(where_typeclass_constraint.restriction);
post_do_visit(_where_typeclass_constraint);
}
public override void visit(typeclass_param_list _typeclass_param_list)
{
DefaultVisit(_typeclass_param_list);
pre_do_visit(_typeclass_param_list);
post_do_visit(_typeclass_param_list);
}
public override void visit(typeclass_reference _typeclass_reference)
{
DefaultVisit(_typeclass_reference);
pre_do_visit(_typeclass_reference);
visit(typeclass_reference.restriction_args);
post_do_visit(_typeclass_reference);
}
public override void visit(pattern_node _pattern_node)
{
DefaultVisit(_pattern_node);

View file

@ -465,32 +465,44 @@ namespace PascalABCCompiler.SyntaxTree
case 221:
return new double_question_node();
case 222:
return new pattern_node();
return new typeclass_restriction();
case 223:
return new type_pattern();
return new instance_definition();
case 224:
return new is_pattern_expr();
return new typeclass_definition();
case 225:
return new match_with();
return new where_typeclass_constraint();
case 226:
return new pattern_case();
return new typeclass_param_list();
case 227:
return new pattern_cases();
return new typeclass_reference();
case 228:
return new deconstructor_pattern();
return new pattern_node();
case 229:
return new pattern_deconstructor_parameter();
return new type_pattern();
case 230:
return new desugared_deconstruction();
return new is_pattern_expr();
case 231:
return new var_deconstructor_parameter();
return new match_with();
case 232:
return new recursive_deconstructor_parameter();
return new pattern_case();
case 233:
return new deconstruction_variables_definition();
return new pattern_cases();
case 234:
return new var_tuple_def_statement();
return new deconstructor_pattern();
case 235:
return new pattern_deconstructor_parameter();
case 236:
return new desugared_deconstruction();
case 237:
return new var_deconstructor_parameter();
case 238:
return new recursive_deconstructor_parameter();
case 239:
return new deconstruction_variables_definition();
case 240:
return new var_tuple_def_statement();
case 241:
return new semantic_check_sugared_var_def_statement_node();
}
return null;
@ -3955,6 +3967,78 @@ namespace PascalABCCompiler.SyntaxTree
}
public void visit(typeclass_restriction _typeclass_restriction)
{
read_typeclass_restriction(_typeclass_restriction);
}
public void read_typeclass_restriction(typeclass_restriction _typeclass_restriction)
{
read_ident(_typeclass_restriction);
_typeclass_restriction.restriction_args = _read_node() as template_param_list;
}
public void visit(instance_definition _instance_definition)
{
read_instance_definition(_instance_definition);
}
public void read_instance_definition(instance_definition _instance_definition)
{
read_type_definition(_instance_definition);
_instance_definition.body = _read_node() as class_body_list;
}
public void visit(typeclass_definition _typeclass_definition)
{
read_typeclass_definition(_typeclass_definition);
}
public void read_typeclass_definition(typeclass_definition _typeclass_definition)
{
read_type_definition(_typeclass_definition);
_typeclass_definition.additional_restrictions = _read_node() as named_type_reference_list;
_typeclass_definition.body = _read_node() as class_body_list;
}
public void visit(where_typeclass_constraint _where_typeclass_constraint)
{
read_where_typeclass_constraint(_where_typeclass_constraint);
}
public void read_where_typeclass_constraint(where_typeclass_constraint _where_typeclass_constraint)
{
read_where_definition(_where_typeclass_constraint);
_where_typeclass_constraint.restriction = _read_node() as typeclass_restriction;
}
public void visit(typeclass_param_list _typeclass_param_list)
{
read_typeclass_param_list(_typeclass_param_list);
}
public void read_typeclass_param_list(typeclass_param_list _typeclass_param_list)
{
read_template_param_list(_typeclass_param_list);
}
public void visit(typeclass_reference _typeclass_reference)
{
read_typeclass_reference(_typeclass_reference);
}
public void read_typeclass_reference(typeclass_reference _typeclass_reference)
{
read_named_type_reference(_typeclass_reference);
_typeclass_reference.restriction_args = _read_node() as template_param_list;
}
public void visit(pattern_node _pattern_node)
{
read_pattern_node(_pattern_node);

View file

@ -6178,9 +6178,135 @@ namespace PascalABCCompiler.SyntaxTree
}
public void visit(pattern_node _pattern_node)
public void visit(typeclass_restriction _typeclass_restriction)
{
bw.Write((Int16)222);
write_typeclass_restriction(_typeclass_restriction);
}
public void write_typeclass_restriction(typeclass_restriction _typeclass_restriction)
{
write_ident(_typeclass_restriction);
if (_typeclass_restriction.restriction_args == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_typeclass_restriction.restriction_args.visit(this);
}
}
public void visit(instance_definition _instance_definition)
{
bw.Write((Int16)223);
write_instance_definition(_instance_definition);
}
public void write_instance_definition(instance_definition _instance_definition)
{
write_type_definition(_instance_definition);
if (_instance_definition.body == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_instance_definition.body.visit(this);
}
}
public void visit(typeclass_definition _typeclass_definition)
{
bw.Write((Int16)224);
write_typeclass_definition(_typeclass_definition);
}
public void write_typeclass_definition(typeclass_definition _typeclass_definition)
{
write_type_definition(_typeclass_definition);
if (_typeclass_definition.additional_restrictions == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_typeclass_definition.additional_restrictions.visit(this);
}
if (_typeclass_definition.body == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_typeclass_definition.body.visit(this);
}
}
public void visit(where_typeclass_constraint _where_typeclass_constraint)
{
bw.Write((Int16)225);
write_where_typeclass_constraint(_where_typeclass_constraint);
}
public void write_where_typeclass_constraint(where_typeclass_constraint _where_typeclass_constraint)
{
write_where_definition(_where_typeclass_constraint);
if (_where_typeclass_constraint.restriction == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_where_typeclass_constraint.restriction.visit(this);
}
}
public void visit(typeclass_param_list _typeclass_param_list)
{
bw.Write((Int16)226);
write_typeclass_param_list(_typeclass_param_list);
}
public void write_typeclass_param_list(typeclass_param_list _typeclass_param_list)
{
write_template_param_list(_typeclass_param_list);
}
public void visit(typeclass_reference _typeclass_reference)
{
bw.Write((Int16)227);
write_typeclass_reference(_typeclass_reference);
}
public void write_typeclass_reference(typeclass_reference _typeclass_reference)
{
write_named_type_reference(_typeclass_reference);
if (_typeclass_reference.restriction_args == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_typeclass_reference.restriction_args.visit(this);
}
}
public void visit(pattern_node _pattern_node)
{
bw.Write((Int16)228);
write_pattern_node(_pattern_node);
}
@ -6192,7 +6318,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(type_pattern _type_pattern)
{
bw.Write((Int16)223);
bw.Write((Int16)229);
write_type_pattern(_type_pattern);
}
@ -6222,7 +6348,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(is_pattern_expr _is_pattern_expr)
{
bw.Write((Int16)224);
bw.Write((Int16)230);
write_is_pattern_expr(_is_pattern_expr);
}
@ -6252,7 +6378,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(match_with _match_with)
{
bw.Write((Int16)225);
bw.Write((Int16)231);
write_match_with(_match_with);
}
@ -6291,7 +6417,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(pattern_case _pattern_case)
{
bw.Write((Int16)226);
bw.Write((Int16)232);
write_pattern_case(_pattern_case);
}
@ -6330,7 +6456,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(pattern_cases _pattern_cases)
{
bw.Write((Int16)227);
bw.Write((Int16)233);
write_pattern_cases(_pattern_cases);
}
@ -6363,7 +6489,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(deconstructor_pattern _deconstructor_pattern)
{
bw.Write((Int16)228);
bw.Write((Int16)234);
write_deconstructor_pattern(_deconstructor_pattern);
}
@ -6405,7 +6531,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
{
bw.Write((Int16)229);
bw.Write((Int16)235);
write_pattern_deconstructor_parameter(_pattern_deconstructor_parameter);
}
@ -6417,7 +6543,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(desugared_deconstruction _desugared_deconstruction)
{
bw.Write((Int16)230);
bw.Write((Int16)236);
write_desugared_deconstruction(_desugared_deconstruction);
}
@ -6447,7 +6573,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(var_deconstructor_parameter _var_deconstructor_parameter)
{
bw.Write((Int16)231);
bw.Write((Int16)237);
write_var_deconstructor_parameter(_var_deconstructor_parameter);
}
@ -6477,7 +6603,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(recursive_deconstructor_parameter _recursive_deconstructor_parameter)
{
bw.Write((Int16)232);
bw.Write((Int16)238);
write_recursive_deconstructor_parameter(_recursive_deconstructor_parameter);
}
@ -6498,7 +6624,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(deconstruction_variables_definition _deconstruction_variables_definition)
{
bw.Write((Int16)233);
bw.Write((Int16)239);
write_deconstruction_variables_definition(_deconstruction_variables_definition);
}
@ -6531,7 +6657,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(var_tuple_def_statement _var_tuple_def_statement)
{
bw.Write((Int16)234);
bw.Write((Int16)240);
write_var_tuple_def_statement(_var_tuple_def_statement);
}
@ -6543,7 +6669,7 @@ namespace PascalABCCompiler.SyntaxTree
public void visit(semantic_check_sugared_var_def_statement_node _semantic_check_sugared_var_def_statement_node)
{
bw.Write((Int16)235);
bw.Write((Int16)241);
write_semantic_check_sugared_var_def_statement_node(_semantic_check_sugared_var_def_statement_node);
}

File diff suppressed because it is too large Load diff

View file

@ -1337,6 +1337,42 @@ namespace PascalABCCompiler.SyntaxTree
///<returns> Return value is void </returns>
void visit(double_question_node _double_question_node);
///<summary>
///Method to visit typeclass_restriction.
///</summary>
///<param name="_typeclass_restriction">Node to visit</param>
///<returns> Return value is void </returns>
void visit(typeclass_restriction _typeclass_restriction);
///<summary>
///Method to visit instance_definition.
///</summary>
///<param name="_instance_definition">Node to visit</param>
///<returns> Return value is void </returns>
void visit(instance_definition _instance_definition);
///<summary>
///Method to visit typeclass_definition.
///</summary>
///<param name="_typeclass_definition">Node to visit</param>
///<returns> Return value is void </returns>
void visit(typeclass_definition _typeclass_definition);
///<summary>
///Method to visit where_typeclass_constraint.
///</summary>
///<param name="_where_typeclass_constraint">Node to visit</param>
///<returns> Return value is void </returns>
void visit(where_typeclass_constraint _where_typeclass_constraint);
///<summary>
///Method to visit typeclass_param_list.
///</summary>
///<param name="_typeclass_param_list">Node to visit</param>
///<returns> Return value is void </returns>
void visit(typeclass_param_list _typeclass_param_list);
///<summary>
///Method to visit typeclass_reference.
///</summary>
///<param name="_typeclass_reference">Node to visit</param>
///<returns> Return value is void </returns>
void visit(typeclass_reference _typeclass_reference);
///<summary>
///Method to visit pattern_node.
///</summary>
///<param name="_pattern_node">Node to visit</param>

View file

@ -2863,6 +2863,105 @@
<TagIndices />
</Tags>
</SyntaxNode>
<SyntaxNode Name="typeclass_restriction" BaseName="ident">
<Fields>
<SyntaxField Name="restriction_args" SyntaxType="template_param_list" />
</Fields>
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>10</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="instance_definition" BaseName="type_definition">
<Fields>
<SyntaxField Name="body" SyntaxType="class_body_list" />
</Fields>
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
<CategoryIndex>0</CategoryIndex>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>4</TagIndex>
<TagIndex>5</TagIndex>
<TagIndex>10</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="typeclass_definition" BaseName="type_definition">
<Fields>
<SyntaxField Name="additional_restrictions" SyntaxType="named_type_reference_list" />
<SyntaxField Name="body" SyntaxType="class_body_list" />
</Fields>
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
<CategoryIndex>0</CategoryIndex>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>4</TagIndex>
<TagIndex>5</TagIndex>
<TagIndex>10</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="where_typeclass_constraint" BaseName="where_definition">
<Fields>
<SyntaxField Name="restriction" SyntaxType="typeclass_restriction" />
</Fields>
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>10</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="typeclass_param_list" BaseName="template_param_list">
<Fields />
<Methods>
<Method>
<Text>public typeclass_param_list(template_param_list _template_param_list): this(_template_param_list.dereferencing_value, _template_param_list.params_list, _template_param_list.source_context)
{
}</Text>
</Method>
</Methods>
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>10</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="typeclass_reference" BaseName="named_type_reference">
<Fields>
<SyntaxField Name="restriction_args" SyntaxType="template_param_list" />
</Fields>
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>4</TagIndex>
<TagIndex>10</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="pattern_node" BaseName="syntax_tree_node">
<Fields />
<Methods />

View file

@ -22,6 +22,16 @@ namespace PascalABCCompiler.SyntaxTreeConverters
// Выносим выражения с лямбдами из заголовка foreach
StandOutExprWithLambdaInForeachSequenceVisitor.New.ProcessNode(root);
// type classes - пока закомментировал SSM 20/10/18. Грязный кусок кода. FillParentsInAllChilds вызывается повторно
/*{
var typeclasses = SyntaxVisitors.TypeclassVisitors.FindTypeclassesVisitor.New;
typeclasses.ProcessNode(root);
var instancesAndRestrictedFunctions = SyntaxVisitors.TypeclassVisitors.FindInstancesAndRestrictedFunctionsVisitor.New(typeclasses.typeclasses);
instancesAndRestrictedFunctions.ProcessNode(root);
SyntaxVisitors.TypeclassVisitors.ReplaceTypeclassVisitor.New(instancesAndRestrictedFunctions).ProcessNode(root);
}*/
//root.FillParentsInAllChilds();
#if DEBUG
//new SimplePrettyPrinterVisitor("E:/projs/out.txt").ProcessNode(root);
#endif

View file

@ -58,6 +58,9 @@
<Compile Include="SugarVisitors\PatternsDesugaringVisitor.cs" />
<Compile Include="SugarVisitors\SliceDesugarVisitor.cs" />
<Compile Include="SugarVisitors\TupleVisitor.cs" />
<Compile Include="TypeclassVisitors\FindInstancesAndRestrictedFunctionsVisitor.cs" />
<Compile Include="TypeclassVisitors\FindTypeclassesVisitor.cs" />
<Compile Include="TypeclassVisitors\ReplaceTypeclassVisitor.cs" />
<Compile Include="YieldVisitors\ObjectCopier\ObjectCopier.cs" />
<Compile Include="Optimization\CalcConstExprs.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View file

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PascalABCCompiler;
using PascalABCCompiler.Errors;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors.TypeclassVisitors
{
public class FindInstancesAndRestrictedFunctionsVisitor: WalkingVisitorNew
{
// (Typeclass name) -> (Type arguments count)
public Dictionary<string, type_declaration> typeclasses;
// (Typeclass name) -> [Instances]
public Dictionary<string, List<typeclass_param_list>> instances = new Dictionary<string, List<typeclass_param_list>>();
public Dictionary<string, List<string>> restrictedFunctions = new Dictionary<string, List<string>>();
public FindInstancesAndRestrictedFunctionsVisitor(Dictionary<string, type_declaration> typeclasses)
{
this.typeclasses = typeclasses;
foreach (var typeclass in typeclasses)
{
instances.Add(typeclass.Key, new List<typeclass_param_list>());
}
}
public static FindInstancesAndRestrictedFunctionsVisitor New(Dictionary<string, type_declaration> typeclasses)
{
return new FindInstancesAndRestrictedFunctionsVisitor(typeclasses);
}
public override void visit(type_declaration instanceDeclaration)
{
var instanceDefinition = instanceDeclaration.type_def as instance_definition;
if (instanceDefinition == null)
{
return;
}
var instanceName = instanceDeclaration.type_name as typeclass_restriction;
instances[instanceName.name].Add(instanceName.restriction_args as typeclass_param_list);
}
public override void visit(procedure_definition procedureDefinition)
{
bool isConstrainted = procedureDefinition.proc_header.where_defs != null &&
procedureDefinition.proc_header.where_defs.defs.Any(x => x is where_typeclass_constraint);
if (!isConstrainted)
return;
var usedTypeclasses = procedureDefinition.proc_header.where_defs.
defs.OfType<where_typeclass_constraint>()
.Select(x => x.restriction.name).ToList();
restrictedFunctions.Add(procedureDefinition.proc_header.name.meth_name.name,
usedTypeclasses);
}
}
}

View file

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PascalABCCompiler;
using PascalABCCompiler.Errors;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors.TypeclassVisitors
{
public class FindTypeclassesVisitor: WalkingVisitorNew
{
//TODO: add searching typeclasses at libraries
// (Typeclass name) -> (Type arguments count)
public Dictionary<string, type_declaration> typeclasses = new Dictionary<string, type_declaration>();
public FindTypeclassesVisitor()
{
}
public static FindTypeclassesVisitor New
{
get
{
return new FindTypeclassesVisitor();
}
}
public override void visit(type_declaration typeclassDeclaration)
{
var typeclassDefinition = typeclassDeclaration.type_def as typeclass_definition;
if (typeclassDefinition == null)
{
return;
}
var typeclassName = typeclassDeclaration.type_name as typeclass_restriction;
typeclasses.Add(typeclassName.name, typeclassDeclaration);
}
}
}

View file

@ -0,0 +1,622 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text;
using PascalABCCompiler;
using PascalABCCompiler.Errors;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors.TypeclassVisitors
{
public class ReplaceTypeclassVisitor: BaseChangeVisitor
{
FindInstancesAndRestrictedFunctionsVisitor instancesAndRestrictedFunctions;
public ReplaceTypeclassVisitor(FindInstancesAndRestrictedFunctionsVisitor instancesAndRestrictedFunctions)
{
this.instancesAndRestrictedFunctions = instancesAndRestrictedFunctions;
}
public static ReplaceTypeclassVisitor New(FindInstancesAndRestrictedFunctionsVisitor instancesAndRestrictedFunctions)
{
return new ReplaceTypeclassVisitor(instancesAndRestrictedFunctions);
}
bool VisitInstanceDeclaration(type_declaration instanceDeclaration)
{
var instanceDefinition = instanceDeclaration.type_def as instance_definition;
if (instanceDefinition == null)
{
return false;
}
var instanceName = instanceDeclaration.type_name as typeclass_restriction;
// If it is instance of derived typelass than it should have template parameters
var templateArgs = new ident_list();
where_definition_list whereSection = null;
var originalTypeclass = instancesAndRestrictedFunctions.typeclasses[instanceName.name].type_def as typeclass_definition;
var typeclassParents = originalTypeclass.additional_restrictions;
if (typeclassParents != null && typeclassParents.Count > 0)
{
whereSection = new where_definition_list();
for (int i = 0; i < typeclassParents.Count; i++)
{
ident template_name;
if (typeclassParents[i] is typeclass_reference tr)
{
string name = tr.names[0].name;
template_name = TypeclassRestrctionToTemplateName(name, tr.restriction_args);
whereSection.Add(GetWhereRestriction(
TypeclassReferenceToInterfaceName(name, instanceName.restriction_args),
template_name));
}
else
{
throw new NotImplementedException("Should be syntactic error");
}
templateArgs.Add(template_name);
}
}
List<type_definition> templateLists = instanceName.restriction_args.params_list.Concat(templateArgs.idents.Select(x => new named_type_reference(x.name)).OfType<type_definition>()).ToList();
var parents = new named_type_reference_list(new List<named_type_reference> {
new template_type_reference(instanceName.name, new template_param_list(templateLists)),
new template_type_reference("I" + instanceName.name, instanceName.restriction_args)});
var instanceDefTranslated =
SyntaxTreeBuilder.BuildClassDefinition(
parents,
null, instanceDefinition.body.class_def_blocks.ToArray());
instanceDefTranslated.template_args = templateArgs;
instanceDefTranslated.where_section = whereSection;
instanceDefTranslated.source_context = instanceDefinition.source_context;
for (int i = 0; i < instanceDefTranslated.body.class_def_blocks.Count; i++)
{
var cm = instanceDefTranslated.body.class_def_blocks[i].members;
for (int j = 0; j < cm.Count; j++)
{
procedure_header header = null;
if (cm[j] is procedure_header ph)
{
cm[j] = ph;
}
else if (cm[j] is procedure_definition pd)
{
header = pd.proc_header;
}
header.proc_attributes.Add(new procedure_attribute("override", proc_attribute.attr_override));
ConvertOperatorNameIdent(header);
}
}
/*
{
// Add constructor
var cm = instanceDefTranslated.body.class_def_blocks[0];
var def = new procedure_definition(
new constructor(),
new statement_list(new empty_statement()));
def.proc_body.Parent = def;
def.proc_header.proc_attributes = new procedure_attributes_list();
cm.Add(def);
}
*/
var typeName = new ident(CreateInstanceName(instanceName.restriction_args as typeclass_param_list, instanceName.name), instanceName.source_context);
var instanceDeclTranslated = new type_declaration(typeName, instanceDefTranslated, instanceDeclaration.source_context);
instanceDeclTranslated.attributes = instanceDeclaration.attributes;
AddAttribute(
instanceDeclTranslated, "__TypeclassInstanceAttribute",
new expression_list(new string_const(TypeclassRestrictionToString(instanceName))));
AddAttribute(instanceDeclTranslated, "__TypeclassAttribute",
new expression_list(new string_const(TypeclassRestrictionToString(
(originalTypeclass.Parent as type_declaration).type_name as typeclass_restriction))));
Replace(instanceDeclaration, instanceDeclTranslated);
visit(instanceDeclTranslated);
return true;
}
private static string TypeclassRestrictionToString(typeclass_restriction instanceName)
{
return instanceName.name + "[" + string.Join(",", instanceName.restriction_args.params_list) + "]";
}
private static string CreateInstanceName(typeclass_param_list restriction_args, string typeName)
{
for (int i = 0; i < restriction_args.Count; i++)
{
typeName += "_" + (restriction_args.params_list[i] as named_type_reference).names[0];
}
return typeName;
}
bool VisitTypeclassDeclaration(type_declaration typeclassDeclaration)
{
var typeclassDefinition = typeclassDeclaration.type_def as typeclass_definition;
if (typeclassDefinition == null)
{
return false;
}
var typeclassName = typeclassDeclaration.type_name as typeclass_restriction;
// TODO: typeclassDefinition.additional_restrictions - translate to usual classes
// Creating interface
// Get members for typeclass interface
var interfaceMembers = new List<class_members>();
foreach (var cm in typeclassDefinition.body.class_def_blocks)
{
var cmNew = (class_members)cm.Clone();
for (int i = 0; i < cmNew.members.Count; i++)
{
var member = cmNew.members[i];
if (member is function_header || member is procedure_header)
{
cmNew.members[i] = member;
}
else if (member is procedure_definition procDef)
{
cmNew.members[i] = procDef.proc_header;
}
AddAttribute(cmNew.members[i], "__TypeclassMemberAttribute");
if (cmNew.members[i] is procedure_header ph)
{
ConvertOperatorNameIdent(ph);
}
}
interfaceMembers.Add(cmNew);
}
var interfaceInheritance = (named_type_reference_list)typeclassDefinition.additional_restrictions?.Clone();
if (interfaceInheritance != null)
{
interfaceInheritance.source_context = null;
for (int i = 0; i < interfaceInheritance.types.Count; i++)
{
if (interfaceInheritance.types[i] is typeclass_reference tr)
{
interfaceInheritance.types[i] = TypeclassReferenceToInterfaceName(tr.names[0].name, tr.restriction_args);
}
else
{
throw new NotImplementedException("Syntactic Error");
}
}
}
var typeclassInterfaceDef =
SyntaxTreeBuilder.BuildClassDefinition(
interfaceInheritance,
null, interfaceMembers.ToArray());
typeclassInterfaceDef.keyword = class_keyword.Interface;
var typeclassInterfaceName = new template_type_name("I" + typeclassName.name, RestrictionsToIdentList(typeclassName.restriction_args));
var typeclassInterfaceDecl = new type_declaration(typeclassInterfaceName, typeclassInterfaceDef);
typeclassInterfaceDecl.attributes = typeclassDeclaration.attributes;
AddAttribute(
typeclassInterfaceDecl, "__TypeclassAttribute",
new expression_list(new string_const(TypeclassRestrictionToString(typeclassName))));
// Creating class
var typeclassDefTranslated =
SyntaxTreeBuilder.BuildClassDefinition(
new named_type_reference_list(new template_type_reference(typeclassInterfaceName.name, typeclassName.restriction_args)),
null, typeclassDefinition.body.class_def_blocks.ToArray());
typeclassDefTranslated.attribute = class_attribute.Abstract;
for (int i = 0; i < typeclassDefTranslated.body.class_def_blocks.Count; i++)
{
var cm = typeclassDefTranslated.body.class_def_blocks[i].members;
for (int j = 0; j < cm.Count; j++)
{
procedure_header header = null;
if (cm[j] is procedure_header ph)
{
header = ph;
header.proc_attributes.Add(new procedure_attribute("abstract", proc_attribute.attr_abstract));
}
else if (cm[j] is procedure_definition pd)
{
header = pd.proc_header;
header.proc_attributes.Add(new procedure_attribute("virtual", proc_attribute.attr_virtual));
}
ConvertOperatorNameIdent(header);
}
}
/*
{
// Add constructor
var cm = typeclassDefTranslated.body.class_def_blocks[0];
var def = new procedure_definition(
new constructor(),
new statement_list(new empty_statement()));
def.proc_body.Parent = def;
def.proc_header.proc_attributes = new procedure_attributes_list();
cm.Add(def);
}
*/
// Add template parameters for typeclass class(derived typeclasses)
ident_list templates = RestrictionsToIdentList(typeclassName.restriction_args);
if (typeclassDefinition.additional_restrictions != null)
{
for (int i = 0; i < typeclassDefinition.additional_restrictions.types.Count; i++)
{
string name;
string templateName;
if (typeclassDefinition.additional_restrictions.types[i] is typeclass_reference tr)
{
name = tr.names[0].name;
templateName = TypeclassRestrctionToTemplateName(name, tr.restriction_args).name;
}
else
{
throw new NotImplementedException("SyntaxError");
}
// Add template parameter
templates.Add(templateName);
// Add where restriction
if (typeclassDefTranslated.where_section == null)
{
typeclassDefTranslated.where_section = new where_definition_list();
}
typeclassDefTranslated.where_section.Add(GetWhereRestriction(
interfaceInheritance.types[i],
templateName));
// Add methods from derived typeclasses
var body = (instancesAndRestrictedFunctions.typeclasses[name].type_def as typeclass_definition).body;
foreach (var cdb in body.class_def_blocks)
{
var cdbNew = new class_members(cdb.access_mod == null ? access_modifer.none : cdb.access_mod.access_level);
foreach (var member in cdb.members)
{
procedure_header memberHeaderNew;
if (member is procedure_header || member is function_header)
{
memberHeaderNew = (procedure_header)member.Clone();
memberHeaderNew.source_context = null;
}
else if (member is procedure_definition procDefinition)
{
memberHeaderNew = (procedure_header)procDefinition.proc_header.Clone();
memberHeaderNew.Parent = null;
memberHeaderNew.source_context = null;
}
else
{
continue;
}
var variableName = templateName + "Instance";
var parameters = memberHeaderNew.parameters.params_list.Aggregate(new expression_list(), (x, y) => new expression_list(x.expressions.Concat(y.idents.idents).ToList()));
expression methodCall = null;
if (memberHeaderNew.name.meth_name is operator_name_ident oni)
{
ConvertOperatorNameIdent(memberHeaderNew);
Debug.Assert(parameters.expressions.Count == 2, "Parameters count for operation should be equal to 2");
//methodCall = new bin_expr(parameters.expressions[0], parameters.expressions[1], oni.operator_type);
}
var callName = new dot_node(variableName, memberHeaderNew.name.meth_name.name);
methodCall = new method_call(callName, parameters);
statement exec = null;
if (memberHeaderNew is function_header)
{
exec = new assign("Result", methodCall);
}
else if (memberHeaderNew is procedure_header)
{
exec = new procedure_call(methodCall as method_call);
}
var procDef = new procedure_definition(
memberHeaderNew,
new statement_list(
GetInstanceSingletonVarStatement(templateName),
exec));
cdbNew.Add(procDef);
}
typeclassDefTranslated.body.class_def_blocks.Add(cdbNew);
}
}
}
var typeclassNameTanslated = new template_type_name(typeclassName.name, templates, typeclassName.source_context);
var typeclassDeclTranslated = new type_declaration(typeclassNameTanslated, typeclassDefTranslated, typeclassDeclaration.source_context);
typeclassDeclTranslated.attributes = typeclassDeclaration.attributes;
AddAttribute(
typeclassDeclTranslated, "__TypeclassAttribute",
new expression_list(new string_const(TypeclassRestrictionToString(typeclassName))));
Replace(typeclassDeclaration, typeclassDeclTranslated);
UpperNodeAs<type_declarations>().InsertBefore(typeclassDeclTranslated, typeclassInterfaceDecl);
visit(typeclassInterfaceDecl);
visit(typeclassDeclTranslated);
return true;
}
private static void ConvertOperatorNameIdent(procedure_header ph)
{
if (ph.name.meth_name is operator_name_ident oni)
{
var methName = "$typeclass" + PascalABCCompiler.TreeConverter.name_reflector.get_name(oni.operator_type);
ph.name.meth_name = methName;
}
}
private static void AddAttribute(declaration typeclassInterfaceDecl, string newAttribute, expression_list expressionList = null)
{
if (expressionList == null)
{
expressionList = new expression_list();
}
if (typeclassInterfaceDecl.attributes == null)
{
typeclassInterfaceDecl.attributes = new attribute_list();
}
typeclassInterfaceDecl.attributes.Add(new simple_attribute_list(new attribute(null, new named_type_reference(newAttribute), expressionList)));
}
private static template_type_reference TypeclassReferenceToInterfaceName(string name, template_param_list restriction_args)
{
return new template_type_reference(
new named_type_reference("I" + name), restriction_args);
}
private static ident_list RestrictionsToIdentList(template_param_list restrictions)
{
var templates = new ident_list();
templates.source_context = restrictions.source_context;
for (int i = 0; i < restrictions.Count; i++)
{
templates.Add((restrictions.params_list[i] as named_type_reference).names[0]);
}
return templates;
}
public override void visit(type_declaration _type_declaration)
{
if (VisitInstanceDeclaration(_type_declaration))
{
return;
}
if (VisitTypeclassDeclaration(_type_declaration))
{
return;
}
DefaultVisit(_type_declaration);
}
public override void visit(procedure_definition _procedure_definition)
{
bool isConstrainted = _procedure_definition.proc_header.where_defs != null &&
_procedure_definition.proc_header.where_defs.defs.Any(x => x is where_typeclass_constraint);
if (!isConstrainted)
{
DefaultVisit(_procedure_definition);
return;
}
var header = _procedure_definition.proc_header;
var headerTranslated = header.Clone() as procedure_header;
headerTranslated.where_defs = new where_definition_list();
var additionalTemplateArgs = new ident_list();
for (int i = 0; i < header.where_defs.defs.Count; i++)
{
var where = header.where_defs.defs[i];
if (where is where_typeclass_constraint)
{
var typeclassWhere = where as where_typeclass_constraint;
var newName = TypeclassRestrctionToTemplateName(typeclassWhere.restriction.name, typeclassWhere.restriction.restriction_args);
AddAttribute(
newName, "__TypeclassGenericParameter",
new expression_list(new string_const(GetInstanceSingletonName(newName.name))));
additionalTemplateArgs.Add(newName);
// Create name for template that replaces typeclass(for ex. SumTC)
headerTranslated.where_defs.defs.Add(
GetWhereRestriction(
new template_type_reference(new named_type_reference("I" + typeclassWhere.restriction.name), typeclassWhere.restriction.restriction_args),
newName));
}
else
{
headerTranslated.where_defs.defs.Add(where);
}
}
// Add new templates devoted to constraints to template list
// TODO: template_args can be empty, if there is no <T> or smth, need to check
headerTranslated.template_args.idents.AddRange(additionalTemplateArgs.idents);
var blockProc = (_procedure_definition.proc_body as block);
foreach (var arg in additionalTemplateArgs.idents)
{
blockProc.program_code.AddFirst(GetInstanceSingletonVarStatement(arg.name));
}
//var list = _procedure_definition.proc_body.DescendantNodes().OfType<typeclass_param_list>();
foreach (var tcr in _procedure_definition.proc_body.DescendantNodes().OfType<ident_with_templateparams>())
{
if (tcr.template_params is typeclass_param_list)
{
// TODO: Check tcr.name - typeclass from where
// TODO: Check - that there is such typeclass with such args at where
// TODO: Ensure that we don't replace another constraint funciton call
var str = tcr.template_params.params_list
.Select(x => (x as named_type_reference).names[0].name)
.Aggregate((tcr.name as ident).name, (x, y) => x + y);
var id = new ident(str + "Instance");
var parent = tcr.Parent;
parent.ReplaceDescendant((addressed_value)tcr, (addressed_value)id, Desc.All);
}
//var id = new ident(TypeclassRestrctionToTemplateName(tcr) + "Instance");
}
var procedureDefTranslated = new procedure_definition(
headerTranslated, _procedure_definition.proc_body,
_procedure_definition.is_short_definition, _procedure_definition.source_context);
procedureDefTranslated.proc_header.attributes = _procedure_definition.proc_header.attributes;
AddAttribute(procedureDefTranslated.proc_header, "__TypeclassRestrictedFunctionAttribute");
Replace(_procedure_definition, procedureDefTranslated);
visit(procedureDefTranslated);
}
private static var_statement GetInstanceSingletonVarStatement(string typeName)
{
return new var_statement(new var_def_statement(
GetInstanceSingletonName(typeName),
new dot_node(
new ident_with_templateparams(new ident("__ConceptSingleton"), new template_param_list(new List<type_definition> { new named_type_reference(typeName) })),
new ident("Instance")
)));
}
private static string GetInstanceSingletonName(string typeName)
{
return typeName + "Instance";
}
private static where_definition GetWhereRestriction(type_definition restriction, ident templateName)
{
return // where
new where_definition(
// ConstraintTC :
new ident_list(templateName),
new where_type_specificator_list(new List<type_definition> {
// IConstraint<T, C>,
restriction,
// constructor
new declaration_specificator(DeclarationSpecificator.WhereDefConstructor, "constructor")
}));
}
public override void visit(method_call methodCall)
{
var methodName = methodCall.dereferencing_value as ident_with_templateparams;
if (methodName == null)
{
DefaultVisit(methodCall);
return;
}
var typeclassRestrictions = methodName.template_params as typeclass_param_list;
if (typeclassRestrictions == null)
{
DefaultVisit(methodCall);
return;
}
var paramList = new List<type_definition>();
paramList.AddRange(typeclassRestrictions.params_list);
// TODO: Add template types for typeclass instances
var methodStrName = (methodName.name as ident).name;
var typeclasses = instancesAndRestrictedFunctions.restrictedFunctions[methodStrName];
List<type_definition> newParams = GetTranslatedTypeclassParameters(paramList, typeclasses);
paramList.AddRange(newParams);
var methodCallTranslated = new method_call(
new ident_with_templateparams(methodName.name, new template_param_list(paramList), methodName.source_context),
methodCall.parameters,
methodCall.source_context);
Replace(methodCall, methodCallTranslated);
}
private List<type_definition> GetTranslatedTypeclassParameters(List<type_definition> paramList, IEnumerable<string> typeclasses)
{
var possibleOverloadingsForEachTypeclass = typeclasses.Select(x =>
new KeyValuePair<string, List<typeclass_param_list>>(x, instancesAndRestrictedFunctions.instances[x]));
// Find current overloading in possible
var newParams = new List<type_definition>();
foreach (var typeclassOverloadings in possibleOverloadingsForEachTypeclass)
{
foreach (var possibleParamList in typeclassOverloadings.Value)
{
bool isEqual = true;
for (int i = 0; i < possibleParamList.params_list.Count; i++)
{
if ((possibleParamList.params_list[i] as named_type_reference).names[0].name !=
(paramList[i] as named_type_reference).names[0].name)
{
isEqual = false;
break;
}
}
// TODO: need many checks
// Typeclass params and function restriction params are mixed up
// Fix it as soon as it possible
// Btw for 1 argument it's ok.
if (isEqual)
{
var derived_typeclass =
(instancesAndRestrictedFunctions.typeclasses[typeclassOverloadings.Key].type_def as typeclass_definition);
var base_typeclasses = derived_typeclass.additional_restrictions?.types.OfType<typeclass_reference>().Select(x => x.names[0].name);
var typeName = new named_type_reference(CreateInstanceName(possibleParamList, typeclassOverloadings.Key));
if (base_typeclasses == null || base_typeclasses.Count() == 0)
{
newParams.Add(typeName);
}
else
{
var translatedParams = GetTranslatedTypeclassParameters(paramList, base_typeclasses);
newParams.Add(new template_type_reference(
typeName,
new template_param_list(translatedParams)));
}
}
}
}
return newParams;
}
private static ident TypeclassRestrctionToTemplateName(string name, template_param_list restriction_args)
{
// Concatenate type constraint into new type name
// For example:
// Constaint[T, C] => ConstraintTC
return RestrictionsToIdentList(restriction_args).idents.Aggregate(
new ident(name), (x, y) => x.name + y.name);
}
}
}

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()
@ -2726,6 +2729,18 @@ namespace PascalABCCompiler.TreeConverter
}
}
var testIsInstance = _ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassInstanceAttribute");
if (testIsInstance is true)
{
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;
AddError(_ctn.location, "INSTANCE_{0}_DOES_NOT_IMPLEMENT_REQUIREMENT_{1}_OF_TYPECLASS_{2}",
instanceName.ToString(), Tools.GetFullMethodHeaderString(meth), typeclassName.ToString());
}
}
if (find_method == null)
{
//Нет функции с таким именем, набором параметров и возвращаемым значением

View file

@ -1081,6 +1081,46 @@ namespace PascalABCCompiler.TreeConverter
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)
{
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)
{
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
var silTmp = (item as type_node)?.find_in_type("$typeclass" + name, context.CurrentScope);
if (silTmp != null)
{
var dn = new ident((args.First() as string_const_node).constant_value);
var dns = convert_strong(dn);
var exp = convertion_data_and_alghoritms.create_method_call(silTmp[0].sym_info as function_node, null, dns, left, right);
return exp;
}
}
}
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))
{
var type = context._ctn;
var silTmp = (type.ImplementingInterfaces[0] as type_node)?.find_in_type("$typeclass" + name, context.CurrentScope);
if (silTmp != null)
{
var methodName = convert_strong(new ident("$typeclass" + 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);
return exp;
}
}
// ! voloshinbogdan Typeclasses 21.05.2018
type_node left_type = left.type;
type_node right_type = right.type;
@ -3505,6 +3545,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)
AddError(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)
@ -5068,6 +5114,28 @@ 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)
{
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)
{
var args = item.Attributes.First(x => x.AttributeType.name == "__TypeclassGenericParameterAttribute").Arguments;
var silTmp = (item as type_node)?.find_in_type(id.name, context.CurrentScope);
if (silTmp != null)
{
deref_value = new dot_node((args.First() as string_const_node).constant_value, id);
break;
}
}
}
}
// ! Typeclasses
}
if (sil == null)
{
@ -12949,7 +13017,8 @@ namespace PascalABCCompiler.TreeConverter
if (context.top_function is common_method_node)
{
common_method_node cmmn = context.top_function as common_method_node;
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static)
var testIsTypeclass = context._ctn?.Attributes?.Any(x => x.AttributeType.name == "__TypeclassAttribute");
if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
{
AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION");
}
@ -12994,7 +13063,7 @@ namespace PascalABCCompiler.TreeConverter
if (ptn == cmmn.cont_type)
has_types = true;
}
if (!has_types)
if (!has_types && !(testIsTypeclass.HasValue && testIsTypeclass.Value))
AddError(new SimpleSemanticError(cmmn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cmmn.cont_type.name));
}
}
@ -13631,7 +13700,9 @@ namespace PascalABCCompiler.TreeConverter
}
first_param = false;
common_method_node cnode = context.top_function as common_method_node;
if (cnode != null && cnode.IsOperator)
// 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))
{
parameter_list pars = context.top_function.parameters;
if (cnode.name != compiler_string_consts.implicit_operator_name && cnode.name != compiler_string_consts.explicit_operator_name)
@ -16822,6 +16893,17 @@ namespace PascalABCCompiler.TreeConverter
expression_node left = convert_strong(_bin_expr.left);
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))
{
return_value(res);
return;
}
if (res.type is undefined_type)
AddError(get_location(_bin_expr), "OPERATOR_RETURN_TYPE_UNDEFINED_{0}", name_reflector.get_name(_bin_expr.operation_type));

View file

@ -837,6 +837,9 @@ 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
while (continue_trying_to_infer_types) //Продолжаем пытаться вычислить типы до тех пор пока состояние о выведенных типах не будет отличаться от состояния на предыдущей итерации
{
var previous_deduce_state = deduced // Текущее состояние выведенных на данный момент типов. Простой список индексов с уже выведенными типами из массива deduced
@ -919,7 +922,37 @@ namespace PascalABCCompiler.TreeRealization
}
}
}
if (isTypeclassRestricted)
{
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 is true)
{
type_node[] deducedInstances = new type_node[foundInstance.generic_params.Count];
DeduceTypeclassInstances(context, deducedInstances, foundInstance.generic_params.OfType<type_node>());
deduced[tc.generic_param_index] = foundInstance.get_instance(deducedInstances.ToList());
}
else
{
deduced[tc.generic_param_index] = appropriateInstances.First();
}
}
}
}
var current_deduce_state = deduced //текущее состояние выведенных типов
.Select((t, ii) => new {Type = t, Index = ii})
.Where(t => t.Type != null)
@ -987,6 +1020,38 @@ namespace PascalABCCompiler.TreeRealization
return func.get_instance(deduced_list, alone, loc);
}
private static void DeduceTypeclassInstances(compilation_context context, type_node[] deduced, IEnumerable<type_node> typeclasses)
{
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));
if (appropriateInstances.Count() == 1)
{
var foundInstance = appropriateInstances.First() as common_type_node;
if (foundInstance.generic_params?.Count > 0 is true)
{
List<type_node> instanceTypes = null;
deduced[tc.generic_param_index] = foundInstance.get_instance(instanceTypes);
}
else
{
deduced[tc.generic_param_index] = appropriateInstances.First();
}
}
else
{
// TODO: typeclasses add error message
}
}
}
//Выведение типов
public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List<int> nils)
{