Merge commit '082a998786a49e4e3f3ce0ad799fe1c7b6a90fb7' into features/typeclasses-another-approach
# Conflicts: # Parsers/PascalABCParserNewSaushkin/ABCPascal.cs # Parsers/PascalABCParserNewSaushkin/ABCPascal.lex # Parsers/PascalABCParserNewSaushkin/ABCPascal.y # Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs # SyntaxTree/tree/AbstractVisitor.cs # SyntaxTree/tree/HierarchyVisitor.cs # SyntaxTree/tree/SyntaxTreeStreamReader.cs # SyntaxTree/tree/SyntaxTreeStreamWriter.cs # SyntaxTree/tree/Tree.cs # SyntaxTree/tree/Visitor.cs # SyntaxTree/tree/tree.xml # TestSuite/CompilationSamples/PABCSystem.pas # bin/Lib/PABCSystem.pas
This commit is contained in:
commit
a315f9f063
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -8,6 +8,8 @@ bin/*.dll
|
|||
bin/*.pdb
|
||||
bin/*.config
|
||||
bin/*.xml
|
||||
bin/log.txt
|
||||
bin/CompilerController.ini
|
||||
|
||||
TestSuite/CompilationSamples/*.pcu
|
||||
TestSuite/CompilationSamples/*.pdb
|
||||
|
|
|
|||
|
|
@ -2954,6 +2954,69 @@ namespace CodeFormatters
|
|||
visit_node(_slice_expr_question.step);
|
||||
}
|
||||
|
||||
public override void visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
if (_is_pattern_expr.left != null)
|
||||
{
|
||||
add_space_after = true;
|
||||
visit_node(_is_pattern_expr.left);
|
||||
}
|
||||
if (_is_pattern_expr.right != null)
|
||||
{
|
||||
add_space_before = true;
|
||||
visit_node(_is_pattern_expr.right);
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(type_pattern _type_pattern)
|
||||
{
|
||||
if (_type_pattern.type != null)
|
||||
visit_node(_type_pattern.type);
|
||||
//if (_type_pattern.identifier != null)
|
||||
// visit_node(_type_pattern.identifier);
|
||||
}
|
||||
|
||||
public override void visit(match_with _match_with)
|
||||
{
|
||||
visit_node(_match_with.expr);
|
||||
IncOffset();
|
||||
add_space_before = true;
|
||||
visit_node(_match_with.case_list);
|
||||
//add_space_before = false;
|
||||
DecOffset();
|
||||
}
|
||||
|
||||
public override void visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
foreach (var patternCase in _pattern_cases.elements)
|
||||
visit_node(patternCase);
|
||||
}
|
||||
|
||||
public override void visit(pattern_case _pattern_case)
|
||||
{
|
||||
visit_node(_pattern_case.pattern);
|
||||
|
||||
if (_pattern_case.condition != null)
|
||||
{
|
||||
add_space_before = true;
|
||||
visit_node(_pattern_case.condition);
|
||||
}
|
||||
|
||||
add_space_before = true;
|
||||
visit_node(_pattern_case.case_action);
|
||||
}
|
||||
|
||||
public override void visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
visit_node(_deconstructor_pattern.type);
|
||||
foreach (var parameter in _deconstructor_pattern.parameters)
|
||||
{
|
||||
visit_node(parameter.identifier);
|
||||
if (parameter.type != null)
|
||||
visit_node(parameter.type);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -124,6 +124,7 @@ namespace PascalABCCompiler.Parsers
|
|||
keywords.Add("namespace", "namespace"); keys.Add("namespace");
|
||||
keywords.Add("exit", "exit"); keys.Add("exit");
|
||||
keywords.Add("event", "event"); keys.Add("event");
|
||||
keywords.Add("match", "match"); keys.Add("match");
|
||||
//keywords.Add("typeof", "typeof"); //keys.Add("typeof");
|
||||
//keywords.Add("sizeof", "sizeof"); //keys.Add("sizeof");
|
||||
keywords_array = new string[keywords.Count + 2];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// This CSharp output file generated by Gardens Point LEX
|
||||
// Version: 1.1.3.301
|
||||
// Machine: OBERON
|
||||
// DateTime: 5/14/2018 5:22:51 PM
|
||||
// DateTime: 5/14/2018 5:56:10 PM
|
||||
// UserName: voganesyan
|
||||
// GPLEX input file <ABCPascal.lex>
|
||||
// GPLEX frame file <embedded resource>
|
||||
|
|
@ -1954,6 +1954,8 @@ string cur_yytext = yytext;
|
|||
case (int)Tokens.tkSequence:
|
||||
case (int)Tokens.tkTypeclass:
|
||||
case (int)Tokens.tkInstance:
|
||||
case (int)Tokens.tkMatch:
|
||||
case (int)Tokens.tkWhen:
|
||||
yylval = new Union();
|
||||
yylval.ti = new token_info(cur_yytext,currentLexLocation);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -362,6 +362,8 @@ UNICODEARROW \x890
|
|||
case (int)Tokens.tkSequence:
|
||||
case (int)Tokens.tkTypeclass:
|
||||
case (int)Tokens.tkInstance:
|
||||
case (int)Tokens.tkMatch:
|
||||
case (int)Tokens.tkWhen:
|
||||
yylval = new Union();
|
||||
yylval.ti = new token_info(cur_yytext,currentLexLocation);
|
||||
break;
|
||||
|
|
|
|||
4077
Parsers/PascalABCParserNewSaushkin/ABCPascal.lst
Normal file
4077
Parsers/PascalABCParserNewSaushkin/ABCPascal.lst
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -32,7 +32,7 @@
|
|||
%start parse_goal
|
||||
|
||||
%token <ti> tkDirectiveName tkAmpersend tkColon tkDotDot tkPoint tkRoundOpen tkRoundClose tkSemiColon tkSquareOpen tkSquareClose tkQuestion tkQuestionPoint tkDoubleQuestion tkQuestionSquareOpen
|
||||
%token <ti> tkSizeOf tkTypeOf tkWhere tkArray tkCase tkClass tkAuto tkConst tkConstructor tkDestructor tkElse tkExcept tkFile tkFor tkForeach tkFunction
|
||||
%token <ti> tkSizeOf tkTypeOf tkWhere tkArray tkCase tkClass tkAuto tkConst tkConstructor tkDestructor tkElse tkExcept tkFile tkFor tkForeach tkFunction tkMatch tkWhen
|
||||
%token <ti> tkIf tkImplementation tkInherited tkInterface tkTypeclass tkInstance tkProcedure tkOperator tkProperty tkRaise tkRecord tkSet tkType tkThen tkUses tkVar tkWhile tkWith tkNil
|
||||
%token <ti> tkGoto tkOf tkLabel tkLock tkProgram tkEvent tkDefault tkTemplate tkPacked tkExports tkResourceString tkThreadvar tkSealed tkPartial tkTo tkDownto
|
||||
%token <ti> tkLoop
|
||||
|
|
@ -145,7 +145,7 @@
|
|||
%type <stn> simple_prim_property_definition simple_property_definition
|
||||
%type <stn> stmt_or_expression unlabelled_stmt stmt case_item
|
||||
%type <td> set_type
|
||||
%type <ex> as_is_expr as_is_constexpr power_expr power_constexpr
|
||||
%type <ex> as_is_expr as_is_constexpr is_expr as_expr power_expr power_constexpr
|
||||
%type <td> unsized_array_type simple_type_or_ simple_type array_name_for_new_expr foreach_stmt_ident_dype_opt fptype type_ref fptype_noproctype array_type
|
||||
%type <td> template_param structured_type unpacked_structured_type simple_or_template_type_reference type_ref_or_secific for_stmt_decl_or_assign type_decl_type
|
||||
%type <stn> type_ref_and_secific_list
|
||||
|
|
@ -175,7 +175,8 @@
|
|||
%type <stn> full_lambda_fp_list lambda_simple_fp_sect lambda_function_body lambda_procedure_body optional_full_lambda_fp_list
|
||||
%type <ob> field_in_unnamed_object list_fields_in_unnamed_object func_class_name_ident_list rem_lambda variable_list var_ident_list
|
||||
%type <ti> tkAssignOrEqual
|
||||
|
||||
%type <stn> pattern match_with pattern_case pattern_cases pattern_out_param
|
||||
%type <ob> pattern_out_param_list
|
||||
%%
|
||||
|
||||
parse_goal
|
||||
|
|
@ -2447,6 +2448,8 @@ unlabelled_stmt
|
|||
{ $$ = $1; }
|
||||
| loop_stmt
|
||||
{ $$ = $1; }
|
||||
| match_with
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
loop_stmt
|
||||
|
|
@ -2576,6 +2579,37 @@ if_stmt
|
|||
}
|
||||
;
|
||||
|
||||
match_with
|
||||
: tkMatch expr_l1 tkWith pattern_cases else_case tkEnd
|
||||
{
|
||||
$$ = new match_with($2, $4 as pattern_cases, $5 as statement, @$);
|
||||
}
|
||||
;
|
||||
|
||||
pattern_cases
|
||||
: pattern_case
|
||||
{
|
||||
$$ = new pattern_cases($1 as pattern_case);
|
||||
}
|
||||
| pattern_cases tkSemiColon pattern_case
|
||||
{
|
||||
$$ = ($1 as pattern_cases).Add($3 as pattern_case);
|
||||
}
|
||||
;
|
||||
|
||||
pattern_case
|
||||
:
|
||||
{ $$ = new empty_statement(); }
|
||||
| pattern tkWhen expr_l1 tkColon unlabelled_stmt
|
||||
{
|
||||
$$ = new pattern_case($1 as pattern_node, $5 as statement, $3, @$);
|
||||
}
|
||||
| pattern tkColon unlabelled_stmt
|
||||
{
|
||||
$$ = new pattern_case($1 as pattern_node, $3 as statement, null, @$);
|
||||
}
|
||||
;
|
||||
|
||||
case_stmt
|
||||
: tkCase expr_l1 tkOf case_list else_case tkEnd
|
||||
{
|
||||
|
|
@ -2584,7 +2618,7 @@ case_stmt
|
|||
;
|
||||
|
||||
case_list
|
||||
: case_item
|
||||
: case_item
|
||||
{
|
||||
if ($1 is empty_statement)
|
||||
$$ = NewCaseItem($1, null);
|
||||
|
|
@ -3019,8 +3053,47 @@ relop_expr
|
|||
{
|
||||
$$ = new bin_expr($1, $3, $2.type, @$);
|
||||
}
|
||||
| is_expr tkRoundOpen tkVar identifier tkRoundClose
|
||||
{
|
||||
var isTypeCheck = $1 as typecast_node;
|
||||
var typeDef = isTypeCheck.type_def;
|
||||
var pattern = new type_pattern($4, typeDef, typeDef.source_context);
|
||||
$$ = new is_pattern_expr(isTypeCheck.expr, pattern, @$);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
pattern
|
||||
: simple_or_template_type_reference tkRoundOpen pattern_out_param_list tkRoundClose
|
||||
{
|
||||
$$ = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, $1, @$);
|
||||
}
|
||||
;
|
||||
|
||||
pattern_out_param_list
|
||||
: pattern_out_param
|
||||
{
|
||||
$$ = new List<pattern_deconstructor_parameter>();
|
||||
($$ as List<pattern_deconstructor_parameter>).Add($1 as pattern_deconstructor_parameter);
|
||||
}
|
||||
| pattern_out_param_list tkSemiColon pattern_out_param
|
||||
{
|
||||
var list = $1 as List<pattern_deconstructor_parameter>;
|
||||
list.Add($3 as pattern_deconstructor_parameter);
|
||||
$$ = list;
|
||||
}
|
||||
;
|
||||
|
||||
pattern_out_param
|
||||
: identifier tkColon type_ref
|
||||
{
|
||||
$$ = new pattern_deconstructor_parameter($1, $3, @$);
|
||||
}
|
||||
| identifier
|
||||
{
|
||||
$$ = new pattern_deconstructor_parameter($1, null, @$);
|
||||
}
|
||||
;
|
||||
|
||||
simple_expr_or_nothing
|
||||
: simple_expr
|
||||
{
|
||||
|
|
@ -3102,12 +3175,26 @@ typecast_op
|
|||
;
|
||||
|
||||
as_is_expr
|
||||
: term typecast_op simple_or_template_type_reference
|
||||
{
|
||||
$$ = NewAsIsExpr($1, (op_typecast)$2, $3, @$);
|
||||
}
|
||||
: is_expr
|
||||
{ $$ = $1; }
|
||||
| as_expr
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
as_expr
|
||||
: term tkAs simple_or_template_type_reference
|
||||
{
|
||||
$$ = NewAsIsExpr($1, op_typecast.as_op, $3, @$);
|
||||
}
|
||||
;
|
||||
|
||||
is_expr
|
||||
: term tkIs simple_or_template_type_reference
|
||||
{
|
||||
$$ = NewAsIsExpr($1, op_typecast.is_op, $3, @$);
|
||||
}
|
||||
;
|
||||
|
||||
simple_term
|
||||
: factor
|
||||
{ $$ = $1; }
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -141,6 +141,8 @@ namespace GPPGParserScanner
|
|||
keywords.Add(Convert("auto"), (int)Tokens.tkAuto);
|
||||
keywords.Add(Convert("sequence"), (int)Tokens.tkSequence);
|
||||
keywords.Add(Convert("yield"), (int)Tokens.tkYield);
|
||||
keywords.Add(Convert("match"), (int)Tokens.tkMatch);
|
||||
keywords.Add(Convert("when"), (int)Tokens.tkWhen);
|
||||
keywords.Add(Convert("namespace"), (int)Tokens.tkNamespace);
|
||||
keywords.Add(Convert("typeclass"), (int)Tokens.tkTypeclass);
|
||||
keywords.Add(Convert("instance"), (int)Tokens.tkInstance);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
|||
using System.Runtime.Serialization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using System.IO;
|
||||
|
||||
namespace QUT.Gppg
|
||||
{
|
||||
|
|
@ -140,7 +141,7 @@ namespace QUT.Gppg
|
|||
/// <param name="names">Non-terminal symbol names</param>
|
||||
protected void InitNonTerminals(string[] names) { nonTerminals = names; }
|
||||
|
||||
#region YYAbort, YYAccept etcetera.
|
||||
#region YYAbort, YYAccept etcetera.
|
||||
[Serializable]
|
||||
[SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic")]
|
||||
// Reason for FxCop message suppression -
|
||||
|
|
@ -194,7 +195,7 @@ namespace QUT.Gppg
|
|||
/// Check if parser in error recovery state.
|
||||
/// </summary>
|
||||
protected bool YYRecovering { get { return recovering; } }
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base method. ShiftReduceParser calls this
|
||||
|
|
@ -488,7 +489,7 @@ namespace QUT.Gppg
|
|||
{
|
||||
#if TRACE_ACTIONS
|
||||
Console.Error.Write("Reading a token: ");
|
||||
#endif
|
||||
#endif
|
||||
NextToken = scanner.yylex();
|
||||
}
|
||||
|
||||
|
|
|
|||
3
Patterns/.gitignore
vendored
Normal file
3
Patterns/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// Ignore PascalABC.NET compiler output
|
||||
*.pdb
|
||||
*.exe
|
||||
39
Patterns/All-examples.pas
Normal file
39
Patterns/All-examples.pas
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Switch-statement
|
||||
|
||||
begin
|
||||
var a := new List<integer>(arr(1, 2));
|
||||
match a with
|
||||
integer(var c) when c = 3: write(1);
|
||||
string(var s) when not string.IsNullOrEmpty(s): write(2);
|
||||
List<integer>(var l) when l.Count > 0: write(3)
|
||||
end;
|
||||
end.
|
||||
|
||||
// User defined
|
||||
|
||||
type
|
||||
Person = class
|
||||
name: string;
|
||||
age: integer;
|
||||
|
||||
function Deconstruct(p: Person; name: string; age: integer): boolean;
|
||||
begin
|
||||
name := p.name;
|
||||
age := p.age;
|
||||
result := true;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
var p := new Person;
|
||||
if p is Person(var name, var age) then
|
||||
Print(name, ' ', age);
|
||||
end.
|
||||
|
||||
// Recursive patterns
|
||||
|
||||
begin
|
||||
if (tree is BinOp(IntConst(var ln), IntConst(var rn))) then
|
||||
tree = new IntConst(ln + rn);
|
||||
end.
|
||||
57
Patterns/Desugaring-v2.pas
Normal file
57
Patterns/Desugaring-v2.pas
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Source
|
||||
match e with
|
||||
Person(var value): <ACTION>
|
||||
end;
|
||||
|
||||
// Desugared code
|
||||
|
||||
var <>genVarExpr := e;
|
||||
var <>genVar: Person;
|
||||
if IsTest(<>genVarExpr, <>genVar) then
|
||||
begin
|
||||
// always the same code
|
||||
var value: ?; // should be filled during semantic analysis
|
||||
<>genVar.Deconstruct(value);
|
||||
|
||||
<ACTION>
|
||||
end;
|
||||
|
||||
{
|
||||
info we need to fill the tree:
|
||||
1. Syntactic nodes of parameters' types
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
|
||||
// Source
|
||||
if e is Person(var value) then
|
||||
<ACTION>
|
||||
|
||||
// Desugared code
|
||||
|
||||
var <>genVar: Person;
|
||||
if IsTest(e, <>genVar) then
|
||||
begin
|
||||
// always the same code
|
||||
var value: ?; // should be filled during semantic analysis
|
||||
<>genVar.Deconstruct(value);
|
||||
|
||||
<ACTION>
|
||||
end;
|
||||
|
||||
// ****************************************************************************
|
||||
|
||||
// Source
|
||||
var res := e is Person(var value);
|
||||
|
||||
// Desugared code
|
||||
|
||||
var <>genVar: Person;
|
||||
if IsTest(e, <>genVar) then
|
||||
begin
|
||||
// always the same code
|
||||
var value: ?; // should be filled during semantic analysis
|
||||
<>genVar.Deconstruct(value);
|
||||
|
||||
<ACTION>
|
||||
end;
|
||||
45
Patterns/Desugaring.pas
Normal file
45
Patterns/Desugaring.pas
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Source
|
||||
match e with
|
||||
Person(var value): <ACTION>
|
||||
end;
|
||||
|
||||
// Desugared code
|
||||
|
||||
var <>genVar: Person;
|
||||
if IsTest(e, <>genVar) then
|
||||
begin
|
||||
// one of 3 cases
|
||||
|
||||
// *********************************************************
|
||||
|
||||
// 1 - instance deconstruct
|
||||
var value: ?; // should be filled during semantic analysis
|
||||
<>genVar.Deconstruct(value);
|
||||
|
||||
// 2 - extension deconstruct
|
||||
var value: ?; // should be filled during semantic analysis
|
||||
PersonExt.Deconstruct(<>genVar, value);
|
||||
|
||||
// 3 - typecast - when there's only one deconstruction parameter and no Deconstruct methods were found
|
||||
var value := <>genVar;
|
||||
|
||||
// *********************************************************
|
||||
|
||||
<ACTION>
|
||||
end;
|
||||
|
||||
{
|
||||
info we need to fill the tree:
|
||||
1. Method type (instance or static) and a qualifier if static
|
||||
2. Syntactic nodes of parameters' types
|
||||
|
||||
General: how to get the type of expression
|
||||
|
||||
case 1:
|
||||
How to check if a certain type has instance method with given name - option 1
|
||||
Save information about all Deconstruct methods during creation of a semantic tree - option 2
|
||||
|
||||
case 2:
|
||||
|
||||
|
||||
}
|
||||
8
Patterns/patterns-switch.pas
Normal file
8
Patterns/patterns-switch.pas
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
begin
|
||||
var a := new List<integer>(arr(1, 2));
|
||||
match a with
|
||||
integer(var c): write(1);
|
||||
boolean(var s): write(2);
|
||||
List<integer>(var l) when l.Count > 0 :write(3)
|
||||
end;
|
||||
end.
|
||||
19
Patterns/patterns-user-defined.pas
Normal file
19
Patterns/patterns-user-defined.pas
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
type
|
||||
Person = class
|
||||
name: string;
|
||||
age: integer;
|
||||
|
||||
class function Deconstruct(p: Person; name: string; age: integer): boolean;
|
||||
begin
|
||||
name := p.name;
|
||||
age := p.age;
|
||||
result := true;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
var p := new Person;
|
||||
if p is Person(var name, var age) then
|
||||
Print(name, ' ', age);
|
||||
end.
|
||||
26
Patterns/patterns.pas
Normal file
26
Patterns/patterns.pas
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
type
|
||||
Person = auto class
|
||||
name: string;
|
||||
age: integer;
|
||||
end;
|
||||
|
||||
type
|
||||
Student = class(Person);
|
||||
|
||||
begin
|
||||
var b1 := new Student('asd', 30) is Person(var c);
|
||||
writeln(c);
|
||||
|
||||
var b2 := 1 is integer(var d);
|
||||
writeln(d);
|
||||
|
||||
var arr := Arr(1, 3, 5, 7, 9);
|
||||
|
||||
var l := new List<integer>(arr);
|
||||
var b4 := l is List<integer>(var f);
|
||||
writeln(f);
|
||||
|
||||
var delegate: Func<word, char> := PABCSystem.ChrUnicode;
|
||||
var b5 := delegate is Func<word, char>(var g);
|
||||
writeln(g);
|
||||
end.
|
||||
|
|
@ -1147,6 +1147,51 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
DefaultVisit(_typeclass_reference);
|
||||
}
|
||||
|
||||
public virtual void visit(pattern_node _pattern_node)
|
||||
{
|
||||
DefaultVisit(_pattern_node);
|
||||
}
|
||||
|
||||
public virtual void visit(type_pattern _type_pattern)
|
||||
{
|
||||
DefaultVisit(_type_pattern);
|
||||
}
|
||||
|
||||
public virtual void visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
DefaultVisit(_is_pattern_expr);
|
||||
}
|
||||
|
||||
public virtual void visit(match_with _match_with)
|
||||
{
|
||||
DefaultVisit(_match_with);
|
||||
}
|
||||
|
||||
public virtual void visit(pattern_case _pattern_case)
|
||||
{
|
||||
DefaultVisit(_pattern_case);
|
||||
}
|
||||
|
||||
public virtual void visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
DefaultVisit(_pattern_cases);
|
||||
}
|
||||
|
||||
public virtual void visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
DefaultVisit(_deconstructor_pattern);
|
||||
}
|
||||
|
||||
public virtual void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
DefaultVisit(_pattern_deconstructor_parameter);
|
||||
}
|
||||
|
||||
public virtual void visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
DefaultVisit(_desugared_deconstruction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1829,6 +1829,78 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(pattern_node _pattern_node)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(pattern_node _pattern_node)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(type_pattern _type_pattern)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(type_pattern _type_pattern)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(match_with _match_with)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(match_with _match_with)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(pattern_case _pattern_case)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(pattern_case _pattern_case)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
}
|
||||
|
||||
public override void visit(expression _expression)
|
||||
{
|
||||
DefaultVisit(_expression);
|
||||
|
|
@ -3779,6 +3851,88 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
visit(typeclass_reference.restriction_args);
|
||||
post_do_visit(_typeclass_reference);
|
||||
}
|
||||
|
||||
public override void visit(pattern_node _pattern_node)
|
||||
{
|
||||
DefaultVisit(_pattern_node);
|
||||
pre_do_visit(_pattern_node);
|
||||
post_do_visit(_pattern_node);
|
||||
}
|
||||
|
||||
public override void visit(type_pattern _type_pattern)
|
||||
{
|
||||
DefaultVisit(_type_pattern);
|
||||
pre_do_visit(_type_pattern);
|
||||
visit(type_pattern.identifier);
|
||||
visit(type_pattern.type);
|
||||
post_do_visit(_type_pattern);
|
||||
}
|
||||
|
||||
public override void visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
DefaultVisit(_is_pattern_expr);
|
||||
pre_do_visit(_is_pattern_expr);
|
||||
visit(is_pattern_expr.left);
|
||||
visit(is_pattern_expr.right);
|
||||
post_do_visit(_is_pattern_expr);
|
||||
}
|
||||
|
||||
public override void visit(match_with _match_with)
|
||||
{
|
||||
DefaultVisit(_match_with);
|
||||
pre_do_visit(_match_with);
|
||||
visit(match_with.expr);
|
||||
visit(match_with.case_list);
|
||||
visit(match_with.defaultAction);
|
||||
post_do_visit(_match_with);
|
||||
}
|
||||
|
||||
public override void visit(pattern_case _pattern_case)
|
||||
{
|
||||
DefaultVisit(_pattern_case);
|
||||
pre_do_visit(_pattern_case);
|
||||
visit(pattern_case.pattern);
|
||||
visit(pattern_case.case_action);
|
||||
visit(pattern_case.condition);
|
||||
post_do_visit(_pattern_case);
|
||||
}
|
||||
|
||||
public override void visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
DefaultVisit(_pattern_cases);
|
||||
pre_do_visit(_pattern_cases);
|
||||
for (int i = 0; i < elements.Count; i++)
|
||||
visit(pattern_cases.elements[i]);
|
||||
post_do_visit(_pattern_cases);
|
||||
}
|
||||
|
||||
public override void visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
DefaultVisit(_deconstructor_pattern);
|
||||
pre_do_visit(_deconstructor_pattern);
|
||||
for (int i = 0; i < parameters.Count; i++)
|
||||
visit(deconstructor_pattern.parameters[i]);
|
||||
visit(deconstructor_pattern.type);
|
||||
post_do_visit(_deconstructor_pattern);
|
||||
}
|
||||
|
||||
public override void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
DefaultVisit(_pattern_deconstructor_parameter);
|
||||
pre_do_visit(_pattern_deconstructor_parameter);
|
||||
visit(pattern_deconstructor_parameter.identifier);
|
||||
visit(pattern_deconstructor_parameter.type);
|
||||
post_do_visit(_pattern_deconstructor_parameter);
|
||||
}
|
||||
|
||||
public override void visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
DefaultVisit(_desugared_deconstruction);
|
||||
pre_do_visit(_desugared_deconstruction);
|
||||
for (int i = 0; i < definitions.Count; i++)
|
||||
visit(desugared_deconstruction.definitions[i]);
|
||||
post_do_visit(_desugared_deconstruction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -476,6 +476,24 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
return new typeclass_param_list();
|
||||
case 227:
|
||||
return new typeclass_reference();
|
||||
case 228:
|
||||
return new pattern_node();
|
||||
case 229:
|
||||
return new type_pattern();
|
||||
case 230:
|
||||
return new is_pattern_expr();
|
||||
case 231:
|
||||
return new match_with();
|
||||
case 232:
|
||||
return new pattern_case();
|
||||
case 233:
|
||||
return new pattern_cases();
|
||||
case 234:
|
||||
return new deconstructor_pattern();
|
||||
case 235:
|
||||
return new pattern_deconstructor_parameter();
|
||||
case 236:
|
||||
return new desugared_deconstruction();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -4004,6 +4022,158 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
_typeclass_reference.restriction_args = _read_node() as template_param_list;
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_node _pattern_node)
|
||||
{
|
||||
read_pattern_node(_pattern_node);
|
||||
}
|
||||
|
||||
public void read_pattern_node(pattern_node _pattern_node)
|
||||
{
|
||||
read_syntax_tree_node(_pattern_node);
|
||||
}
|
||||
|
||||
|
||||
public void visit(type_pattern _type_pattern)
|
||||
{
|
||||
read_type_pattern(_type_pattern);
|
||||
}
|
||||
|
||||
public void read_type_pattern(type_pattern _type_pattern)
|
||||
{
|
||||
read_pattern_node(_type_pattern);
|
||||
_type_pattern.identifier = _read_node() as ident;
|
||||
_type_pattern.type = _read_node() as type_definition;
|
||||
}
|
||||
|
||||
|
||||
public void visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
read_is_pattern_expr(_is_pattern_expr);
|
||||
}
|
||||
|
||||
public void read_is_pattern_expr(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
read_expression(_is_pattern_expr);
|
||||
_is_pattern_expr.left = _read_node() as expression;
|
||||
_is_pattern_expr.right = _read_node() as pattern_node;
|
||||
}
|
||||
|
||||
|
||||
public void visit(match_with _match_with)
|
||||
{
|
||||
read_match_with(_match_with);
|
||||
}
|
||||
|
||||
public void read_match_with(match_with _match_with)
|
||||
{
|
||||
read_statement(_match_with);
|
||||
_match_with.expr = _read_node() as expression;
|
||||
_match_with.case_list = _read_node() as pattern_cases;
|
||||
_match_with.defaultAction = _read_node() as statement;
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_case _pattern_case)
|
||||
{
|
||||
read_pattern_case(_pattern_case);
|
||||
}
|
||||
|
||||
public void read_pattern_case(pattern_case _pattern_case)
|
||||
{
|
||||
read_statement(_pattern_case);
|
||||
_pattern_case.pattern = _read_node() as pattern_node;
|
||||
_pattern_case.case_action = _read_node() as statement;
|
||||
_pattern_case.condition = _read_node() as expression;
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
read_pattern_cases(_pattern_cases);
|
||||
}
|
||||
|
||||
public void read_pattern_cases(pattern_cases _pattern_cases)
|
||||
{
|
||||
read_statement(_pattern_cases);
|
||||
if (br.ReadByte() == 0)
|
||||
{
|
||||
_pattern_cases.elements = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pattern_cases.elements = new List<pattern_case>();
|
||||
Int32 ssyy_count = br.ReadInt32();
|
||||
for(Int32 ssyy_i = 0; ssyy_i < ssyy_count; ssyy_i++)
|
||||
{
|
||||
_pattern_cases.elements.Add(_read_node() as pattern_case);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
read_deconstructor_pattern(_deconstructor_pattern);
|
||||
}
|
||||
|
||||
public void read_deconstructor_pattern(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
read_pattern_node(_deconstructor_pattern);
|
||||
if (br.ReadByte() == 0)
|
||||
{
|
||||
_deconstructor_pattern.parameters = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_deconstructor_pattern.parameters = new List<pattern_deconstructor_parameter>();
|
||||
Int32 ssyy_count = br.ReadInt32();
|
||||
for(Int32 ssyy_i = 0; ssyy_i < ssyy_count; ssyy_i++)
|
||||
{
|
||||
_deconstructor_pattern.parameters.Add(_read_node() as pattern_deconstructor_parameter);
|
||||
}
|
||||
}
|
||||
_deconstructor_pattern.type = _read_node() as type_definition;
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
read_pattern_deconstructor_parameter(_pattern_deconstructor_parameter);
|
||||
}
|
||||
|
||||
public void read_pattern_deconstructor_parameter(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
read_syntax_tree_node(_pattern_deconstructor_parameter);
|
||||
_pattern_deconstructor_parameter.identifier = _read_node() as ident;
|
||||
_pattern_deconstructor_parameter.type = _read_node() as type_definition;
|
||||
}
|
||||
|
||||
|
||||
public void visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
read_desugared_deconstruction(_desugared_deconstruction);
|
||||
}
|
||||
|
||||
public void read_desugared_deconstruction(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
read_statement(_desugared_deconstruction);
|
||||
if (br.ReadByte() == 0)
|
||||
{
|
||||
_desugared_deconstruction.definitions = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_desugared_deconstruction.definitions = new List<var_def_statement>();
|
||||
Int32 ssyy_count = br.ReadInt32();
|
||||
for(Int32 ssyy_i = 0; ssyy_i < ssyy_count; ssyy_i++)
|
||||
{
|
||||
_desugared_deconstruction.definitions.Add(_read_node() as var_def_statement);
|
||||
}
|
||||
}
|
||||
_desugared_deconstruction.deconstruction_target = (object)br.ReadByte();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6265,6 +6265,295 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_node _pattern_node)
|
||||
{
|
||||
bw.Write((Int16)228);
|
||||
write_pattern_node(_pattern_node);
|
||||
}
|
||||
|
||||
public void write_pattern_node(pattern_node _pattern_node)
|
||||
{
|
||||
write_syntax_tree_node(_pattern_node);
|
||||
}
|
||||
|
||||
|
||||
public void visit(type_pattern _type_pattern)
|
||||
{
|
||||
bw.Write((Int16)229);
|
||||
write_type_pattern(_type_pattern);
|
||||
}
|
||||
|
||||
public void write_type_pattern(type_pattern _type_pattern)
|
||||
{
|
||||
write_pattern_node(_type_pattern);
|
||||
if (_type_pattern.identifier == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_type_pattern.identifier.visit(this);
|
||||
}
|
||||
if (_type_pattern.type == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_type_pattern.type.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
bw.Write((Int16)230);
|
||||
write_is_pattern_expr(_is_pattern_expr);
|
||||
}
|
||||
|
||||
public void write_is_pattern_expr(is_pattern_expr _is_pattern_expr)
|
||||
{
|
||||
write_expression(_is_pattern_expr);
|
||||
if (_is_pattern_expr.left == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_is_pattern_expr.left.visit(this);
|
||||
}
|
||||
if (_is_pattern_expr.right == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_is_pattern_expr.right.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(match_with _match_with)
|
||||
{
|
||||
bw.Write((Int16)231);
|
||||
write_match_with(_match_with);
|
||||
}
|
||||
|
||||
public void write_match_with(match_with _match_with)
|
||||
{
|
||||
write_statement(_match_with);
|
||||
if (_match_with.expr == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_match_with.expr.visit(this);
|
||||
}
|
||||
if (_match_with.case_list == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_match_with.case_list.visit(this);
|
||||
}
|
||||
if (_match_with.defaultAction == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_match_with.defaultAction.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_case _pattern_case)
|
||||
{
|
||||
bw.Write((Int16)232);
|
||||
write_pattern_case(_pattern_case);
|
||||
}
|
||||
|
||||
public void write_pattern_case(pattern_case _pattern_case)
|
||||
{
|
||||
write_statement(_pattern_case);
|
||||
if (_pattern_case.pattern == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_pattern_case.pattern.visit(this);
|
||||
}
|
||||
if (_pattern_case.case_action == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_pattern_case.case_action.visit(this);
|
||||
}
|
||||
if (_pattern_case.condition == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_pattern_case.condition.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_cases _pattern_cases)
|
||||
{
|
||||
bw.Write((Int16)233);
|
||||
write_pattern_cases(_pattern_cases);
|
||||
}
|
||||
|
||||
public void write_pattern_cases(pattern_cases _pattern_cases)
|
||||
{
|
||||
write_statement(_pattern_cases);
|
||||
if (_pattern_cases.elements == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
bw.Write(_pattern_cases.elements.Count);
|
||||
for(Int32 ssyy_i = 0; ssyy_i < _pattern_cases.elements.Count; ssyy_i++)
|
||||
{
|
||||
if (_pattern_cases.elements[ssyy_i] == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_pattern_cases.elements[ssyy_i].visit(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
bw.Write((Int16)234);
|
||||
write_deconstructor_pattern(_deconstructor_pattern);
|
||||
}
|
||||
|
||||
public void write_deconstructor_pattern(deconstructor_pattern _deconstructor_pattern)
|
||||
{
|
||||
write_pattern_node(_deconstructor_pattern);
|
||||
if (_deconstructor_pattern.parameters == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
bw.Write(_deconstructor_pattern.parameters.Count);
|
||||
for(Int32 ssyy_i = 0; ssyy_i < _deconstructor_pattern.parameters.Count; ssyy_i++)
|
||||
{
|
||||
if (_deconstructor_pattern.parameters[ssyy_i] == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_deconstructor_pattern.parameters[ssyy_i].visit(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_deconstructor_pattern.type == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_deconstructor_pattern.type.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
bw.Write((Int16)235);
|
||||
write_pattern_deconstructor_parameter(_pattern_deconstructor_parameter);
|
||||
}
|
||||
|
||||
public void write_pattern_deconstructor_parameter(pattern_deconstructor_parameter _pattern_deconstructor_parameter)
|
||||
{
|
||||
write_syntax_tree_node(_pattern_deconstructor_parameter);
|
||||
if (_pattern_deconstructor_parameter.identifier == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_pattern_deconstructor_parameter.identifier.visit(this);
|
||||
}
|
||||
if (_pattern_deconstructor_parameter.type == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_pattern_deconstructor_parameter.type.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
bw.Write((Int16)236);
|
||||
write_desugared_deconstruction(_desugared_deconstruction);
|
||||
}
|
||||
|
||||
public void write_desugared_deconstruction(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
write_statement(_desugared_deconstruction);
|
||||
if (_desugared_deconstruction.definitions == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
bw.Write(_desugared_deconstruction.definitions.Count);
|
||||
for(Int32 ssyy_i = 0; ssyy_i < _desugared_deconstruction.definitions.Count; ssyy_i++)
|
||||
{
|
||||
if (_desugared_deconstruction.definitions[ssyy_i] == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_desugared_deconstruction.definitions[ssyy_i].visit(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
bw.Write((byte)_desugared_deconstruction.deconstruction_target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,6 +2,7 @@
|
|||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
|
|
@ -83,6 +84,35 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переименовывает все идентификаторы с данным значением в поддереве
|
||||
/// </summary>
|
||||
/// <param name="from">Исходное значение</param>
|
||||
/// <param name="to">Новое значение</param>
|
||||
public void RenameIdentifierInDescendants(string from, string to, bool includingThis = true)
|
||||
{
|
||||
foreach (var identifier in DescendantNodes(TraversalType.PostOrder, null, includingThis).OfType<ident>().Where(x => x.name == from))
|
||||
identifier.name = to;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает коллекцию предков текущего узла
|
||||
/// </summary>
|
||||
/// <param name="includeSelf">Включить в список текущий узел</param>
|
||||
/// <returns>Коллекция предков узла</returns>
|
||||
public IEnumerable<syntax_tree_node> AscendantNodes(bool includeSelf = false)
|
||||
{
|
||||
if (includeSelf)
|
||||
yield return this;
|
||||
|
||||
var parentNode = Parent;
|
||||
while (parentNode != null)
|
||||
{
|
||||
yield return parentNode;
|
||||
parentNode = parentNode.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает коллекцию узлов поддерева, в котором корнем является текущий узел.
|
||||
/// </summary>
|
||||
|
|
@ -295,6 +325,9 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
public void AddMany(IEnumerable<statement> els)
|
||||
{
|
||||
list.AddRange(els);
|
||||
foreach (var elem in els)
|
||||
if (elem != null)
|
||||
elem.Parent = this;
|
||||
}
|
||||
|
||||
public static statement_list Empty
|
||||
|
|
@ -349,6 +382,11 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
return new bin_expr(left, right, Operators.Less);
|
||||
}
|
||||
|
||||
public static bin_expr LogicalAnd(expression left, expression right)
|
||||
{
|
||||
return new bin_expr(left, right, Operators.LogicalAND);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} {2} {1}", left, right, OperatorServices.ToString(operation_type, LanguageId.PascalABCNET));
|
||||
|
|
@ -1244,40 +1282,32 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
|
||||
public partial class var_statement
|
||||
{
|
||||
public var_statement(ident_list vars, type_definition type, expression iv)
|
||||
public var_statement(ident_list vars, type_definition type, expression iv) : this(new var_def_statement(vars, type, iv))
|
||||
{
|
||||
var_def = new var_def_statement(vars, type, iv);
|
||||
}
|
||||
|
||||
public var_statement(ident_list vars, type_definition type)
|
||||
public var_statement(ident_list vars, type_definition type): this(new var_def_statement(vars, type))
|
||||
{
|
||||
var_def = new var_def_statement(vars, type);
|
||||
}
|
||||
|
||||
public var_statement(ident id, type_definition type, expression iv)
|
||||
public var_statement(ident id, type_definition type, expression iv) : this(new var_def_statement(new ident_list(id), type, iv))
|
||||
{
|
||||
var_def = new var_def_statement(new ident_list(id), type, iv);
|
||||
}
|
||||
|
||||
public var_statement(ident id, type_definition type)
|
||||
public var_statement(ident id, type_definition type) : this(new var_def_statement(new ident_list(id), type))
|
||||
{
|
||||
var_def = new var_def_statement(new ident_list(id), type);
|
||||
}
|
||||
|
||||
public var_statement(ident id, string type)
|
||||
public var_statement(ident id, string type) : this(new var_def_statement(new ident_list(id), new named_type_reference(type)))
|
||||
{
|
||||
var_def = new var_def_statement(new ident_list(id), new named_type_reference(type));
|
||||
}
|
||||
|
||||
public var_statement(ident id, expression iv)
|
||||
public var_statement(ident id, expression iv) :this(new var_def_statement(new ident_list(id), null, iv))
|
||||
{
|
||||
var_def = new var_def_statement(new ident_list(id), null, iv);
|
||||
}
|
||||
|
||||
public var_statement(ident id, expression iv,SourceContext sc)
|
||||
public var_statement(ident id, expression iv,SourceContext sc) : this(new var_def_statement(new ident_list(id), null, iv, sc))
|
||||
{
|
||||
var_def = new var_def_statement(new ident_list(id), null, iv);
|
||||
var_def.source_context = sc;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
|
@ -1718,6 +1748,23 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
public override string ToString() => "lam_inferred";
|
||||
}
|
||||
|
||||
public partial class desugared_deconstruction
|
||||
{
|
||||
public bool HasAllExplicitTypes => definitions.All(x => x.vars_type != null);
|
||||
|
||||
public var_statement[] WithTypes(type_definition[] types)
|
||||
{
|
||||
var_statement[] result = new var_statement[types.Length];
|
||||
Debug.Assert(types.Length == definitions.Count, "Inconsistent types count");
|
||||
|
||||
for (int i = 0; i < definitions.Count; i++)
|
||||
{
|
||||
definitions[i].vars_type = types[i];
|
||||
result[i] = new var_statement(definitions[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1372,6 +1372,60 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
///<param name="_typeclass_reference">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(typeclass_reference _typeclass_reference);
|
||||
///<summary>
|
||||
///Method to visit pattern_node.
|
||||
///</summary>
|
||||
///<param name="_pattern_node">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(pattern_node _pattern_node);
|
||||
///<summary>
|
||||
///Method to visit type_pattern.
|
||||
///</summary>
|
||||
///<param name="_type_pattern">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(type_pattern _type_pattern);
|
||||
///<summary>
|
||||
///Method to visit is_pattern_expr.
|
||||
///</summary>
|
||||
///<param name="_is_pattern_expr">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(is_pattern_expr _is_pattern_expr);
|
||||
///<summary>
|
||||
///Method to visit match_with.
|
||||
///</summary>
|
||||
///<param name="_match_with">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(match_with _match_with);
|
||||
///<summary>
|
||||
///Method to visit pattern_case.
|
||||
///</summary>
|
||||
///<param name="_pattern_case">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(pattern_case _pattern_case);
|
||||
///<summary>
|
||||
///Method to visit pattern_cases.
|
||||
///</summary>
|
||||
///<param name="_pattern_cases">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(pattern_cases _pattern_cases);
|
||||
///<summary>
|
||||
///Method to visit deconstructor_pattern.
|
||||
///</summary>
|
||||
///<param name="_deconstructor_pattern">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(deconstructor_pattern _deconstructor_pattern);
|
||||
///<summary>
|
||||
///Method to visit pattern_deconstructor_parameter.
|
||||
///</summary>
|
||||
///<param name="_pattern_deconstructor_parameter">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter);
|
||||
///<summary>
|
||||
///Method to visit desugared_deconstruction.
|
||||
///</summary>
|
||||
///<param name="_desugared_deconstruction">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(desugared_deconstruction _desugared_deconstruction);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2863,12 +2863,8 @@
|
|||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
<CategoryIndices />
|
||||
<TagIndices />
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="instance_definition" BaseName="type_definition">
|
||||
|
|
@ -2880,11 +2876,9 @@
|
|||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>4</TagIndex>
|
||||
<TagIndex>9</TagIndex>
|
||||
<TagIndex>5</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
|
|
@ -2899,10 +2893,8 @@
|
|||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
<TagIndex>4</TagIndex>
|
||||
<TagIndex>5</TagIndex>
|
||||
</TagIndices>
|
||||
|
|
@ -2914,12 +2906,8 @@
|
|||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
<CategoryIndices />
|
||||
<TagIndices />
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="typeclass_param_list" BaseName="template_param_list">
|
||||
|
|
@ -2932,12 +2920,8 @@
|
|||
</Method>
|
||||
</Methods>
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
<CategoryIndices />
|
||||
<TagIndices />
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="typeclass_reference" BaseName="named_type_reference">
|
||||
|
|
@ -2948,11 +2932,142 @@
|
|||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>4</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="pattern_node" BaseName="syntax_tree_node">
|
||||
<Fields />
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="type_pattern" BaseName="pattern_node">
|
||||
<Fields>
|
||||
<SyntaxField Name="identifier" SyntaxType="ident" />
|
||||
<SyntaxField Name="type" SyntaxType="type_definition" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="is_pattern_expr" BaseName="expression">
|
||||
<Fields>
|
||||
<SyntaxField Name="left" SyntaxType="expression" />
|
||||
<SyntaxField Name="right" SyntaxType="pattern_node" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="match_with" BaseName="statement">
|
||||
<Fields>
|
||||
<SyntaxField Name="expr" SyntaxType="expression" />
|
||||
<SyntaxField Name="case_list" SyntaxType="pattern_cases" />
|
||||
<SyntaxField Name="defaultAction" SyntaxType="statement" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="pattern_case" BaseName="statement">
|
||||
<Fields>
|
||||
<SyntaxField Name="pattern" SyntaxType="pattern_node" />
|
||||
<SyntaxField Name="case_action" SyntaxType="statement" />
|
||||
<SyntaxField Name="condition" SyntaxType="expression" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="pattern_cases" BaseName="statement">
|
||||
<Fields>
|
||||
<ExtendedField Name="elements" Type="List<pattern_case>" CreateVariable="true" DeleteVariable="false" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="deconstructor_pattern" BaseName="pattern_node">
|
||||
<Fields>
|
||||
<ExtendedField Name="parameters" Type="List<pattern_deconstructor_parameter>" CreateVariable="true" DeleteVariable="false" />
|
||||
<SyntaxField Name="type" SyntaxType="type_definition" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="pattern_deconstructor_parameter" BaseName="syntax_tree_node">
|
||||
<Fields>
|
||||
<SyntaxField Name="identifier" SyntaxType="ident" />
|
||||
<SyntaxField Name="type" SyntaxType="type_definition" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
<SyntaxNode Name="desugared_deconstruction" BaseName="statement">
|
||||
<Fields>
|
||||
<ExtendedField Name="definitions" Type="List<var_def_statement>" CreateVariable="true" DeleteVariable="false" />
|
||||
<ExtendedField Name="deconstruction_target" Type="object" CreateVariable="false" DeleteVariable="false" />
|
||||
</Fields>
|
||||
<Methods />
|
||||
<Tags>
|
||||
<CategoryIndices>
|
||||
<CategoryIndex>0</CategoryIndex>
|
||||
</CategoryIndices>
|
||||
<TagIndices>
|
||||
<TagIndex>9</TagIndex>
|
||||
<TagIndex>4</TagIndex>
|
||||
</TagIndices>
|
||||
</Tags>
|
||||
</SyntaxNode>
|
||||
|
|
@ -2981,6 +3096,7 @@
|
|||
<Tag Name="Важнейшие" ReferenceCount="207" />
|
||||
<Tag Name="Method_Procedure_Call" ReferenceCount="2" />
|
||||
<Tag Name="Yield" ReferenceCount="8" />
|
||||
<Tag Name="Patterns" ReferenceCount="9" />
|
||||
<Tag Name="Typeclasses" ReferenceCount="7" />
|
||||
</Tags>
|
||||
</FilterCategory>
|
||||
|
|
@ -3286,6 +3402,9 @@
|
|||
<HelpData Key="declarations.void Add(declaration d, SourceContext sc)" Value="" />
|
||||
<HelpData Key="declarations_as_statement" Value="" />
|
||||
<HelpData Key="declarations_as_statement.defs" Value="" />
|
||||
<HelpData Key="deconstructor_pattern" Value="" />
|
||||
<HelpData Key="deconstructor_pattern.parameters" Value="Результат деконструирования" />
|
||||
<HelpData Key="deconstructor_pattern.type" Value="Деконструируемый тип" />
|
||||
<HelpData Key="default_indexer_property_node" Value="" />
|
||||
<HelpData Key="default_operator" Value="" />
|
||||
<HelpData Key="default_operator." Value="" />
|
||||
|
|
@ -3298,6 +3417,12 @@
|
|||
<HelpData Key="dereference.dereferencing_value" Value="" />
|
||||
<HelpData Key="dereference.override string ToString()" Value="" />
|
||||
<HelpData Key="destructor" Value="" />
|
||||
<HelpData Key="desugared_deconstruction" Value="Представляет объединение объявлений пременных, порожденных деконструкцией. Деконструируемое выражение необходимо хранить для выведения типа на этапе семантики, однако оно не должно входить в обход дерева." />
|
||||
<HelpData Key="desugared_deconstruction.deconstruct_call" Value="Вызов метода Deconstruct" />
|
||||
<HelpData Key="desugared_deconstruction.deconstruction_target" Value="Деконструируемое выражение" />
|
||||
<HelpData Key="desugared_deconstruction.definitions" Value="Объявления порожденных переменных" />
|
||||
<HelpData Key="desugared_deconstruction.destruct_call" Value="" />
|
||||
<HelpData Key="desugared_deconstruction.expressionVariableName" Value="Деконструируемое выражение" />
|
||||
<HelpData Key="diap_expr" Value="" />
|
||||
<HelpData Key="diap_expr." Value="" />
|
||||
<HelpData Key="diap_expr.left" Value="" />
|
||||
|
|
@ -3589,6 +3714,9 @@
|
|||
<HelpData Key="interface_node.interface_defsinitions" Value="" />
|
||||
<HelpData Key="interface_node.uses_modules" Value="" />
|
||||
<HelpData Key="interface_node.using_namespaces" Value="" />
|
||||
<HelpData Key="is_pattern_expr" Value="" />
|
||||
<HelpData Key="is_pattern_expr.left" Value="" />
|
||||
<HelpData Key="is_pattern_expr.right" Value="" />
|
||||
<HelpData Key="jump_stmt" Value="" />
|
||||
<HelpData Key="jump_stmt.JumpType" Value="" />
|
||||
<HelpData Key="jump_stmt.expr" Value="" />
|
||||
|
|
@ -3641,6 +3769,10 @@
|
|||
<HelpData Key="loop_stmt." Value="" />
|
||||
<HelpData Key="loop_stmt.count" Value="" />
|
||||
<HelpData Key="loop_stmt.stmt" Value="" />
|
||||
<HelpData Key="match_with" Value="" />
|
||||
<HelpData Key="match_with.case_list" Value="" />
|
||||
<HelpData Key="match_with.defaultAction" Value="" />
|
||||
<HelpData Key="match_with.expr" Value="" />
|
||||
<HelpData Key="matching_expression" Value="" />
|
||||
<HelpData Key="matching_expression.left" Value="" />
|
||||
<HelpData Key="matching_expression.right" Value="" />
|
||||
|
|
@ -3798,6 +3930,20 @@
|
|||
<HelpData Key="pascal_set_constant." Value="" />
|
||||
<HelpData Key="pascal_set_constant.values" Value="" />
|
||||
<HelpData Key="pascal_set_constant.void Add(expression value)" Value="Добавляет во множество элемент" />
|
||||
<HelpData Key="pattern_case" Value="" />
|
||||
<HelpData Key="pattern_case.case_action" Value="" />
|
||||
<HelpData Key="pattern_case.condition" Value="" />
|
||||
<HelpData Key="pattern_case.isDefault" Value="" />
|
||||
<HelpData Key="pattern_case.pattern" Value="" />
|
||||
<HelpData Key="pattern_cases" Value="" />
|
||||
<HelpData Key="pattern_cases.elements" Value="" />
|
||||
<HelpData Key="pattern_deconstructor_call_params" Value="" />
|
||||
<HelpData Key="pattern_deconstructor_call_params.parameters" Value="" />
|
||||
<HelpData Key="pattern_deconstructor_parameter" Value="" />
|
||||
<HelpData Key="pattern_deconstructor_parameter.identifier" Value="" />
|
||||
<HelpData Key="pattern_deconstructor_parameter.name" Value="" />
|
||||
<HelpData Key="pattern_deconstructor_parameter.type" Value="" />
|
||||
<HelpData Key="pattern_node" Value="" />
|
||||
<HelpData Key="proc_block" Value="" />
|
||||
<HelpData Key="procedure_attribute" Value="" />
|
||||
<HelpData Key="procedure_attribute.attribute_type" Value="" />
|
||||
|
|
@ -4162,6 +4308,9 @@
|
|||
<HelpData Key="type_definition_list.type_definition_list Add(type_definition _type_definition)" Value="" />
|
||||
<HelpData Key="type_definition_list.type_definition_list Add(type_definition _type_definition, SourceContext sc)" Value="" />
|
||||
<HelpData Key="type_definition_list.type_definition_list(type_definition _type_definition, SourceContext sc)" Value="" />
|
||||
<HelpData Key="type_pattern" Value="" />
|
||||
<HelpData Key="type_pattern.identifier" Value="" />
|
||||
<HelpData Key="type_pattern.type" Value="" />
|
||||
<HelpData Key="typecast_expr" Value="" />
|
||||
<HelpData Key="typecast_expr." Value="" />
|
||||
<HelpData Key="typecast_expr.type_def" Value="" />
|
||||
|
|
@ -4244,6 +4393,8 @@
|
|||
<HelpData Key="unknown_ident" Value="" />
|
||||
<HelpData Key="unknown_ident.ClassName" Value="" />
|
||||
<HelpData Key="unknown_ident.UnknownID" Value="" />
|
||||
<HelpData Key="unknown_type" Value="" />
|
||||
<HelpData Key="unknown_type.context" Value="" />
|
||||
<HelpData Key="unnamed_type_object" Value="Это - сахарная конструкция.
/// Объект безымянного класса. Например: new class(Name := 'Иванов'; Age := 25);
/// ne - это узел для генерации кода, основной узел предназначен для форматирования" />
|
||||
<HelpData Key="unnamed_type_object.is_class" Value="" />
|
||||
<HelpData Key="unnamed_type_object.ne" Value="" />
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
// double_question_desugar_visitor
|
||||
DoubleQuestionDesugarVisitor.New.ProcessNode(root);
|
||||
|
||||
// Patterns
|
||||
MatchWithVisitor.New.ProcessNode(root);
|
||||
//IsPatternVisitor.New.ProcessNode(root);
|
||||
|
||||
// Всё, связанное с yield
|
||||
MarkMethodHasYieldAndCheckSomeErrorsVisitor.New.ProcessNode(root);
|
||||
|
|
|
|||
42
SyntaxVisitors/SugarVisitors/IsPatternVisitor.cs
Normal file
42
SyntaxVisitors/SugarVisitors/IsPatternVisitor.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.TreeConversion;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace SyntaxVisitors.SugarVisitors
|
||||
{
|
||||
// Patterns
|
||||
public class IsPatternVisitor : BaseChangeVisitor
|
||||
{
|
||||
public static IsPatternVisitor New => new IsPatternVisitor();
|
||||
|
||||
public override void visit(is_pattern_expr isPatternExpr)
|
||||
{
|
||||
if (isPatternExpr.right is type_pattern)
|
||||
DesugarTypePattern(isPatternExpr);
|
||||
}
|
||||
|
||||
private void DesugarTypePattern(is_pattern_expr isPatternExpr)
|
||||
{
|
||||
Debug.Assert(isPatternExpr.right is type_pattern);
|
||||
|
||||
// Замена is_pattern на вызов вспомогательной функции PABCSystem.IsTest
|
||||
expression expression = isPatternExpr.left;
|
||||
type_pattern pattern = (type_pattern) isPatternExpr.right;
|
||||
var isTestFunc = SubtreeCreator.CreateSystemFunctionCall("IsTest", expression, pattern.identifier);
|
||||
ReplaceUsingParent(isPatternExpr, isTestFunc);
|
||||
|
||||
// Объявление переменной в ближайшем statement_list
|
||||
for (int i = listNodes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var statements = listNodes[i] as statement_list;
|
||||
statements?.InsertBefore(
|
||||
listNodes[i + 1] as statement,
|
||||
new var_statement(pattern.identifier, pattern.type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
192
SyntaxVisitors/SugarVisitors/MatchWithVisitor.cs
Normal file
192
SyntaxVisitors/SugarVisitors/MatchWithVisitor.cs
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.TreeConversion;
|
||||
|
||||
namespace SyntaxVisitors.SugarVisitors
|
||||
{
|
||||
// Patterns
|
||||
|
||||
public class DeconstructionDesugaringResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Переменная, имеющая тип паттерна
|
||||
/// </summary>
|
||||
public var_statement CastVariableDefinition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Переменные, полученные в результате деконструкции
|
||||
/// </summary>
|
||||
public List<var_def_statement> DeconstructionVariables { get; private set; } = new List<var_def_statement>();
|
||||
|
||||
/// <summary>
|
||||
/// Проверка соответствия типа выражения типу паттерна
|
||||
/// </summary>
|
||||
public expression TypeCastCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Вызов Deconstruct
|
||||
/// </summary>
|
||||
public statement DeconstructCall { get; set; }
|
||||
|
||||
public ident CastVariable
|
||||
{
|
||||
get
|
||||
{
|
||||
return CastVariableDefinition.var_def.vars.list[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchWithVisitor : BaseChangeVisitor
|
||||
{
|
||||
private const string DeconstructMethodName = "Deconstruct";
|
||||
|
||||
private int _variableCounter = 0;
|
||||
private if_node _previousIf;
|
||||
private statement desugaredMatchWith;
|
||||
|
||||
public static MatchWithVisitor New => new MatchWithVisitor();
|
||||
|
||||
public override void visit(match_with matchWith)
|
||||
{
|
||||
desugaredMatchWith = null;
|
||||
_previousIf = null;
|
||||
|
||||
// Преобразование из сахара в известную конструкцию каждого case
|
||||
foreach (var patternCase in matchWith.case_list.elements)
|
||||
{
|
||||
if (patternCase == null)
|
||||
continue;
|
||||
|
||||
if (patternCase.pattern is deconstructor_pattern)
|
||||
// TODO: introduce a variable for expression and cache it
|
||||
DesugarDeconstructorPatternCase(matchWith.expr, patternCase);
|
||||
}
|
||||
|
||||
if (matchWith.defaultAction != null)
|
||||
AddDefaultCase(matchWith.defaultAction as statement_list);
|
||||
|
||||
if (desugaredMatchWith == null)
|
||||
desugaredMatchWith = new empty_statement();
|
||||
|
||||
// Замена выражения match with на новое несахарное поддерево и его обход
|
||||
ReplaceUsingParent(matchWith, desugaredMatchWith);
|
||||
visit(desugaredMatchWith);
|
||||
}
|
||||
|
||||
void DesugarTypePatternCase(expression matchingExpression, pattern_case patternCase)
|
||||
{
|
||||
Debug.Assert(patternCase.pattern is type_pattern);
|
||||
|
||||
//var result = new statement_list();
|
||||
//// создание фиктивной переменной необходимого типа
|
||||
//var pattern = (type_pattern) patternCase.pattern;
|
||||
|
||||
//// Конструируем условие мэтчинга
|
||||
//expression matchCondition = isTest;
|
||||
//if (patternCase.condition == null)
|
||||
// matchCondition = isTest;
|
||||
//else
|
||||
//// Если есть секция when - добавляем ее в условие
|
||||
//{
|
||||
// // Переименовываем идентификатор, т.к. мы сгенерировали внутреннее имя
|
||||
// patternCase.condition.RenameIdentifierInDescendants(pattern.identifier.name, matchResultVariableName.name);
|
||||
// matchCondition = new bin_expr(isTest, patternCase.condition, Operators.LogicalAND);
|
||||
//}
|
||||
|
||||
//// Создание узла if с объявлением переменной из паттерна и присвоение ей значения
|
||||
//// сгенерированной переменной
|
||||
//var patternVarDef = new var_statement(pattern.identifier, matchResultVariableName);
|
||||
//// Создание тела if из объявления переменной и соттветствующего тела case
|
||||
//var ifCheck = SubtreeCreator.CreateIf(matchCondition, new statement_list(patternVarDef, patternCase.case_action));
|
||||
//result.Add(ifCheck);
|
||||
|
||||
//// Добавляем полученные statements в результат
|
||||
//AddDesugaredCaseToResult(result, ifCheck);
|
||||
}
|
||||
|
||||
void DesugarDeconstructorPatternCase(expression matchingExpression, pattern_case patternCase)
|
||||
{
|
||||
Debug.Assert(patternCase.pattern is deconstructor_pattern);
|
||||
|
||||
var result = new statement_list();
|
||||
var pattern = patternCase.pattern as deconstructor_pattern;
|
||||
// создание фиктивной переменной необходимого типа
|
||||
var desugaredPattern = DesugarPattern(pattern, matchingExpression);
|
||||
result.Add(desugaredPattern.CastVariableDefinition);
|
||||
|
||||
|
||||
|
||||
// Создание тела if из объявлений переменных, вызова Deconstruct и соответствующего тела case
|
||||
var ifBody = new statement_list();
|
||||
ifBody.Add(new desugared_deconstruction(desugaredPattern.DeconstructionVariables, desugaredPattern.CastVariable, patternCase.pattern.source_context));
|
||||
ifBody.Add(desugaredPattern.DeconstructCall);
|
||||
|
||||
if (patternCase.condition != null)
|
||||
{
|
||||
// Выполняем тело, если выполняется условие when
|
||||
ifBody.Add(SubtreeCreator.CreateIf(patternCase.condition, patternCase.case_action));
|
||||
}
|
||||
else
|
||||
ifBody.Add(patternCase.case_action);
|
||||
|
||||
var ifCondition = desugaredPattern.TypeCastCheck;
|
||||
var ifCheck = SubtreeCreator.CreateIf(ifCondition, ifBody);
|
||||
|
||||
result.Add(ifCheck);
|
||||
|
||||
// Добавляем полученные statements в результат
|
||||
AddDesugaredCaseToResult(result, ifCheck);
|
||||
}
|
||||
|
||||
private ident GenerateIdent()
|
||||
{
|
||||
return new ident("<>patternGenVar" + _variableCounter++);
|
||||
}
|
||||
|
||||
private void AddDefaultCase(statement_list statements)
|
||||
{
|
||||
AddDesugaredCaseToResult(statements, _previousIf);
|
||||
}
|
||||
|
||||
private void AddDesugaredCaseToResult(statement_list statements, if_node newIf)
|
||||
{
|
||||
// Если результат пустой, значит это первый case
|
||||
if (desugaredMatchWith == null)
|
||||
desugaredMatchWith = statements;
|
||||
else
|
||||
{
|
||||
_previousIf.else_body = statements;
|
||||
_previousIf.FillParentsInDirectChilds();
|
||||
}
|
||||
|
||||
// Запоминаем только что сгенерированный if
|
||||
_previousIf = newIf;
|
||||
}
|
||||
|
||||
private DeconstructionDesugaringResult DesugarPattern(deconstructor_pattern pattern, expression matchingExpression)
|
||||
{
|
||||
var desugarResult = new DeconstructionDesugaringResult();
|
||||
var castVariableName = GenerateIdent();
|
||||
desugarResult.CastVariableDefinition = new var_statement(castVariableName, pattern.type);
|
||||
|
||||
// делегирование проверки паттерна функции IsTest
|
||||
desugarResult.TypeCastCheck = SubtreeCreator.CreateSystemFunctionCall("IsTest", matchingExpression, castVariableName);
|
||||
|
||||
foreach (var deconstructedVariable in pattern.parameters)
|
||||
desugarResult.DeconstructionVariables.Add(
|
||||
new var_def_statement(deconstructedVariable.identifier, deconstructedVariable.type));
|
||||
|
||||
var deconstructCall = new procedure_call();
|
||||
deconstructCall.func_name = SubtreeCreator.CreateMethodCall(DeconstructMethodName, castVariableName.name, pattern.parameters.Select(x => x.identifier).ToArray());
|
||||
desugarResult.DeconstructCall = deconstructCall;
|
||||
|
||||
return desugarResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +55,8 @@
|
|||
<Compile Include="SugarVisitors\DoubleQuestionDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\LoopDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\QuestionPointDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\IsPatternVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\MatchWithVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\SliceDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\TupleVisitor.cs" />
|
||||
<Compile Include="TypeclassVisitors\FindInstancesAndRestrictedFunctionsVisitor.cs" />
|
||||
|
|
@ -104,6 +106,10 @@
|
|||
<Project>{c2cac65a-b2ae-4ccc-b067-e6b8e75df73a}</Project>
|
||||
<Name>SyntaxTree</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TreeConverter\TreeConverter.csproj">
|
||||
<Project>{1C9C945A-586D-42A2-A06B-65D84FA7FF78}</Project>
|
||||
<Name>TreeConverter</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Yield\YieldHelpers\YieldHelpers.csproj">
|
||||
<Project>{ce5c55c2-a11c-4e94-a9fa-3fc6ca3e4c09}</Project>
|
||||
<Name>YieldHelpers</Name>
|
||||
|
|
|
|||
223
TestSuite/CompilationSamples/GraphWPFBase.pas
Normal file
223
TestSuite/CompilationSamples/GraphWPFBase.pas
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
///--
|
||||
unit GraphWPFBase;
|
||||
|
||||
{$reference 'PresentationFramework.dll'}
|
||||
{$reference 'WindowsBase.dll'}
|
||||
{$reference 'PresentationCore.dll'}
|
||||
|
||||
{$apptype windows}
|
||||
|
||||
uses System.Windows;
|
||||
uses System.Windows.Controls;
|
||||
|
||||
type
|
||||
/// Тип цвета
|
||||
GColor = System.Windows.Media.Color;
|
||||
/// Тип прямоугольника
|
||||
GRect = System.Windows.Rect;
|
||||
|
||||
GWindow = System.Windows.Window;
|
||||
GMainWindow = class(GWindow)
|
||||
public
|
||||
function CreateContent: DockPanel; virtual;
|
||||
begin
|
||||
var g := new DockPanel;
|
||||
g.LastChildFill := True;
|
||||
Result := g;
|
||||
end;
|
||||
|
||||
procedure InitMainGraphControl; virtual;
|
||||
begin
|
||||
end;
|
||||
procedure InitWindowProperties; virtual;
|
||||
begin
|
||||
end;
|
||||
procedure InitGlobals; virtual;
|
||||
begin
|
||||
end;
|
||||
procedure InitHandlers; virtual;
|
||||
begin
|
||||
end;
|
||||
|
||||
constructor Create;
|
||||
begin
|
||||
Content := CreateContent;
|
||||
InitMainGraphControl;
|
||||
InitGlobals;
|
||||
InitWindowProperties;
|
||||
InitHandlers;
|
||||
end;
|
||||
|
||||
function MainPanel: DockPanel := Content as DockPanel;
|
||||
end;
|
||||
|
||||
var
|
||||
app: Application;
|
||||
MainWindow: GMainWindow;
|
||||
|
||||
procedure Invoke(d: System.Delegate; params args: array of object) := app.Dispatcher.Invoke(d, args);
|
||||
procedure InvokeP(p: procedure(r: real); r: real) := Invoke(p,r);
|
||||
|
||||
procedure Invoke(d: ()->()) := app.Dispatcher.Invoke(d);
|
||||
|
||||
function Invoke<T>(d: Func0<T>): T := app.Dispatcher.Invoke&<T>(d);
|
||||
function InvokeReal(f: ()->real): real := Invoke&<Real>(f);
|
||||
function InvokeString(f: ()->string): string := Invoke&<string>(f);
|
||||
function InvokeBoolean(d: Func0<boolean>): boolean := Invoke&<boolean>(d);
|
||||
function InvokeInteger(d: Func0<integer>): integer := Invoke&<integer>(d);
|
||||
function Inv<T>(p: ()->T): T := Invoke&<T>(p); // Теперь это работает!
|
||||
|
||||
function MainDockPanel: DockPanel := MainWindow.MainPanel;
|
||||
|
||||
type
|
||||
///!#
|
||||
WindowType = class
|
||||
private
|
||||
procedure SetLeft(l: real);
|
||||
function GetLeft: real;
|
||||
procedure SetTop(t: real);
|
||||
function GetTop: real;
|
||||
procedure SetWidth(w: real);
|
||||
function GetWidth: real;
|
||||
procedure SetHeight(h: real);
|
||||
function GetHeight: real;
|
||||
procedure SetCaption(c: string);
|
||||
function GetCaption: string;
|
||||
public
|
||||
/// Отступ главного окна от левого края экрана
|
||||
property Left: real read GetLeft write SetLeft;
|
||||
/// Отступ главного окна от верхнего края экрана
|
||||
property Top: real read GetTop write SetTop;
|
||||
/// Ширина клиентской части главного окна
|
||||
property Width: real read GetWidth write SetWidth;
|
||||
/// Высота клиентской части главного окна
|
||||
property Height: real read GetHeight write SetHeight;
|
||||
/// Заголовок окна
|
||||
property Caption: string read GetCaption write SetCaption;
|
||||
/// Заголовок окна
|
||||
property Title: string read GetCaption write SetCaption;
|
||||
/// Очищает графическое окно белым цветом
|
||||
procedure Clear; virtual;
|
||||
/// Очищает графическое окно цветом c
|
||||
procedure Clear(c: GColor);
|
||||
/// Устанавливает размеры клиентской части главного окна
|
||||
procedure SetSize(w, h: real);
|
||||
/// Устанавливает отступ главного окна от левого верхнего края экрана
|
||||
procedure SetPos(l, t: real);
|
||||
/// Закрывает главное окно и завершает приложение
|
||||
procedure Close;
|
||||
/// Сворачивает главное окно
|
||||
procedure Minimize;
|
||||
/// Максимизирует главное окно
|
||||
procedure Maximize;
|
||||
/// Возвращает главное окно к нормальному размеру
|
||||
procedure Normalize;
|
||||
/// Центрирует главное окно по центру экрана
|
||||
procedure CenterOnScreen;
|
||||
/// Возвращает центр главного окна
|
||||
function Center: Point;
|
||||
/// Возвращает прямоугольник клиентской области окна
|
||||
function ClientRect: GRect;
|
||||
end;
|
||||
|
||||
|
||||
function wplus := SystemParameters.WindowResizeBorderThickness.Left + SystemParameters.WindowResizeBorderThickness.Right;
|
||||
function hplus := SystemParameters.WindowCaptionHeight + SystemParameters.WindowResizeBorderThickness.Top + SystemParameters.WindowResizeBorderThickness.Bottom;
|
||||
|
||||
///---- Window -----
|
||||
|
||||
procedure WindowTypeSetLeftP(l: real) := MainWindow.Left := l;
|
||||
procedure WindowType.SetLeft(l: real) := Invoke(WindowTypeSetLeftP,l);
|
||||
|
||||
function WindowTypeGetLeftP := MainWindow.Left;
|
||||
function WindowType.GetLeft := InvokeReal(WindowTypeGetLeftP);
|
||||
|
||||
procedure WindowTypeSetTopP(t: real) := MainWindow.Top := t;
|
||||
procedure WindowType.SetTop(t: real) := Invoke(WindowTypeSetTopP,t);
|
||||
|
||||
function WindowTypeGetTopP := MainWindow.Top;
|
||||
function WindowType.GetTop := InvokeReal(WindowTypeGetTopP);
|
||||
|
||||
procedure WindowTypeSetWidthP(w: real) := MainWindow.Width := w + wplus;
|
||||
procedure WindowType.SetWidth(w: real) := Invoke(WindowTypeSetWidthP,w);
|
||||
|
||||
function WindowTypeGetWidthP := MainWindow.Width - wplus;
|
||||
function WindowType.GetWidth := InvokeReal(WindowTypeGetWidthP);
|
||||
|
||||
procedure WindowTypeSetHeightP(h: real) := MainWindow.Height := h + hplus;
|
||||
procedure WindowType.SetHeight(h: real) := Invoke(WindowTypeSetHeightP,h);
|
||||
|
||||
function WindowTypeGetHeightP := MainWindow.Height - hplus;
|
||||
function WindowType.GetHeight := InvokeReal(WindowTypeGetHeightP);
|
||||
|
||||
procedure WindowTypeSetCaptionP(c: string) := MainWindow.Title := c;
|
||||
procedure WindowType.SetCaption(c: string) := Invoke(WindowTypeSetCaptionP,c);
|
||||
|
||||
function WindowTypeGetCaptionP := MainWindow.Title;
|
||||
function WindowType.GetCaption := Invoke&<string>(WindowTypeGetCaptionP);
|
||||
|
||||
procedure WindowTypeClearP := begin {Host.children.Clear; CountVisuals := 0;} end;
|
||||
procedure WindowType.Clear := Invoke(WindowTypeClearP);
|
||||
|
||||
procedure WindowType.Clear(c: GColor);
|
||||
begin
|
||||
raise new System.NotImplementedException('WindowType.Clear(c) пока не реализовано. Честное слово - в будущем!')
|
||||
end;
|
||||
|
||||
procedure WindowTypeSetSizeP(w, h: real);
|
||||
begin
|
||||
WindowTypeSetWidthP(w);
|
||||
WindowTypeSetHeightP(h);
|
||||
end;
|
||||
procedure WindowType.SetSize(w, h: real) := Invoke(WindowTypeSetSizeP,w,h);
|
||||
|
||||
procedure WindowTypeSetPosP(l, t: real);
|
||||
begin
|
||||
WindowTypeSetLeftP(l);
|
||||
WindowTypeSetTopP(t);
|
||||
end;
|
||||
procedure WindowType.SetPos(l, t: real) := Invoke(WindowTypeSetPosP,l,t);
|
||||
|
||||
procedure WindowType.Close := Invoke(MainWindow.Close);
|
||||
|
||||
procedure WindowTypeMinimizeP := MainWindow.WindowState := WindowState.Minimized;
|
||||
procedure WindowType.Minimize := Invoke(WindowTypeMinimizeP);
|
||||
|
||||
procedure WindowTypeMaximizeP := MainWindow.WindowState := WindowState.Maximized;
|
||||
procedure WindowType.Maximize := Invoke(WindowTypeMaximizeP);
|
||||
|
||||
procedure WindowTypeNormalizeP := MainWindow.WindowState := WindowState.Normal;
|
||||
procedure WindowType.Normalize := Invoke(WindowTypeNormalizeP);
|
||||
|
||||
procedure WindowTypeCenterOnScreenP := MainWindow.WindowStartupLocation := WindowStartupLocation.CenterScreen;
|
||||
procedure WindowType.CenterOnScreen := Invoke(WindowTypeCenterOnScreenP);
|
||||
|
||||
function Pnt(x,y: real) := new Point(x,y);
|
||||
function Rect(x,y,w,h: real) := new System.Windows.Rect(x,y,w,h);
|
||||
|
||||
function WindowType.Center := Pnt(Width/2,Height/2);
|
||||
|
||||
function WindowType.ClientRect := Rect(0,0,Width,Height);
|
||||
|
||||
|
||||
|
||||
var __initialized: boolean;
|
||||
|
||||
procedure __InitModule;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure __InitModule__;
|
||||
begin
|
||||
if not __initialized then
|
||||
begin
|
||||
__initialized := true;
|
||||
__InitModule;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
__InitModule;
|
||||
end.
|
||||
File diff suppressed because it is too large
Load diff
26
TestSuite/CompilationSamples/Sounds.pas
Normal file
26
TestSuite/CompilationSamples/Sounds.pas
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
unit Sounds;
|
||||
|
||||
{$reference 'PresentationCore.dll'}
|
||||
|
||||
procedure PlaySound(fname: string);
|
||||
begin
|
||||
var fsound := new System.Windows.Media.MediaPlayer;
|
||||
fsound.Open(new System.Uri(fname,System.UriKind.RelativeOrAbsolute));
|
||||
fsound.Play;
|
||||
end;
|
||||
|
||||
type Sound = class
|
||||
fsound := new System.Windows.Media.MediaPlayer;
|
||||
public
|
||||
constructor (fname: string);
|
||||
begin
|
||||
Open(fname);
|
||||
end;
|
||||
procedure Open(fname: string) := fsound.Open(new System.Uri(fname,System.UriKind.RelativeOrAbsolute));
|
||||
procedure Play := fsound.Play;
|
||||
procedure Stop := fsound.Stop;
|
||||
procedure Pause := fsound.Pause;
|
||||
procedure Reset := fsound.Position := new System.Timespan(0);
|
||||
end;
|
||||
|
||||
end.
|
||||
10522
TestSuite/intellisense_tests/PABCSystem.pas
Normal file
10522
TestSuite/intellisense_tests/PABCSystem.pas
Normal file
File diff suppressed because it is too large
Load diff
15
TestSuite/patterns-deconstruct-default.pas
Normal file
15
TestSuite/patterns-deconstruct-default.pas
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
begin
|
||||
match 'asd' with
|
||||
string(s):
|
||||
match s with
|
||||
integer(i): Assert(false);
|
||||
string(s1) when s.Length > 1: ;
|
||||
else Assert(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
match 'asd' with
|
||||
integer(i): Assert(false);
|
||||
string(s1) when s1.Length > 3: Assert(false);
|
||||
end;
|
||||
end.
|
||||
34
TestSuite/patterns-deconstruct-generic-extension.pas
Normal file
34
TestSuite/patterns-deconstruct-generic-extension.pas
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
procedure Deconstruct<T>(self: List<T>; var f: T); extensionmethod;
|
||||
begin
|
||||
if self.Count > 0 then f := self[0];
|
||||
end;
|
||||
|
||||
procedure Deconstruct<T>(self: Dictionary<integer,List<T>>; var f: T); extensionmethod;
|
||||
begin
|
||||
var fst := self.First;
|
||||
var lst := fst.Value;
|
||||
if not (lst = nil) and (lst.Count > 0) then
|
||||
f := lst[0];
|
||||
end;
|
||||
|
||||
procedure Deconstruct<K,V>(self: Dictionary<K,V>; var kk: Dictionary<List<K>, V>; var vv: V); extensionmethod;
|
||||
begin
|
||||
kk := Dict((self.Keys.ToList, self.Values.First));
|
||||
end;
|
||||
|
||||
begin
|
||||
var pair := ('asd', Arr(1,2,3).ToList);
|
||||
var lst := Arr(4,5,6).ToList as object;
|
||||
var d := Dict(Arr(pair)) as object;
|
||||
var d2 := Dict((7, 8.0)) as object;
|
||||
var collection := Arr(lst, d, d2);
|
||||
foreach var x in collection do
|
||||
match x with
|
||||
Dictionary<integer,real>(s; k): Assert((s is Dictionary<List<integer>, real>) and (k is real));
|
||||
Dictionary<string,List<integer>>(first): Assert(first['asd'][0] = 1);
|
||||
List<real>(l: real): Assert(false);
|
||||
List<integer>(first: integer): Assert(first = 4);
|
||||
else Assert(false)
|
||||
end;
|
||||
end.
|
||||
38
TestSuite/patterns-lambda-test.pas
Normal file
38
TestSuite/patterns-lambda-test.pas
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
uses System.Linq;
|
||||
|
||||
begin
|
||||
match 'a b c'.Any(x -> x = 'a') with
|
||||
string(s): Assert(false);
|
||||
boolean(b): Assert(b);
|
||||
integer(i): Assert(false);
|
||||
else Assert(false)
|
||||
end;
|
||||
|
||||
var count := 0;
|
||||
match Arr('aa', 'bb').Select(x -> x = 'aa' ? x : nil).ToList with
|
||||
List<string>(l):
|
||||
foreach var x in l do
|
||||
if not (x = nil) then
|
||||
loop 5 do count += 1;
|
||||
end;
|
||||
Assert(count = 5);
|
||||
|
||||
match 'a b c'.Any(x -> x = 'a') with
|
||||
string(s): Assert(false);
|
||||
boolean(b):
|
||||
begin
|
||||
var r := Enumerable
|
||||
.Repeat(b, 3)
|
||||
.Select(
|
||||
x ->
|
||||
begin
|
||||
match x with
|
||||
boolean(b): Result := not b;
|
||||
end;
|
||||
end);
|
||||
Assert(Enumerable.Repeat(false, 3).SequenceEqual(r));
|
||||
end;
|
||||
integer(i): Assert(false);
|
||||
else Assert(false);
|
||||
end;
|
||||
end.
|
||||
6
TestSuite/patterns-nil-test.pas
Normal file
6
TestSuite/patterns-nil-test.pas
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
begin
|
||||
match nil with
|
||||
List<integer>(s): Assert(false);
|
||||
integer(i): Assert(false);
|
||||
end;
|
||||
end.
|
||||
38
TestSuite/patterns-overloading-and-ambiguity.pas
Normal file
38
TestSuite/patterns-overloading-and-ambiguity.pas
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
type
|
||||
My<T> = class
|
||||
public
|
||||
_a: T;
|
||||
|
||||
procedure Deconstruct(var a: T);
|
||||
begin
|
||||
a := _a;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Deconstruct<T>(self: My<T>; var a: T); extensionmethod;
|
||||
begin
|
||||
Assert(false);
|
||||
a := self._a;
|
||||
end;
|
||||
|
||||
procedure Deconstruct<T>(self: My<T>; var a: object); extensionmethod;
|
||||
begin
|
||||
a := self._a;
|
||||
end;
|
||||
|
||||
procedure Deconstruct<T>(self: My<T>; var a: object; var b: object); extensionmethod;
|
||||
begin
|
||||
Assert(false);
|
||||
a := self._a;
|
||||
end;
|
||||
|
||||
begin
|
||||
var l := new My<List<integer>>;
|
||||
l._a := Arr(1, 2, 3).ToList;
|
||||
match l with
|
||||
My<real>(a: real): Assert(false);
|
||||
My<integer>(a: integer): Assert(false);
|
||||
My<List<integer>>(a: object): ;
|
||||
else Assert(false);
|
||||
end;
|
||||
end.
|
||||
|
|
@ -69,6 +69,14 @@ namespace TreeConverter.LambdaExpressions
|
|||
syntaxTreeVisitor.visit(varStmt);
|
||||
}
|
||||
|
||||
// Patterns
|
||||
public override void visit(desugared_deconstruction _desugared_deconstruction)
|
||||
{
|
||||
// позволяем вывести типы объявленных переменных
|
||||
syntaxTreeVisitor.visit(_desugared_deconstruction);
|
||||
}
|
||||
// !Patterns
|
||||
|
||||
public override void visit(assign assignment)
|
||||
{
|
||||
var to = assignment.to as ident;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace PascalABCCompiler.TreeConversion
|
|||
/// <param name="name">Имя переменной</param>
|
||||
/// <param name="initialValue">Начальное значение</param>
|
||||
/// <returns></returns>
|
||||
public var_def_statement CreateVarDef(string name, expression initialValue)
|
||||
public static var_def_statement CreateVarDef(string name, expression initialValue)
|
||||
{
|
||||
ident_list list = new ident_list();
|
||||
list.idents.Add(new ident(name));
|
||||
|
|
@ -41,13 +41,27 @@ namespace PascalABCCompiler.TreeConversion
|
|||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Объявление пременной с именованным типом
|
||||
/// </summary>
|
||||
/// <param name="variableName"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static var_statement NamedTypeVariableDefinition(string variableName, string typeName)
|
||||
{
|
||||
var_def_statement varDefStatement = new var_def_statement();
|
||||
varDefStatement.vars.Add(new ident(variableName));
|
||||
varDefStatement.vars_type = new named_type_reference(typeName);
|
||||
return new var_statement(varDefStatement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создать var-выражение с несколькими переменными
|
||||
/// </summary>
|
||||
/// <param name="type">Тип переменных</param>
|
||||
/// <param name="idents">Имена переменных</param>
|
||||
/// <returns></returns>
|
||||
public var_def_statement CreateVarDef(named_type_reference type, params string[] names)
|
||||
public static var_def_statement CreateVarDef(named_type_reference type, params string[] names)
|
||||
{
|
||||
var_def_statement res = new var_def_statement();
|
||||
foreach (string x in names)
|
||||
|
|
@ -65,7 +79,7 @@ namespace PascalABCCompiler.TreeConversion
|
|||
/// <param name="body">Тело цикла</param>
|
||||
/// <param name="type">Тип цикла(to / downto)</param>
|
||||
/// <returns></returns>
|
||||
public SyntaxTree.for_node CreateFor(string varName, expression initValue, expression finishValue, statement body, for_cycle_type type)
|
||||
public static SyntaxTree.for_node CreateFor(string varName, expression initValue, expression finishValue, statement body, for_cycle_type type)
|
||||
{
|
||||
SyntaxTree.for_node res = new SyntaxTree.for_node();
|
||||
res.loop_variable = new ident(varName);
|
||||
|
|
@ -82,7 +96,7 @@ namespace PascalABCCompiler.TreeConversion
|
|||
/// <param name="condition">Условие цикла</param>
|
||||
/// <param name="body">Тело цикла</param>
|
||||
/// <returns></returns>
|
||||
public SyntaxTree.while_node CreateWhile(expression condition, statement body)
|
||||
public static SyntaxTree.while_node CreateWhile(expression condition, statement body)
|
||||
{
|
||||
SyntaxTree.while_node res = new SyntaxTree.while_node();
|
||||
res.CycleType = WhileCycleType.While;
|
||||
|
|
@ -91,13 +105,9 @@ namespace PascalABCCompiler.TreeConversion
|
|||
return res;
|
||||
}
|
||||
|
||||
private SyntaxTree.if_node CreateIfElse(expression condition, statement thenBody, statement elseBody)
|
||||
private static SyntaxTree.if_node CreateIfElse(expression condition, statement thenBody, statement elseBody)
|
||||
{
|
||||
SyntaxTree.if_node res = new SyntaxTree.if_node();
|
||||
res.condition = condition;
|
||||
res.then_body = thenBody;
|
||||
res.else_body = elseBody;
|
||||
return res;
|
||||
return new SyntaxTree.if_node(condition, thenBody, elseBody);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -106,7 +116,7 @@ namespace PascalABCCompiler.TreeConversion
|
|||
/// <param name="condition">Условие</param>
|
||||
/// <param name="thenBody">Тело, выполняемое если условие истино</param>
|
||||
/// <returns></returns>
|
||||
public SyntaxTree.if_node CreateIf(expression condition, statement thenBody)
|
||||
public static SyntaxTree.if_node CreateIf(expression condition, statement thenBody)
|
||||
{
|
||||
return CreateIfElse(condition, thenBody, null);
|
||||
}
|
||||
|
|
@ -118,12 +128,12 @@ namespace PascalABCCompiler.TreeConversion
|
|||
/// <param name="thenBody">Тело, выполняемое если условие истино</param>
|
||||
/// <param name="elseBody">Тело, выполняемое если условие ложно</param>
|
||||
/// <returns></returns>
|
||||
public SyntaxTree.if_node CreateIf(expression condition, statement thenBody, statement elseBody)
|
||||
public static SyntaxTree.if_node CreateIf(expression condition, statement thenBody, statement elseBody)
|
||||
{
|
||||
return CreateIfElse(condition, thenBody, elseBody);
|
||||
}
|
||||
|
||||
private SyntaxTree.program_module InternalCreateProgramModule(statement_list statements, declarations defs)
|
||||
private static SyntaxTree.program_module InternalCreateProgramModule(statement_list statements, declarations defs)
|
||||
{
|
||||
block block = new block();
|
||||
if (defs != null)
|
||||
|
|
@ -139,12 +149,12 @@ namespace PascalABCCompiler.TreeConversion
|
|||
return res;
|
||||
}
|
||||
|
||||
public SyntaxTree.program_module CreateProgramModule(statement_list statements, declarations defs)
|
||||
public static SyntaxTree.program_module CreateProgramModule(statement_list statements, declarations defs)
|
||||
{
|
||||
return InternalCreateProgramModule(statements, defs);
|
||||
}
|
||||
|
||||
public SyntaxTree.program_module CreateProgramModule(statement_list statements)
|
||||
public static SyntaxTree.program_module CreateProgramModule(statement_list statements)
|
||||
{
|
||||
return InternalCreateProgramModule(statements, null);
|
||||
}
|
||||
|
|
@ -158,21 +168,59 @@ namespace PascalABCCompiler.TreeConversion
|
|||
// return res;
|
||||
//}
|
||||
|
||||
public procedure_call CreateProcedureCall(string procName, params expression[] exprList)
|
||||
/// <summary>
|
||||
/// Создает узел вызова процедуры из PABCSystem
|
||||
/// </summary>
|
||||
/// <param name="procName">Имя процедуры</param>
|
||||
/// <param name="exprList">Параметры процедуры</param>
|
||||
/// <returns></returns>
|
||||
public static procedure_call CreateSystemProcedureCall(string procName, params expression[] exprList)
|
||||
{
|
||||
var procedureCall = CreateProcedureCall(procName, exprList);
|
||||
(procedureCall.func_name as method_call).dereferencing_value = new dot_node(new ident("PABCSystem"), new ident(procName));
|
||||
|
||||
return procedureCall;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает узел вызова функции из PABCSystem
|
||||
/// </summary>
|
||||
/// <param name="funcName">Имя функции</param>
|
||||
/// <param name="exprList">Параметры функции</param>
|
||||
/// <returns></returns>
|
||||
public static method_call CreateSystemFunctionCall(string funcName, params expression[] exprList)
|
||||
{
|
||||
return CreateMethodCall(funcName, "PABCSystem", exprList);
|
||||
}
|
||||
|
||||
public static method_call CreateMethodCall(string funcName, string qualifier, params expression[] exprList)
|
||||
{
|
||||
var methodCall = CreateMethodCall(funcName, exprList);
|
||||
methodCall.dereferencing_value = new dot_node(new ident(qualifier), new ident(funcName));
|
||||
return methodCall;
|
||||
}
|
||||
|
||||
public static procedure_call CreateProcedureCall(string procName, params expression[] exprList)
|
||||
{
|
||||
SyntaxTree.procedure_call pc = new SyntaxTree.procedure_call();
|
||||
pc.func_name = CreateMethodCall(procName, exprList);
|
||||
return pc;
|
||||
}
|
||||
|
||||
private static method_call CreateMethodCall(string methodName, params expression[] exprList)
|
||||
{
|
||||
SyntaxTree.method_call mc = new SyntaxTree.method_call();
|
||||
mc.dereferencing_value = new ident(procName);
|
||||
pc.func_name = mc;
|
||||
mc.dereferencing_value = new ident(methodName);
|
||||
SyntaxTree.expression_list exl = new PascalABCCompiler.SyntaxTree.expression_list();
|
||||
foreach (expression x in exprList)
|
||||
exl.Add(x);
|
||||
mc.parameters = exl;
|
||||
return pc;
|
||||
|
||||
return mc;
|
||||
}
|
||||
|
||||
// From LamdaHelper
|
||||
private procedure_definition InternalCreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, SourceContext sc)
|
||||
private static procedure_definition InternalCreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, SourceContext sc)
|
||||
{
|
||||
return PascalABCCompiler.TreeConverter.LambdaHelper.SyntaxTreeNodesConstructor.CreateProcedureDefinitionNode(new method_name(methName),
|
||||
formalPars,
|
||||
|
|
@ -182,17 +230,17 @@ namespace PascalABCCompiler.TreeConversion
|
|||
sc);
|
||||
}
|
||||
|
||||
public procedure_definition CreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, SourceContext sc)
|
||||
public static procedure_definition CreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, SourceContext sc)
|
||||
{
|
||||
return InternalCreateProcedureDefinitionNode(methName, formalPars, classKeyword, procBody, sc);
|
||||
}
|
||||
|
||||
public procedure_definition CreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody)
|
||||
public static procedure_definition CreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody)
|
||||
{
|
||||
return InternalCreateProcedureDefinitionNode(methName, formalPars, classKeyword, procBody, null);
|
||||
}
|
||||
|
||||
private procedure_definition InternalCreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType, SourceContext sc)
|
||||
private static procedure_definition InternalCreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType, SourceContext sc)
|
||||
{
|
||||
return PascalABCCompiler.TreeConverter.LambdaHelper.SyntaxTreeNodesConstructor.CreateFunctionDefinitionNode(new method_name(methName),
|
||||
formalPars,
|
||||
|
|
@ -203,18 +251,18 @@ namespace PascalABCCompiler.TreeConversion
|
|||
sc);
|
||||
}
|
||||
|
||||
public procedure_definition CreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType, SourceContext sc)
|
||||
public static procedure_definition CreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType, SourceContext sc)
|
||||
{
|
||||
return InternalCreateFunctionDefinitionNode(methName, formalPars, classKeyword, procBody, returnType, sc);
|
||||
}
|
||||
|
||||
public procedure_definition CreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType)
|
||||
public static procedure_definition CreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType)
|
||||
{
|
||||
return InternalCreateFunctionDefinitionNode(methName, formalPars, classKeyword, procBody, returnType, null);
|
||||
}
|
||||
// From !LamdaHelper
|
||||
|
||||
public declarations CreateDeclarations(params declaration[] decls)
|
||||
public static declarations CreateDeclarations(params declaration[] decls)
|
||||
{
|
||||
declarations res = new declarations();
|
||||
foreach (declaration x in decls)
|
||||
|
|
@ -222,7 +270,7 @@ namespace PascalABCCompiler.TreeConversion
|
|||
return res;
|
||||
}
|
||||
|
||||
public statement_list CreateStatementList(params statement[] stmts)
|
||||
public static statement_list CreateStatementList(params statement[] stmts)
|
||||
{
|
||||
statement_list res = new statement_list();
|
||||
foreach (statement x in stmts)
|
||||
|
|
|
|||
185
TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs
Normal file
185
TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.TreeRealization;
|
||||
|
||||
namespace PascalABCCompiler.TreeConverter
|
||||
{
|
||||
// Patterns
|
||||
public partial class syntax_tree_visitor
|
||||
{
|
||||
public override void visit(desugared_deconstruction deconstruction)
|
||||
{
|
||||
var invokationTarget = convert_strong(deconstruction.deconstruction_target as expression);
|
||||
var types = InferAndCheckPatternVariableTypes(deconstruction.definitions, invokationTarget, deconstruction);
|
||||
if (types == null)
|
||||
return;
|
||||
|
||||
foreach (var definition in deconstruction.WithTypes(types.Select(x => new semantic_type_node(x)).ToArray()))
|
||||
definition.visit(this);
|
||||
}
|
||||
|
||||
private type_node[] InferAndCheckPatternVariableTypes(List<var_def_statement> variableDefinitions, expression_node patternInstance, desugared_deconstruction deconstruction)
|
||||
{
|
||||
var parameterTypes = variableDefinitions.Select(x => x.vars_type == null ? null : convert_strong(x.vars_type)).ToArray();
|
||||
List<function_node> candidates = new List<function_node>();
|
||||
List<type_node[]> deducedParametersList = new List<type_node[]>();
|
||||
|
||||
var allDeconstructs = patternInstance.type.find_in_type("deconstruct", context.CurrentScope);
|
||||
foreach (var canditateSymbol in allDeconstructs)
|
||||
{
|
||||
var deducedParameters = new type_node[parameterTypes.Length];
|
||||
var possibleCandidate = canditateSymbol.sym_info as function_node;
|
||||
if (!IsSuitableFunction(possibleCandidate, parameterTypes, patternInstance, get_location(deconstruction), out deducedParameters))
|
||||
continue;
|
||||
|
||||
deducedParametersList.Add(deducedParameters);
|
||||
candidates.Add(possibleCandidate);
|
||||
}
|
||||
|
||||
if (candidates.Count == 0)
|
||||
{
|
||||
AddError(get_location(deconstruction), "NO_SUITABLE_DECONSTRUCT_FOUND");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
if (candidates.Count > 1)
|
||||
{
|
||||
RemoveDefaultDeconstruct(candidates);
|
||||
if (candidates.Count > 1 && !CheckIfParameterListElementsAreTheSame(deducedParametersList))
|
||||
{
|
||||
AddError(get_location(deconstruction), "DECONSTRUCTOR_METHOD_AMBIGUITY");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Единственный подхдящий кандидат найден, либо их несколько, с одинаковыми выходными параметрами
|
||||
var chosenFunction = candidates.First();
|
||||
if (chosenFunction.is_extension_method)
|
||||
{
|
||||
if (chosenFunction.is_generic_function)
|
||||
chosenFunction = generic_convertions.get_function_instance(chosenFunction, deducedParametersList.First().ToList());
|
||||
|
||||
return chosenFunction.parameters.Where(x => !IsSelfParameter(x)).Select(x => x.type).ToArray();
|
||||
}
|
||||
else
|
||||
return chosenFunction.parameters.Select(x => x.type).ToArray();//deducedParametersList[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет, подходит ли фаункция для вызова с указанными параметрами
|
||||
/// </summary>
|
||||
/// <param name="candidate"></param>
|
||||
/// <param name="givenParameterTypes">Типы параметров, указанные пользователем</param>
|
||||
/// <returns></returns>
|
||||
private bool IsSuitableFunction(
|
||||
function_node candidate,
|
||||
type_node[] givenParameterTypes,
|
||||
expression_node patternInstance,
|
||||
location deconstructionLocation,
|
||||
out type_node[] parameterTypes)
|
||||
{
|
||||
parameterTypes = new type_node[givenParameterTypes.Length];
|
||||
var selfParameter = candidate.is_extension_method ? candidate.parameters.First(IsSelfParameter) : null;
|
||||
Debug.Assert(!candidate.is_extension_method || selfParameter != null, "Couldn't find self parameter in extension method");
|
||||
var candidateParameterTypes =
|
||||
candidate.is_extension_method ?
|
||||
candidate.parameters.Where(x => !IsSelfParameter(x)).ToArray() :
|
||||
candidate.parameters.ToArray();
|
||||
|
||||
if (candidateParameterTypes.Length != givenParameterTypes.Length)
|
||||
return false;
|
||||
|
||||
var genericDeduceNeeded = candidate.is_extension_method && candidate.is_generic_function;
|
||||
type_node[] deducedGenerics = new type_node[candidate.generic_parameters_count];
|
||||
if (genericDeduceNeeded)
|
||||
{
|
||||
// Выводим дженерики по self
|
||||
var nils = new List<int>();
|
||||
var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils);
|
||||
if (!deduceSucceded || deducedGenerics.Contains(null))
|
||||
// Проверка на то, что в Deconstruct все дженерики выводятся по self делается в другом месте
|
||||
// TODO: сделать проверку
|
||||
// TODO: запретить дженерик методы в классах. Можно использовать только дженерик-типы самого класса в качестве параметров
|
||||
//AddError(deconstructionLocation, "COULDNT_DEDUCE_DECONSTRUCT_GENERIC_TYPE");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < givenParameterTypes.Length; i++)
|
||||
{
|
||||
var givenParameter = givenParameterTypes[i];
|
||||
var candidateParameter = candidateParameterTypes[i].type;
|
||||
if (genericDeduceNeeded && (candidateParameter.is_generic_parameter || candidateParameter.is_generic_type_instance))
|
||||
candidateParameter = InstantiateParameter(candidateParameter, deducedGenerics);
|
||||
|
||||
if (givenParameter != null && !AreTheSameTypes(candidateParameter, givenParameter))
|
||||
return false;
|
||||
|
||||
parameterTypes[i] = candidateParameter;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool AreTheSameTypes(type_node type1, type_node type2)
|
||||
{
|
||||
return convertion_data_and_alghoritms.possible_equal_types(type1, type2);
|
||||
}
|
||||
|
||||
private bool IsSelfParameter(parameter parameter) => parameter.name.ToLower() == compiler_string_consts.self_word;
|
||||
|
||||
private void RemoveDefaultDeconstruct(List<function_node> candidates)
|
||||
{
|
||||
var index = candidates.FindIndex(IsDefaultDeconstruct);
|
||||
if (index >= 0)
|
||||
candidates.RemoveAt(index);
|
||||
}
|
||||
|
||||
private bool IsDefaultDeconstruct(function_node function)
|
||||
{
|
||||
// TODO: fix
|
||||
return
|
||||
function.generic_parameters_count == 1 &&
|
||||
function.parameters.Count == 2 &&
|
||||
function.parameters[0].type.is_generic_parameter &&
|
||||
function.parameters[1].type.is_generic_parameter &&
|
||||
AreTheSameTypes(function.parameters[0].type, function.parameters[1].type);
|
||||
}
|
||||
|
||||
private bool CheckIfParameterListElementsAreTheSame(List<type_node[]> parametersList)
|
||||
{
|
||||
var first = parametersList.First();
|
||||
for (int i = 1; i < parametersList.Count; i++)
|
||||
{
|
||||
if (first.Length != parametersList[i].Length)
|
||||
return false;
|
||||
|
||||
for (int j = 0; j < first.Length; j++)
|
||||
if (!AreTheSameTypes(first[j], parametersList[i][j]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private type_node InstantiateParameter(SemanticTree.ITypeNode genericType, type_node[] instances)
|
||||
{
|
||||
if (genericType.is_generic_parameter)
|
||||
return instances[(genericType as type_node).generic_param_index];
|
||||
else
|
||||
{
|
||||
var genericNode = (genericType as generic_instance_type_node);
|
||||
if (genericNode != null)
|
||||
{
|
||||
var parameters = genericNode.instance_params.Select(x => InstantiateParameter(x, instances)).ToList();
|
||||
genericNode.instance_params = parameters;
|
||||
}
|
||||
|
||||
return genericNode as type_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19398,4 +19398,4 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -168,6 +168,7 @@
|
|||
<Compile Include="TreeConversion\SyntaxTreeVisitorNodes\Assign.cs" />
|
||||
<Compile Include="TreeConversion\SyntaxTreeVisitorNodes\Foreach.cs" />
|
||||
<Compile Include="TreeConversion\SyntaxTreeVisitorNodes\ForLoop.cs" />
|
||||
<Compile Include="TreeConversion\SyntaxTreeVisitorNodes\Patterns.cs" />
|
||||
<Compile Include="TreeConversion\syntax_tree_visitor.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -409,7 +409,7 @@ namespace PascalABCCompiler
|
|||
|
||||
|
||||
public static int Main(string[] initialArgs)
|
||||
{
|
||||
{
|
||||
var args = initialArgs.ToList();
|
||||
if (args.Remove("/noconsole"))
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue