Collection patterns

This commit is contained in:
Александр Погорелов 2019-03-30 06:18:58 +03:00
parent 6e0c964f87
commit 38f124a682
17 changed files with 3555 additions and 2703 deletions

View file

@ -759,7 +759,7 @@ namespace CodeCompletion
} }
else else
{ {
foreach (pattern_deconstructor_parameter pdp in _deconstructor_pattern.parameters) foreach (pattern_parameter pdp in _deconstructor_pattern.parameters)
{ {
if (pdp is var_deconstructor_parameter) if (pdp is var_deconstructor_parameter)
{ {

View file

@ -1682,7 +1682,7 @@ namespace CodeCompletion
public override void visit(deconstructor_pattern _deconstructor_pattern) public override void visit(deconstructor_pattern _deconstructor_pattern)
{ {
_deconstructor_pattern.type.visit(this); _deconstructor_pattern.type.visit(this);
foreach (pattern_deconstructor_parameter pdp in _deconstructor_pattern.parameters) foreach (pattern_parameter pdp in _deconstructor_pattern.parameters)
pdp.visit(this); pdp.visit(this);
} }
public override void visit(recursive_deconstructor_parameter _recursive_deconstructor_parameter) public override void visit(recursive_deconstructor_parameter _recursive_deconstructor_parameter)

View file

@ -2313,7 +2313,7 @@ namespace PascalABCCompiler.SyntaxTree
} }
} }
public void CompareInternal(pattern_deconstructor_parameter left, pattern_deconstructor_parameter right) public void CompareInternal(pattern_parameter left, pattern_parameter right)
{ {
if (left == null && right != null || left != null && right == null) if (left == null && right != null || left != null && right == null)
throw_not_equal(left, right); throw_not_equal(left, right);

View file

@ -2,7 +2,7 @@
// This CSharp output file generated by Gardens Point LEX // This CSharp output file generated by Gardens Point LEX
// Version: 1.1.3.301 // Version: 1.1.3.301
// Machine: DESKTOP-IF20NRO // Machine: DESKTOP-IF20NRO
// DateTime: 3/13/2019 12:33:32 PM // DateTime: 3/17/2019 11:23:05 AM
// UserName: FatCow // UserName: FatCow
// GPLEX input file <ABCPascal.lex> // GPLEX input file <ABCPascal.lex>
// GPLEX frame file <embedded resource> // GPLEX frame file <embedded resource>

View file

@ -145,7 +145,7 @@
%type <stn> simple_property_definition %type <stn> simple_property_definition
%type <stn> stmt_or_expression unlabelled_stmt stmt case_item %type <stn> stmt_or_expression unlabelled_stmt stmt case_item
%type <td> set_type %type <td> set_type
%type <ex> as_is_expr as_is_constexpr is_expr as_expr power_expr power_constexpr %type <ex> as_is_expr as_is_constexpr is_type_expr as_expr power_expr power_constexpr
%type <td> unsized_array_type simple_type_or_ simple_type simple_type_question/*array_name_for_new_expr*/ foreach_stmt_ident_dype_opt fptype type_ref fptype_noproctype array_type %type <td> unsized_array_type simple_type_or_ simple_type simple_type_question/*array_name_for_new_expr*/ foreach_stmt_ident_dype_opt fptype type_ref fptype_noproctype array_type
%type <td> template_param template_empty_param structured_type unpacked_structured_type empty_template_type_reference simple_or_template_type_reference type_ref_or_secific for_stmt_decl_or_assign type_decl_type %type <td> template_param template_empty_param structured_type unpacked_structured_type empty_template_type_reference simple_or_template_type_reference type_ref_or_secific for_stmt_decl_or_assign type_decl_type
%type <stn> type_ref_and_secific_list %type <stn> type_ref_and_secific_list
@ -174,8 +174,8 @@
%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 <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 <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 <ti> tkAssignOrEqual
%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 <stn> pattern pattern_optional_var const_pattern collection_pattern collection_pattern_list_item 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 <ob> pattern_out_param_list pattern_out_param_list_optional_var collection_pattern_expr_list
%type <ex> const_pattern_expression tuple_pattern tuple_pattern_expr %type <ex> const_pattern_expression tuple_pattern tuple_pattern_expr
%% %%
@ -2798,6 +2798,10 @@ pattern_case
{ {
$$ = new pattern_case($1 as pattern_node, $3 as statement, null, @$); $$ = new pattern_case($1 as pattern_node, $3 as statement, null, @$);
} }
| collection_pattern tkColon unlabelled_stmt
{
$$ = new pattern_case($1 as pattern_node, $3 as statement, null, @$);
}
; ;
case_stmt case_stmt
@ -3272,28 +3276,73 @@ relop_expr
{ {
$$ = new bin_expr($1, $3, $2.type, @$); $$ = new bin_expr($1, $3, $2.type, @$);
} }
| is_expr tkRoundOpen pattern_out_param_list tkRoundClose | is_type_expr tkRoundOpen pattern_out_param_list tkRoundClose
{ {
var isTypeCheck = $1 as typecast_node; var isTypeCheck = $1 as typecast_node;
var deconstructorPattern = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, isTypeCheck.type_def, @$); var deconstructorPattern = new deconstructor_pattern($3 as List<pattern_parameter>, isTypeCheck.type_def, @$);
$$ = new is_pattern_expr(isTypeCheck.expr, deconstructorPattern, null, @$); $$ = new is_pattern_expr(isTypeCheck.expr, deconstructorPattern, @$);
}
| term tkIs collection_pattern
{
$$ = new is_pattern_expr($1, $3 as pattern_node, @$);
} }
; ;
pattern pattern
: simple_or_template_type_reference tkRoundOpen pattern_out_param_list tkRoundClose : simple_or_template_type_reference tkRoundOpen pattern_out_param_list tkRoundClose
{ {
$$ = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, $1, @$); $$ = new deconstructor_pattern($3 as List<pattern_parameter>, $1, @$);
} }
; ;
pattern_optional_var pattern_optional_var
: simple_or_template_type_reference tkRoundOpen pattern_out_param_list_optional_var tkRoundClose : simple_or_template_type_reference tkRoundOpen pattern_out_param_list_optional_var tkRoundClose
{ {
$$ = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, $1, @$); $$ = new deconstructor_pattern($3 as List<pattern_parameter>, $1, @$);
} }
; ;
collection_pattern
: tkSquareOpen collection_pattern_expr_list tkSquareClose
{
$$ = new collection_pattern($2 as List<pattern_parameter>, @$);
}
;
collection_pattern_expr_list
: collection_pattern_list_item
{
$$ = new List<pattern_parameter>();
($$ as List<pattern_parameter>).Add($1 as pattern_parameter);
}
| collection_pattern_expr_list tkComma collection_pattern_list_item
{
var list = $1 as List<pattern_parameter>;
list.Add($3 as pattern_parameter);
$$ = list;
}
;
collection_pattern_list_item
: literal_or_number
{
$$ = new const_pattern_parameter($1, @$);
}
| pattern
{
$$ = new recursive_deconstructor_parameter($1 as pattern_node, @$);
}
| pattern_optional_var
{
$$ = new recursive_deconstructor_parameter($1 as pattern_node, @$);
}
| tkDotDot
{
$$ = new collection_pattern_gap_parameter();
}
;
const_pattern const_pattern
: const_pattern_expr_list : const_pattern_expr_list
{ {
@ -3351,19 +3400,19 @@ tuple_pattern_expr_list
pattern_out_param_list_optional_var pattern_out_param_list_optional_var
: pattern_out_param_optional_var : pattern_out_param_optional_var
{ {
$$ = new List<pattern_deconstructor_parameter>(); $$ = new List<pattern_parameter>();
($$ as List<pattern_deconstructor_parameter>).Add($1 as pattern_deconstructor_parameter); ($$ as List<pattern_parameter>).Add($1 as pattern_parameter);
} }
| pattern_out_param_list_optional_var tkSemiColon pattern_out_param_optional_var | pattern_out_param_list_optional_var tkSemiColon pattern_out_param_optional_var
{ {
var list = $1 as List<pattern_deconstructor_parameter>; var list = $1 as List<pattern_parameter>;
list.Add($3 as pattern_deconstructor_parameter); list.Add($3 as pattern_parameter);
$$ = list; $$ = list;
} }
| pattern_out_param_list_optional_var tkComma pattern_out_param_optional_var | pattern_out_param_list_optional_var tkComma pattern_out_param_optional_var
{ {
var list = $1 as List<pattern_deconstructor_parameter>; var list = $1 as List<pattern_parameter>;
list.Add($3 as pattern_deconstructor_parameter); list.Add($3 as pattern_parameter);
$$ = list; $$ = list;
} }
; ;
@ -3371,19 +3420,19 @@ pattern_out_param_list_optional_var
pattern_out_param_list pattern_out_param_list
: pattern_out_param : pattern_out_param
{ {
$$ = new List<pattern_deconstructor_parameter>(); $$ = new List<pattern_parameter>();
($$ as List<pattern_deconstructor_parameter>).Add($1 as pattern_deconstructor_parameter); ($$ as List<pattern_parameter>).Add($1 as pattern_parameter);
} }
| pattern_out_param_list tkSemiColon pattern_out_param | pattern_out_param_list tkSemiColon pattern_out_param
{ {
var list = $1 as List<pattern_deconstructor_parameter>; var list = $1 as List<pattern_parameter>;
list.Add($3 as pattern_deconstructor_parameter); list.Add($3 as pattern_parameter);
$$ = list; $$ = list;
} }
| pattern_out_param_list tkComma pattern_out_param | pattern_out_param_list tkComma pattern_out_param
{ {
var list = $1 as List<pattern_deconstructor_parameter>; var list = $1 as List<pattern_parameter>;
list.Add($3 as pattern_deconstructor_parameter); list.Add($3 as pattern_parameter);
$$ = list; $$ = list;
} }
; ;
@ -3395,7 +3444,7 @@ pattern_out_param
} }
| literal_or_number | literal_or_number
{ {
$$ = new const_deconstructor_parameter($1, @$); $$ = new const_pattern_parameter($1, @$);
} }
| tkVar identifier tkColon type_ref | tkVar identifier tkColon type_ref
{ {
@ -3418,7 +3467,7 @@ pattern_out_param_optional_var
} }
| literal_or_number | literal_or_number
{ {
$$ = new const_deconstructor_parameter($1, @$); $$ = new const_pattern_parameter($1, @$);
} }
| identifier tkColon type_ref | identifier tkColon type_ref
{ {
@ -3554,7 +3603,7 @@ typecast_op
; ;
as_is_expr as_is_expr
: is_expr : is_type_expr
{ $$ = $1; } { $$ = $1; }
| as_expr | as_expr
{ $$ = $1; } { $$ = $1; }
@ -3567,15 +3616,11 @@ as_expr
} }
; ;
is_expr is_type_expr
: term tkIs simple_or_template_type_reference : term tkIs simple_or_template_type_reference
{ {
$$ = NewAsIsExpr($1, op_typecast.is_op, $3, @$); $$ = NewAsIsExpr($1, op_typecast.is_op, $3, @$);
} }
| term tkIs literal_or_number
{
$$ = NewIsObjectExpr($1, $3, @$);
}
; ;
simple_term simple_term

File diff suppressed because it is too large Load diff

View file

@ -321,29 +321,6 @@ namespace GPPGParserScanner
return naie; return naie;
} }
public method_call NewIsObjectExpr(syntax_tree_node left_term, syntax_tree_node right_term, LexLocation loc)
{
var eq_params = new expression_list(
new List<expression>()
{
(addressed_value)left_term,
(addressed_value)right_term
}
);
var equals_call_node = new method_call(
new dot_node(new ident("object"), new ident("Equals")),
eq_params,
loc);
if (!(left_term is addressed_value))
parsertools.errors.Add(new bad_operand_type(parsertools.CurrentFileName, left_term.source_context, equals_call_node));
if (!(right_term is addressed_value))
parsertools.errors.Add(new bad_operand_type(parsertools.CurrentFileName, right_term.source_context, equals_call_node));
return equals_call_node;
}
public function_lambda_call NewFactor(ident func_decl_lambda, expression_list expr_list, LexLocation loc) public function_lambda_call NewFactor(ident func_decl_lambda, expression_list expr_list, LexLocation loc)
{ {
var fld = parsertools.find_pascalABC_lambda_name(func_decl_lambda.name); var fld = parsertools.find_pascalABC_lambda_name(func_decl_lambda.name);

View file

@ -1153,9 +1153,9 @@ namespace PascalABCCompiler.SyntaxTree
DefaultVisit(_deconstructor_pattern); DefaultVisit(_deconstructor_pattern);
} }
public virtual void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public virtual void visit(pattern_parameter _pattern_parameter)
{ {
DefaultVisit(_pattern_deconstructor_parameter); DefaultVisit(_pattern_parameter);
} }
public virtual void visit(desugared_deconstruction _desugared_deconstruction) public virtual void visit(desugared_deconstruction _desugared_deconstruction)
@ -1198,15 +1198,25 @@ namespace PascalABCCompiler.SyntaxTree
DefaultVisit(_tuple_wild_card); DefaultVisit(_tuple_wild_card);
} }
public virtual void visit(const_deconstructor_parameter _const_deconstructor_parameter) public virtual void visit(const_pattern_parameter _const_pattern_parameter)
{ {
DefaultVisit(_const_deconstructor_parameter); DefaultVisit(_const_pattern_parameter);
} }
public virtual void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter) public virtual void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
{ {
DefaultVisit(_wild_card_deconstructor_parameter); DefaultVisit(_wild_card_deconstructor_parameter);
} }
public virtual void visit(collection_pattern _collection_pattern)
{
DefaultVisit(_collection_pattern);
}
public virtual void visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
DefaultVisit(_collection_pattern_gap_parameter);
}
} }

