Skip to content

Commit 28be6d2

Browse files
committed
MatchSingleton
1 parent 646e07f commit 28be6d2

10 files changed

Lines changed: 462 additions & 283 deletions

File tree

‎graalpython/com.oracle.graal.python.pegparser.generator/pegjava/java_generator.py‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ def __str__(self) -> str:
127127
"asdl_stmt_seq*": "StmtTy[]",
128128
"asdl_stmt_seq**": "StmtTy[]",
129129
"asdl_withitem_seq*": "WithItemTy[]",
130+
"asdl_pattern_seq*": "PatternTy[]",
130131
"comprehension_ty": "ComprehensionTy",
131132
"comprehension_ty*": "ComprehensionTy[]",
132133
"excepthandler_ty": "ExceptHandlerTy",
@@ -140,8 +141,8 @@ def __str__(self) -> str:
140141
"match_case_ty": "MatchCaseTy",
141142
"match_case_ty*": "MatchCaseTy[]",
142143
"mod_ty": "ModTy",
143-
"pattern_ty": "Object",
144-
"pattern_ty*": "Object[]",
144+
"pattern_ty": "PatternTy",
145+
"pattern_ty*": "PatternTy[]",
145146
"stmt_ty": "StmtTy",
146147
"stmt_ty*": "StmtTy[]",
147148
"stmt_ty**": "StmtTy[]",
@@ -308,25 +309,26 @@ def __str__(self) -> str:
308309
't': (1, 't'),
309310
'z': (11, 'z'),
310311

