@@ -347,13 +347,6 @@ func (c *compiler) Jump(Op byte, Dest *Label) {
347
347
}
348
348
}
349
349
350
- // Compile statements
351
- func (c * compiler ) Stmts (stmts []ast.Stmt ) {
352
- for _ , stmt := range stmts {
353
- c .Stmt (stmt )
354
- }
355
- }
356
-
357
350
/* The test for LOCAL must come before the test for FREE in order to
358
351
handle classes where name is both local and free. The local var is
359
352
a method and the free var is a free var referenced within a method.
@@ -494,9 +487,7 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
494
487
code .Kwonlyargcount = int32 (len (Args .Kwonlyargs ))
495
488
496
489
// Defaults
497
- for _ , expr := range Args .Defaults {
498
- c .Expr (expr )
499
- }
490
+ c .Exprs (Args .Defaults )
500
491
501
492
// KwDefaults
502
493
if len (Args .Kwonlyargs ) != len (Args .KwDefaults ) {
@@ -532,9 +523,7 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
532
523
}
533
524
534
525
// Load decorators onto stack
535
- for _ , expr := range DecoratorList {
536
- c .Expr (expr )
537
- }
526
+ c .Exprs (DecoratorList )
538
527
539
528
// Make function or closure, leaving it on the stack
540
529
posdefaults := uint32 (len (Args .Defaults ))
@@ -551,9 +540,7 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
551
540
// Compile class definition
552
541
func (c * compiler ) class (Ast ast.Ast , class * ast.ClassDef ) {
553
542
// Load decorators onto stack
554
- for _ , expr := range class .DecoratorList {
555
- c .Expr (expr )
556
- }
543
+ c .Exprs (class .DecoratorList )
557
544
558
545
/* ultimately generate code for:
559
546
<name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
@@ -643,9 +630,7 @@ func (c *compiler) with(node *ast.With, pos int) {
643
630
pos ++
644
631
if pos == len (node .Items ) {
645
632
/* BLOCK code */
646
- for _ , stmt := range node .Body {
647
- c .Stmt (stmt )
648
- }
633
+ c .Stmts (node .Body )
649
634
} else {
650
635
c .with (node , pos )
651
636
}
@@ -664,6 +649,176 @@ func (c *compiler) with(node *ast.With, pos int) {
664
649
c .Op (vm .END_FINALLY )
665
650
}
666
651
652
+ /* Code generated for "try: <body> finally: <finalbody>" is as follows:
653
+
654
+ SETUP_FINALLY L
655
+ <code for body>
656
+ POP_BLOCK
657
+ LOAD_CONST <None>
658
+ L: <code for finalbody>
659
+ END_FINALLY
660
+
661
+ The special instructions use the block stack. Each block
662
+ stack entry contains the instruction that created it (here
663
+ SETUP_FINALLY), the level of the value stack at the time the
664
+ block stack entry was created, and a label (here L).
665
+
666
+ SETUP_FINALLY:
667
+ Pushes the current value stack level and the label
668
+ onto the block stack.
669
+ POP_BLOCK:
670
+ Pops en entry from the block stack, and pops the value
671
+ stack until its level is the same as indicated on the
672
+ block stack. (The label is ignored.)
673
+ END_FINALLY:
674
+ Pops a variable number of entries from the *value* stack
675
+ and re-raises the exception they specify. The number of
676
+ entries popped depends on the (pseudo) exception type.
677
+
678
+ The block stack is unwound when an exception is raised:
679
+ when a SETUP_FINALLY entry is found, the exception is pushed
680
+ onto the value stack (and the exception condition is cleared),
681
+ and the interpreter jumps to the label gotten from the block
682
+ stack.
683
+ */
684
+ func (c * compiler ) tryFinally (node * ast.Try ) {
685
+ end := new (Label )
686
+ c .Jump (vm .SETUP_FINALLY , end )
687
+ if len (node .Handlers ) > 0 {
688
+ c .tryExcept (node )
689
+ } else {
690
+ c .Stmts (node .Body )
691
+ }
692
+ c .Op (vm .POP_BLOCK )
693
+ c .LoadConst (py .None )
694
+ c .Label (end )
695
+ c .Stmts (node .Finalbody )
696
+ c .Op (vm .END_FINALLY )
697
+ }
698
+
699
+ /*
700
+ Code generated for "try: S except E1 as V1: S1 except E2 as V2: S2 ...":
701
+ (The contents of the value stack is shown in [], with the top
702
+ at the right; 'tb' is trace-back info, 'val' the exception's
703
+ associated value, and 'exc' the exception.)
704
+
705
+ Value stack Label Instruction Argument
706
+ [] SETUP_EXCEPT L1
707
+ [] <code for S>
708
+ [] POP_BLOCK
709
+ [] JUMP_FORWARD L0
710
+
711
+ [tb, val, exc] L1: DUP )
712
+ [tb, val, exc, exc] <evaluate E1> )
713
+ [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1
714
+ [tb, val, exc, 1-or-0] POP_JUMP_IF_FALSE L2 )
715
+ [tb, val, exc] POP
716
+ [tb, val] <assign to V1> (or POP if no V1)
717
+ [tb] POP
718
+ [] <code for S1>
719
+ JUMP_FORWARD L0
720
+
721
+ [tb, val, exc] L2: DUP
722
+ .............................etc.......................
723
+
724
+ [tb, val, exc] Ln+1: END_FINALLY # re-raise exception
725
+
726
+ [] L0: <next statement>
727
+
728
+ Of course, parts are not generated if Vi or Ei is not present.
729
+ */
730
+ func (c * compiler ) tryExcept (node * ast.Try ) {
731
+ except := new (Label )
732
+ orelse := new (Label )
733
+ end := new (Label )
734
+ c .Jump (vm .SETUP_EXCEPT , except )
735
+ c .Stmts (node .Body )
736
+ c .Op (vm .POP_BLOCK )
737
+ c .Jump (vm .JUMP_FORWARD , orelse )
738
+ n := len (node .Handlers )
739
+ c .Label (except )
740
+ for i , handler := range node .Handlers {
741
+ if handler .ExprType == nil && i < n - 1 {
742
+ panic (py .ExceptionNewf (py .SyntaxError , "default 'except:' must be last" ))
743
+ }
744
+ // FIXME c.u.u_lineno_set = 0
745
+ // c.u.u_lineno = handler.lineno
746
+ // c.u.u_col_offset = handler.col_offset
747
+ except := new (Label )
748
+ if handler .ExprType != nil {
749
+ c .Op (vm .DUP_TOP )
750
+ c .Expr (handler .ExprType )
751
+ c .OpArg (vm .COMPARE_OP , vm .PyCmp_EXC_MATCH )
752
+ c .Jump (vm .POP_JUMP_IF_FALSE , except )
753
+ }
754
+ c .Op (vm .POP_TOP )
755
+ if handler .Name != "" {
756
+ cleanup_end := new (Label )
757
+ c .NameOp (string (handler .Name ), ast .Store )
758
+ c .Op (vm .POP_TOP )
759
+
760
+ /*
761
+ try:
762
+ # body
763
+ except type as name:
764
+ try:
765
+ # body
766
+ finally:
767
+ name = None
768
+ del name
769
+ */
770
+
771
+ /* second try: */
772
+ c .Jump (vm .SETUP_FINALLY , cleanup_end )
773
+
774
+ /* second # body */
775
+ c .Stmts (handler .Body )
776
+ c .Op (vm .POP_BLOCK )
777
+ c .Op (vm .POP_EXCEPT )
778
+
779
+ /* finally: */
780
+ c .LoadConst (py .None )
781
+ c .Label (cleanup_end )
782
+
783
+ /* name = None */
784
+ c .LoadConst (py .None )
785
+ c .NameOp (string (handler .Name ), ast .Store )
786
+
787
+ /* del name */
788
+ c .NameOp (string (handler .Name ), ast .Del )
789
+
790
+ c .Op (vm .END_FINALLY )
791
+ } else {
792
+ c .Op (vm .POP_TOP )
793
+ c .Op (vm .POP_TOP )
794
+ c .Stmts (handler .Body )
795
+ c .Op (vm .POP_EXCEPT )
796
+ }
797
+ c .Jump (vm .JUMP_FORWARD , end )
798
+ c .Label (except )
799
+ }
800
+ c .Op (vm .END_FINALLY )
801
+ c .Label (orelse )
802
+ c .Stmts (node .Orelse )
803
+ c .Label (end )
804
+ }
805
+
806
+ // Compile a try statement
807
+ func (c * compiler ) try (node * ast.Try ) {
808
+ if len (node .Finalbody ) > 0 {
809
+ c .tryFinally (node )
810
+ } else {
811
+ c .tryExcept (node )
812
+ }
813
+ }
814
+
815
+ // Compile statements
816
+ func (c * compiler ) Stmts (stmts []ast.Stmt ) {
817
+ for _ , stmt := range stmts {
818
+ c .Stmt (stmt )
819
+ }
820
+ }
821
+
667
822
// Compile statement
668
823
func (c * compiler ) Stmt (stmt ast.Stmt ) {
669
824
switch node := stmt .(type ) {
@@ -766,16 +921,12 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
766
921
c .loops .Push (loop {Start : forloop , End : endpopblock , IsForLoop : true })
767
922
c .Jump (vm .FOR_ITER , endfor )
768
923
c .Expr (node .Target )
769
- for _ , stmt := range node .Body {
770
- c .Stmt (stmt )
771
- }
924
+ c .Stmts (node .Body )
772
925
c .Jump (vm .JUMP_ABSOLUTE , forloop )
773
926
c .Label (endfor )
774
927
c .Op (vm .POP_BLOCK )
775
928
c .loops .Pop ()
776
- for _ , stmt := range node .Orelse {
777
- c .Stmt (stmt )
778
- }
929
+ c .Stmts (node .Orelse )
779
930
c .Label (endpopblock )
780
931
case * ast.While :
781
932
// Test Expr
@@ -788,16 +939,12 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
788
939
c .loops .Push (loop {Start : while , End : endpopblock })
789
940
c .Expr (node .Test )
790
941
c .Jump (vm .POP_JUMP_IF_FALSE , endwhile )
791
- for _ , stmt := range node .Body {
792
- c .Stmt (stmt )
793
- }
942
+ c .Stmts (node .Body )
794
943
c .Jump (vm .JUMP_ABSOLUTE , while )
795
944
c .Label (endwhile )
796
945
c .Op (vm .POP_BLOCK )
797
946
c .loops .Pop ()
798
- for _ , stmt := range node .Orelse {
799
- c .Stmt (stmt )
800
- }
947
+ c .Stmts (node .Orelse )
801
948
c .Label (endpopblock )
802
949
case * ast.If :
803
950
// Test Expr
@@ -807,17 +954,13 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
807
954
endif := new (Label )
808
955
c .Expr (node .Test )
809
956
c .Jump (vm .POP_JUMP_IF_FALSE , orelse )
810
- for _ , stmt := range node .Body {
811
- c .Stmt (stmt )
812
- }
957
+ c .Stmts (node .Body )
813
958
// FIXME this puts a JUMP_FORWARD in when not
814
959
// necessary (when no Orelse statements) but it
815
960
// matches python3.4 (this is fixed in py3.5)
816
961
c .Jump (vm .JUMP_FORWARD , endif )
817
962
c .Label (orelse )
818
- for _ , stmt := range node .Orelse {
819
- c .Stmt (stmt )
820
- }
963
+ c .Stmts (node .Orelse )
821
964
c .Label (endif )
822
965
case * ast.With :
823
966
// Items []*WithItem
@@ -841,7 +984,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
841
984
// Handlers []*ExceptHandler
842
985
// Orelse []Stmt
843
986
// Finalbody []Stmt
844
- panic ( "FIXME compile: Try not implemented" )
987
+ c . try ( node )
845
988
case * ast.Assert :
846
989
// Test Expr
847
990
// Msg Expr
@@ -913,7 +1056,7 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
913
1056
// PyObject *mangled;
914
1057
/* XXX AugStore isn't used anywhere! */
915
1058
916
- // FIXME mangled = _Py_Mangle(c->u-> u_private, name);
1059
+ // FIXME mangled = _Py_Mangle(c.u. u_private, name);
917
1060
mangled := name
918
1061
919
1062
if name == "None" || name == "True" || name == "False" {
@@ -1143,6 +1286,13 @@ func (c *compiler) comprehension(expr ast.Expr, generators []ast.Comprehension)
1143
1286
}
1144
1287
1145
1288
// Compile expressions
1289
+ func (c * compiler ) Exprs (exprs []ast.Expr ) {
1290
+ for _ , expr := range exprs {
1291
+ c .Expr (expr )
1292
+ }
1293
+ }
1294
+
1295
+ // Compile and expression
1146
1296
func (c * compiler ) Expr (expr ast.Expr ) {
1147
1297
switch node := expr .(type ) {
1148
1298
case * ast.BoolOp :
0 commit comments