diff --git a/CodeCompletion/CodeFormatter.cs b/CodeCompletion/CodeFormatter.cs index a793e9368..819ab4680 100644 --- a/CodeCompletion/CodeFormatter.cs +++ b/CodeCompletion/CodeFormatter.cs @@ -466,7 +466,7 @@ namespace CodeFormatters prev_pos = GetPosition(prev_sn.source_context.begin_position.line_num, prev_sn.source_context.begin_position.column_num) + keyword_offset; } else - prev_pos = GetPosition(prev_sn.source_context.end_position.line_num, prev_sn.source_context.end_position.column_num)+1; + prev_pos = GetPosition(prev_sn.source_context.end_position.line_num, prev_sn.source_context.end_position.column_num) + 1; if (prev_pos < pos) { string comm = Text.Substring(prev_pos, pos - prev_pos); @@ -499,7 +499,7 @@ namespace CodeFormatters sb.AppendLine(); insert_newline_after_prev = false; } - if (force_tab && sb[sb.Length-1] == '\n') + if (force_tab && sb[sb.Length - 1] == '\n') sb.Append(new string(' ', off)); force_tab = false; } @@ -2984,7 +2984,7 @@ namespace CodeFormatters public override void visit(match_with _match_with) { - sb.Append("match "); + sb.Append("match"); visit_node(_match_with.expr); IncOffset(); add_space_before = true; @@ -3018,11 +3018,18 @@ namespace CodeFormatters { visit_node(_deconstructor_pattern.type); foreach (var parameter in _deconstructor_pattern.parameters) + { visit_node(parameter); + add_space_after = true; + } + add_space_after = false; } public override void visit(var_deconstructor_parameter _var_deconstructor_parameter) { + sb.Append("var"); + SetKeywordOffset("var"); + read_from_beg_pos = true; visit_node(_var_deconstructor_parameter.identifier); if (_var_deconstructor_parameter.type != null) visit_node(_var_deconstructor_parameter.type); diff --git a/CodeCompletion/DomSyntaxTreeVisitor.cs b/CodeCompletion/DomSyntaxTreeVisitor.cs index 0cfc060f9..47f2fa749 100644 --- a/CodeCompletion/DomSyntaxTreeVisitor.cs +++ b/CodeCompletion/DomSyntaxTreeVisitor.cs @@ -744,14 +744,33 @@ namespace CodeCompletion public override void visit(deconstructor_pattern _deconstructor_pattern) { _deconstructor_pattern.type.visit(this); - foreach (pattern_deconstructor_parameter pdp in _deconstructor_pattern.parameters) + if (_deconstructor_pattern.parameters.Count == 1) { + var pdp = _deconstructor_pattern.parameters[0]; if (pdp is var_deconstructor_parameter) { var_deconstructor_parameter vdp = pdp as var_deconstructor_parameter; pending_is_pattern_vars.Add(new var_def_statement(vdp.identifier, _deconstructor_pattern.type, _deconstructor_pattern.source_context)); } } + else + { + foreach (pattern_deconstructor_parameter pdp in _deconstructor_pattern.parameters) + { + if (pdp is var_deconstructor_parameter) + { + var_deconstructor_parameter vdp = pdp as var_deconstructor_parameter; + SymScope ss = returned_scope.FindName(vdp.identifier.name); + if (ss is ElementScope) + { + TypeScope ts = (ss as ElementScope).sc as TypeScope; + pending_is_pattern_vars.Add(new var_def_statement(vdp.identifier, new named_type_reference(new ident(ts.si.name)), _deconstructor_pattern.source_context)); + } + + } + } + } + } public override void visit(match_with _match_with) diff --git a/ParserTools/SyntaxTreeVisitors/SyntaxTreeComparer.cs b/ParserTools/SyntaxTreeVisitors/SyntaxTreeComparer.cs index 5732c4c5d..e5f1f21e1 100644 --- a/ParserTools/SyntaxTreeVisitors/SyntaxTreeComparer.cs +++ b/ParserTools/SyntaxTreeVisitors/SyntaxTreeComparer.cs @@ -697,6 +697,8 @@ namespace PascalABCCompiler.SyntaxTree CompareInternal(left as tuple_node, right as tuple_node); else if (left is slice_expr) CompareInternal(left as slice_expr, right as slice_expr); + else if (left is is_pattern_expr) + CompareInternal(left as is_pattern_expr, right as is_pattern_expr); else throw new NotImplementedException(left.GetType().ToString()); @@ -2257,5 +2259,81 @@ namespace PascalABCCompiler.SyntaxTree CompareInternal(left.el, right.el); } } + + public void CompareInternal(is_pattern_expr left, is_pattern_expr right) + { + if (left == null && right != null || left != null && right == null) + throw_not_equal(left, right); + if (left != null && right != null) + { + CompareInternal(left.left, right.left); + CompareInternal(left.right, right.right); + } + } + + public void CompareInternal(pattern_node left, pattern_node right) + { + if (left == null && right != null || left != null && right == null) + throw_not_equal(left, right); + if (left != null && right != null) + { + if (left.GetType() != right.GetType()) + throw_not_equal(left, right); + if (left is deconstructor_pattern) + CompareInternal(left as deconstructor_pattern, right as deconstructor_pattern); + } + } + + public void CompareInternal(deconstructor_pattern left, deconstructor_pattern right) + { + if (left == null && right != null || left != null && right == null) + throw_not_equal(left, right); + if (left != null && right != null) + { + CompareInternal(left.type, right.type); + if (left.parameters.Count != right.parameters.Count) + throw_not_equal(left, right); + for (int i = 0; i < left.Count; i++) + { + CompareInternal(left.parameters[i], right.parameters[i]); + } + } + } + + public void CompareInternal(pattern_deconstructor_parameter left, pattern_deconstructor_parameter right) + { + if (left == null && right != null || left != null && right == null) + throw_not_equal(left, right); + if (left != null && right != null) + { + if (left.GetType() != right.GetType()) + throw_not_equal(left, right); + if (left is var_deconstructor_parameter) + CompareInternal(left as var_deconstructor_parameter, right as var_deconstructor_parameter); + if (left is recursive_deconstructor_parameter) + CompareInternal(left as recursive_deconstructor_parameter, right as recursive_deconstructor_parameter); + } + } + + public void CompareInternal(var_deconstructor_parameter left, var_deconstructor_parameter right) + { + if (left == null && right != null || left != null && right == null) + throw_not_equal(left, right); + if (left != null && right != null) + { + CompareInternal(left.identifier, right.identifier); + CompareInternal(left.type, right.type); + } + } + + public void CompareInternal(recursive_deconstructor_parameter left, recursive_deconstructor_parameter right) + { + if (left == null && right != null || left != null && right == null) + throw_not_equal(left, right); + if (left != null && right != null) + { + CompareInternal(left.pattern, right.pattern); + } + } } } \ No newline at end of file diff --git a/TestSuite/formatter_tests/input/pattern1.pas b/TestSuite/formatter_tests/input/pattern1.pas new file mode 100644 index 000000000..b834383fe --- /dev/null +++ b/TestSuite/formatter_tests/input/pattern1.pas @@ -0,0 +1,19 @@ +type + Person = class + name: string; + age: integer; + + class function Deconstruct(p: Person; name: string; age: integer): boolean; + begin + name := p.name; + age := p.age; + result := true; + end; + end; + + +begin + var p := new Person; + if p is Person(var name,var age) then + Print(name, ' ', age); +end. \ No newline at end of file diff --git a/TestSuite/formatter_tests/should/pattern1.pas b/TestSuite/formatter_tests/should/pattern1.pas new file mode 100644 index 000000000..b846a7aa4 --- /dev/null +++ b/TestSuite/formatter_tests/should/pattern1.pas @@ -0,0 +1,19 @@ +type + Person = class + name: string; + age: integer; + + class function Deconstruct(p: Person; name: string; age: integer): boolean; + begin + name := p.name; + age := p.age; + result := true; + end; + end; + + +begin + var p := new Person; + if p is Person(var name, var age) then + Print(name, ' ', age); +end. \ No newline at end of file diff --git a/TestSuite/intellisense_tests/match2.pas b/TestSuite/intellisense_tests/match2.pas new file mode 100644 index 000000000..e12fc9017 --- /dev/null +++ b/TestSuite/intellisense_tests/match2.pas @@ -0,0 +1,21 @@ +type + Person = class + name: string; + age: integer; + + class function Deconstruct(p: Person; name: string; age: integer): boolean; + begin + name := p.name; + age := p.age; + result := true; + end; + end; + + +begin + var p := new Person; + if p is Person(var name, var age) then + Print(name{@var name: string;@}, ' ', + age{@var age: integer;@}); + +end. \ No newline at end of file