View file

@ -1837,11 +1837,11 @@ namespace PascalABCCompiler.SyntaxTree
{ {
} }
public virtual void pre_do_visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public virtual void pre_do_visit(pattern_parameter _pattern_parameter)
{ {
} }
public virtual void post_do_visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public virtual void post_do_visit(pattern_parameter _pattern_parameter)
{ {
} }
@ -1909,11 +1909,11 @@ namespace PascalABCCompiler.SyntaxTree
{ {
} }
public virtual void pre_do_visit(const_deconstructor_parameter _const_deconstructor_parameter) public virtual void pre_do_visit(const_pattern_parameter _const_pattern_parameter)
{ {
} }
public virtual void post_do_visit(const_deconstructor_parameter _const_deconstructor_parameter) public virtual void post_do_visit(const_pattern_parameter _const_pattern_parameter)
{ {
} }
@ -1925,6 +1925,22 @@ namespace PascalABCCompiler.SyntaxTree
{ {
} }
public virtual void pre_do_visit(collection_pattern _collection_pattern)
{
}
public virtual void post_do_visit(collection_pattern _collection_pattern)
{
}
public virtual void pre_do_visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
}
public virtual void post_do_visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
}
public override void visit(expression _expression) public override void visit(expression _expression)
{ {
DefaultVisit(_expression); DefaultVisit(_expression);
@ -3836,6 +3852,8 @@ namespace PascalABCCompiler.SyntaxTree
{ {
DefaultVisit(_pattern_node); DefaultVisit(_pattern_node);
pre_do_visit(_pattern_node); pre_do_visit(_pattern_node);
for (int i = 0; i < parameters.Count; i++)
visit(pattern_node.parameters[i]);
post_do_visit(_pattern_node); post_do_visit(_pattern_node);
} }
@ -3854,7 +3872,6 @@ namespace PascalABCCompiler.SyntaxTree
pre_do_visit(_is_pattern_expr); pre_do_visit(_is_pattern_expr);
visit(is_pattern_expr.left); visit(is_pattern_expr.left);
visit(is_pattern_expr.right); visit(is_pattern_expr.right);
visit(is_pattern_expr.constDeconstructorParamCheck);
post_do_visit(_is_pattern_expr); post_do_visit(_is_pattern_expr);
} }
@ -3891,17 +3908,16 @@ namespace PascalABCCompiler.SyntaxTree
{ {
DefaultVisit(_deconstructor_pattern); DefaultVisit(_deconstructor_pattern);
pre_do_visit(_deconstructor_pattern); pre_do_visit(_deconstructor_pattern);
for (int i = 0; i < parameters.Count; i++)
visit(deconstructor_pattern.parameters[i]);
visit(deconstructor_pattern.type); visit(deconstructor_pattern.type);
visit(deconstructor_pattern.const_params_check);
post_do_visit(_deconstructor_pattern); post_do_visit(_deconstructor_pattern);
} }
public override void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public override void visit(pattern_parameter _pattern_parameter)
{ {
DefaultVisit(_pattern_deconstructor_parameter); DefaultVisit(_pattern_parameter);
pre_do_visit(_pattern_deconstructor_parameter); pre_do_visit(_pattern_parameter);
post_do_visit(_pattern_deconstructor_parameter); post_do_visit(_pattern_parameter);
} }
public override void visit(desugared_deconstruction _desugared_deconstruction) public override void visit(desugared_deconstruction _desugared_deconstruction)
@ -3970,12 +3986,12 @@ namespace PascalABCCompiler.SyntaxTree
post_do_visit(_tuple_wild_card); post_do_visit(_tuple_wild_card);
} }
public override void visit(const_deconstructor_parameter _const_deconstructor_parameter) public override void visit(const_pattern_parameter _const_pattern_parameter)
{ {
DefaultVisit(_const_deconstructor_parameter); DefaultVisit(_const_pattern_parameter);
pre_do_visit(_const_deconstructor_parameter); pre_do_visit(_const_pattern_parameter);
visit(const_deconstructor_parameter.const_param); visit(const_pattern_parameter.const_param);
post_do_visit(_const_deconstructor_parameter); post_do_visit(_const_pattern_parameter);
} }
public override void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter) public override void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter)
@ -3984,6 +4000,20 @@ namespace PascalABCCompiler.SyntaxTree
pre_do_visit(_wild_card_deconstructor_parameter); pre_do_visit(_wild_card_deconstructor_parameter);
post_do_visit(_wild_card_deconstructor_parameter); post_do_visit(_wild_card_deconstructor_parameter);
} }
public override void visit(collection_pattern _collection_pattern)
{
DefaultVisit(_collection_pattern);
pre_do_visit(_collection_pattern);
post_do_visit(_collection_pattern);
}
public override void visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
DefaultVisit(_collection_pattern_gap_parameter);
pre_do_visit(_collection_pattern_gap_parameter);
post_do_visit(_collection_pattern_gap_parameter);
}
} }

