Skip to content

Commit d7653f2

Browse files
committed
compile: Implement if expression and JUMP_FORWARD
1 parent 6fa5265 commit d7653f2

File tree

3 files changed

+108
-4
lines changed

3 files changed

+108
-4
lines changed

compile/compile.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func (c *compiler) Jump(Op byte, Dest *Label) {
173173
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
174174
c.OpCodes.Add(&JumpAbs{OpArg: OpArg{Op: Op}, Dest: Dest})
175175
case vm.JUMP_FORWARD: // Relative
176-
panic("FIXME JUMP_FORWARD NOT implemented")
176+
c.OpCodes.Add(&JumpRel{OpArg: OpArg{Op: Op}, Dest: Dest})
177177
default:
178178
panic("Jump called with non jump instruction")
179179
}
@@ -368,7 +368,15 @@ func (c *compiler) compileExpr(expr ast.Expr) {
368368
// Test Expr
369369
// Body Expr
370370
// Orelse Expr
371-
panic("FIXME not implemented")
371+
elseBranch := new(Label)
372+
endifBranch := new(Label)
373+
c.compileExpr(node.Test)
374+
c.Jump(vm.POP_JUMP_IF_FALSE, elseBranch)
375+
c.compileExpr(node.Body)
376+
c.Jump(vm.JUMP_FORWARD, endifBranch)
377+
c.Label(elseBranch)
378+
c.compileExpr(node.Body)
379+
c.Label(endifBranch)
372380
case *ast.Dict:
373381
// Keys []Expr
374382
// Values []Expr
@@ -471,7 +479,8 @@ func (is Instructions) Pass(pass int) bool {
471479
addr := uint32(0)
472480
changed := false
473481
for _, i := range is {
474-
changed = changed || i.SetPos(addr)
482+
posChanged := i.SetPos(addr)
483+
changed = changed || posChanged
475484
if pass > 0 {
476485
// Only resolve addresses on 2nd pass
477486
if resolver, ok := i.(Resolver); ok {
@@ -595,4 +604,25 @@ func (o *JumpAbs) Resolve() {
595604
o.OpArg.Arg = o.Dest.Pos()
596605
}
597606

598-
// FIXME Jump Relative
607+
// A relative JUMP with destination label
608+
type JumpRel struct {
609+
pos
610+
OpArg
611+
Dest *Label
612+
}
613+
614+
// Set the Arg from the Jump Label
615+
func (o *JumpRel) Resolve() {
616+
currentSize := o.Size()
617+
currentPos := o.Pos() + currentSize
618+
if o.Dest.Pos() < currentPos {
619+
panic("Attempt use JUMP_FORWARD to jump backwards")
620+
}
621+
o.OpArg.Arg = o.Dest.Pos() - currentPos
622+
if o.Size() != currentSize {
623+
// There is an awkward moment where jump forwards is
624+
// between 0x1000 and 0x1002 where the Arg oscillates
625+
// between 2 and 4 bytes
626+
panic("FIXME JUMP_FOWARDS size changed")
627+
}
628+
}

compile/compile_data_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,4 +403,72 @@ var compileTestData = []struct {
403403
Firstlineno: 1,
404404
Lnotab: "",
405405
}, " 1 0 LOAD_CONST 0 (1)\n 3 JUMP_IF_TRUE_OR_POP 21\n 6 LOAD_CONST 1 (2)\n 9 JUMP_IF_TRUE_OR_POP 21\n 12 LOAD_CONST 2 (3)\n 15 JUMP_IF_TRUE_OR_POP 21\n 18 LOAD_CONST 3 (4)\n >> 21 RETURN_VALUE\n"},
406+
{"\"1\"+\"2\"*\"3\"", "eval", py.Code{
407+
Argcount: 0,
408+
Kwonlyargcount: 0,
409+
Nlocals: 0,
410+
Stacksize: 3,
411+
Flags: 64,
412+
Code: "\x64\x00\x00\x64\x01\x00\x64\x02\x00\x14\x17\x53",
413+
Consts: []py.Object{py.String("1"), py.String("2"), py.String("3")},
414+
Names: []string{},
415+
Varnames: []string{},
416+
Freevars: []string{},
417+
Cellvars: []string{},
418+
Filename: "<string>",
419+
Name: "<module>",
420+
Firstlineno: 1,
421+
Lnotab: "",
422+
}, " 1 0 LOAD_CONST 0 ('1')\n 3 LOAD_CONST 1 ('2')\n 6 LOAD_CONST 2 ('3')\n 9 BINARY_MULTIPLY\n 10 BINARY_ADD\n 11 RETURN_VALUE\n"},
423+
{"\"1\"+(\"2\"*\"3\")", "eval", py.Code{
424+
Argcount: 0,
425+
Kwonlyargcount: 0,
426+
Nlocals: 0,
427+
Stacksize: 3,
428+
Flags: 64,
429+
Code: "\x64\x00\x00\x64\x01\x00\x64\x02\x00\x14\x17\x53",
430+
Consts: []py.Object{py.String("1"), py.String("2"), py.String("3")},
431+
Names: []string{},
432+
Varnames: []string{},
433+
Freevars: []string{},
434+
Cellvars: []string{},
435+
Filename: "<string>",
436+
Name: "<module>",
437+
Firstlineno: 1,
438+
Lnotab: "",
439+
}, " 1 0 LOAD_CONST 0 ('1')\n 3 LOAD_CONST 1 ('2')\n 6 LOAD_CONST 2 ('3')\n 9 BINARY_MULTIPLY\n 10 BINARY_ADD\n 11 RETURN_VALUE\n"},
440+
{"(1+\"2\")*\"3\"", "eval", py.Code{
441+
Argcount: 0,
442+
Kwonlyargcount: 0,
443+
Nlocals: 0,
444+
Stacksize: 2,
445+
Flags: 64,
446+
Code: "\x64\x00\x00\x64\x01\x00\x17\x64\x02\x00\x14\x53",
447+
Consts: []py.Object{py.Int(1), py.String("2"), py.String("3")},
448+
Names: []string{},
449+
Varnames: []string{},
450+
Freevars: []string{},
451+
Cellvars: []string{},
452+
Filename: "<string>",
453+
Name: "<module>",
454+
Firstlineno: 1,
455+
Lnotab: "",
456+
}, " 1 0 LOAD_CONST 0 (1)\n 3 LOAD_CONST 1 ('2')\n 6 BINARY_ADD\n 7 LOAD_CONST 2 ('3')\n 10 BINARY_MULTIPLY\n 11 RETURN_VALUE\n"},
457+
{"(\"true\" if 1+\"2\" else \"false\")+\"a\"", "eval", py.Code{
458+
Argcount: 0,
459+
Kwonlyargcount: 0,
460+
Nlocals: 0,
461+
Stacksize: 2,
462+
Flags: 64,
463+
Code: "\x64\x00\x00\x64\x01\x00\x17\x72\x10\x00\x64\x02\x00\x6e\x03\x00\x64\x03\x00\x64\x04\x00\x17\x53",
464+
Consts: []py.Object{py.Int(1), py.String("2"), py.String("true"), py.String("false"), py.String("a")},
465+
Names: []string{},
466+
Varnames: []string{},
467+
Freevars: []string{},
468+
Cellvars: []string{},
469+
Filename: "<string>",
470+
Name: "<module>",
471+
Firstlineno: 1,
472+
Lnotab: "",
473+
}, " 1 0 LOAD_CONST 0 (1)\n 3 LOAD_CONST 1 ('2')\n 6 BINARY_ADD\n 7 POP_JUMP_IF_FALSE 16\n 10 LOAD_CONST 2 ('true')\n 13 JUMP_FORWARD 3 (to 19)\n >> 16 LOAD_CONST 3 ('false')\n >> 19 LOAD_CONST 4 ('a')\n 22 BINARY_ADD\n 23 RETURN_VALUE\n"},
406474
}

compile/make_compile_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
('''1 and 2''', "eval"),
3636
('''1 or 2''', "eval"),
3737
('''1 or 2 or 3 or 4''', "eval"),
38+
# With brackets
39+
('''"1"+"2"*"3"''', "eval"),
40+
('''"1"+("2"*"3")''', "eval"),
41+
('''(1+"2")*"3"''', "eval"),
42+
# If expression
43+
('''("true" if 1+"2" else "false")+"a"''', "eval"),
3844

3945
]
4046

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy