multiple constant matching

This commit is contained in:
Александр Погорелов 2019-01-28 12:10:06 +03:00
parent 1f9e140730
commit 1d6c0e334a
13 changed files with 1906 additions and 1700 deletions

View file

@ -3189,7 +3189,7 @@ namespace CodeFormatters
public override void visit(const_pattern _const_pattern)
{
visit_node(_const_pattern.pattern_expression);
visit_node(_const_pattern.pattern_expressions);
add_space_after = false;
}

View file

@ -2,7 +2,7 @@
// This CSharp output file generated by Gardens Point LEX
// Version: 1.1.3.301
// Machine: DESKTOP-IF20NRO
// DateTime: 1/22/2019 9:37:35 AM
// DateTime: 1/27/2019 3:56:43 PM
// UserName: FatCow
// GPLEX input file <ABCPascal.lex>
// GPLEX frame file <embedded resource>

View file

@ -174,7 +174,7 @@
%type <stn> full_lambda_fp_list lambda_simple_fp_sect lambda_function_body lambda_procedure_body common_lambda_body optional_full_lambda_fp_list
%type <ob> field_in_unnamed_object list_fields_in_unnamed_object func_class_name_ident_list rem_lambda variable_list var_ident_list
%type <ti> tkAssignOrEqual
%type <stn> pattern pattern_optional_var match_with pattern_case pattern_cases pattern_out_param pattern_out_param_optional_var tuple_pattern_expr_list
%type <stn> pattern pattern_optional_var match_with pattern_case pattern_cases pattern_out_param pattern_out_param_optional_var tuple_pattern_expr_list const_pattern_expr_list
%type <ob> pattern_out_param_list pattern_out_param_list_optional_var
%type <ex> const_pattern_expression tuple_pattern tuple_pattern_expr
@ -3284,15 +3284,26 @@ pattern_optional_var
{
$$ = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, $1, @$);
}
| const_pattern_expression
| const_pattern_expr_list
{
$$ = new const_pattern($1, @$);
$$ = new const_pattern($1 as expression_list, @$);
}
;
const_pattern_expr_list
: const_pattern_expression
{
$$ = new expression_list($1, @$);
}
| const_pattern_expr_list tkComma const_pattern_expression
{
$$ = ($1 as expression_list).Add($3, @$);
}
;
const_pattern_expression
: literal_or_number { $$ = $1; }
| tuple_pattern { $$ = $1; }
: literal_or_number { $$ = $1; }
| tuple_pattern { $$ = $1; }
;
tuple_pattern
@ -3311,8 +3322,8 @@ tuple_pattern
;
tuple_pattern_expr
: tkQuestion { $$ = null; }
| expr_l1 { $$ = $1; }
: tkQuestion { $$ = new tuple_wild_card(); }
| literal_or_number { $$ = $1; }
;
tuple_pattern_expr_list

File diff suppressed because it is too large Load diff

View file

@ -1192,6 +1192,11 @@ namespace PascalABCCompiler.SyntaxTree
{
DefaultVisit(_const_pattern);
}
public virtual void visit(tuple_wild_card _tuple_wild_card)
{
DefaultVisit(_tuple_wild_card);
}
}

View file

@ -1901,6 +1901,14 @@ namespace PascalABCCompiler.SyntaxTree
{
}
public virtual void pre_do_visit(tuple_wild_card _tuple_wild_card)
{
}
public virtual void post_do_visit(tuple_wild_card _tuple_wild_card)
{
}
public override void visit(expression _expression)
{
DefaultVisit(_expression);
@ -3934,9 +3942,16 @@ namespace PascalABCCompiler.SyntaxTree
{
DefaultVisit(_const_pattern);
pre_do_visit(_const_pattern);
visit(const_pattern.pattern_expression);
visit(const_pattern.pattern_expressions);
post_do_visit(_const_pattern);
}
public override void visit(tuple_wild_card _tuple_wild_card)
{
DefaultVisit(_tuple_wild_card);
pre_do_visit(_tuple_wild_card);
post_do_visit(_tuple_wild_card);
}
}

View file

@ -494,6 +494,8 @@ namespace PascalABCCompiler.SyntaxTree
return new semantic_check_sugared_var_def_statement_node();
case 236:
return new const_pattern();
case 237:
return new tuple_wild_card();
}
return null;
}
@ -4188,7 +4190,18 @@ namespace PascalABCCompiler.SyntaxTree
public void read_const_pattern(const_pattern _const_pattern)
{
read_pattern_node(_const_pattern);
_const_pattern.pattern_expression = _read_node() as expression;
_const_pattern.pattern_expressions = _read_node() as expression_list;
}
public void visit(tuple_wild_card _tuple_wild_card)
{
read_tuple_wild_card(_tuple_wild_card);
}
public void read_tuple_wild_card(tuple_wild_card _tuple_wild_card)
{
read_expression(_tuple_wild_card);
}
}

View file