View file

@ -479,7 +479,7 @@ namespace PascalABCCompiler.SyntaxTree
case 228: case 228:
return new deconstructor_pattern(); return new deconstructor_pattern();
case 229: case 229:
return new pattern_deconstructor_parameter(); return new pattern_parameter();
case 230: case 230:
return new desugared_deconstruction(); return new desugared_deconstruction();
case 231: case 231:
@ -497,9 +497,13 @@ namespace PascalABCCompiler.SyntaxTree
case 237: case 237:
return new tuple_wild_card(); return new tuple_wild_card();
case 238: case 238:
return new const_deconstructor_parameter(); return new const_pattern_parameter();
case 239: case 239:
return new wild_card_deconstructor_parameter(); return new wild_card_deconstructor_parameter();
case 240:
return new collection_pattern();
case 241:
return new collection_pattern_gap_parameter();
} }
return null; return null;
} }
@ -3971,6 +3975,19 @@ namespace PascalABCCompiler.SyntaxTree
public void read_pattern_node(pattern_node _pattern_node) public void read_pattern_node(pattern_node _pattern_node)
{ {
read_syntax_tree_node(_pattern_node); read_syntax_tree_node(_pattern_node);
if (br.ReadByte() == 0)
{
_pattern_node.parameters = null;
}
else
{
_pattern_node.parameters = new List<pattern_parameter>();
Int32 ssyy_count = br.ReadInt32();
for(Int32 ssyy_i = 0; ssyy_i < ssyy_count; ssyy_i++)
{
_pattern_node.parameters.Add(_read_node() as pattern_parameter);
}
}
} }
@ -3997,7 +4014,6 @@ namespace PascalABCCompiler.SyntaxTree
read_expression(_is_pattern_expr); read_expression(_is_pattern_expr);
_is_pattern_expr.left = _read_node() as expression; _is_pattern_expr.left = _read_node() as expression;
_is_pattern_expr.right = _read_node() as pattern_node; _is_pattern_expr.right = _read_node() as pattern_node;
_is_pattern_expr.constDeconstructorParamCheck = _read_node() as expression;
} }
@ -4061,31 +4077,19 @@ namespace PascalABCCompiler.SyntaxTree
public void read_deconstructor_pattern(deconstructor_pattern _deconstructor_pattern) public void read_deconstructor_pattern(deconstructor_pattern _deconstructor_pattern)
{ {
read_pattern_node(_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; _deconstructor_pattern.type = _read_node() as type_definition;
_deconstructor_pattern.const_params_check = _read_node() as expression;
} }
public void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public void visit(pattern_parameter _pattern_parameter)
{ {
read_pattern_deconstructor_parameter(_pattern_deconstructor_parameter); read_pattern_parameter(_pattern_parameter);
} }
public void read_pattern_deconstructor_parameter(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public void read_pattern_parameter(pattern_parameter _pattern_parameter)
{ {
read_syntax_tree_node(_pattern_deconstructor_parameter); read_syntax_tree_node(_pattern_parameter);
} }
@ -4109,7 +4113,7 @@ namespace PascalABCCompiler.SyntaxTree
public void read_var_deconstructor_parameter(var_deconstructor_parameter _var_deconstructor_parameter) public void read_var_deconstructor_parameter(var_deconstructor_parameter _var_deconstructor_parameter)
{ {
read_pattern_deconstructor_parameter(_var_deconstructor_parameter); read_pattern_parameter(_var_deconstructor_parameter);
_var_deconstructor_parameter.identifier = _read_node() as ident; _var_deconstructor_parameter.identifier = _read_node() as ident;
_var_deconstructor_parameter.type = _read_node() as type_definition; _var_deconstructor_parameter.type = _read_node() as type_definition;
} }
@ -4122,7 +4126,7 @@ namespace PascalABCCompiler.SyntaxTree
public void read_recursive_deconstructor_parameter(recursive_deconstructor_parameter _recursive_deconstructor_parameter) public void read_recursive_deconstructor_parameter(recursive_deconstructor_parameter _recursive_deconstructor_parameter)
{ {
read_pattern_deconstructor_parameter(_recursive_deconstructor_parameter); read_pattern_parameter(_recursive_deconstructor_parameter);
_recursive_deconstructor_parameter.pattern = _read_node() as pattern_node; _recursive_deconstructor_parameter.pattern = _read_node() as pattern_node;
} }
@ -4210,15 +4214,15 @@ namespace PascalABCCompiler.SyntaxTree
} }
public void visit(const_deconstructor_parameter _const_deconstructor_parameter) public void visit(const_pattern_parameter _const_pattern_parameter)
{ {
read_const_deconstructor_parameter(_const_deconstructor_parameter); read_const_pattern_parameter(_const_pattern_parameter);
} }
public void read_const_deconstructor_parameter(const_deconstructor_parameter _const_deconstructor_parameter) public void read_const_pattern_parameter(const_pattern_parameter _const_pattern_parameter)
{ {
read_pattern_deconstructor_parameter(_const_deconstructor_parameter); read_pattern_parameter(_const_pattern_parameter);
_const_deconstructor_parameter.const_param = _read_node() as expression; _const_pattern_parameter.const_param = _read_node() as expression;
} }
@ -4229,7 +4233,29 @@ namespace PascalABCCompiler.SyntaxTree
public void read_wild_card_deconstructor_parameter(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); read_pattern_parameter(_wild_card_deconstructor_parameter);
}
public void visit(collection_pattern _collection_pattern)
{
read_collection_pattern(_collection_pattern);
}
public void read_collection_pattern(collection_pattern _collection_pattern)
{
read_pattern_node(_collection_pattern);
}
public void visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
read_collection_pattern_gap_parameter(_collection_pattern_gap_parameter);
}
public void read_collection_pattern_gap_parameter(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
read_pattern_parameter(_collection_pattern_gap_parameter);
} }
} }

View file

