Matching const deconstructor parameter.

This commit is contained in:
Александр Погорелов 2019-03-13 10:54:24 +03:00
parent 082428027e
commit 6eaeb932d3
12 changed files with 3922 additions and 3393 deletions

File diff suppressed because it is too large Load diff

View file

@ -191,6 +191,7 @@ UNICODEARROW \x890
"[" { return (int)Tokens.tkSquareOpen; }
"]" { return (int)Tokens.tkSquareClose; }
"?" { return (int)Tokens.tkQuestion; }
"_" { return (int)Tokens.tkUnderscore; }
"?." { return (int)Tokens.tkQuestionPoint; }
"??" { return (int)Tokens.tkDoubleQuestion; }
"?[" { return (int)Tokens.tkQuestionSquareOpen; }

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> tkDirectiveName tkAmpersend tkColon tkDotDot tkPoint tkRoundOpen tkRoundClose tkSemiColon tkSquareOpen tkSquareClose tkQuestion tkUnderscore tkQuestionPoint tkDoubleQuestion tkQuestionSquareOpen
%token <ti> tkSizeOf tkTypeOf tkWhere tkArray tkCase tkClass tkAuto tkStatic tkConst tkConstructor tkDestructor tkElse tkExcept tkFile tkFor tkForeach tkFunction tkMatch tkWhen
%token <ti> tkIf tkImplementation tkInherited tkInterface 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
@ -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 const_pattern_expr_list
%type <stn> pattern pattern_optional_var const_pattern 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
@ -2790,6 +2790,14 @@ pattern_case
{
$$ = new pattern_case($1 as pattern_node, $3 as statement, null, @$);
}
| const_pattern tkWhen expr_l1 tkColon unlabelled_stmt
{
$$ = new pattern_case($1 as pattern_node, $5 as statement, $3, @$);
}
| const_pattern tkColon unlabelled_stmt
{
$$ = new pattern_case($1 as pattern_node, $3 as statement, null, @$);
}
;
case_stmt
@ -3284,11 +3292,14 @@ pattern_optional_var
{
$$ = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, $1, @$);
}
| const_pattern_expr_list
;
const_pattern
: const_pattern_expr_list
{
$$ = new const_pattern($1 as expression_list, @$);
}
;
;
const_pattern_expr_list
: const_pattern_expression
@ -3322,7 +3333,7 @@ tuple_pattern
;
tuple_pattern_expr
: tkQuestion { $$ = new tuple_wild_card(); }
: tkUnderscore { $$ = new tuple_wild_card(); }
| literal_or_number { $$ = $1; }
;
@ -3378,7 +3389,15 @@ pattern_out_param_list
;
pattern_out_param
: tkVar identifier tkColon type_ref
: tkUnderscore
{
$$ = new wild_card_deconstructor_parameter();
}
| literal_or_number
{
$$ = new const_deconstructor_parameter($1, @$);
}
| tkVar identifier tkColon type_ref
{
$$ = new var_deconstructor_parameter($2, $4, @$);
}
@ -3393,7 +3412,15 @@ pattern_out_param
;
pattern_out_param_optional_var
: identifier tkColon type_ref
: tkUnderscore
{
$$ = new wild_card_deconstructor_parameter();
}
| literal_or_number
{
$$ = new const_deconstructor_parameter($1, @$);
}
| identifier tkColon type_ref
{
$$ = new var_deconstructor_parameter($1, $3, @$);
}

File diff suppressed because it is too large Load diff

View file

@ -1197,6 +1197,16 @@ namespace PascalABCCompiler.SyntaxTree
{
DefaultVisit(_tuple_wild_card);
}
public virtual void visit(const_deconstructor_parameter _const_deconstructor_parameter)
{
DefaultVisit(_const_deconstructor_parameter);
}
public virtual void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
DefaultVisit(_wild_card_deconstructor_parameter);
}
}

View file

@ -1909,6 +1909,22 @@ namespace PascalABCCompiler.SyntaxTree
{
}
public virtual void pre_do_visit(const_deconstructor_parameter _const_deconstructor_parameter)
{
}
public virtual void post_do_visit(const_deconstructor_parameter _const_deconstructor_parameter)
{
}
public virtual void pre_do_visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
}
public virtual void post_do_visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
}
public override void visit(expression _expression)
{
DefaultVisit(_expression);
@ -3952,6 +3968,21 @@ namespace PascalABCCompiler.SyntaxTree
pre_do_visit(_tuple_wild_card);
post_do_visit(_tuple_wild_card);
}
public override void visit(const_deconstructor_parameter _const_deconstructor_parameter)
{
DefaultVisit(_const_deconstructor_parameter);
pre_do_visit(_const_deconstructor_parameter);
visit(const_deconstructor_parameter.const_param);
post_do_visit(_const_deconstructor_parameter);
}
public override void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
DefaultVisit(_wild_card_deconstructor_parameter);
pre_do_visit(_wild_card_deconstructor_parameter);
post_do_visit(_wild_card_deconstructor_parameter);
}
}

