@@ -155,6 +155,30 @@ func (c *compiler) Op(op byte) {
155
155
c .OpCodes .Add (& Op {Op : op })
156
156
}
157
157
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
+
158
182
// Compile statements
159
183
func (c * compiler ) compileStmts (stmts []ast.Stmt ) {
160
184
for _ , stmt := range stmts {
@@ -265,8 +289,23 @@ func (c *compiler) compileExpr(expr ast.Expr) {
265
289
case * ast.BoolOp :
266
290
// Op BoolOpNumber
267
291
// 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 )
270
309
case * ast.BinOp :
271
310
// Left Expr
272
311
// Op OperatorNumber
@@ -425,8 +464,35 @@ func (is *Instructions) Add(i Instruction) {
425
464
* is = append (* is , i )
426
465
}
427
466
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
429
487
func (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:
430
496
out := make ([]byte , 0 , 3 * len (is ))
431
497
for _ , i := range is {
432
498
out = append (out , i .Output ()... )
@@ -437,10 +503,14 @@ func (is Instructions) Assemble() string {
437
503
type Instruction interface {
438
504
Pos () uint32
439
505
SetPos (uint32 )
440
- Size () int
506
+ Size () uint32
441
507
Output () []byte
442
508
}
443
509
510
+ type Resolver interface {
511
+ Resolve () bool
512
+ }
513
+
444
514
// Position
445
515
type pos uint32
446
516
@@ -461,7 +531,7 @@ type Op struct {
461
531
}
462
532
463
533
// Uses 1 byte in the output stream
464
- func (o * Op ) Size () int {
534
+ func (o * Op ) Size () uint32 {
465
535
return 1
466
536
}
467
537
@@ -478,7 +548,7 @@ type OpArg struct {
478
548
}
479
549
480
550
// Uses 1 byte in the output stream
481
- func (o * OpArg ) Size () int {
551
+ func (o * OpArg ) Size () uint32 {
482
552
if o .Arg <= 0xFFFF {
483
553
return 3 // Op Arg1 Arg2
484
554
} else {
@@ -501,7 +571,7 @@ type Label struct {
501
571
}
502
572
503
573
// Uses 0 bytes in the output stream
504
- func (o * Label ) Size () int {
574
+ func (o * Label ) Size () uint32 {
505
575
return 0
506
576
}
507
577
@@ -517,15 +587,18 @@ type JumpAbs struct {
517
587
Dest * Label
518
588
}
519
589
520
- // FIXME need changed flags?
521
-
522
590
// 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
525
598
}
526
599
527
600
// Bytes used in the output stream
528
- func (o * JumpAbs ) Size () int {
601
+ func (o * JumpAbs ) Size () uint32 {
529
602
o .Resolve ()
530
603
return o .OpArg .Size ()
531
604
}
0 commit comments