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:
Bogdan Voloshin 2018-05-14 18:01:14 +03:00
commit a315f9f063
46 changed files with 23487 additions and 4383 deletions

2
.gitignore vendored
View file

@ -8,6 +8,8 @@ bin/*.dll
bin/*.pdb
bin/*.config
bin/*.xml
bin/log.txt
bin/CompilerController.ini
TestSuite/CompilationSamples/*.pcu
TestSuite/CompilationSamples/*.pdb

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

@ -0,0 +1,3 @@
// Ignore PascalABC.NET compiler output
*.pdb
*.exe

39
Patterns/All-examples.pas Normal file
View 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.

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

View 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.

View 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
View 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.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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&lt;pattern_case&gt;" 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&lt;pattern_deconstructor_parameter&gt;" 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&lt;var_def_statement&gt;" 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="Это - сахарная конструкция.&#xD;&#xA;/// Объект безымянного класса. Например: new class(Name := 'Иванов'; Age := 25);&#xD;&#xA;/// ne - это узел для генерации кода, основной узел предназначен для форматирования" />
<HelpData Key="unnamed_type_object.is_class" Value="" />
<HelpData Key="unnamed_type_object.ne" Value="" />

View file

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

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

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

View file

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

View 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

View 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.

File diff suppressed because it is too large Load diff

View 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.

View 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.

View 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.

View file

@ -0,0 +1,6 @@
begin
match nil with
List<integer>(s): Assert(false);
integer(i): Assert(false);
end;
end.

View 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.

View file

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

View file

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

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

View file

@ -19398,4 +19398,4 @@ namespace PascalABCCompiler.TreeConverter
}
}
}

View file

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

View file

@ -409,7 +409,7 @@ namespace PascalABCCompiler
public static int Main(string[] initialArgs)
{
{
var args = initialArgs.ToList();
if (args.Remove("/noconsole"))
{