@ -6584,17 +6584,29 @@ namespace PascalABCCompiler.SyntaxTree
public void write_const_pattern(const_pattern _const_pattern)
{
write_pattern_node(_const_pattern);
if (_const_pattern.pattern_expression == null)
if (_const_pattern.pattern_expressions == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_const_pattern.pattern_expression.visit(this);
_const_pattern.pattern_expressions.visit(this);
}
}
public void visit(tuple_wild_card _tuple_wild_card)
{
bw.Write((Int16)237);
write_tuple_wild_card(_tuple_wild_card);
}
public void write_tuple_wild_card(tuple_wild_card _tuple_wild_card)
{
write_expression(_tuple_wild_card);
}
}

View file

@ -51266,37 +51266,37 @@ namespace PascalABCCompiler.SyntaxTree
///<summary>
///Конструктор с параметрами.
///</summary>
public const_pattern(expression _pattern_expression)
public const_pattern(expression_list _pattern_expressions)
{
this._pattern_expression=_pattern_expression;
this._pattern_expressions=_pattern_expressions;
FillParentsInDirectChilds();
}
///<summary>
///Конструктор с параметрами.
///</summary>
public const_pattern(expression _pattern_expression,SourceContext sc)
public const_pattern(expression_list _pattern_expressions,SourceContext sc)
{
this._pattern_expression=_pattern_expression;
this._pattern_expressions=_pattern_expressions;
source_context = sc;
FillParentsInDirectChilds();
}
protected expression _pattern_expression;
protected expression_list _pattern_expressions;
///<summary>
///
///</summary>
public expression pattern_expression
public expression_list pattern_expressions
{
get
{
return _pattern_expression;
return _pattern_expressions;
}
set
{
_pattern_expression=value;
if (_pattern_expression != null)
_pattern_expression.Parent = this;
_pattern_expressions=value;
if (_pattern_expressions != null)
_pattern_expressions.Parent = this;
}
}
@ -51308,10 +51308,10 @@ namespace PascalABCCompiler.SyntaxTree
copy.Parent = this.Parent;
if (source_context != null)
copy.source_context = new SourceContext(source_context);
if (pattern_expression != null)
if (pattern_expressions != null)
{
copy.pattern_expression = (expression)pattern_expression.Clone();
copy.pattern_expression.Parent = copy;
copy.pattern_expressions = (expression_list)pattern_expressions.Clone();
copy.pattern_expressions.Parent = copy;
}
return copy;
}
@ -51325,15 +51325,15 @@ namespace PascalABCCompiler.SyntaxTree
///<summary> Заполняет поля Parent в непосредственных дочерних узлах </summary>
public override void FillParentsInDirectChilds()
{
if (pattern_expression != null)
pattern_expression.Parent = this;
if (pattern_expressions != null)
pattern_expressions.Parent = this;
}
///<summary> Заполняет поля Parent во всем поддереве </summary>
public override void FillParentsInAllChilds()
{
FillParentsInDirectChilds();
pattern_expression?.FillParentsInAllChilds();
pattern_expressions?.FillParentsInAllChilds();
}
///<summary>
@ -51368,7 +51368,7 @@ namespace PascalABCCompiler.SyntaxTree
switch(ind)
{
case 0:
return pattern_expression;
return pattern_expressions;
}
return null;
}
@ -51379,7 +51379,7 @@ namespace PascalABCCompiler.SyntaxTree
switch(ind)
{
case 0:
pattern_expression = (expression)value;
pattern_expressions = (expression_list)value;
break;
}
}
@ -51397,6 +51397,106 @@ namespace PascalABCCompiler.SyntaxTree
}
///<summary>
///
///</summary>
[Serializable]
public partial class tuple_wild_card : expression
{
///<summary>
///Конструктор без параметров.
///</summary>
public tuple_wild_card()
{
}
/// <summary> Создает копию узла </summary>
public override syntax_tree_node Clone()
{
tuple_wild_card copy = new tuple_wild_card();
copy.Parent = this.Parent;
if (source_context != null)
copy.source_context = new SourceContext(source_context);
if (attributes != null)
{
copy.attributes = (attribute_list)attributes.Clone();
copy.attributes.Parent = copy;
}
return copy;
}
/// <summary> Получает копию данного узла корректного типа </summary>
public new tuple_wild_card TypedClone()
{
return Clone() as tuple_wild_card;
}
///<summary> Заполняет поля Parent в непосредственных дочерних узлах </summary>
public override void FillParentsInDirectChilds()
{
if (attributes != null)
attributes.Parent = this;
}
///<summary> Заполняет поля Parent во всем поддереве </summary>
public override void FillParentsInAllChilds()
{
FillParentsInDirectChilds();
attributes?.FillParentsInAllChilds();
}
///<summary>
///Свойство для получения количества всех подузлов без элементов поля типа List
///</summary>
public override Int32 subnodes_without_list_elements_count
{
get
{
return 0;
}
}
///<summary>
///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List
///</summary>
public override Int32 subnodes_count
{
get
{
return 0;
}
}
///<summary>
///Индексатор для получения всех подузлов
///</summary>
public override syntax_tree_node this[Int32 ind]
{
get
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
return null;
}
set
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
}
}
///<summary>
///Метод для обхода дерева посетителем
///</summary>
///<param name="visitor">Объект-посетитель.</param>
///<returns>Return value is void</returns>
public override void visit(IVisitor visitor)
{
visitor.visit(this);
}
}
}

