@@ -347,13 +347,6 @@ func (c *compiler) Jump(Op byte, Dest *Label) {
347347 }
348348}
349349
350- // Compile statements
351- func (c *compiler) Stmts(stmts []ast.Stmt) {
352- for _, stmt := range stmts {
353- c.Stmt(stmt)
354- }
355- }
356-
357350/* The test for LOCAL must come before the test for FREE in order to
358351 handle classes where name is both local and free. The local var is
359352 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
494487 code.Kwonlyargcount = int32(len(Args.Kwonlyargs))
495488
496489 // Defaults
497- for _, expr := range Args.Defaults {
498- c.Expr(expr)
499- }
490+ c.Exprs(Args.Defaults)
500491
501492 // KwDefaults
502493 if len(Args.Kwonlyargs) != len(Args.KwDefaults) {
@@ -532,9 +523,7 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
532523 }
533524
534525 // Load decorators onto stack
535- for _, expr := range DecoratorList {
536- c.Expr(expr)
537- }
526+ c.Exprs(DecoratorList)
538527
539528 // Make function or closure, leaving it on the stack
540529 posdefaults := uint32(len(Args.Defaults))
@@ -551,9 +540,7 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
551540// Compile class definition
552541func (c *compiler) class(Ast ast.Ast, class *ast.ClassDef) {
553542 // Load decorators onto stack
554- for _, expr := range class.DecoratorList {
555- c.Expr(expr)
556- }
543+ c.Exprs(class.DecoratorList)
557544
558545 /* ultimately generate code for:
559546 <name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)
@@ -643,9 +630,7 @@ func (c *compiler) with(node *ast.With, pos int) {
643630 pos++
644631 if pos == len(node.Items) {
645632 /* BLOCK code */
646- for _, stmt := range node.Body {
647- c.Stmt(stmt)
648- }
633+ c.Stmts(node.Body)
649634 } else {
650635 c.with(node, pos)
651636 }
@@ -664,6 +649,176 @@ func (c *compiler) with(node *ast.With, pos int) {
664649 c.Op(vm.END_FINALLY)
665650}
666651
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+
667822// Compile statement
668823func (c *compiler) Stmt(stmt ast.Stmt) {
669824 switch node := stmt.(type) {
@@ -766,16 +921,12 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
766921 c.loops.Push(loop{Start: forloop, End: endpopblock, IsForLoop: true})
767922 c.Jump(vm.FOR_ITER, endfor)
768923 c.Expr(node.Target)
769- for _, stmt := range node.Body {
770- c.Stmt(stmt)
771- }
924+ c.Stmts(node.Body)
772925 c.Jump(vm.JUMP_ABSOLUTE, forloop)
773926 c.Label(endfor)
774927 c.Op(vm.POP_BLOCK)
775928 c.loops.Pop()
776- for _, stmt := range node.Orelse {
777- c.Stmt(stmt)
778- }
929+ c.Stmts(node.Orelse)
779930 c.Label(endpopblock)
780931 case *ast.While:
781932 // Test Expr
@@ -788,16 +939,12 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
788939 c.loops.Push(loop{Start: while, End: endpopblock})
789940 c.Expr(node.Test)
790941 c.Jump(vm.POP_JUMP_IF_FALSE, endwhile)
791- for _, stmt := range node.Body {
792- c.Stmt(stmt)
793- }
942+ c.Stmts(node.Body)
794943 c.Jump(vm.JUMP_ABSOLUTE, while)
795944 c.Label(endwhile)
796945 c.Op(vm.POP_BLOCK)
797946 c.loops.Pop()
798- for _, stmt := range node.Orelse {
799- c.Stmt(stmt)
800- }
947+ c.Stmts(node.Orelse)
801948 c.Label(endpopblock)
802949 case *ast.If:
803950 // Test Expr
@@ -807,17 +954,13 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
807954 endif := new(Label)
808955 c.Expr(node.Test)
809956 c.Jump(vm.POP_JUMP_IF_FALSE, orelse)
810- for _, stmt := range node.Body {
811- c.Stmt(stmt)
812- }
957+ c.Stmts(node.Body)
813958 // FIXME this puts a JUMP_FORWARD in when not
814959 // necessary (when no Orelse statements) but it
815960 // matches python3.4 (this is fixed in py3.5)
816961 c.Jump(vm.JUMP_FORWARD, endif)
817962 c.Label(orelse)
818- for _, stmt := range node.Orelse {
819- c.Stmt(stmt)
820- }
963+ c.Stmts(node.Orelse)
821964 c.Label(endif)
822965 case *ast.With:
823966 // Items []*WithItem
@@ -841,7 +984,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
841984 // Handlers []*ExceptHandler
842985 // Orelse []Stmt
843986 // Finalbody []Stmt
844- panic("FIXME compile: Try not implemented" )
987+ c.try(node )
845988 case *ast.Assert:
846989 // Test Expr
847990 // Msg Expr
@@ -913,7 +1056,7 @@ func (c *compiler) NameOp(name string, ctx ast.ExprContext) {
9131056 // PyObject *mangled;
9141057 /* XXX AugStore isn't used anywhere! */
9151058
916- // FIXME mangled = _Py_Mangle(c->u-> u_private, name);
1059+ // FIXME mangled = _Py_Mangle(c.u. u_private, name);
9171060 mangled := name
9181061
9191062 if name == "None" || name == "True" || name == "False" {
@@ -1143,6 +1286,13 @@ func (c *compiler) comprehension(expr ast.Expr, generators []ast.Comprehension)
11431286}
11441287
11451288// 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
11461296func (c *compiler) Expr(expr ast.Expr) {
11471297 switch node := expr.(type) {
11481298 case *ast.BoolOp:
0 commit comments