@ -6187,6 +6187,27 @@ namespace PascalABCCompiler.SyntaxTree
public void write_pattern_node(pattern_node _pattern_node) public void write_pattern_node(pattern_node _pattern_node)
{ {
write_syntax_tree_node(_pattern_node); write_syntax_tree_node(_pattern_node);
if (_pattern_node.parameters == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
bw.Write(_pattern_node.parameters.Count);
for(Int32 ssyy_i = 0; ssyy_i < _pattern_node.parameters.Count; ssyy_i++)
{
if (_pattern_node.parameters[ssyy_i] == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_pattern_node.parameters[ssyy_i].visit(this);
}
}
}
} }
@ -6247,15 +6268,6 @@ namespace PascalABCCompiler.SyntaxTree
bw.Write((byte)1); bw.Write((byte)1);
_is_pattern_expr.right.visit(this); _is_pattern_expr.right.visit(this);
} }
if (_is_pattern_expr.constDeconstructorParamCheck == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_is_pattern_expr.constDeconstructorParamCheck.visit(this);
}
} }
@ -6379,27 +6391,6 @@ namespace PascalABCCompiler.SyntaxTree
public void write_deconstructor_pattern(deconstructor_pattern _deconstructor_pattern) public void write_deconstructor_pattern(deconstructor_pattern _deconstructor_pattern)
{ {
write_pattern_node(_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) if (_deconstructor_pattern.type == null)
{ {
bw.Write((byte)0); bw.Write((byte)0);
@ -6409,18 +6400,27 @@ namespace PascalABCCompiler.SyntaxTree
bw.Write((byte)1); bw.Write((byte)1);
_deconstructor_pattern.type.visit(this); _deconstructor_pattern.type.visit(this);
} }
if (_deconstructor_pattern.const_params_check == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_deconstructor_pattern.const_params_check.visit(this);
}
} }
public void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public void visit(pattern_parameter _pattern_parameter)
{ {
bw.Write((Int16)229); bw.Write((Int16)229);
write_pattern_deconstructor_parameter(_pattern_deconstructor_parameter); write_pattern_parameter(_pattern_parameter);
} }
public void write_pattern_deconstructor_parameter(pattern_deconstructor_parameter _pattern_deconstructor_parameter) public void write_pattern_parameter(pattern_parameter _pattern_parameter)
{ {
write_syntax_tree_node(_pattern_deconstructor_parameter); write_syntax_tree_node(_pattern_parameter);
} }
@ -6462,7 +6462,7 @@ namespace PascalABCCompiler.SyntaxTree
public void write_var_deconstructor_parameter(var_deconstructor_parameter _var_deconstructor_parameter) public void write_var_deconstructor_parameter(var_deconstructor_parameter _var_deconstructor_parameter)
{ {
write_pattern_deconstructor_parameter(_var_deconstructor_parameter); write_pattern_parameter(_var_deconstructor_parameter);
if (_var_deconstructor_parameter.identifier == null) if (_var_deconstructor_parameter.identifier == null)
{ {
bw.Write((byte)0); bw.Write((byte)0);
@ -6492,7 +6492,7 @@ namespace PascalABCCompiler.SyntaxTree
public void write_recursive_deconstructor_parameter(recursive_deconstructor_parameter _recursive_deconstructor_parameter) public void write_recursive_deconstructor_parameter(recursive_deconstructor_parameter _recursive_deconstructor_parameter)
{ {
write_pattern_deconstructor_parameter(_recursive_deconstructor_parameter); write_pattern_parameter(_recursive_deconstructor_parameter);
if (_recursive_deconstructor_parameter.pattern == null) if (_recursive_deconstructor_parameter.pattern == null)
{ {
bw.Write((byte)0); bw.Write((byte)0);
@ -6617,23 +6617,23 @@ namespace PascalABCCompiler.SyntaxTree
} }
public void visit(const_deconstructor_parameter _const_deconstructor_parameter) public void visit(const_pattern_parameter _const_pattern_parameter)
{ {
bw.Write((Int16)238); bw.Write((Int16)238);
write_const_deconstructor_parameter(_const_deconstructor_parameter); write_const_pattern_parameter(_const_pattern_parameter);
} }
public void write_const_deconstructor_parameter(const_deconstructor_parameter _const_deconstructor_parameter) public void write_const_pattern_parameter(const_pattern_parameter _const_pattern_parameter)
{ {
write_pattern_deconstructor_parameter(_const_deconstructor_parameter); write_pattern_parameter(_const_pattern_parameter);
if (_const_deconstructor_parameter.const_param == null) if (_const_pattern_parameter.const_param == null)
{ {
bw.Write((byte)0); bw.Write((byte)0);
} }
else else
{ {
bw.Write((byte)1); bw.Write((byte)1);
_const_deconstructor_parameter.const_param.visit(this); _const_pattern_parameter.const_param.visit(this);
} }
} }
@ -6646,7 +6646,31 @@ namespace PascalABCCompiler.SyntaxTree
public void write_wild_card_deconstructor_parameter(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); write_pattern_parameter(_wild_card_deconstructor_parameter);
}
public void visit(collection_pattern _collection_pattern)
{
bw.Write((Int16)240);
write_collection_pattern(_collection_pattern);
}
public void write_collection_pattern(collection_pattern _collection_pattern)
{
write_pattern_node(_collection_pattern);
}
public void visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
bw.Write((Int16)241);
write_collection_pattern_gap_parameter(_collection_pattern_gap_parameter);
}
public void write_collection_pattern_gap_parameter(collection_pattern_gap_parameter _collection_pattern_gap_parameter)
{
write_pattern_parameter(_collection_pattern_gap_parameter);
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1818,11 +1818,14 @@ namespace PascalABCCompiler.SyntaxTree
public partial class deconstructor_pattern public partial class deconstructor_pattern
{ {
public bool IsRecursive => parameters.Any(x => x is recursive_deconstructor_parameter);
public override string ToString() => $"{type}({string.Join(", ", parameters.Select(x => x.ToString()))})"; public override string ToString() => $"{type}({string.Join(", ", parameters.Select(x => x.ToString()))})";
} }
public partial class pattern_node
{
public bool IsRecursive => parameters.Any(x => x is recursive_deconstructor_parameter);
}
public partial class var_deconstructor_parameter public partial class var_deconstructor_parameter
{ {
public override string ToString() => identifier.ToString() + (type == null ? "" : $": {type}"); public override string ToString() => identifier.ToString() + (type == null ? "" : $": {type}");

View file

@ -1379,11 +1379,11 @@ namespace PascalABCCompiler.SyntaxTree
///<returns> Return value is void </returns> ///<returns> Return value is void </returns>
void visit(deconstructor_pattern _deconstructor_pattern); void visit(deconstructor_pattern _deconstructor_pattern);
///<summary> ///<summary>
///Method to visit pattern_deconstructor_parameter. ///Method to visit pattern_parameter.
///</summary> ///</summary>
///<param name="_pattern_deconstructor_parameter">Node to visit</param> ///<param name="_pattern_parameter">Node to visit</param>
///<returns> Return value is void </returns> ///<returns> Return value is void </returns>
void visit(pattern_deconstructor_parameter _pattern_deconstructor_parameter); void visit(pattern_parameter _pattern_parameter);
///<summary> ///<summary>
///Method to visit desugared_deconstruction. ///Method to visit desugared_deconstruction.
///</summary> ///</summary>
@ -1433,17 +1433,29 @@ namespace PascalABCCompiler.SyntaxTree
///<returns> Return value is void </returns> ///<returns> Return value is void </returns>
void visit(tuple_wild_card _tuple_wild_card); void visit(tuple_wild_card _tuple_wild_card);
///<summary> ///<summary>
///Method to visit const_deconstructor_parameter. ///Method to visit const_pattern_parameter.
///</summary> ///</summary>
///<param name="_const_deconstructor_parameter">Node to visit</param> ///<param name="_const_pattern_parameter">Node to visit</param>
///<returns> Return value is void </returns> ///<returns> Return value is void </returns>
void visit(const_deconstructor_parameter _const_deconstructor_parameter); void visit(const_pattern_parameter _const_pattern_parameter);
///<summary> ///<summary>
///Method to visit wild_card_deconstructor_parameter. ///Method to visit wild_card_deconstructor_parameter.
///</summary> ///</summary>
///<param name="_wild_card_deconstructor_parameter">Node to visit</param> ///<param name="_wild_card_deconstructor_parameter">Node to visit</param>
///<returns> Return value is void </returns> ///<returns> Return value is void </returns>
void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter); void visit(wild_card_deconstructor_parameter _wild_card_deconstructor_parameter);
///<summary>
///Method to visit collection_pattern.
///</summary>
///<param name="_collection_pattern">Node to visit</param>
///<returns> Return value is void </returns>
void visit(collection_pattern _collection_pattern);
///<summary>
///Method to visit collection_pattern_gap_parameter.
///</summary>
///<param name="_collection_pattern_gap_parameter">Node to visit</param>
///<returns> Return value is void </returns>
void visit(collection_pattern_gap_parameter _collection_pattern_gap_parameter);
} }

View file

@ -2864,7 +2864,9 @@
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="pattern_node" BaseName="syntax_tree_node"> <SyntaxNode Name="pattern_node" BaseName="syntax_tree_node">
<Fields /> <Fields>
<ExtendedField Name="parameters" Type="List&lt;pattern_parameter&gt;" CreateVariable="true" DeleteVariable="false" />
</Fields>
<Methods /> <Methods />
<Tags> <Tags>
<CategoryIndices> <CategoryIndices>
@ -2894,7 +2896,6 @@
<Fields> <Fields>
<SyntaxField Name="left" SyntaxType="expression" /> <SyntaxField Name="left" SyntaxType="expression" />
<SyntaxField Name="right" SyntaxType="pattern_node" /> <SyntaxField Name="right" SyntaxType="pattern_node" />
<SyntaxField Name="constDeconstructorParamCheck" SyntaxType="expression" />
</Fields> </Fields>
<Methods /> <Methods />
<Tags> <Tags>
@ -2954,8 +2955,8 @@
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="deconstructor_pattern" BaseName="pattern_node"> <SyntaxNode Name="deconstructor_pattern" BaseName="pattern_node">
<Fields> <Fields>
<ExtendedField Name="parameters" Type="List&lt;pattern_deconstructor_parameter&gt;" CreateVariable="true" DeleteVariable="false" />
<SyntaxField Name="type" SyntaxType="type_definition" /> <SyntaxField Name="type" SyntaxType="type_definition" />
<SyntaxField Name="const_params_check" SyntaxType="expression" />
</Fields> </Fields>
<Methods /> <Methods />
<Tags> <Tags>
@ -2967,7 +2968,7 @@
</TagIndices> </TagIndices>
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="pattern_deconstructor_parameter" BaseName="syntax_tree_node"> <SyntaxNode Name="pattern_parameter" BaseName="syntax_tree_node">
<Fields /> <Fields />
<Methods /> <Methods />
<Tags> <Tags>
@ -2994,7 +2995,7 @@
</TagIndices> </TagIndices>
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="var_deconstructor_parameter" BaseName="pattern_deconstructor_parameter"> <SyntaxNode Name="var_deconstructor_parameter" BaseName="pattern_parameter">
<Fields> <Fields>
<SyntaxField Name="identifier" SyntaxType="ident" /> <SyntaxField Name="identifier" SyntaxType="ident" />
<SyntaxField Name="type" SyntaxType="type_definition" /> <SyntaxField Name="type" SyntaxType="type_definition" />
@ -3009,7 +3010,7 @@
</TagIndices> </TagIndices>
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="recursive_deconstructor_parameter" BaseName="pattern_deconstructor_parameter"> <SyntaxNode Name="recursive_deconstructor_parameter" BaseName="pattern_parameter">
<Fields> <Fields>
<SyntaxField Name="pattern" SyntaxType="pattern_node" /> <SyntaxField Name="pattern" SyntaxType="pattern_node" />
</Fields> </Fields>
@ -3066,7 +3067,7 @@
<CategoryIndex>0</CategoryIndex> <CategoryIndex>0</CategoryIndex>
</CategoryIndices> </CategoryIndices>
<TagIndices> <TagIndices>
<TagIndex>11</TagIndex> <TagIndex>9</TagIndex>
</TagIndices> </TagIndices>
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
@ -3078,7 +3079,7 @@
<TagIndices /> <TagIndices />
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="const_deconstructor_parameter" BaseName="pattern_deconstructor_parameter"> <SyntaxNode Name="const_pattern_parameter" BaseName="pattern_parameter">
<Fields> <Fields>
<SyntaxField Name="const_param" SyntaxType="expression" /> <SyntaxField Name="const_param" SyntaxType="expression" />
</Fields> </Fields>
@ -3088,11 +3089,11 @@
<CategoryIndex>0</CategoryIndex> <CategoryIndex>0</CategoryIndex>
</CategoryIndices> </CategoryIndices>
<TagIndices> <TagIndices>
<TagIndex>11</TagIndex> <TagIndex>9</TagIndex>
</TagIndices> </TagIndices>
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
<SyntaxNode Name="wild_card_deconstructor_parameter" BaseName="pattern_deconstructor_parameter"> <SyntaxNode Name="wild_card_deconstructor_parameter" BaseName="pattern_parameter">
<Fields /> <Fields />
<Methods /> <Methods />
<Tags> <Tags>
@ -3100,7 +3101,31 @@
<CategoryIndex>0</CategoryIndex> <CategoryIndex>0</CategoryIndex>
</CategoryIndices> </CategoryIndices>
<TagIndices> <TagIndices>
<TagIndex>11</TagIndex> <TagIndex>9</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="collection_pattern" BaseName="pattern_node">
<Fields />
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>9</TagIndex>
</TagIndices>
</Tags>
</SyntaxNode>
<SyntaxNode Name="collection_pattern_gap_parameter" BaseName="pattern_parameter">
<Fields />
<Methods />
<Tags>
<CategoryIndices>
<CategoryIndex>0</CategoryIndex>
</CategoryIndices>
<TagIndices>
<TagIndex>9</TagIndex>
</TagIndices> </TagIndices>
</Tags> </Tags>
</SyntaxNode> </SyntaxNode>
@ -3129,9 +3154,8 @@
<Tag Name="Важнейшие" ReferenceCount="207" /> <Tag Name="Важнейшие" ReferenceCount="207" />
<Tag Name="Method_Procedure_Call" ReferenceCount="2" /> <Tag Name="Method_Procedure_Call" ReferenceCount="2" />
<Tag Name="Yield" ReferenceCount="8" /> <Tag Name="Yield" ReferenceCount="8" />
<Tag Name="Patterns" ReferenceCount="12" /> <Tag Name="Patterns" ReferenceCount="17" />
<Tag Name="Typeclasses" ReferenceCount="13" /> <Tag Name="Typeclasses" ReferenceCount="13" />
<Tag Name="patterns" ReferenceCount="7" />
</Tags> </Tags>
</FilterCategory> </FilterCategory>
</TagCategories> </TagCategories>
@ -3168,6 +3192,7 @@
<HelpData Key=".guardstats" Value="" /> <HelpData Key=".guardstats" Value="" />
<HelpData Key=".handlers" Value="" /> <HelpData Key=".handlers" Value="" />
<HelpData Key=".i" Value="" /> <HelpData Key=".i" Value="" />
<HelpData Key=".item_expression" Value="" />
<HelpData Key=".left" Value="" /> <HelpData Key=".left" Value="" />
<HelpData Key=".lists" Value="" /> <HelpData Key=".lists" Value="" />
<HelpData Key=".listunitsections" Value="" /> <HelpData Key=".listunitsections" Value="" />
@ -3379,6 +3404,13 @@
<HelpData Key="class_predefinition.class_name" Value="" /> <HelpData Key="class_predefinition.class_name" Value="" />
<HelpData Key="closure_substituting_node" Value="" /> <HelpData Key="closure_substituting_node" Value="" />
<HelpData Key="closure_substituting_node.substitution" Value="" /> <HelpData Key="closure_substituting_node.substitution" Value="" />
<HelpData Key="collection_pattern" Value="" />
<HelpData Key="collection_pattern.collection_items" Value="" />
<HelpData Key="collection_pattern_expr_item" Value="" />
<HelpData Key="collection_pattern_expr_item.item_expression" Value="" />
<HelpData Key="collection_pattern_gap_item" Value="" />
<HelpData Key="collection_pattern_gap_parameter" Value="" />
<HelpData Key="collection_pattern_item" Value="" />
<HelpData Key="compilation_unit" Value="" /> <HelpData Key="compilation_unit" Value="" />
<HelpData Key="compilation_unit." Value="" /> <HelpData Key="compilation_unit." Value="" />
<HelpData Key="compilation_unit.Language" Value="" /> <HelpData Key="compilation_unit.Language" Value="" />
@ -3414,6 +3446,8 @@
<HelpData Key="const_pattern" Value="паттерн для константного матчинга" /> <HelpData Key="const_pattern" Value="паттерн для константного матчинга" />
<HelpData Key="const_pattern.pattern_expression" Value="" /> <HelpData Key="const_pattern.pattern_expression" Value="" />
<HelpData Key="const_pattern.pattern_expressions" Value="" /> <HelpData Key="const_pattern.pattern_expressions" Value="" />
<HelpData Key="const_pattern_parameter" Value="" />
<HelpData Key="const_pattern_parameter.const_param" Value="" />
<HelpData Key="constructor" Value="" /> <HelpData Key="constructor" Value="" />
<HelpData Key="constructor.constructor(formal_parameters fp): this(fp, null)" 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="" /> <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="" />
@ -3451,6 +3485,7 @@
<HelpData Key="deconstruction_variables_definition" Value="Список объявлений для deconstructor pattern" /> <HelpData Key="deconstruction_variables_definition" Value="Список объявлений для deconstructor pattern" />
<HelpData Key="deconstruction_variables_definition.definitions" Value="" /> <HelpData Key="deconstruction_variables_definition.definitions" Value="" />
<HelpData Key="deconstructor_pattern" Value="" /> <HelpData Key="deconstructor_pattern" Value="" />
<HelpData Key="deconstructor_pattern.const_params_check" Value="Проверка соответствия для константных параметрах деконструирования" />
<HelpData Key="deconstructor_pattern.parameters" Value="Результат деконструирования" /> <HelpData Key="deconstructor_pattern.parameters" Value="Результат деконструирования" />
<HelpData Key="deconstructor_pattern.type" Value="Деконструируемый тип" /> <HelpData Key="deconstructor_pattern.type" Value="Деконструируемый тип" />
<HelpData Key="default_indexer_property_node" Value="" /> <HelpData Key="default_indexer_property_node" Value="" />
@ -3570,6 +3605,8 @@
<HelpData Key="exception_identifier.type_name" Value="" /> <HelpData Key="exception_identifier.type_name" Value="" />
<HelpData Key="exception_identifier.variable" Value="" /> <HelpData Key="exception_identifier.variable" Value="" />
<HelpData Key="exit_directive" Value="" /> <HelpData Key="exit_directive" Value="" />
<HelpData Key="expr_collection_pattern_item" Value="" />
<HelpData Key="expr_collection_pattern_item.item_expression" Value="" />
<HelpData Key="expression" Value="Выражение" /> <HelpData Key="expression" Value="Выражение" />
<HelpData Key="expression." Value="" /> <HelpData Key="expression." Value="" />
<HelpData Key="expression_as_statement" Value="" /> <HelpData Key="expression_as_statement" Value="" />
@ -3995,6 +4032,8 @@
<HelpData Key="pattern_deconstructor_parameter.name" Value="" /> <HelpData Key="pattern_deconstructor_parameter.name" Value="" />
<HelpData Key="pattern_deconstructor_parameter.type" Value="" /> <HelpData Key="pattern_deconstructor_parameter.type" Value="" />
<HelpData Key="pattern_node" Value="" /> <HelpData Key="pattern_node" Value="" />
<HelpData Key="pattern_node.parameters" Value="" />
<HelpData Key="pattern_parameter" Value="Базовый класс параметра для pattern_node" />
<HelpData Key="proc_block" Value="" /> <HelpData Key="proc_block" Value="" />
<HelpData Key="procedure_attribute" Value="" /> <HelpData Key="procedure_attribute" Value="" />
<HelpData Key="procedure_attribute.attribute_type" Value="" /> <HelpData Key="procedure_attribute.attribute_type" Value="" />

View file

@ -46,7 +46,7 @@ namespace SyntaxVisitors.SugarVisitors
{ {
var result = new List<statement>(); var result = new List<statement>();
result.Add(CastVariableDefinition); result.Add(CastVariableDefinition);
result.Add(new desugared_deconstruction(DeconstructionVariables, CastVariable, patternContext)); result.Add(new desugared_deconstruction(DeconstructionVariables, CastVariable, patternContext));
result.Add(SuccessVariableDefinition); result.Add(SuccessVariableDefinition);
return result; return result;
@ -74,6 +74,7 @@ namespace SyntaxVisitors.SugarVisitors
private int generalVariableCounter = 0; private int generalVariableCounter = 0;
private int successVariableCounter = 0; private int successVariableCounter = 0;
private int labelVariableCounter = 0; private int labelVariableCounter = 0;
private int deconstructParamVariableCounter = 0;
private if_node _previousIf; private if_node _previousIf;
private statement desugaredMatchWith; private statement desugaredMatchWith;
@ -100,31 +101,40 @@ namespace SyntaxVisitors.SugarVisitors
if (patternCase == null) if (patternCase == null)
continue; continue;
if (patternCase.pattern is deconstructor_pattern) switch (patternCase.pattern)
{ {
// Проверяем встречался ли уже такой тип при деконструкции case deconstructor_pattern pattern:
// SSM 02.01.19 пока закомментировал этот кусок т.к. при этом коде падает стандартный пример ArithmSimplify.cs. #1408 снова открыл
/*var deconstructionType = (patternCase.pattern as deconstructor_pattern).
type as named_type_reference;
if (deconstructionType != null &&
deconstructionType.names != null &&
deconstructionType.names.Count != 0)
{
var deconstructionTypeName = deconstructionType.names[0].name;
if (usedDeconstructionTypes.Contains(deconstructionTypeName))
{ {
throw new SyntaxVisitorError("REPEATED_DECONSTRUCTION_TYPE", // Проверяем встречался ли уже такой тип при деконструкции
patternCase.pattern.source_context); // SSM 02.01.19 пока закомментировал этот кусок т.к. при этом коде падает стандартный пример ArithmSimplify.cs. #1408 снова открыл
/*var deconstructionType = (patternCase.pattern as deconstructor_pattern).
type as named_type_reference;
if (deconstructionType != null &&
deconstructionType.names != null &&
deconstructionType.names.Count != 0)
{
var deconstructionTypeName = deconstructionType.names[0].name;
if (usedDeconstructionTypes.Contains(deconstructionTypeName))
{
throw new SyntaxVisitorError("REPEATED_DECONSTRUCTION_TYPE",
patternCase.pattern.source_context);
}
usedDeconstructionTypes.Add(deconstructionTypeName);
} */
DesugarDeconstructorPatternCase(matchWith.expr, patternCase);
break;
}
case const_pattern p:
{
DesugarConstPatternCase(matchWith.expr, patternCase);
break;
}
case collection_pattern p:
{
DesugarDeconstructorPatternCase(matchWith.expr, patternCase);
break;
} }
usedDeconstructionTypes.Add(deconstructionTypeName);
} */
DesugarDeconstructorPatternCase(matchWith.expr, patternCase);
}
if (patternCase.pattern is const_pattern)
{
DesugarConstPatternCase(matchWith.expr, patternCase);
} }
} }
@ -150,16 +160,15 @@ namespace SyntaxVisitors.SugarVisitors
throw new SyntaxVisitorError("PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT", isPatternExpr.source_context); throw new SyntaxVisitorError("PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT", isPatternExpr.source_context);
Debug.Assert(GetAscendant<statement_list>(isPatternExpr) != null, "Couldn't find statement list in upper nodes"); Debug.Assert(GetAscendant<statement_list>(isPatternExpr) != null, "Couldn't find statement list in upper nodes");
DesugarIsExpression(isPatternExpr); DesugarIsExpression(isPatternExpr);
} }
private void DesugarDeconstructorPatternCase(expression matchingExpression, pattern_case patternCase) private void DesugarDeconstructorPatternCase(expression matchingExpression, pattern_case patternCase)
{ {
Debug.Assert(patternCase.pattern is deconstructor_pattern); //var paramCheckExpr = DesugarDeconstructorPatternParameters(patternCase.pattern as deconstructor_pattern);
var paramCheckExpr = DesugarDeconstructorPatternParameters(patternCase.pattern as deconstructor_pattern);
var isExpression = new is_pattern_expr(matchingExpression, patternCase.pattern, paramCheckExpr); var isExpression = new is_pattern_expr(matchingExpression, patternCase.pattern, patternCase.source_context);
var ifCondition = patternCase.condition == null ? (expression)isExpression : bin_expr.LogicalAnd(isExpression, patternCase.condition); var ifCondition = patternCase.condition == null ? (expression)isExpression : bin_expr.LogicalAnd(isExpression, patternCase.condition);
var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action); var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action);
@ -173,7 +182,7 @@ namespace SyntaxVisitors.SugarVisitors
for (int i = 0; i < pattern.parameters.Count; ++i) for (int i = 0; i < pattern.parameters.Count; ++i)
{ {
if (pattern.parameters[i] is const_deconstructor_parameter constPattern) if (pattern.parameters[i] is const_pattern_parameter constPattern)
{ {
var constParamIdent = new ident(NewDeconstructParamId(), pattern.parameters[i].source_context); var constParamIdent = new ident(NewDeconstructParamId(), pattern.parameters[i].source_context);
@ -202,7 +211,6 @@ namespace SyntaxVisitors.SugarVisitors
if (pattern.parameters[i] is wild_card_deconstructor_parameter) if (pattern.parameters[i] is wild_card_deconstructor_parameter)
{ {
var wildCardGeneratedParamIdent = new ident(NewDeconstructParamId(), pattern.parameters[i].source_context); var wildCardGeneratedParamIdent = new ident(NewDeconstructParamId(), pattern.parameters[i].source_context);
pattern.parameters[i] = new var_deconstructor_parameter( pattern.parameters[i] = new var_deconstructor_parameter(
wildCardGeneratedParamIdent, wildCardGeneratedParamIdent,
null, null,
@ -214,8 +222,8 @@ namespace SyntaxVisitors.SugarVisitors
if (deconstructor_param.pattern is deconstructor_pattern deconstructor_pattern) if (deconstructor_param.pattern is deconstructor_pattern deconstructor_pattern)
{ {
var recursiveChecks = DesugarDeconstructorPatternParameters(deconstructor_pattern); var recursiveChecks = DesugarDeconstructorPatternParameters(deconstructor_pattern);
paramCheckExpr = paramCheckExpr == null ? paramCheckExpr = paramCheckExpr == null ?
recursiveChecks : recursiveChecks :
bin_expr.LogicalAnd(paramCheckExpr, recursiveChecks); bin_expr.LogicalAnd(paramCheckExpr, recursiveChecks);
} }
} }
@ -254,7 +262,6 @@ namespace SyntaxVisitors.SugarVisitors
elemsToCompare.Add(currentInd); elemsToCompare.Add(currentInd);
} else } else
{ {
//possibleTupleCase.parameters.ReplaceInList(possibleTupleCase.parameters.expressions[currentInd], new nil_const());
possibleTupleCase.parameters[currentInd] = new int32_const(0, patternCase.source_context); possibleTupleCase.parameters[currentInd] = new int32_const(0, patternCase.source_context);
} }
} }
@ -269,7 +276,7 @@ namespace SyntaxVisitors.SugarVisitors
var tupleEqualsCall = SubtreeCreator. var tupleEqualsCall = SubtreeCreator.
CreateSystemFunctionCall( CreateSystemFunctionCall(
WildCardsTupleEqualFunctionName, WildCardsTupleEqualFunctionName,
possibleTupleCase, possibleTupleCase,
matchingExpression, matchingExpression,
seqCall seqCall
); );
@ -313,11 +320,92 @@ namespace SyntaxVisitors.SugarVisitors
} }
var ifCondition = patternCase.condition == null ? orPatternCases : bin_expr.LogicalAnd(orPatternCases, patternCase.condition); var ifCondition = patternCase.condition == null ? orPatternCases : bin_expr.LogicalAnd(orPatternCases, patternCase.condition);
var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action); var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action);
// Добавляем полученные statements в результат // Добавляем полученные statements в результат
AddDesugaredCaseToResult(ifCheck, ifCheck); AddDesugaredCaseToResult(ifCheck, ifCheck);
} }
private expression GetCollectionItemsEqualCheckBeforeGap(addressed_value matchingExpression, List<pattern_parameter> toCompare)
{
var fromIndex = 0;
expression equalChecks = null;
foreach (var param in toCompare)
{
if (param is const_pattern_parameter const_params)
{
var indexerCall = new indexer(
matchingExpression,
new expression_list(
new int32_const(fromIndex++, matchingExpression.source_context),
matchingExpression.source_context),
matchingExpression.source_context);
var eqParams = new expression_list(
new List<expression>()
{
indexerCall,
const_params.const_param
}
);
var equalCall = new method_call(
new dot_node(
new ident("object"),
new ident("Equals")),
eqParams,
matchingExpression.source_context
);
equalChecks = equalChecks == null ? (expression)equalCall : bin_expr.LogicalAnd(equalChecks, equalCall);
}
}
return equalChecks;
}
private expression GetCollectionItemsEqualCheckAfterGap(addressed_value matchingExpression, List<pattern_parameter> toCompare)
{
var elemFromTail = 1;
expression equalChecks = null;
foreach (var param in toCompare)
{
if (param is const_pattern_parameter const_param)
{
var indexerCall = new indexer(
matchingExpression,
new expression_list(
new bin_expr(
new method_call(
new dot_node(
matchingExpression,
new ident("Count", matchingExpression.source_context)),
new expression_list()),
new int32_const(elemFromTail++, matchingExpression.source_context),
Operators.Minus),
matchingExpression.source_context),
matchingExpression.source_context);
var eqParams = new expression_list(
new List<expression>()
{
indexerCall,
const_param.const_param
}
);
var equalCall = new method_call(
new dot_node(
new ident("object"),
new ident("Equals")),
eqParams,
matchingExpression.source_context
);
equalChecks = equalChecks == null ? (expression)equalCall : bin_expr.LogicalAnd(equalChecks, equalCall);
}
}
return equalChecks;
}
private ident NewGeneralName() => new ident(GeneratedPatternNamePrefix + "GenVar" + generalVariableCounter++); private ident NewGeneralName() => new ident(GeneratedPatternNamePrefix + "GenVar" + generalVariableCounter++);
private ident NewSuccessName() => new ident(GeneratedPatternNamePrefix + "Success" + successVariableCounter++); private ident NewSuccessName() => new ident(GeneratedPatternNamePrefix + "Success" + successVariableCounter++);
@ -346,7 +434,7 @@ namespace SyntaxVisitors.SugarVisitors
_previousIf = newIf; _previousIf = newIf;
} }
private DeconstructionDesugaringResult DesugarPattern(deconstructor_pattern pattern, expression matchingExpression, expression constParamCheck) private DeconstructionDesugaringResult DesugarDeconstructorPattern(deconstructor_pattern pattern, expression matchingExpression)
{ {
Debug.Assert(!pattern.IsRecursive, "All recursive patterns should be desugared into simple patterns at this point"); Debug.Assert(!pattern.IsRecursive, "All recursive patterns should be desugared into simple patterns at this point");
@ -359,10 +447,6 @@ namespace SyntaxVisitors.SugarVisitors
// делегирование проверки паттерна функции IsTest // делегирование проверки паттерна функции IsTest
desugarResult.TypeCastCheck = SubtreeCreator.CreateSystemFunctionCall(IsTestMethodName, matchingExpression, castVariableName); desugarResult.TypeCastCheck = SubtreeCreator.CreateSystemFunctionCall(IsTestMethodName, matchingExpression, castVariableName);
if (constParamCheck != null)
{
desugarResult.TypeCastCheck = bin_expr.LogicalAnd(desugarResult.TypeCastCheck, constParamCheck);
}
var parameters = pattern.parameters.Cast<var_deconstructor_parameter>(); var parameters = pattern.parameters.Cast<var_deconstructor_parameter>();
foreach (var deconstructedVariable in parameters) foreach (var deconstructedVariable in parameters)
@ -378,35 +462,90 @@ namespace SyntaxVisitors.SugarVisitors
return desugarResult; return desugarResult;
} }
private expression DesugarCollectionPattern(collection_pattern pattern, expression matchingExpression)
{
Debug.Assert(!pattern.IsRecursive, "All recursive patterns should be desugared into simple patterns at this point");
var collectionItems = pattern.parameters;
var gapItemMet = false;
var gapIndex = 0;
var exprBeforeGap = new List<pattern_parameter>();
var exprAfterGap = new List<pattern_parameter>();
for (int i = 0; i < collectionItems.Count; ++i)
{
if (collectionItems[i] is collection_pattern_gap_parameter)
{
if (gapItemMet)
{
throw new SyntaxVisitorError("REPEATED_DOTDOT_COLLECTION_PATTERN_EXPR",
pattern.source_context);
}
gapItemMet = true;
gapIndex = i;
continue;
}
if (gapItemMet)
{
exprAfterGap.Insert(0, collectionItems[i]);
}
else
{
exprBeforeGap.Add(collectionItems[i]);
}
}
var itemsEqualCalls = GetCollectionItemsEqualCheckBeforeGap(matchingExpression as addressed_value, exprBeforeGap);
if (gapItemMet && exprAfterGap.Count != 0)
{
var afterGapEqual = GetCollectionItemsEqualCheckAfterGap(matchingExpression as addressed_value, exprAfterGap);
itemsEqualCalls = itemsEqualCalls == null ? afterGapEqual : bin_expr.LogicalAnd(itemsEqualCalls, afterGapEqual);
}
return itemsEqualCalls;
}
private void DesugarIsExpression(is_pattern_expr isPatternExpr) private void DesugarIsExpression(is_pattern_expr isPatternExpr)
{ {
Debug.Assert(isPatternExpr.right is deconstructor_pattern); if (isPatternExpr.right.IsRecursive)
var constParamCheck = DesugarDeconstructorPatternParameters(isPatternExpr.right as deconstructor_pattern);
isPatternExpr.constDeconstructorParamCheck = constParamCheck;
var patternLocation = GetLocation(isPatternExpr);
var pattern = isPatternExpr.right as deconstructor_pattern;
//AddDefinitionsInUpperStatementList(isPatternExpr, new[] { GetTypeCompatibilityCheck(isPatternExpr) });
if (pattern.IsRecursive)
{ {
var desugaredRecursiveIs = DesugarRecursiveDeconstructor(isPatternExpr.left, pattern); var desugaredRecursiveIs = DesugarRecursiveDeconstructor(isPatternExpr.left, isPatternExpr.right);
ReplaceUsingParent(isPatternExpr, desugaredRecursiveIs); ReplaceUsingParent(isPatternExpr, desugaredRecursiveIs);
desugaredRecursiveIs.visit(this); desugaredRecursiveIs.visit(this);
return; return;
} }
var patternLocation = GetLocation(isPatternExpr);
switch (patternLocation) switch (isPatternExpr.right)
{ {
case PatternLocation.IfCondition: DesugarIsExpressionInIfCondition(isPatternExpr); break; case deconstructor_pattern pattern:
case PatternLocation.Assign: DesugarIsExpressionInAssignment(isPatternExpr); break; {
var constParamCheck = DesugarDeconstructorPatternParameters(isPatternExpr.right as deconstructor_pattern);
pattern.const_params_check = constParamCheck;
//AddDefinitionsInUpperStatementList(isPatternExpr, new[] { GetTypeCompatibilityCheck(isPatternExpr) });
switch (patternLocation)
{
case PatternLocation.IfCondition: DesugarIsExpressionInIfCondition(isPatternExpr); break;
case PatternLocation.Assign: DesugarIsExpressionInAssignment(isPatternExpr); break;
}
break;
}
case collection_pattern pattern:
{
switch (patternLocation)
{
case PatternLocation.IfCondition: DesugarIsExpressionInIfCondition(isPatternExpr); break;
}
break;
}
} }
} }
private expression DesugarRecursiveDeconstructor(expression expression, deconstructor_pattern pattern) private expression DesugarRecursiveDeconstructor(expression expression, pattern_node pattern)
{ {
List<pattern_deconstructor_parameter> parameters = pattern.parameters; List<pattern_parameter> parameters = pattern.parameters;
expression conjunction = new is_pattern_expr(expression, pattern, null); expression conjunction = new is_pattern_expr(expression, pattern, pattern.source_context);
for (int i = 0; i < parameters.Count; i++) for (int i = 0; i < parameters.Count; i++)
{ {
if (parameters[i] is recursive_deconstructor_parameter parameter) if (parameters[i] is recursive_deconstructor_parameter parameter)
@ -416,41 +555,40 @@ namespace SyntaxVisitors.SugarVisitors
var varParameter = new var_deconstructor_parameter(newName, null); var varParameter = new var_deconstructor_parameter(newName, null);
parameters[i] = varParameter; parameters[i] = varParameter;
varParameter.Parent = parameters[i]; varParameter.Parent = parameters[i];
conjunction = bin_expr.LogicalAnd(conjunction, DesugarRecursiveDeconstructor(newName, parameter.pattern as deconstructor_pattern)); conjunction = bin_expr.LogicalAnd(conjunction, DesugarRecursiveDeconstructor(newName, parameter.pattern));
} }
} }
return conjunction; return conjunction;
} }
private void DesugarIsExpressionInAssignment(is_pattern_expr isExpression) private void DesugarIsExpressionInAssignment(is_pattern_expr isExpression)
{ {
var pattern = isExpression.right as deconstructor_pattern; var statementsToAdd = ProcessDesugaringForDeconstructorPattern(isExpression);
var desugaringResult = DesugarPattern(pattern, isExpression.left, isExpression.constDeconstructorParamCheck);
ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable);
var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context);
statementsToAdd.Add(GetMatchedExpressionCheck(isExpression.left));
statementsToAdd.Add(GetTypeCompatibilityCheck(isExpression));
statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall());
AddDefinitionsInUpperStatementList(isExpression, statementsToAdd); AddDefinitionsInUpperStatementList(isExpression, statementsToAdd);
} }
private void DesugarIsExpressionInIfCondition(is_pattern_expr isExpression) private void DesugarIsExpressionInIfCondition(is_pattern_expr isExpression)
{ {
var pattern = isExpression.right as deconstructor_pattern; List<statement> statementsToAdd = null;
var desugaringResult = DesugarPattern(pattern, isExpression.left, isExpression.constDeconstructorParamCheck);
ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable);
var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context); switch (isExpression.right)
statementsToAdd.Add(GetMatchedExpressionCheck(isExpression.left)); {
statementsToAdd.Add(GetTypeCompatibilityCheck(isExpression)); case deconstructor_pattern dp:
statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall()); if (dp.const_params_check != null)
{
var ifToAddConstParamsCheck = GetAscendant<if_node>(isExpression);
ifToAddConstParamsCheck.condition = bin_expr.LogicalAnd(ifToAddConstParamsCheck.condition, dp.const_params_check);
}
statementsToAdd = ProcessDesugaringForDeconstructorPattern(isExpression);
break;
case collection_pattern cp:
statementsToAdd = ProcessDesugaringForCollectionPattern(isExpression);
break;
}
var enclosingIf = GetAscendant<if_node>(isExpression); var enclosingIf = GetAscendant<if_node>(isExpression);
// Если уже обрабатывался ранее (второй встретившийся в том же условии is), то не изменяем if // Если уже обрабатывался ранее (второй встретившийся в том же условии is), то не изменяем if
if (processedIfNodes.Contains(enclosingIf)) if (processedIfNodes.Contains(enclosingIf))
AddDefinitionsInUpperStatementList(isExpression, statementsToAdd); AddDefinitionsInUpperStatementList(isExpression, statementsToAdd);
// Иначе помещаем определения и if-then в отдельный блок, а else после этого блока // Иначе помещаем определения и if-then в отдельный блок, а else после этого блока
else else
@ -466,6 +604,30 @@ namespace SyntaxVisitors.SugarVisitors
} }
} }
private List<statement> ProcessDesugaringForDeconstructorPattern(is_pattern_expr isExpression)
{
var pattern = isExpression.right as deconstructor_pattern;
var desugaringResult = DesugarDeconstructorPattern(pattern, isExpression.left);
ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable);
var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context);
statementsToAdd.Add(GetMatchedExpressionCheck(isExpression.left));
statementsToAdd.Add(GetTypeCompatibilityCheck(isExpression));
statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall());
return statementsToAdd;
}
private List<statement> ProcessDesugaringForCollectionPattern(is_pattern_expr isExpression)
{
var pattern = isExpression.right as collection_pattern;
var successCheck = DesugarCollectionPattern(pattern, isExpression.left);
ReplaceUsingParent(isExpression, successCheck);
var statementsToAdd = new List<statement>();
return statementsToAdd;
}
private semantic_check_sugared_statement_node GetMatchedExpressionCheck(expression matchedExpression) private semantic_check_sugared_statement_node GetMatchedExpressionCheck(expression matchedExpression)
=> new semantic_check_sugared_statement_node(SemanticCheckType.MatchedExpression, new List<syntax_tree_node>() { matchedExpression }); => new semantic_check_sugared_statement_node(SemanticCheckType.MatchedExpression, new List<syntax_tree_node>() { matchedExpression });
@ -596,12 +758,10 @@ namespace SyntaxVisitors.SugarVisitors
return null; return null;
} }
//random id generator
private int postfix = 0;
private string NewDeconstructParamId() private string NewDeconstructParamId()
{ {
return GeneratedDeconstructParamPrefix + postfix++.ToString(); return GeneratedPatternNamePrefix + "DeconstructParam" + deconstructParamVariableCounter++.ToString();
} }
} }
} }

View file

@ -18,6 +18,7 @@ LAMBDA_EXPRESSIONS_CANNOT_CONTAIN_YIELD=Лямбда-выражения не м
PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT=Сопоставление с образцом не поддерживается в данном контексте PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT=Сопоставление с образцом не поддерживается в данном контексте
ONLY_ONE_DECONSTRUCT_ALLOWED=Можно определить только один пользовательский деконструктор ONLY_ONE_DECONSTRUCT_ALLOWED=Можно определить только один пользовательский деконструктор
REPEATED_DECONSTRUCTION_TYPE=Повторение типов при сопоставлении с образцом REPEATED_DECONSTRUCTION_TYPE=Повторение типов при сопоставлении с образцом
REPEATED_DOTDOT_COLLECTION_PATTERN_EXPR=Конструкция '..' встречена более одного раза в выражении для сопоставления
Var_{0}_is_already_defined=Переменная {0} уже определена Var_{0}_is_already_defined=Переменная {0} уже определена