View file

@ -496,6 +496,10 @@ namespace PascalABCCompiler.SyntaxTree
return new const_pattern();
case 237:
return new tuple_wild_card();
case 238:
return new const_deconstructor_parameter();
case 239:
return new wild_card_deconstructor_parameter();
}
return null;
}
@ -4204,6 +4208,29 @@ namespace PascalABCCompiler.SyntaxTree
read_expression(_tuple_wild_card);
}
public void visit(const_deconstructor_parameter _const_deconstructor_parameter)
{
read_const_deconstructor_parameter(_const_deconstructor_parameter);
}
public void read_const_deconstructor_parameter(const_deconstructor_parameter _const_deconstructor_parameter)
{
read_pattern_deconstructor_parameter(_const_deconstructor_parameter);
_const_deconstructor_parameter.const_param = _read_node() as expression;
}
public void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
read_wild_card_deconstructor_parameter(_wild_card_deconstructor_parameter);
}
public void read_wild_card_deconstructor_parameter(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
read_pattern_deconstructor_parameter(_wild_card_deconstructor_parameter);
}
}

View file

@ -6607,6 +6607,39 @@ namespace PascalABCCompiler.SyntaxTree
write_expression(_tuple_wild_card);
}
public void visit(const_deconstructor_parameter _const_deconstructor_parameter)
{
bw.Write((Int16)238);
write_const_deconstructor_parameter(_const_deconstructor_parameter);
}
public void write_const_deconstructor_parameter(const_deconstructor_parameter _const_deconstructor_parameter)
{
write_pattern_deconstructor_parameter(_const_deconstructor_parameter);
if (_const_deconstructor_parameter.const_param == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_const_deconstructor_parameter.const_param.visit(this);
}
}
public void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
bw.Write((Int16)239);
write_wild_card_deconstructor_parameter(_wild_card_deconstructor_parameter);
}
public void write_wild_card_deconstructor_parameter(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{
write_pattern_deconstructor_parameter(_wild_card_deconstructor_parameter);
}
}

View file

@ -51497,6 +51497,247 @@ namespace PascalABCCompiler.SyntaxTree
}
///<summary>
///
///</summary>
[Serializable]
public partial class const_deconstructor_parameter : pattern_deconstructor_parameter
{
///<summary>
///Конструктор без параметров.
///</summary>
public const_deconstructor_parameter()
{
}
///<summary>
///Конструктор с параметрами.
///</summary>
public const_deconstructor_parameter(expression _const_param)
{
this._const_param=_const_param;
FillParentsInDirectChilds();
}
///<summary>
///Конструктор с параметрами.
///</summary>
public const_deconstructor_parameter(expression _const_param,SourceContext sc)
{
this._const_param=_const_param;
source_context = sc;
FillParentsInDirectChilds();
}
protected expression _const_param;
///<summary>
///
///</summary>
public expression const_param
{
get
{
return _const_param;
}
set
{
_const_param=value;
if (_const_param != null)
_const_param.Parent = this;
}
}
/// <summary> Создает копию узла </summary>
public override syntax_tree_node Clone()
{
const_deconstructor_parameter copy = new const_deconstructor_parameter();
copy.Parent = this.Parent;
if (source_context != null)
copy.source_context = new SourceContext(source_context);
if (const_param != null)
{
copy.const_param = (expression)const_param.Clone();
copy.const_param.Parent = copy;
}
return copy;
}
/// <summary> Получает копию данного узла корректного типа </summary>
public new const_deconstructor_parameter TypedClone()
{
return Clone() as const_deconstructor_parameter;
}
///<summary> Заполняет поля Parent в непосредственных дочерних узлах </summary>
public override void FillParentsInDirectChilds()
{
if (const_param != null)
const_param.Parent = this;
}
///<summary> Заполняет поля Parent во всем поддереве </summary>
public override void FillParentsInAllChilds()
{
FillParentsInDirectChilds();
const_param?.FillParentsInAllChilds();
}
///<summary>
///Свойство для получения количества всех подузлов без элементов поля типа List
///</summary>
public override Int32 subnodes_without_list_elements_count
{
get
{
return 1;
}
}
///<summary>
///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List
///</summary>
public override Int32 subnodes_count
{
get
{
return 1;
}
}
///<summary>
///Индексатор для получения всех подузлов
///</summary>
public override syntax_tree_node this[Int32 ind]
{
get
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
switch(ind)
{
case 0:
return const_param;
}
return null;
}
set
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
switch(ind)
{
case 0:
const_param = (expression)value;
break;
}
}
}
///<summary>
///Метод для обхода дерева посетителем
///</summary>
///<param name="visitor">Объект-посетитель.</param>
///<returns>Return value is void</returns>
public override void visit(IVisitor visitor)
{
visitor.visit(this);
}
}
///<summary>
///
///</summary>
[Serializable]
public partial class wild_card_deconstructor_parameter : pattern_deconstructor_parameter
{
///<summary>
///Конструктор без параметров.
///</summary>
public wild_card_deconstructor_parameter()
{
}
/// <summary> Создает копию узла </summary>
public override syntax_tree_node Clone()
{
wild_card_deconstructor_parameter copy = new wild_card_deconstructor_parameter();
copy.Parent = this.Parent;
if (source_context != null)
copy.source_context = new SourceContext(source_context);
return copy;
}
/// <summary> Получает копию данного узла корректного типа </summary>
public new wild_card_deconstructor_parameter TypedClone()
{
return Clone() as wild_card_deconstructor_parameter;
}
///<summary> Заполняет поля Parent в непосредственных дочерних узлах </summary>
public override void FillParentsInDirectChilds()
{
}
///<summary> Заполняет поля Parent во всем поддереве </summary>
public override void FillParentsInAllChilds()
{
FillParentsInDirectChilds();
}
///<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

@ -1432,6 +1432,18 @@ namespace PascalABCCompiler.SyntaxTree
///<param name="_tuple_wild_card">Node to visit</param>
///<returns> Return value is void </returns>
void visit(tuple_wild_card _tuple_wild_card);
///<summary>
///Method to visit const_deconstructor_parameter.
///</summary>
///<param name="_const_deconstructor_parameter">Node to visit</param>
///<returns> Return value is void </returns>
void visit(const_deconstructor_parameter _const_deconstructor_parameter);
///<summary>
///Method to visit wild_card_deconstructor_parameter.
///</summary>
///<param name="_wild_card_deconstructor_parameter">Node to visit</param>
///<returns> Return value is void </returns>
void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter);
}

