@@ -85,6 +85,20 @@ def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
85
85
return tree
86
86
87
87
88
+ class Argument :
89
+ """Ideally this would be in nodes and be an actual node. However,
90
+ since its not yet used by FuncItem, etc, it makes sense to keep
91
+ it here so that it avoids confusion. It should be easily relocatable
92
+ in the future.
93
+ """
94
+ def __init__ (self , variable : Var , type : Optional [Type ],
95
+ initializer : Optional [Node ], kind : int ) -> None :
96
+ self .variable = variable
97
+ self .type = type
98
+ self .initializer = initializer
99
+ self .kind = kind
100
+
101
+
88
102
class Parser :
89
103
"""Mypy parser that parses a string into an AST.
90
104
@@ -385,8 +399,12 @@ def parse_function(self, no_type_checks: bool=False) -> FuncDef:
385
399
is_method = self .is_class_body
386
400
self .is_class_body = False
387
401
try :
388
- (name , args , init , kinds ,
389
- typ , is_error ) = self .parse_function_header (no_type_checks )
402
+ (name , args , typ , is_error ) = self .parse_function_header (no_type_checks )
403
+
404
+ init = [arg .initializer for arg in args ]
405
+ kinds = [arg .kind for arg in args ]
406
+ arg_names = [arg .variable .name () for arg in args ]
407
+ arg_vars = [arg .variable for arg in args ]
390
408
391
409
body , comment_type = self .parse_block (allow_type = True )
392
410
if comment_type :
@@ -404,7 +422,7 @@ def parse_function(self, no_type_checks: bool=False) -> FuncDef:
404
422
typ = CallableType (
405
423
first_arg + sig .arg_types ,
406
424
kinds ,
407
- [ arg . name () for arg in args ] ,
425
+ arg_names ,
408
426
sig .ret_type ,
409
427
None )
410
428
else :
@@ -413,7 +431,7 @@ def parse_function(self, no_type_checks: bool=False) -> FuncDef:
413
431
typ = CallableType (
414
432
sig .arg_types ,
415
433
kinds ,
416
- [ arg . name () for arg in args ] ,
434
+ arg_names ,
417
435
sig .ret_type ,
418
436
None )
419
437
@@ -422,7 +440,7 @@ def parse_function(self, no_type_checks: bool=False) -> FuncDef:
422
440
if is_error :
423
441
return None
424
442
425
- node = FuncDef (name , args , kinds , init , body , typ )
443
+ node = FuncDef (name , arg_vars , kinds , init , body , typ )
426
444
node .set_line (def_tok )
427
445
return node
428
446
finally :
@@ -445,19 +463,15 @@ def check_argument_kinds(self, funckinds: List[int], sigkinds: List[int],
445
463
"Inconsistent use of '{}' in function "
446
464
"signature" .format (token ), line )
447
465
448
- def parse_function_header (self , no_type_checks : bool = False ) -> Tuple [str , List [Var ],
449
- List [Node ], List [int ],
466
+ def parse_function_header (self , no_type_checks : bool = False ) -> Tuple [str , List [Argument ],
450
467
CallableType , bool ]:
451
468
"""Parse function header (a name followed by arguments)
452
469
453
- Returns a 7 -tuple with the following items:
470
+ Returns a 4 -tuple with the following items:
454
471
name
455
472
arguments
456
- initializers
457
- kinds
458
473
signature (annotation)
459
474
error flag (True if error)
460
- (name token, representation of arguments)
461
475
"""
462
476
name = ''
463
477
@@ -467,27 +481,24 @@ def parse_function_header(self, no_type_checks: bool=False) -> Tuple[str, List[V
467
481
468
482
self .errors .push_function (name )
469
483
470
- ( args , init , kinds , typ ) = self .parse_args (no_type_checks )
484
+ args , typ = self .parse_args (no_type_checks )
471
485
except ParseError :
472
486
if not isinstance (self .current (), Break ):
473
487
self .ind -= 1 # Kludge: go back to the Break token
474
488
# Resynchronise parsing by going back over :, if present.
475
489
if isinstance (self .tok [self .ind - 1 ], Colon ):
476
490
self .ind -= 1
477
- return (name , [], [], [], None , True )
491
+ return (name , [], None , True )
478
492
479
- return (name , args , init , kinds , typ , False )
493
+ return (name , args , typ , False )
480
494
481
- def parse_args (self , no_type_checks : bool = False ) -> Tuple [List [Var ], List [ Node ], List [ int ],
495
+ def parse_args (self , no_type_checks : bool = False ) -> Tuple [List [Argument ],
482
496
CallableType ]:
483
497
"""Parse a function signature (...) [-> t]."""
484
498
lparen = self .expect ('(' )
485
499
486
500
# Parse the argument list (everything within '(' and ')').
487
- (args , init , kinds ,
488
- has_inits , arg_names ,
489
- commas , asterisk ,
490
- assigns , arg_types ) = self .parse_arg_list (no_type_checks = no_type_checks )
501
+ args = self .parse_arg_list (no_type_checks = no_type_checks )
491
502
492
503
self .expect (')' )
493
504
@@ -501,53 +512,32 @@ def parse_args(self, no_type_checks: bool=False) -> Tuple[List[Var], List[Node],
501
512
else :
502
513
ret_type = None
503
514
504
- self .verify_argument_kinds (kinds , lparen .line )
505
-
506
- names = [arg .name () for arg in args ]
515
+ arg_kinds = [arg .kind for arg in args ]
516
+ self .verify_argument_kinds (arg_kinds , lparen .line )
507
517
508
518
annotation = self .build_func_annotation (
509
- ret_type , arg_types , kinds , names , lparen .line )
519
+ ret_type , args , lparen .line )
510
520
511
- return args , init , kinds , annotation
521
+ return args , annotation
512
522
513
- def build_func_annotation (self , ret_type : Type , arg_types : List [Type ],
514
- kinds : List [ int ], names : List [ str ],
515
- line : int , is_default_ret : bool = False ) -> CallableType :
523
+ def build_func_annotation (self , ret_type : Type , args : List [Argument ],
524
+ line : int , is_default_ret : bool = False ) -> CallableType :
525
+ arg_types = [ arg . type for arg in args ]
516
526
# Are there any type annotations?
517
527
if ((ret_type and not is_default_ret )
518
528
or arg_types != [None ] * len (arg_types )):
519
529
# Yes. Construct a type for the function signature.
520
- return self .construct_function_type (arg_types , kinds , names ,
521
- ret_type , line )
530
+ return self .construct_function_type (args , ret_type , line )
522
531
else :
523
532
return None
524
533
525
- def parse_arg_list (
526
- self , allow_signature : bool = True ,
527
- no_type_checks : bool = False ) -> Tuple [List [Var ], List [Node ],
528
- List [int ], bool ,
529
- List [Token ], List [Token ],
530
- List [Token ], List [Token ],
531
- List [Type ]]:
534
+ def parse_arg_list (self , allow_signature : bool = True ,
535
+ no_type_checks : bool = False ) -> List [Argument ]:
532
536
"""Parse function definition argument list.
533
537
534
538
This includes everything between '(' and ')').
535
-
536
- Return a 9-tuple with these items:
537
- arguments, initializers, kinds, has inits, arg name tokens,
538
- comma tokens, asterisk tokens, assignment tokens, argument types
539
539
"""
540
- args = [] # type: List[Var]
541
- kinds = [] # type: List[int]
542
- names = [] # type: List[str]
543
- init = [] # type: List[Node]
544
- has_inits = False
545
- arg_types = [] # type: List[Type]
546
-
547
- arg_names = [] # type: List[Token]
548
- commas = [] # type: List[Token]
549
- asterisk = [] # type: List[Token]
550
- assigns = [] # type: List[Token]
540
+ args = [] # type: List[Argument]
551
541
552
542
require_named = False
553
543
bare_asterisk_before = - 1
@@ -562,60 +552,74 @@ def parse_arg_list(
562
552
if bare_asterisk_before == len (args ):
563
553
# named arguments must follow bare *
564
554
self .parse_error ()
565
- asterisk .append (self .skip ())
566
- isdict = asterisk [- 1 ].string == '**'
567
- name = self .expect_type (Name )
568
- arg_names .append (name )
569
- names .append (name .string )
570
- var_arg = Var (name .string )
571
- args .append (var_arg )
572
- init .append (None )
573
- assigns .append (none )
574
- if isdict :
575
- kinds .append (nodes .ARG_STAR2 )
576
- else :
577
- kinds .append (nodes .ARG_STAR )
578
555
579
- if no_type_checks :
580
- self . parse_parameter_annotation ()
581
- arg_types . append ( None )
582
- else :
583
- arg_types .append (self . parse_arg_type ( allow_signature ) )
556
+ arg = self . parse_asterisk_arg (
557
+ allow_signature ,
558
+ no_type_checks ,
559
+ )
560
+ args .append (arg )
584
561
require_named = True
585
562
else :
586
- name = self .expect_type (Name )
587
- arg_names .append (name )
588
- args .append (Var (name .string ))
589
-
590
- if no_type_checks :
591
- self .parse_parameter_annotation ()
592
- arg_types .append (None )
593
- else :
594
- arg_types .append (self .parse_arg_type (allow_signature ))
595
-
596
- if self .current_str () == '=' :
597
- assigns .append (self .expect ('=' ))
598
- init .append (self .parse_expression (precedence [',' ]))
599
- has_inits = True
600
- if require_named :
601
- kinds .append (nodes .ARG_NAMED )
602
- else :
603
- kinds .append (nodes .ARG_OPT )
604
- else :
605
- init .append (None )
606
- assigns .append (none )
607
- if require_named :
608
- # required keyword-only argument
609
- kinds .append (nodes .ARG_NAMED )
610
- else :
611
- kinds .append (nodes .ARG_POS )
563
+ arg , require_named = self .parse_normal_arg (
564
+ require_named ,
565
+ allow_signature ,
566
+ no_type_checks ,
567
+ )
568
+ args .append (arg )
612
569
613
570
if self .current ().string != ',' :
614
571
break
615
- commas .append (self .expect (',' ))
616
572
617
- return (args , init , kinds , has_inits , arg_names , commas , asterisk ,
618
- assigns , arg_types )
573
+ self .expect (',' )
574
+
575
+ return args
576
+
577
+ def parse_asterisk_arg (self ,
578
+ allow_signature : bool ,
579
+ no_type_checks : bool ) -> Argument :
580
+ asterisk = self .skip ()
581
+ name = self .expect_type (Name )
582
+ variable = Var (name .string )
583
+ if asterisk .string == '*' :
584
+ kind = nodes .ARG_STAR
585
+ else :
586
+ kind = nodes .ARG_STAR2
587
+
588
+ type = None # type: Type
589
+ if no_type_checks :
590
+ self .parse_parameter_annotation ()
591
+ else :
592
+ type = self .parse_arg_type (allow_signature )
593
+
594
+ return Argument (variable , type , None , kind )
595
+
596
+ def parse_normal_arg (self , require_named : bool ,
597
+ allow_signature : bool ,
598
+ no_type_checks : bool ) -> Tuple [Argument , bool ]:
599
+ name = self .expect_type (Name )
600
+ variable = Var (name .string )
601
+
602
+ type = None # type: Type
603
+ if no_type_checks :
604
+ self .parse_parameter_annotation ()
605
+ else :
606
+ type = self .parse_arg_type (allow_signature )
607
+
608
+ initializer = None # type: Node
609
+ if self .current_str () == '=' :
610
+ self .expect ('=' )
611
+ initializer = self .parse_expression (precedence [',' ])
612
+ if require_named :
613
+ kind = nodes .ARG_NAMED
614
+ else :
615
+ kind = nodes .ARG_OPT
616
+ else :
617
+ if require_named :
618
+ kind = nodes .ARG_NAMED
619
+ else :
620
+ kind = nodes .ARG_POS
621
+
622
+ return Argument (variable , type , initializer , kind ), require_named
619
623
620
624
def parse_parameter_annotation (self ) -> Node :
621
625
if self .current_str () == ':' :
@@ -642,17 +646,18 @@ def verify_argument_kinds(self, kinds: List[int], line: int) -> None:
642
646
self .fail ('Invalid argument list' , line )
643
647
found .add (kind )
644
648
645
- def construct_function_type (self , arg_types : List [Type ], kinds : List [int ],
646
- names : List [str ], ret_type : Type ,
649
+ def construct_function_type (self , args : List [Argument ], ret_type : Type ,
647
650
line : int ) -> CallableType :
648
651
# Complete the type annotation by replacing omitted types with 'Any'.
649
- arg_types = arg_types [: ]
652
+ arg_types = [ arg . type for arg in args ]
650
653
for i in range (len (arg_types )):
651
654
if arg_types [i ] is None :
652
655
arg_types [i ] = AnyType ()
653
656
if ret_type is None :
654
657
ret_type = AnyType ()
655
- return CallableType (arg_types , kinds , names , ret_type , None , None ,
658
+ arg_kinds = [arg .kind for arg in args ]
659
+ arg_names = [arg .variable .name () for arg in args ]
660
+ return CallableType (arg_types , arg_kinds , arg_names , ret_type , None , None ,
656
661
None , [], line )
657
662
658
663
# Parsing statements
@@ -1626,19 +1631,13 @@ def parse_unary_expr(self) -> UnaryExpr:
1626
1631
def parse_lambda_expr (self ) -> FuncExpr :
1627
1632
lambda_tok = self .expect ('lambda' )
1628
1633
1629
- (args , init , kinds , has_inits ,
1630
- arg_names , commas , asterisk ,
1631
- assigns , arg_types ) = self .parse_arg_list (allow_signature = False )
1632
-
1633
- names = [] # type: List[str]
1634
- for arg in args :
1635
- names .append (arg .name ())
1634
+ args = self .parse_arg_list (allow_signature = False )
1636
1635
1637
1636
# Use 'object' as the placeholder return type; it will be inferred
1638
1637
# later. We can't use 'Any' since it could make type inference results
1639
1638
# less precise.
1640
1639
ret_type = UnboundType ('__builtins__.object' )
1641
- typ = self .build_func_annotation (ret_type , arg_types , kinds , names ,
1640
+ typ = self .build_func_annotation (ret_type , args ,
1642
1641
lambda_tok .line , is_default_ret = True )
1643
1642
1644
1643
colon = self .expect (':' )
@@ -1648,7 +1647,11 @@ def parse_lambda_expr(self) -> FuncExpr:
1648
1647
body = Block ([ReturnStmt (expr ).set_line (lambda_tok )])
1649
1648
body .set_line (colon )
1650
1649
1651
- node = FuncExpr (args , kinds , init , body , typ )
1650
+ arg_vars = [arg .variable for arg in args ]
1651
+ arg_kinds = [arg .kind for arg in args ]
1652
+ arg_initializers = [arg .initializer for arg in args ]
1653
+
1654
+ node = FuncExpr (arg_vars , arg_kinds , arg_initializers , body , typ )
1652
1655
return node
1653
1656
1654
1657
# Helper methods
0 commit comments