312+
# Pattern matching:
313+
'CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) )': (1, 'checkVersion(10, "Pattern matching is", factory.createMatch(subject, cases, $RANGE))'),
314+
'CHECK_VERSION ( void * , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected \':\'" ) )': (1, 'checkVersion(10, "Pattern matching is", () -> this.raiseSyntaxError("expected \':\'"))'),
315+
'_PyAST_match_case ( pattern , guard , body , p -> arena )': (1, 'factory.createMatchCase(pattern, guard, body, $RANGE)'),
316+
'asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA )': (1, 'patterns.length == 1 ? patterns[0] : factory.createMatchOr(patterns, $RANGE)'),
317+
'_PyAST_MatchSingleton ( Py_None , EXTRA )': (1, 'factory.createMatchSingleton(ConstantValue.NONE, $RANGE)'),
318+
'_PyAST_MatchSingleton ( Py_True , EXTRA )': (1, 'factory.createMatchSingleton(ConstantValue.TRUE, $RANGE)'),
319+
'_PyAST_MatchSingleton ( Py_False , EXTRA )': (1, 'factory.createMatchSingleton(ConstantValue.FALSE, $RANGE)'),
320+
311321
# TODO
312322
# Interactive mode:
313323
# '_PyPegen_interactive_exit ( p )' in rule "statement_newline: with rhs $"
314324
#
315325
# compile(..., mode='func_type') - used by ast module only
316326
# '_PyAST_FunctionType ( a , b , p -> arena )' in rule "func_type: with rhs '(' type_expressions? ')' '->' expression NEWLINE* $"
317-
#
318-
# Pattern matching:
319-
# 'CHECK_VERSION ( stmt_ty , 10 , "Pattern matching is" , _PyAST_Match ( subject , cases , EXTRA ) )' in rule "match_stmt: with rhs "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT"
320-
# '_PyAST_match_case ( pattern , guard , body , p -> arena )' in rule "case_block: with rhs "case" patterns guard? ':' block"
321327
# '_PyAST_MatchSequence ( patterns , EXTRA )' in rule "patterns: with rhs open_sequence_pattern"
322328
# '_PyAST_MatchAs ( pattern , target -> v . Name . id , EXTRA )' in rule "as_pattern: with rhs or_pattern 'as' pattern_capture_target"
323-
# 'asdl_seq_LEN ( patterns ) == 1 ? asdl_seq_GET ( patterns , 0 ) : _PyAST_MatchOr ( patterns , EXTRA )' in rule "or_pattern: with rhs '|'.closed_pattern+"
324329
# '_PyAST_MatchValue ( value , EXTRA )' in rule "literal_pattern: with rhs signed_number !('+' | '-')"
325330
# '_PyAST_MatchValue ( value , EXTRA )' in rule "literal_pattern: with rhs complex_number"
326331
# '_PyAST_MatchValue ( value , EXTRA )' in rule "literal_pattern: with rhs strings"
327-
# '_PyAST_MatchSingleton ( Py_None , EXTRA )' in rule "literal_pattern: with rhs 'None'"
328-
# '_PyAST_MatchSingleton ( Py_True , EXTRA )' in rule "literal_pattern: with rhs 'True'"
329-
# '_PyAST_MatchSingleton ( Py_False , EXTRA )' in rule "literal_pattern: with rhs 'False'"
330332
# '_PyAST_MatchAs ( NULL , target -> v . Name . id , EXTRA )' in rule "capture_pattern: with rhs pattern_capture_target"
331333
# '_PyPegen_set_expr_context ( p , name , Store )' in rule "pattern_capture_target: with rhs !"_" NAME !('.' | '(' | '=')"
332334
# '_PyAST_MatchAs ( NULL , NULL , EXTRA )' in rule "wildcard_pattern: with rhs "_""
@@ -348,7 +350,6 @@ def __str__(self) -> str:
348350
# '_PyAST_MatchClass ( cls , NULL , CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA )' in rule "class_pattern: with rhs name_or_attr '(' keyword_patterns ','? ')'"
349351
# '_PyAST_MatchClass ( cls , patterns , CHECK ( asdl_identifier_seq * , _PyPegen_map_names_to_ids ( p , CHECK ( asdl_expr_seq * , _PyPegen_get_pattern_keys ( p , keywords ) ) ) ) , CHECK ( asdl_pattern_seq * , _PyPegen_get_patterns ( p , keywords ) ) , EXTRA )' in rule "class_pattern: with rhs name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'"
350352
# '_PyPegen_key_pattern_pair ( p , arg , value )' in rule "keyword_pattern: with rhs NAME '=' pattern"
351-
# 'CHECK_VERSION ( void * , 10 , "Pattern matching is" , RAISE_SYNTAX_ERROR ( "expected ':'" ) )' in rule "invalid_match_stmt: with rhs "match" subject_expr !':'"
352353
# 'RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , pattern_ty ) , PyPegen_last_item ( a , pattern_ty ) , "positional patterns follow keyword patterns" )' in rule "invalid_class_pattern: with rhs name_or_attr '(' invalid_class_argument_pattern"
353354
# '_PyPegen_ensure_real ( p , real )' in rule "real_number: with rhs NUMBER"
354355
# '_PyPegen_ensure_imaginary ( p , imag )' in rule "imaginary_number: with rhs NUMBER"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.oracle.graal.python.pegparser;
2+
3+
import java.io.File;
4+
5+
import org.junit.Test;
6+
7+
public class PatternMatchingTests extends ParserTestBase {
8+
9+
@Test
10+
public void singletons() throws Exception {
11+
checkScopeAndTree();
12+
}
13+
14+
@Test
15+
public void missingColon() {
16+
checkSyntaxErrorMessage("match a\n case None: pass", "expected ':'");
17+
}
18+
19+
@Test
20+
public void missingIndent() {
21+
checkIndentationError("match a:\ncase None: pass");
22+
}
23+
24+
private void checkScopeAndTree() throws Exception {
25+
File testFile = getTestFileFromTestAndTestMethod();
26+
checkScopeFromFile(testFile, false);
27+
checkTreeFromFile(testFile, false);
28+
}
29+
}

