@@ -155,6 +155,30 @@ func (c *compiler) Op(op byte) {
155155 c .OpCodes .Add (& Op {Op : op })
156156}
157157
158+ // Inserts an existing label
159+ func (c * compiler ) Label (Dest * Label ) {
160+ c .OpCodes .Add (Dest )
161+ }
162+
163+ // Inserts and creates a label
164+ func (c * compiler ) NewLabel () * Label {
165+ Dest := new (Label )
166+ c .OpCodes .Add (Dest )
167+ return Dest
168+ }
169+
170+ // Compiles a jump instruction
171+ func (c * compiler ) Jump (Op byte , Dest * Label ) {
172+ switch Op {
173+ case vm .JUMP_IF_FALSE_OR_POP , vm .JUMP_IF_TRUE_OR_POP , vm .JUMP_ABSOLUTE , vm .POP_JUMP_IF_FALSE , vm .POP_JUMP_IF_TRUE : // Absolute
174+ c .OpCodes .Add (& JumpAbs {OpArg : OpArg {Op : Op }, Dest : Dest })
175+ case vm .JUMP_FORWARD : // Relative
176+ panic ("FIXME JUMP_FORWARD NOT implemented" )
177+ default :
178+ panic ("Jump called with non jump instruction" )
179+ }
180+ }
181+
158182// Compile statements
159183func (c * compiler ) compileStmts (stmts []ast.Stmt ) {
160184 for _ , stmt := range stmts {
@@ -265,8 +289,23 @@ func (c *compiler) compileExpr(expr ast.Expr) {
265289 case * ast.BoolOp :
266290 // Op BoolOpNumber
267291 // Values []Expr
268- _ = node
269- panic ("FIXME not implemented" )
292+ var op byte
293+ switch node .Op {
294+ case ast .And :
295+ op = vm .JUMP_IF_FALSE_OR_POP
296+ case ast .Or :
297+ op = vm .JUMP_IF_TRUE_OR_POP
298+ default :
299+ panic ("Unknown BoolOp" )
300+ }
301+ label := new (Label )
302+ for i , e := range node .Values {
303+ c .compileExpr (e )
304+ if i != len (node .Values )- 1 {
305+ c .Jump (op , label )
306+ }
307+ }
308+ c .Label (label )
270309 case * ast.BinOp :
271310 // Left Expr
272311 // Op OperatorNumber
@@ -425,8 +464,35 @@ func (is *Instructions) Add(i Instruction) {
425464 * is = append (* is , i )
426465}
427466
428- // Assembler the instructions into an Opcode string
467+ // Do a pass of assembly
468+ //
469+ // Returns a boolean as to whether the stream changed
470+ func (is Instructions ) Pass (pass int ) bool {
471+ addr := uint32 (0 )
472+ changed := pass == 0
473+ for _ , i := range is {
474+ i .SetPos (addr )
475+ if pass > 0 {
476+ // Only resolve addresses on 2nd pass
477+ if resolver , ok := i .(Resolver ); ok {
478+ changed = changed || resolver .Resolve ()
479+ }
480+ }
481+ addr += i .Size ()
482+ }
483+ return changed
484+ }
485+
486+ // Assemble the instructions into an Opcode string
429487func (is Instructions ) Assemble () string {
488+ for i := 0 ; i < 10 ; i ++ {
489+ changed := is .Pass (i )
490+ if ! changed {
491+ goto done
492+ }
493+ }
494+ panic ("Failed to assemble after 10 passes" )
495+ done:
430496 out := make ([]byte , 0 , 3 * len (is ))
431497 for _ , i := range is {
432498 out = append (out , i .Output ()... )
@@ -437,10 +503,14 @@ func (is Instructions) Assemble() string {
437503type Instruction interface {
438504 Pos () uint32
439505 SetPos (uint32 )
440- Size () int
506+ Size () uint32
441507 Output () []byte
442508}
443509
510+ type Resolver interface {
511+ Resolve () bool
512+ }
513+
444514// Position
445515type pos uint32
446516
@@ -461,7 +531,7 @@ type Op struct {
461531}
462532
463533// Uses 1 byte in the output stream
464- func (o * Op ) Size () int {
534+ func (o * Op ) Size () uint32 {
465535 return 1
466536}
467537
@@ -478,7 +548,7 @@ type OpArg struct {
478548}
479549
480550// Uses 1 byte in the output stream
481- func (o * OpArg ) Size () int {
551+ func (o * OpArg ) Size () uint32 {
482552 if o .Arg <= 0xFFFF {
483553 return 3 // Op Arg1 Arg2
484554 } else {
@@ -501,7 +571,7 @@ type Label struct {
501571}
502572
503573// Uses 0 bytes in the output stream
504- func (o * Label ) Size () int {
574+ func (o * Label ) Size () uint32 {
505575 return 0
506576}
507577
@@ -517,15 +587,18 @@ type JumpAbs struct {
517587 Dest * Label
518588}
519589
520- // FIXME need changed flags?
521-
522590// Set the Arg from the Jump Label
523- func (o * JumpAbs ) Resolve () {
524- o .OpArg .Arg = o .Dest .Pos ()
591+ //
592+ // Returns a changed flag
593+ func (o * JumpAbs ) Resolve () bool {
594+ newPos := o .Dest .Pos ()
595+ changed := o .OpArg .Arg == newPos
596+ o .OpArg .Arg = newPos
597+ return changed
525598}
526599
527600// Bytes used in the output stream
528- func (o * JumpAbs ) Size () int {
601+ func (o * JumpAbs ) Size () uint32 {
529602 o .Resolve ()
530603 return o .OpArg .Size ()
531604}
0 commit comments