View file

@ -3077,6 +3077,32 @@
<TagIndices />
</Tags>
</SyntaxNode>
<SyntaxNode Name="const_deconstructor_parameter" BaseName="pattern_deconstructor_parameter">
<Fields>
<SyntaxField Name="const_param" SyntaxType="expression" />
</Fields>
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>11</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="wild_card_deconstructor_parameter" BaseName="pattern_deconstructor_parameter">
<Fields />
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>11</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
</SyntaxNodes>
<Settings>
<FileName>Tree.cs</FileName>
@ -3104,7 +3130,7 @@
<Tag Name="Yield" ReferenceCount="8" />
<Tag Name="Patterns" ReferenceCount="12" />
<Tag Name="Typeclasses" ReferenceCount="13" />
<Tag Name="patterns" ReferenceCount="5" />
<Tag Name="patterns" ReferenceCount="7" />
</Tags>
</FilterCategory>
</TagCategories>
@ -3140,6 +3166,7 @@
<HelpData Key=".from" Value="" />
<HelpData Key=".guardstats" Value="" />
<HelpData Key=".handlers" Value="" />
<HelpData Key=".i" Value="" />
<HelpData Key=".left" Value="" />
<HelpData Key=".lists" Value="" />
<HelpData Key=".listunitsections" Value="" />
@ -3369,6 +3396,10 @@
<HelpData Key="compiler_directive_list.compiler_directive_list Add(compiler_directive _compiler_directive, SourceContext sc)" Value="" />
<HelpData Key="compiler_directive_list.compiler_directive_list(compiler_directive _compiler_directive, SourceContext sc)" Value="" />
<HelpData Key="compiler_directive_list.directives" Value="" />
<HelpData Key="const_deconstructor_parameter" Value="" />
<HelpData Key="const_deconstructor_parameter.const_param" Value="" />
<HelpData Key="const_deconstructor_parameter.i" Value="" />
<HelpData Key="const_deconstructor_parameter.value" Value="" />
<HelpData Key="const_definition" Value="" />
<HelpData Key="const_definition.const_name" Value="" />
<HelpData Key="const_definition.const_value" Value="" />
@ -4563,6 +4594,9 @@
<HelpData Key="while_node.statements" Value="Тело цикла" />
<HelpData Key="while_type_specificator_list" Value="" />
<HelpData Key="while_type_specificator_list.defs" Value="" />
<HelpData Key="wild_card_deconstructor_parameter" Value="" />
<HelpData Key="wild_card_deconstructor_parameter.exp" Value="" />
<HelpData Key="wildcard_deconstructor_parameter" Value="" />
<HelpData Key="with_statement" Value="Представление оператора with в синтаксическом дереве." />
<HelpData Key="with_statement." Value="" />
<HelpData Key="with_statement.do_with" Value="Список объектов, с которыми производить действия." />

