diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs index e6c556676..152b2d10d 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs @@ -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 // GPLEX frame file diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.lst b/Parsers/PascalABCParserNewSaushkin/ABCPascal.lst index f397106d1..72a8fbd78 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.lst +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.lst @@ -3,9 +3,9 @@ // GPPG error listing for yacc source file // ========================================================================== // 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 tkDirectiveName tkAmpersend tkColon tkDotDot tkPoint tkRoundOpen tkRoundClose tkSemiColon tkSquareOpen tkSquareClose tkQuestion tkQuestionPoint tkDoubleQuestion tkQuestionSquareOpen %token tkSizeOf tkTypeOf tkWhere tkArray tkCase tkClass tkAuto tkStatic tkConst tkConstructor tkDestructor tkElse tkExcept tkFile tkFor tkForeach tkFunction tkMatch tkWhen -%token tkIf tkImplementation tkInherited tkInterface /* tkTypeclass tkInstance */ tkProcedure tkOperator tkProperty tkRaise tkRecord tkSet tkType tkThen tkUses tkVar tkWhile tkWith tkNil +%token tkIf tkImplementation tkInherited tkInterface tkTypeclass tkInstance tkProcedure tkOperator tkProperty tkRaise tkRecord tkSet tkType tkThen tkUses tkVar tkWhile tkWith tkNil %token tkGoto tkOf tkLabel tkLock tkProgram tkEvent tkDefault tkTemplate tkPacked tkExports tkResourceString tkThreadvar tkSealed tkPartial tkTo tkDownto %token tkLoop %token tkSequence tkYield @@ -88,7 +89,7 @@ %type exception_handler %type exception_handler_list %type exception_identifier -%type 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 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 enumeration_id expr_l1_list %type enumeration_id_list %type 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 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 program_param identifier identifier_keyword_operatorname func_class_name_ident /*optional_identifier*/ visibility_specifier %type property_specifier_directives non_reserved -//%type typeclass_restriction +%type typeclass_restriction %type if_stmt %type initialization_part %type template_arguments label_list ident_or_keyword_pointseparator_list ident_list param_name_list @@ -166,7 +167,7 @@ %type typeof_expr %type simple_fp_sect %type template_param_list template_empty_param_list template_type_params template_type_empty_params -//%type template_type_or_typeclass_params typeclass_params +%type template_type_or_typeclass_params typeclass_params %type template_type %type try_stmt %type uses_clause used_units_list @@ -174,7 +175,7 @@ %type used_unit_name %type unit_header %type var_decl_sect -%type var_decl var_decl_part /*var_decl_internal*/ field_definition +%type var_decl var_decl_part /*var_decl_internal*/ field_definition var_decl_with_assign_var_tuple %type var_stmt %type where_part %type where_part_list optional_where_section @@ -183,14 +184,12 @@ %type variable_as_type dotted_identifier %type func_decl_lambda expl_func_decl_lambda %type lambda_type_ref lambda_type_ref_noproctype -%type full_lambda_fp_list lambda_simple_fp_sect lambda_function_body lambda_procedure_body optional_full_lambda_fp_list +%type full_lambda_fp_list lambda_simple_fp_sect lambda_function_body lambda_procedure_body common_lambda_body optional_full_lambda_fp_list %type field_in_unnamed_object list_fields_in_unnamed_object func_class_name_ident_list rem_lambda variable_list var_ident_list %type tkAssignOrEqual %type pattern pattern_optional_var match_with pattern_case pattern_cases pattern_out_param pattern_out_param_optional_var %type 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().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().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().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(); 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; + } ; %%// ========================================================================== diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs index a58039996..fd9a56ef0 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs @@ -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 diff --git a/SyntaxTree/tree/AbstractVisitor.cs b/SyntaxTree/tree/AbstractVisitor.cs index 894e33e30..59dcfa367 100644 --- a/SyntaxTree/tree/AbstractVisitor.cs +++ b/SyntaxTree/tree/AbstractVisitor.cs @@ -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); diff --git a/SyntaxTree/tree/HierarchyVisitor.cs b/SyntaxTree/tree/HierarchyVisitor.cs index d0c8efbde..ff9167114 100644 --- a/SyntaxTree/tree/HierarchyVisitor.cs +++ b/SyntaxTree/tree/HierarchyVisitor.cs @@ -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); diff --git a/SyntaxTree/tree/SyntaxTreeStreamReader.cs b/SyntaxTree/tree/SyntaxTreeStreamReader.cs index f35de324d..950defef0 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamReader.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamReader.cs @@ -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); diff --git a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs index c5085b790..0bef4fbc8 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs @@ -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); } diff --git a/SyntaxTree/tree/Tree.cs b/SyntaxTree/tree/Tree.cs index 02eb5a8db..6583935f4 100644 --- a/SyntaxTree/tree/Tree.cs +++ b/SyntaxTree/tree/Tree.cs @@ -48099,6 +48099,1219 @@ namespace PascalABCCompiler.SyntaxTree } + /// + ///Представляет конструкцию вида Typeclass[T], где Typleclass это ограничение, которое накладывается на тип T + /// + [Serializable] + public partial class typeclass_restriction : ident + { + + /// + ///Конструктор без параметров. + /// + public typeclass_restriction() + { + + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_restriction(template_param_list _restriction_args) + { + this._restriction_args=_restriction_args; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_restriction(template_param_list _restriction_args,SourceContext sc) + { + this._restriction_args=_restriction_args; + source_context = sc; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_restriction(string _name,template_param_list _restriction_args) + { + this._name=_name; + this._restriction_args=_restriction_args; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_restriction(string _name,template_param_list _restriction_args,SourceContext sc) + { + this._name=_name; + this._restriction_args=_restriction_args; + source_context = sc; + FillParentsInDirectChilds(); + } + protected template_param_list _restriction_args; + + /// + /// + /// + public template_param_list restriction_args + { + get + { + return _restriction_args; + } + set + { + _restriction_args=value; + if (_restriction_args != null) + _restriction_args.Parent = this; + } + } + + + /// Создает копию узла + public override syntax_tree_node Clone() + { + typeclass_restriction copy = new typeclass_restriction(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (attributes != null) + { + copy.attributes = (attribute_list)attributes.Clone(); + copy.attributes.Parent = copy; + } + copy.name = name; + if (restriction_args != null) + { + copy.restriction_args = (template_param_list)restriction_args.Clone(); + copy.restriction_args.Parent = copy; + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new typeclass_restriction TypedClone() + { + return Clone() as typeclass_restriction; + } + + /// Заполняет поля Parent в непосредственных дочерних узлах + public override void FillParentsInDirectChilds() + { + if (attributes != null) + attributes.Parent = this; + if (restriction_args != null) + restriction_args.Parent = this; + } + + /// Заполняет поля Parent во всем поддереве + public override void FillParentsInAllChilds() + { + FillParentsInDirectChilds(); + attributes?.FillParentsInAllChilds(); + restriction_args?.FillParentsInAllChilds(); + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 1; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 1; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return restriction_args; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + restriction_args = (template_param_list)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + ///Определение того как конкретный тип удовлетворяет классу типов. + /// + [Serializable] + public partial class instance_definition : type_definition + { + + /// + ///Конструктор без параметров. + /// + public instance_definition() + { + + } + + /// + ///Конструктор с параметрами. + /// + public instance_definition(class_body_list _body) + { + this._body=_body; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public instance_definition(class_body_list _body,SourceContext sc) + { + this._body=_body; + source_context = sc; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public instance_definition(type_definition_attr_list _attr_list,class_body_list _body) + { + this._attr_list=_attr_list; + this._body=_body; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public instance_definition(type_definition_attr_list _attr_list,class_body_list _body,SourceContext sc) + { + this._attr_list=_attr_list; + this._body=_body; + source_context = sc; + FillParentsInDirectChilds(); + } + protected class_body_list _body; + + /// + /// + /// + public class_body_list body + { + get + { + return _body; + } + set + { + _body=value; + if (_body != null) + _body.Parent = this; + } + } + + + /// Создает копию узла + public override syntax_tree_node Clone() + { + instance_definition copy = new instance_definition(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (attributes != null) + { + copy.attributes = (attribute_list)attributes.Clone(); + copy.attributes.Parent = copy; + } + if (attr_list != null) + { + copy.attr_list = (type_definition_attr_list)attr_list.Clone(); + copy.attr_list.Parent = copy; + } + if (body != null) + { + copy.body = (class_body_list)body.Clone(); + copy.body.Parent = copy; + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new instance_definition TypedClone() + { + return Clone() as instance_definition; + } + + /// Заполняет поля Parent в непосредственных дочерних узлах + public override void FillParentsInDirectChilds() + { + if (attributes != null) + attributes.Parent = this; + if (attr_list != null) + attr_list.Parent = this; + if (body != null) + body.Parent = this; + } + + /// Заполняет поля Parent во всем поддереве + public override void FillParentsInAllChilds() + { + FillParentsInDirectChilds(); + attributes?.FillParentsInAllChilds(); + attr_list?.FillParentsInAllChilds(); + body?.FillParentsInAllChilds(); + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 2; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 2; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return attr_list; + case 1: + return body; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + attr_list = (type_definition_attr_list)value; + break; + case 1: + body = (class_body_list)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + ///Определение класса типов + /// + [Serializable] + public partial class typeclass_definition : type_definition + { + + /// + ///Конструктор без параметров. + /// + public typeclass_definition() + { + + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_definition(named_type_reference_list _additional_restrictions,class_body_list _body) + { + this._additional_restrictions=_additional_restrictions; + this._body=_body; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_definition(named_type_reference_list _additional_restrictions,class_body_list _body,SourceContext sc) + { + this._additional_restrictions=_additional_restrictions; + this._body=_body; + source_context = sc; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_definition(type_definition_attr_list _attr_list,named_type_reference_list _additional_restrictions,class_body_list _body) + { + this._attr_list=_attr_list; + this._additional_restrictions=_additional_restrictions; + this._body=_body; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_definition(type_definition_attr_list _attr_list,named_type_reference_list _additional_restrictions,class_body_list _body,SourceContext sc) + { + this._attr_list=_attr_list; + this._additional_restrictions=_additional_restrictions; + this._body=_body; + source_context = sc; + FillParentsInDirectChilds(); + } + protected named_type_reference_list _additional_restrictions; + protected class_body_list _body; + + /// + /// + /// + public named_type_reference_list additional_restrictions + { + get + { + return _additional_restrictions; + } + set + { + _additional_restrictions=value; + if (_additional_restrictions != null) + _additional_restrictions.Parent = this; + } + } + + /// + /// + /// + public class_body_list body + { + get + { + return _body; + } + set + { + _body=value; + if (_body != null) + _body.Parent = this; + } + } + + + /// Создает копию узла + public override syntax_tree_node Clone() + { + typeclass_definition copy = new typeclass_definition(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (attributes != null) + { + copy.attributes = (attribute_list)attributes.Clone(); + copy.attributes.Parent = copy; + } + if (attr_list != null) + { + copy.attr_list = (type_definition_attr_list)attr_list.Clone(); + copy.attr_list.Parent = copy; + } + if (additional_restrictions != null) + { + copy.additional_restrictions = (named_type_reference_list)additional_restrictions.Clone(); + copy.additional_restrictions.Parent = copy; + } + if (body != null) + { + copy.body = (class_body_list)body.Clone(); + copy.body.Parent = copy; + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new typeclass_definition TypedClone() + { + return Clone() as typeclass_definition; + } + + /// Заполняет поля Parent в непосредственных дочерних узлах + public override void FillParentsInDirectChilds() + { + if (attributes != null) + attributes.Parent = this; + if (attr_list != null) + attr_list.Parent = this; + if (additional_restrictions != null) + additional_restrictions.Parent = this; + if (body != null) + body.Parent = this; + } + + /// Заполняет поля Parent во всем поддереве + public override void FillParentsInAllChilds() + { + FillParentsInDirectChilds(); + attributes?.FillParentsInAllChilds(); + attr_list?.FillParentsInAllChilds(); + additional_restrictions?.FillParentsInAllChilds(); + body?.FillParentsInAllChilds(); + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 3; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 3; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return attr_list; + case 1: + return additional_restrictions; + case 2: + return body; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + attr_list = (type_definition_attr_list)value; + break; + case 1: + additional_restrictions = (named_type_reference_list)value; + break; + case 2: + body = (class_body_list)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + /// + /// + [Serializable] + public partial class where_typeclass_constraint : where_definition + { + + /// + ///Конструктор без параметров. + /// + public where_typeclass_constraint() + { + + } + + /// + ///Конструктор с параметрами. + /// + public where_typeclass_constraint(typeclass_restriction _restriction) + { + this._restriction=_restriction; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public where_typeclass_constraint(typeclass_restriction _restriction,SourceContext sc) + { + this._restriction=_restriction; + source_context = sc; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public where_typeclass_constraint(ident_list _names,where_type_specificator_list _types,typeclass_restriction _restriction) + { + this._names=_names; + this._types=_types; + this._restriction=_restriction; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public where_typeclass_constraint(ident_list _names,where_type_specificator_list _types,typeclass_restriction _restriction,SourceContext sc) + { + this._names=_names; + this._types=_types; + this._restriction=_restriction; + source_context = sc; + FillParentsInDirectChilds(); + } + protected typeclass_restriction _restriction; + + /// + /// + /// + public typeclass_restriction restriction + { + get + { + return _restriction; + } + set + { + _restriction=value; + if (_restriction != null) + _restriction.Parent = this; + } + } + + + /// Создает копию узла + public override syntax_tree_node Clone() + { + where_typeclass_constraint copy = new where_typeclass_constraint(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (names != null) + { + copy.names = (ident_list)names.Clone(); + copy.names.Parent = copy; + } + if (types != null) + { + copy.types = (where_type_specificator_list)types.Clone(); + copy.types.Parent = copy; + } + if (restriction != null) + { + copy.restriction = (typeclass_restriction)restriction.Clone(); + copy.restriction.Parent = copy; + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new where_typeclass_constraint TypedClone() + { + return Clone() as where_typeclass_constraint; + } + + /// Заполняет поля Parent в непосредственных дочерних узлах + public override void FillParentsInDirectChilds() + { + if (names != null) + names.Parent = this; + if (types != null) + types.Parent = this; + if (restriction != null) + restriction.Parent = this; + } + + /// Заполняет поля Parent во всем поддереве + public override void FillParentsInAllChilds() + { + FillParentsInDirectChilds(); + names?.FillParentsInAllChilds(); + types?.FillParentsInAllChilds(); + restriction?.FillParentsInAllChilds(); + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 3; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 3; + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return names; + case 1: + return types; + case 2: + return restriction; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + names = (ident_list)value; + break; + case 1: + types = (where_type_specificator_list)value; + break; + case 2: + restriction = (typeclass_restriction)value; + break; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + ///Список параметров тайпкласса + /// + [Serializable] + public partial class typeclass_param_list : template_param_list + { + + /// + ///Конструктор без параметров. + /// + public typeclass_param_list() + { + + } + + + /// + ///Конструктор с параметрами. + /// + public typeclass_param_list(addressed_value _dereferencing_value,List _params_list) + { + this._dereferencing_value=_dereferencing_value; + this._params_list=_params_list; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_param_list(addressed_value _dereferencing_value,List _params_list,SourceContext sc) + { + this._dereferencing_value=_dereferencing_value; + this._params_list=_params_list; + source_context = sc; + FillParentsInDirectChilds(); + } + 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) +{ +} + + /// Создает копию узла + public override syntax_tree_node Clone() + { + typeclass_param_list copy = new typeclass_param_list(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (attributes != null) + { + copy.attributes = (attribute_list)attributes.Clone(); + copy.attributes.Parent = copy; + } + if (dereferencing_value != null) + { + copy.dereferencing_value = (addressed_value)dereferencing_value.Clone(); + copy.dereferencing_value.Parent = copy; + } + if (params_list != null) + { + foreach (type_definition elem in params_list) + { + if (elem != null) + { + copy.Add((type_definition)elem.Clone()); + copy.Last().Parent = copy; + } + else + copy.Add(null); + } + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new typeclass_param_list TypedClone() + { + return Clone() as typeclass_param_list; + } + + /// Заполняет поля Parent в непосредственных дочерних узлах + public override void FillParentsInDirectChilds() + { + if (attributes != null) + attributes.Parent = this; + if (dereferencing_value != null) + dereferencing_value.Parent = this; + if (params_list != null) + { + foreach (var child in params_list) + if (child != null) + child.Parent = this; + } + } + + /// Заполняет поля Parent во всем поддереве + public override void FillParentsInAllChilds() + { + FillParentsInDirectChilds(); + attributes?.FillParentsInAllChilds(); + dereferencing_value?.FillParentsInAllChilds(); + if (params_list != null) + { + foreach (var child in params_list) + child?.FillParentsInAllChilds(); + } + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 1; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 1 + (params_list == null ? 0 : params_list.Count); + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return dereferencing_value; + } + Int32 index_counter=ind - 1; + if(params_list != null) + { + if(index_counter < params_list.Count) + { + return params_list[index_counter]; + } + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + dereferencing_value = (addressed_value)value; + break; + } + Int32 index_counter=ind - 1; + if(params_list != null) + { + if(index_counter < params_list.Count) + { + params_list[index_counter]= (type_definition)value; + return; + } + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + + /// + /// + /// + [Serializable] + public partial class typeclass_reference : named_type_reference + { + + /// + ///Конструктор без параметров. + /// + public typeclass_reference() + { + + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_reference(template_param_list _restriction_args) + { + this._restriction_args=_restriction_args; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_reference(template_param_list _restriction_args,SourceContext sc) + { + this._restriction_args=_restriction_args; + source_context = sc; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_reference(type_definition_attr_list _attr_list,List _names,template_param_list _restriction_args) + { + this._attr_list=_attr_list; + this._names=_names; + this._restriction_args=_restriction_args; + FillParentsInDirectChilds(); + } + + /// + ///Конструктор с параметрами. + /// + public typeclass_reference(type_definition_attr_list _attr_list,List _names,template_param_list _restriction_args,SourceContext sc) + { + this._attr_list=_attr_list; + this._names=_names; + this._restriction_args=_restriction_args; + source_context = sc; + FillParentsInDirectChilds(); + } + protected template_param_list _restriction_args; + + /// + /// + /// + public template_param_list restriction_args + { + get + { + return _restriction_args; + } + set + { + _restriction_args=value; + if (_restriction_args != null) + _restriction_args.Parent = this; + } + } + + + /// Создает копию узла + public override syntax_tree_node Clone() + { + typeclass_reference copy = new typeclass_reference(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (attributes != null) + { + copy.attributes = (attribute_list)attributes.Clone(); + copy.attributes.Parent = copy; + } + if (attr_list != null) + { + copy.attr_list = (type_definition_attr_list)attr_list.Clone(); + copy.attr_list.Parent = copy; + } + if (names != null) + { + foreach (ident elem in names) + { + if (elem != null) + { + copy.Add((ident)elem.Clone()); + copy.Last().Parent = copy; + } + else + copy.Add(null); + } + } + if (restriction_args != null) + { + copy.restriction_args = (template_param_list)restriction_args.Clone(); + copy.restriction_args.Parent = copy; + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new typeclass_reference TypedClone() + { + return Clone() as typeclass_reference; + } + + /// Заполняет поля Parent в непосредственных дочерних узлах + public override void FillParentsInDirectChilds() + { + if (attributes != null) + attributes.Parent = this; + if (attr_list != null) + attr_list.Parent = this; + if (names != null) + { + foreach (var child in names) + if (child != null) + child.Parent = this; + } + if (restriction_args != null) + restriction_args.Parent = this; + } + + /// Заполняет поля Parent во всем поддереве + public override void FillParentsInAllChilds() + { + FillParentsInDirectChilds(); + attributes?.FillParentsInAllChilds(); + attr_list?.FillParentsInAllChilds(); + if (names != null) + { + foreach (var child in names) + child?.FillParentsInAllChilds(); + } + restriction_args?.FillParentsInAllChilds(); + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 2; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 2 + (names == null ? 0 : names.Count); + } + } + /// + ///Индексатор для получения всех подузлов + /// + public override syntax_tree_node this[Int32 ind] + { + get + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + return attr_list; + case 1: + return restriction_args; + } + Int32 index_counter=ind - 2; + if(names != null) + { + if(index_counter < names.Count) + { + return names[index_counter]; + } + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + attr_list = (type_definition_attr_list)value; + break; + case 1: + restriction_args = (template_param_list)value; + break; + } + Int32 index_counter=ind - 2; + if(names != null) + { + if(index_counter < names.Count) + { + names[index_counter]= (ident)value; + return; + } + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + /// /// /// diff --git a/SyntaxTree/tree/Visitor.cs b/SyntaxTree/tree/Visitor.cs index d1feebca8..65f4d4330 100644 --- a/SyntaxTree/tree/Visitor.cs +++ b/SyntaxTree/tree/Visitor.cs @@ -1337,6 +1337,42 @@ namespace PascalABCCompiler.SyntaxTree /// Return value is void void visit(double_question_node _double_question_node); /// + ///Method to visit typeclass_restriction. + /// + ///Node to visit + /// Return value is void + void visit(typeclass_restriction _typeclass_restriction); + /// + ///Method to visit instance_definition. + /// + ///Node to visit + /// Return value is void + void visit(instance_definition _instance_definition); + /// + ///Method to visit typeclass_definition. + /// + ///Node to visit + /// Return value is void + void visit(typeclass_definition _typeclass_definition); + /// + ///Method to visit where_typeclass_constraint. + /// + ///Node to visit + /// Return value is void + void visit(where_typeclass_constraint _where_typeclass_constraint); + /// + ///Method to visit typeclass_param_list. + /// + ///Node to visit + /// Return value is void + void visit(typeclass_param_list _typeclass_param_list); + /// + ///Method to visit typeclass_reference. + /// + ///Node to visit + /// Return value is void + void visit(typeclass_reference _typeclass_reference); + /// ///Method to visit pattern_node. /// ///Node to visit diff --git a/SyntaxTree/tree/tree.xml b/SyntaxTree/tree/tree.xml index c325736da..dabed3373 100644 --- a/SyntaxTree/tree/tree.xml +++ b/SyntaxTree/tree/tree.xml @@ -2863,6 +2863,105 @@ + + + + + + + + 0 + + + 10 + + + + + + + + + + + 0 + 0 + 0 + + + 4 + 5 + 10 + + + + + + + + + + + + 0 + 0 + 0 + + + 4 + 5 + 10 + + + + + + + + + + + 0 + + + 10 + + + + + + + + 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) +{ +} + + + + + 0 + + + 10 + + + + + + + + + + + 0 + 0 + + + 4 + 10 + + + diff --git a/SyntaxTreeConverters/StandardSyntaxConverter.cs b/SyntaxTreeConverters/StandardSyntaxConverter.cs index a548dfa80..9f22d2154 100644 --- a/SyntaxTreeConverters/StandardSyntaxConverter.cs +++ b/SyntaxTreeConverters/StandardSyntaxConverter.cs @@ -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 diff --git a/SyntaxVisitors/SyntaxVisitors.csproj b/SyntaxVisitors/SyntaxVisitors.csproj index b0fafa43a..43ffb85af 100644 --- a/SyntaxVisitors/SyntaxVisitors.csproj +++ b/SyntaxVisitors/SyntaxVisitors.csproj @@ -58,6 +58,9 @@ + + + diff --git a/SyntaxVisitors/TypeclassVisitors/FindInstancesAndRestrictedFunctionsVisitor.cs b/SyntaxVisitors/TypeclassVisitors/FindInstancesAndRestrictedFunctionsVisitor.cs new file mode 100644 index 000000000..2049a45ba --- /dev/null +++ b/SyntaxVisitors/TypeclassVisitors/FindInstancesAndRestrictedFunctionsVisitor.cs @@ -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 typeclasses; + // (Typeclass name) -> [Instances] + public Dictionary> instances = new Dictionary>(); + public Dictionary> restrictedFunctions = new Dictionary>(); + + + public FindInstancesAndRestrictedFunctionsVisitor(Dictionary typeclasses) + { + this.typeclasses = typeclasses; + + foreach (var typeclass in typeclasses) + { + instances.Add(typeclass.Key, new List()); + } + } + + + public static FindInstancesAndRestrictedFunctionsVisitor New(Dictionary 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() + .Select(x => x.restriction.name).ToList(); + + restrictedFunctions.Add(procedureDefinition.proc_header.name.meth_name.name, + usedTypeclasses); + } + } +} diff --git a/SyntaxVisitors/TypeclassVisitors/FindTypeclassesVisitor.cs b/SyntaxVisitors/TypeclassVisitors/FindTypeclassesVisitor.cs new file mode 100644 index 000000000..9b163a958 --- /dev/null +++ b/SyntaxVisitors/TypeclassVisitors/FindTypeclassesVisitor.cs @@ -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 typeclasses = new Dictionary(); + + + 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); + } + } +} diff --git a/SyntaxVisitors/TypeclassVisitors/ReplaceTypeclassVisitor.cs b/SyntaxVisitors/TypeclassVisitors/ReplaceTypeclassVisitor.cs new file mode 100644 index 000000000..971122aab --- /dev/null +++ b/SyntaxVisitors/TypeclassVisitors/ReplaceTypeclassVisitor.cs @@ -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 templateLists = instanceName.restriction_args.params_list.Concat(templateArgs.idents.Select(x => new named_type_reference(x.name)).OfType()).ToList(); + var parents = new named_type_reference_list(new List { + 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(); + 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().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 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(); + foreach (var tcr in _procedure_definition.proc_body.DescendantNodes().OfType()) + { + 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 { 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 { + // IConstraint, + 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(); + 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 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 GetTranslatedTypeclassParameters(List paramList, IEnumerable typeclasses) + { + var possibleOverloadingsForEachTypeclass = typeclasses.Select(x => + new KeyValuePair>(x, instancesAndRestrictedFunctions.instances[x])); + + // Find current overloading in possible + var newParams = new List(); + 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().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); + } + } + + + +} diff --git a/TreeConverter/TreeConversion/compilation_context.cs b/TreeConverter/TreeConversion/compilation_context.cs index 43a84492f..414b60209 100644 --- a/TreeConverter/TreeConversion/compilation_context.cs +++ b/TreeConverter/TreeConversion/compilation_context.cs @@ -200,6 +200,8 @@ namespace PascalABCCompiler.TreeConverter internal List var_defs = new List(); + public List typeclassInstances = new List(); + internal Stack> var_defs_stack = new Stack>(); @@ -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) { //Нет функции с таким именем, набором параметров и возвращаемым значением diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 354237d99..5f5694d7b 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -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)); diff --git a/TreeConverter/TreeRealization/generics.cs b/TreeConverter/TreeRealization/generics.cs index 24115239e..8df393c4c 100644 --- a/TreeConverter/TreeRealization/generics.cs +++ b/TreeConverter/TreeRealization/generics.cs @@ -837,6 +837,9 @@ namespace PascalABCCompiler.TreeRealization var continue_trying_to_infer_types = true; Dictionary 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()); + + 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 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 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 nils) {