‎graalpython/com.oracle.graal.python.pegparser.test/src/com/oracle/graal/python/pegparser/sst/SSTTreePrinterVisitor.java‎

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -880,54 +880,86 @@ public String visit(StmtTy.ImportFrom node) {
880880
public String visit(StmtTy.Match node) {
881881
StringBuilder sb = new StringBuilder();
882882
sb.append(addHeader(node));
883+
level++;
884+
appendNode(sb, "Subject", node.subject);
885+
appendNodes(sb, "Cases", node.cases);
886+
level--;
883887
return sb.toString();
884-
885888
}
886889

887890
@Override
888891
public String visit(MatchCaseTy node) {
889892
StringBuilder sb = new StringBuilder();
890893
sb.append(addHeader(node));
894+
level++;
895+
appendNode(sb, "Pattern", node.pattern);
896+
appendNode(sb, "Guard", node.guard);
897+
appendNodes(sb, "Body", node.body);
898+
level--;
891899
return sb.toString();
892-
893900
}
894901

895902
@Override
896903
public String visit(PatternTy.MatchAs node) {
897904
StringBuilder sb = new StringBuilder();
898905
sb.append(addHeader(node));
906+
level++;
907+
appendNode(sb, "Pattern", node.pattern);
908+
if (node.name != null) {
909+
appendNewLineIndented(sb, "Name: ").append(node.name);
910+
}
899911
return sb.toString();
900-
901912
}
902913

903914
@Override
904915
public String visit(PatternTy.MatchClass node) {
905916
StringBuilder sb = new StringBuilder();
906917
sb.append(addHeader(node));
918+
level++;
919+
appendNode(sb, "Cls", node.cls);
920+
appendNodes(sb, "Patterns", node.patterns);
921+
if (node.kwdAttrs != null) {
922+
appendNewLineIndented(sb, "KwdAttrs:");
923+
for (String s : node.kwdAttrs) {
924+
sb.append(' ').append(s);
925+
}
926+
}
927+
appendNodes(sb, "KwdPatterns", node.kwdPatterns);
928+
level--;
907929
return sb.toString();
908-
909930
}
910931

911932
@Override
912933
public String visit(PatternTy.MatchMapping node) {
913934
StringBuilder sb = new StringBuilder();
914935
sb.append(addHeader(node));
936+
level++;
937+
appendNodes(sb, "Keys", node.keys);
938+
appendNodes(sb, "Patterns", node.patterns);
939+
if (node.rest != null) {
940+
appendNewLineIndented(sb, "Rest: ").append(node.rest);
941+
}
942+
level--;
915943
return sb.toString();
916-
917944
}
918945

919946
@Override
920947
public String visit(PatternTy.MatchOr node) {
921948
StringBuilder sb = new StringBuilder();
922949
sb.append(addHeader(node));
950+
level++;
951+
appendNodes(sb, "Patterns", node.patterns);
952+
level--;
923953
return sb.toString();
924-
925954
}
926955

927956
@Override
928957
public String visit(PatternTy.MatchSequence node) {
929958
StringBuilder sb = new StringBuilder();
930959
sb.append(addHeader(node));
960+
level++;
961+
appendNodes(sb, "Patterns", node.patterns);
962+
level--;
931963
return sb.toString();
932964

933965
}
@@ -936,14 +968,18 @@ public String visit(PatternTy.MatchSequence node) {
936968
public String visit(PatternTy.MatchSingleton node) {
937969
StringBuilder sb = new StringBuilder();
938970
sb.append(addHeader(node));
971+
sb.append(", value: ");
972+
appendConstantValue(sb, node.value);
939973
return sb.toString();
940-
941974
}
942975

943976
@Override
944977
public String visit(PatternTy.MatchStar node) {
945978
StringBuilder sb = new StringBuilder();
946979
sb.append(addHeader(node));
980+
if (node.name != null) {
981+
sb.append(": ").append(node.name);
982+
}
947983
return sb.toString();
948984

949985
}
@@ -952,8 +988,10 @@ public String visit(PatternTy.MatchStar node) {
952988
public String visit(PatternTy.MatchValue node) {
953989
StringBuilder sb = new StringBuilder();
954990
sb.append(addHeader(node));
991+
level++;
992+
appendNode(sb, "Value", node.value);
993+
level--;
955994
return sb.toString();
956-
957995
}
958996

959997
@Override
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ScopeEnvironment
2+
Scope null Module
3+
Symbols:
4+
a: [Use, GlobalImplicit]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Module[0, 72]
2+
Match[0, 72]
3+
Subject: Name[6, 7] Value: "a"
4+
Cases:
5+
MatchCaseTy[13, 36]
6+
Pattern: MatchSingleton[18, 22], value: null
7+
Body:
8+
Pass[32, 36]
9+
MatchCaseTy[41, 72]
10+
Pattern:
11+
MatchOr[46, 58]
12+
Patterns:
13+
MatchSingleton[46, 50], value: true
14+
MatchSingleton[53, 58], value: false
15+
Body:
16+
Pass[68, 72]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
match a:
2+
case None:
3+
pass
4+
case True | False:
5+
pass

‎graalpython/com.oracle.graal.python.pegparser/src/com/oracle/graal/python/pegparser/AbstractParser.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import java.util.LinkedHashMap;
5151
import java.util.List;
5252
import java.util.Map;
53+
import java.util.function.Supplier;
5354

5455
import com.oracle.graal.python.pegparser.sst.ArgTy;
5556
import com.oracle.graal.python.pegparser.sst.ComprehensionTy;
@@ -1095,4 +1096,10 @@ <T> T check(T node) {
10951096
static <T> T checkVersion(int version, String msg, T node) {
10961097
return node;
10971098
}
1099+
1100+
@SuppressWarnings("unused")
1101+
// TODO implement the check
1102+
static <T> T checkVersion(int version, String msg, Supplier<T> node) {
1103+
return node.get();
1104+
}
10981105
}

‎graalpython/com.oracle.graal.python.pegparser/src/com/oracle/graal/python/pegparser/NodeFactory.java‎

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242

4343
// TODO this class has to be moved to impl package and from this package we need to do api.
4444

45+
import static com.oracle.graal.python.pegparser.AbstractParser.EMPTY_ARG_ARRAY;
46+
import static com.oracle.graal.python.pegparser.AbstractParser.EMPTY_EXPR_ARRAY;
47+
4548
import java.math.BigInteger;
4649
import java.util.Arrays;
4750

@@ -51,27 +54,24 @@
5154
import com.oracle.graal.python.pegparser.sst.AliasTy;
5255
import com.oracle.graal.python.pegparser.sst.ArgTy;
5356
import com.oracle.graal.python.pegparser.sst.ArgumentsTy;
57+
import com.oracle.graal.python.pegparser.sst.BoolOpTy;
58+
import com.oracle.graal.python.pegparser.sst.CmpOpTy;
5459
import com.oracle.graal.python.pegparser.sst.ComprehensionTy;
5560
import com.oracle.graal.python.pegparser.sst.ConstantValue;
5661
import com.oracle.graal.python.pegparser.sst.ExceptHandlerTy;
5762
import com.oracle.graal.python.pegparser.sst.ExprContextTy;
5863
import com.oracle.graal.python.pegparser.sst.ExprTy;
59-
import com.oracle.graal.python.pegparser.sst.BoolOpTy;
60-
import com.oracle.graal.python.pegparser.sst.CmpOpTy;
61-
import com.oracle.graal.python.pegparser.sst.StmtTy.AsyncFunctionDef;
62-
import com.oracle.graal.python.pegparser.sst.StmtTy.FunctionDef;
63-
import com.oracle.graal.python.pegparser.sst.WithItemTy;
64-
import com.oracle.graal.python.pegparser.sst.UnaryOpTy;
65-
import com.oracle.graal.python.pegparser.sst.OperatorTy;
6664
import com.oracle.graal.python.pegparser.sst.KeywordTy;
65+
import com.oracle.graal.python.pegparser.sst.MatchCaseTy;
6766
import com.oracle.graal.python.pegparser.sst.ModTy;
67+
import com.oracle.graal.python.pegparser.sst.OperatorTy;
68+
import com.oracle.graal.python.pegparser.sst.PatternTy;
6869
import com.oracle.graal.python.pegparser.sst.StmtTy;
6970
import com.oracle.graal.python.pegparser.sst.StringLiteralUtils;
71+
import com.oracle.graal.python.pegparser.sst.UnaryOpTy;
72+
import com.oracle.graal.python.pegparser.sst.WithItemTy;
7073
import com.oracle.graal.python.pegparser.tokenizer.SourceRange;
7174

72-
import static com.oracle.graal.python.pegparser.AbstractParser.EMPTY_ARG_ARRAY;
73-
import static com.oracle.graal.python.pegparser.AbstractParser.EMPTY_EXPR_ARRAY;
74-
7575
public class NodeFactory {
7676
public StmtTy createAnnAssignment(ExprTy target, ExprTy annotation, ExprTy rhs, boolean isSimple, SourceRange sourceRange) {
7777
return new StmtTy.AnnAssign(target, annotation, rhs, isSimple, sourceRange);
@@ -399,12 +399,12 @@ public StmtTy createFunctionDef(String name, ArgumentsTy args, StmtTy[] body, Ex
399399
}
400400

401401
public StmtTy createFunctionDefWithDecorators(StmtTy funcDef, ExprTy[] decorators) {
402-
if (funcDef instanceof AsyncFunctionDef) {
402+
if (funcDef instanceof StmtTy.AsyncFunctionDef) {
403403
StmtTy.AsyncFunctionDef f = (StmtTy.AsyncFunctionDef) funcDef;
404-
return new AsyncFunctionDef(f.name, f.args, f.body, decorators, f.returns, f.typeComment, f.getSourceRange());
404+
return new StmtTy.AsyncFunctionDef(f.name, f.args, f.body, decorators, f.returns, f.typeComment, f.getSourceRange());
405405
}
406406
StmtTy.FunctionDef f = (StmtTy.FunctionDef) funcDef;
407-
return new FunctionDef(f.name, f.args, f.body, decorators, f.returns, f.typeComment, f.getSourceRange());
407+
return new StmtTy.FunctionDef(f.name, f.args, f.body, decorators, f.returns, f.typeComment, f.getSourceRange());
408408
}
409409

410410
public StmtTy createAsyncFunctionDef(String name, ArgumentsTy args, StmtTy[] body, ExprTy returns, String typeComment, SourceRange sourceRange) {
@@ -523,4 +523,44 @@ public ExprTy createGetAttribute(ExprTy receiver, String name, SourceRange sourc
523523
public ExprTy.Name createVariable(String name, SourceRange sourceRange) {
524524
return createVariable(name, sourceRange, ExprContextTy.Load);
525525
}
526+
527+
public StmtTy createMatch(ExprTy subject, MatchCaseTy[] cases, SourceRange sourceRange) {
528+
return new StmtTy.Match(subject, cases, sourceRange);
529+
}
530+
531+
public MatchCaseTy createMatchCase(PatternTy pattern, ExprTy guard, StmtTy[] body, SourceRange sourceRange) {
532+
return new MatchCaseTy(pattern, guard, body, sourceRange);
533+
}
534+
535+
public PatternTy createMatchValue(ExprTy value, SourceRange sourceRange) {
536+
return new PatternTy.MatchValue(value, sourceRange);
537+
}
538+
539+
public PatternTy createMatchSingleton(ConstantValue value, SourceRange sourceRange) {
540+
return new PatternTy.MatchSingleton(value, sourceRange);
541+
}
542+
543+
public PatternTy createMatchSequence(PatternTy[] patterns, SourceRange sourceRange) {
544+
return new PatternTy.MatchSequence(patterns, sourceRange);
545+
}
546+
547+
public PatternTy createMatchMapping(ExprTy[] keys, PatternTy[] patterns, String rest, SourceRange sourceRange) {
548+
return new PatternTy.MatchMapping(keys, patterns, rest, sourceRange);
549+
}
550+
551+
public PatternTy createMatchClass(ExprTy cls, PatternTy[] patterns, String[] kwdAttrs, PatternTy[] kwdPatterns, SourceRange sourceRange) {
552+
return new PatternTy.MatchClass(cls, patterns, kwdAttrs, kwdPatterns, sourceRange);
553+
}
554+
555+
public PatternTy createMatchStar(String name, SourceRange sourceRange) {
556+
return new PatternTy.MatchStar(name, sourceRange);
557+
}
558+
559+
public PatternTy createMatchAs(PatternTy pattern, String name, SourceRange sourceRange) {
560+
return new PatternTy.MatchAs(pattern, name, sourceRange);
561+
}
562+
563+
public PatternTy createMatchOr(PatternTy[] patterns, SourceRange sourceRange) {
564+
return new PatternTy.MatchOr(patterns, sourceRange);
565+
}
526566
}

0 commit comments

Comments
 (0)