View file

@ -69,6 +69,7 @@ namespace SyntaxVisitors.SugarVisitors
private const string WildCardsTupleEqualFunctionName = compiler_string_consts.wild_cards_tuple_equal_function_name;
private const string SeqFunctionName = compiler_string_consts.seq_function_name;
private const string GeneratedPatternNamePrefix = "<>pattern";
private const string GeneratedConstPatternParamPrefix = "<>constPatternParam";
private int generalVariableCounter = 0;
private int successVariableCounter = 0;
@ -156,9 +157,41 @@ namespace SyntaxVisitors.SugarVisitors
void DesugarDeconstructorPatternCase(expression matchingExpression, pattern_case patternCase)
{
Debug.Assert(patternCase.pattern is deconstructor_pattern);
var pattern = patternCase.pattern as deconstructor_pattern;
expression paramCheckExpr = null;
for (int i = 0; i < pattern.parameters.Count; ++i)
{
if (pattern.parameters[i] is const_deconstructor_parameter constPattern)
{
var constParamIdent = new ident(NewConstParamId(), pattern.parameters[i].source_context);
var eqParams = new expression_list(
new List<expression>()
{
constPattern.const_param,
constParamIdent
}
);
var constParamCheck = new method_call(
new dot_node(new ident("object"), new ident("Equals")),
eqParams,
patternCase.source_context
);
pattern.parameters[i] = new var_deconstructor_parameter(
constParamIdent,
null,
pattern.parameters[i].source_context);
paramCheckExpr = paramCheckExpr == null ? (expression)constParamCheck : bin_expr.LogicalAnd(paramCheckExpr, constParamCheck);
}
}
var isExpression = new is_pattern_expr(matchingExpression, patternCase.pattern);
var ifCondition = patternCase.condition == null ? (expression)isExpression : bin_expr.LogicalAnd(isExpression, patternCase.condition);
paramCheckExpr = paramCheckExpr == null ? (expression)isExpression : bin_expr.LogicalAnd(isExpression, paramCheckExpr);
var ifCondition = patternCase.condition == null ? paramCheckExpr : bin_expr.LogicalAnd(paramCheckExpr, patternCase.condition);
var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action);
// Добавляем полученные statements в результат
@ -172,7 +205,8 @@ namespace SyntaxVisitors.SugarVisitors
var statementsToAdd = new List<statement>();
var equalCalls = new List<method_call>();
var matchingWithFullWildCardTuple = false;
foreach (var patternExpression in patternExpressionNode.pattern_expressions.expressions)
{
statementsToAdd.Add(GetTypeCompatibilityCheck(matchingExpression, patternExpression));
@ -199,6 +233,11 @@ namespace SyntaxVisitors.SugarVisitors
possibleTupleCase.parameters[currentInd] = new int32_const(0, patternCase.source_context);
}
}
matchingWithFullWildCardTuple = elemsToCompare.Count == 0;
if (matchingWithFullWildCardTuple)
{
break;
}
var seqCall = SubtreeCreator.CreateSystemFunctionCall(
SeqFunctionName, elemsToCompare.ToArray());
@ -232,10 +271,20 @@ namespace SyntaxVisitors.SugarVisitors
);
}
typeChecks.AddRange(statementsToAdd);
expression orPatternCases = equalCalls[0];
for (int i = 1; i < equalCalls.Count; ++i)
expression orPatternCases = null;
// Если в одном из выражений есть тапл со всеми wild-card'ами (напр. (?, ?, ?))
if (matchingWithFullWildCardTuple)
{
orPatternCases = bin_expr.LogicalOr(orPatternCases, equalCalls[i]);
orPatternCases = new bool_const(true, patternCase.source_context);
}
else
{
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);
@ -349,7 +398,7 @@ namespace SyntaxVisitors.SugarVisitors
var pattern = isExpression.right as deconstructor_pattern;
var desugaringResult = DesugarPattern(pattern, isExpression.left);
ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable);
var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context);
statementsToAdd.Add(GetMatchedExpressionCheck(isExpression.left));
statementsToAdd.Add(GetTypeCompatibilityCheck(isExpression));
@ -517,6 +566,13 @@ namespace SyntaxVisitors.SugarVisitors
return null;
}
//random id generator
private int postfix = 0;
private string NewConstParamId()
{
return GeneratedConstPatternParamPrefix + postfix++.ToString();
}
}
}