View file

@ -393,6 +393,11 @@ namespace PascalABCCompiler.SyntaxTree
return new bin_expr(left, right, Operators.LogicalAND);
}
public static bin_expr LogicalOr(expression left, expression right)
{
return new bin_expr(left, right, Operators.LogicalOR);
}
public override string ToString()
{
return string.Format("{0} {2} {1}", left, right, OperatorServices.ToString(operation_type, LanguageId.PascalABCNET));

View file

@ -1426,6 +1426,12 @@ namespace PascalABCCompiler.SyntaxTree
///<param name="_const_pattern">Node to visit</param>
///<returns> Return value is void </returns>
void visit(const_pattern _const_pattern);
///<summary>
///Method to visit tuple_wild_card.
///</summary>
///<param name="_tuple_wild_card">Node to visit</param>
///<returns> Return value is void </returns>
void visit(tuple_wild_card _tuple_wild_card);
}

View file

@ -3057,7 +3057,7 @@
</SyntaxNode>
<SyntaxNode Name="const_pattern" BaseName="pattern_node">
<Fields>
<SyntaxField Name="pattern_expression" SyntaxType="expression" />
<SyntaxField Name="pattern_expressions" SyntaxType="expression_list" />
</Fields>
<Methods />
<Tags>
@ -3069,6 +3069,14 @@
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="tuple_wild_card" BaseName="expression">
<Fields />
<Methods />
<Tags>
<CategoryIndices />
<TagIndices />
</Tags>
</SyntaxNode>
</SyntaxNodes>
<Settings>
<FileName>Tree.cs</FileName>
@ -3373,6 +3381,7 @@
<HelpData Key="const_node" Value="Константа" />
<HelpData Key="const_pattern" Value="паттерн для константного матчинга" />
<HelpData Key="const_pattern.pattern_expression" Value="" />
<HelpData Key="const_pattern.pattern_expressions" Value="" />
<HelpData Key="constructor" Value="" />
<HelpData Key="constructor.constructor(formal_parameters fp): this(fp, null)" Value="" />
<HelpData Key="constructor.constructor(formal_parameters fp,SourceContext sc): this(null, fp, new procedure_attributes_list(proc_attribute.attr_overload), null, false, false, null, null)" Value="" />
@ -4296,6 +4305,7 @@
<HelpData Key="tuple_node.el" Value="" />
<HelpData Key="tuple_node_for_formatter" Value="" />
<HelpData Key="tuple_node_for_formatter.el" Value="" />
<HelpData Key="tuple_wild_card" Value="" />
<HelpData Key="type_declaration" Value="" />
<HelpData Key="type_declaration.type_declaration(string name, type_definition type): this(new ident(name),type)" Value="" />
<HelpData Key="type_declaration.type_declaration(string name, type_definition type, SourceContext sc): this(new ident(name),type,sc)" Value="" />

View file

@ -159,20 +159,33 @@ namespace SyntaxVisitors.SugarVisitors
void DesugarConstPatternCase(expression matchingExpression, pattern_case patternCase)
{
Debug.Assert(patternCase.pattern is const_pattern);
var patternExpressionNode = patternCase.pattern as const_pattern;
//var tuple_pattern_case = patternExpressionNode.pattern_expression as method_call;
var eqParams = new expression_list(
new List<expression>()
{
var equalCalls = new List<method_call>();
foreach (var patternExpression in patternExpressionNode.pattern_expressions.expressions)
{
var eqParams = new expression_list(
new List<expression>()
{
matchingExpression,
(patternCase.pattern as const_pattern).pattern_expression
}
);
var equalsCallNode = new method_call(
new dot_node(new ident("object"), new ident("Equals")),
eqParams,
patternCase.source_context);
var ifCondition = patternCase.condition == null ? (expression)equalsCallNode : bin_expr.LogicalAnd(equalsCallNode, patternCase.condition);
patternExpression
}
);
equalCalls.Add(
new method_call(
new dot_node(new ident("object"), new ident("Equals")),
eqParams,
patternCase.source_context
)
);
}
expression orPatternCases = equalCalls[0];
for (int i = 1; i < equalCalls.Count; ++i)
{
orPatternCases = bin_expr.LogicalOr(orPatternCases, equalCalls[i]);
}
var ifCondition = patternCase.condition == null ? orPatternCases : bin_expr.LogicalAnd(orPatternCases, patternCase.condition);
var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action);
// Добавляем полученные statements в результат