@@ -15,7 +15,8 @@ struct validator {
15
15
};
16
16
17
17
static int validate_stmts (struct validator * , asdl_stmt_seq * );
18
- static int validate_exprs (struct validator * , asdl_expr_seq * , expr_context_ty , int );
18
+ static int validate_exprs (struct validator * , asdl_expr_seq * , expr_context_ty , int );
19
+ static int validate_patterns (struct validator * , asdl_pattern_seq * , int );
19
20
static int _validate_nonempty_seq (asdl_seq * , const char * , const char * );
20
21
static int validate_stmt (struct validator * , stmt_ty );
21
22
static int validate_expr (struct validator * , expr_ty , expr_context_ty );
@@ -33,7 +34,7 @@ validate_name(PyObject *name)
33
34
};
34
35
for (int i = 0 ; forbidden [i ] != NULL ; i ++ ) {
35
36
if (_PyUnicode_EqualToASCIIString (name , forbidden [i ])) {
36
- PyErr_Format (PyExc_ValueError , "Name node can't be used with '%s' constant" , forbidden [i ]);
37
+ PyErr_Format (PyExc_ValueError , "identifier field can't represent '%s' constant" , forbidden [i ]);
37
38
return 0 ;
38
39
}
39
40
}
@@ -448,6 +449,21 @@ validate_pattern_match_value(struct validator *state, expr_ty exp)
448
449
switch (exp -> kind )
449
450
{
450
451
case Constant_kind :
452
+ /* Ellipsis and immutable sequences are not allowed.
453
+ For True, False and None, MatchSingleton() should
454
+ be used */
455
+ if (!validate_expr (state , exp , Load )) {
456
+ return 0 ;
457
+ }
458
+ PyObject * literal = exp -> v .Constant .value ;
459
+ if (PyLong_CheckExact (literal ) || PyFloat_CheckExact (literal ) ||
460
+ PyBytes_CheckExact (literal ) || PyComplex_CheckExact (literal ) ||
461
+ PyUnicode_CheckExact (literal )) {
462
+ return 1 ;
463
+ }
464
+ PyErr_SetString (PyExc_ValueError ,
465
+ "unexpected constant inside of a literal pattern" );
466
+ return 0 ;
451
467
case Attribute_kind :
452
468
// Constants and attribute lookups are always permitted
453
469
return 1 ;
@@ -465,11 +481,14 @@ validate_pattern_match_value(struct validator *state, expr_ty exp)
465
481
return 1 ;
466
482
}
467
483
break ;
484
+ case JoinedStr_kind :
485
+ // Handled in the later stages
486
+ return 1 ;
468
487
default :
469
488
break ;
470
489
}
471
- PyErr_SetString (PyExc_SyntaxError ,
472
- "patterns may only match literals and attribute lookups" );
490
+ PyErr_SetString (PyExc_ValueError ,
491
+ "patterns may only match literals and attribute lookups" );
473
492
return 0 ;
474
493
}
475
494
@@ -489,51 +508,101 @@ validate_pattern(struct validator *state, pattern_ty p)
489
508
ret = validate_pattern_match_value (state , p -> v .MatchValue .value );
490
509
break ;
491
510
case MatchSingleton_kind :
492
- // TODO: Check constant is specifically None, True, or False
493
- ret = validate_constant (state , p -> v .MatchSingleton .value );
511
+ ret = p -> v .MatchSingleton .value == Py_None || PyBool_Check (p -> v .MatchSingleton .value );
512
+ if (!ret ) {
513
+ PyErr_SetString (PyExc_ValueError ,
514
+ "MatchSingleton can only contain True, False and None" );
515
+ }
494
516
break ;
495
517
case MatchSequence_kind :
496
- // TODO: Validate all subpatterns
497
- // return validate_patterns(state, p->v.MatchSequence.patterns);
498
- ret = 1 ;
518
+ ret = validate_patterns (state , p -> v .MatchSequence .patterns , /*star_ok=*/ 1 );
499
519
break ;
500
520
case MatchMapping_kind :
501
- // TODO: check "rest" target name is valid
502
521
if (asdl_seq_LEN (p -> v .MatchMapping .keys ) != asdl_seq_LEN (p -> v .MatchMapping .patterns )) {
503
522
PyErr_SetString (PyExc_ValueError ,
504
523
"MatchMapping doesn't have the same number of keys as patterns" );
505
- return 0 ;
524
+ ret = 0 ;
525
+ break ;
506
526
}
507
- // null_ok=0 for key expressions, as rest-of-mapping is captured in "rest"
508
- // TODO: replace with more restrictive expression validator, as per MatchValue above
509
- if (! validate_exprs ( state , p -> v . MatchMapping . keys , Load , /*null_ok=*/ 0 )) {
510
- return 0 ;
527
+
528
+ if ( p -> v . MatchMapping . rest && ! validate_name ( p -> v . MatchMapping . rest )) {
529
+ ret = 0 ;
530
+ break ;
511
531
}
512
- // TODO: Validate all subpatterns
513
- // ret = validate_patterns(state, p->v.MatchMapping.patterns);
514
- ret = 1 ;
532
+
533
+ asdl_expr_seq * keys = p -> v .MatchMapping .keys ;
534
+ for (Py_ssize_t i = 0 ; i < asdl_seq_LEN (keys ); i ++ ) {
535
+ expr_ty key = asdl_seq_GET (keys , i );
536
+ if (key -> kind == Constant_kind ) {
537
+ PyObject * literal = key -> v .Constant .value ;
538
+ if (literal == Py_None || PyBool_Check (literal )) {
539
+ /* validate_pattern_match_value will ensure the key
540
+ doesn't contain True, False and None but it is
541
+ syntactically valid, so we will pass those on in
542
+ a special case. */
543
+ continue ;
544
+ }
545
+ }
546
+ if (!validate_pattern_match_value (state , key )) {
547
+ ret = 0 ;
548
+ break ;
549
+ }
550
+ }
551
+
552
+ ret = validate_patterns (state , p -> v .MatchMapping .patterns , /*star_ok=*/ 0 );
515
553
break ;
516
554
case MatchClass_kind :
517
555
if (asdl_seq_LEN (p -> v .MatchClass .kwd_attrs ) != asdl_seq_LEN (p -> v .MatchClass .kwd_patterns )) {
518
556
PyErr_SetString (PyExc_ValueError ,
519
557
"MatchClass doesn't have the same number of keyword attributes as patterns" );
520
- return 0 ;
558
+ ret = 0 ;
559
+ break ;
521
560
}
522
- // TODO: Restrict cls lookup to being a name or attribute
523
561
if (!validate_expr (state , p -> v .MatchClass .cls , Load )) {
524
- return 0 ;
562
+ ret = 0 ;
563
+ break ;
525
564
}
526
- // TODO: Validate all subpatterns
527
- // return validate_patterns(state, p->v.MatchClass.patterns) &&
528
- // validate_patterns(state, p->v.MatchClass.kwd_patterns);
529
- ret = 1 ;
565
+
566
+ expr_ty cls = p -> v .MatchClass .cls ;
567
+ while (1 ) {
568
+ if (cls -> kind == Name_kind ) {
569
+ break ;
570
+ }
571
+ else if (cls -> kind == Attribute_kind ) {
572
+ cls = cls -> v .Attribute .value ;
573
+ continue ;
574
+ }
575
+ else {
576
+ PyErr_SetString (PyExc_ValueError ,
577
+ "MatchClass cls field can only contain Name or Attribute nodes." );
578
+ state -> recursion_depth -- ;
579
+ return 0 ;
580
+ }
581
+ }
582
+
583
+ for (Py_ssize_t i = 0 ; i < asdl_seq_LEN (p -> v .MatchClass .kwd_attrs ); i ++ ) {
584
+ PyObject * identifier = asdl_seq_GET (p -> v .MatchClass .kwd_attrs , i );
585
+ if (!validate_name (identifier )) {
586
+ state -> recursion_depth -- ;
587
+ return 0 ;
588
+ }
589
+ }
590
+
591
+ if (!validate_patterns (state , p -> v .MatchClass .patterns , /*star_ok=*/ 0 )) {
592
+ ret = 0 ;
593
+ break ;
594
+ }
595
+
596
+ ret = validate_patterns (state , p -> v .MatchClass .kwd_patterns , /*star_ok=*/ 0 );
530
597
break ;
531
598
case MatchStar_kind :
532
- // TODO: check target name is valid
533
- ret = 1 ;
599
+ ret = p -> v .MatchStar .name == NULL || validate_name (p -> v .MatchStar .name );
534
600
break ;
535
601
case MatchAs_kind :
536
- // TODO: check target name is valid
602
+ if (p -> v .MatchAs .name && !validate_name (p -> v .MatchAs .name )) {
603
+ ret = 0 ;
604
+ break ;
605
+ }
537
606
if (p -> v .MatchAs .pattern == NULL ) {
538
607
ret = 1 ;
539
608
}
@@ -547,9 +616,13 @@ validate_pattern(struct validator *state, pattern_ty p)
547
616
}
548
617
break ;
549
618
case MatchOr_kind :
550
- // TODO: Validate all subpatterns
551
- // return validate_patterns(state, p->v.MatchOr.patterns);
552
- ret = 1 ;
619
+ if (asdl_seq_LEN (p -> v .MatchOr .patterns ) < 2 ) {
620
+ PyErr_SetString (PyExc_ValueError ,
621
+ "MatchOr requires at least 2 patterns" );
622
+ ret = 0 ;
623
+ break ;
624
+ }
625
+ ret = validate_patterns (state , p -> v .MatchOr .patterns , /*star_ok=*/ 0 );
553
626
break ;
554
627
// No default case, so the compiler will emit a warning if new pattern
555
628
// kinds are added without being handled here
@@ -815,6 +888,25 @@ validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ct
815
888
return 1 ;
816
889
}
817
890
891
+ static int
892
+ validate_patterns (struct validator * state , asdl_pattern_seq * patterns , int star_ok )
893
+ {
894
+ Py_ssize_t i ;
895
+ for (i = 0 ; i < asdl_seq_LEN (patterns ); i ++ ) {
896
+ pattern_ty pattern = asdl_seq_GET (patterns , i );
897
+ if (pattern -> kind == MatchStar_kind && !star_ok ) {
898
+ PyErr_SetString (PyExc_ValueError ,
899
+ "Can't use MatchStar within this sequence of patterns" );
900
+ return 0 ;
901
+ }
902
+ if (!validate_pattern (state , pattern )) {
903
+ return 0 ;
904
+ }
905
+ }
906
+ return 1 ;
907
+ }
908
+
909
+
818
910
/* See comments in symtable.c. */
819
911
#define COMPILER_STACK_FRAME_SCALE 3
820
912
0 commit comments