Skip to content

Commit 8d5c74e

Browse files
committed
compile: Implement while and if
1 parent ac9ca13 commit 8d5c74e

File tree

3 files changed

+109
-5
lines changed

3 files changed

+109
-5
lines changed

compile/compile.go

+33-3
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func (c *compiler) Jump(Op byte, Dest *Label) {
209209
switch Op {
210210
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
211211
c.OpCodes.Add(&JumpAbs{OpArg: OpArg{Op: Op}, Dest: Dest})
212-
case vm.JUMP_FORWARD: // Relative
212+
case vm.JUMP_FORWARD, vm.SETUP_WITH, vm.FOR_ITER, vm.SETUP_LOOP, vm.SETUP_EXCEPT, vm.SETUP_FINALLY:
213213
c.OpCodes.Add(&JumpRel{OpArg: OpArg{Op: Op}, Dest: Dest})
214214
default:
215215
panic("Jump called with non jump instruction")
@@ -314,12 +314,42 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
314314
// Test Expr
315315
// Body []Stmt
316316
// Orelse []Stmt
317-
panic("FIXME compile: While not implemented")
317+
endwhile := new(Label)
318+
endpopblock := new(Label)
319+
c.Jump(vm.SETUP_LOOP, endpopblock)
320+
while := c.NewLabel()
321+
c.Expr(node.Test)
322+
c.Jump(vm.POP_JUMP_IF_FALSE, endwhile)
323+
for _, stmt := range node.Body {
324+
c.Stmt(stmt)
325+
}
326+
c.Jump(vm.JUMP_ABSOLUTE, while)
327+
c.Label(endwhile)
328+
c.Op(vm.POP_BLOCK)
329+
for _, stmt := range node.Orelse {
330+
c.Stmt(stmt)
331+
}
332+
c.Label(endpopblock)
318333
case *ast.If:
319334
// Test Expr
320335
// Body []Stmt
321336
// Orelse []Stmt
322-
panic("FIXME compile: If not implemented")
337+
orelse := new(Label)
338+
endif := new(Label)
339+
c.Expr(node.Test)
340+
c.Jump(vm.POP_JUMP_IF_FALSE, orelse)
341+
for _, stmt := range node.Body {
342+
c.Stmt(stmt)
343+
}
344+
// FIXME this puts a JUMP_FORWARD in when not
345+
// necessary (when no Orelse statements) but it
346+
// matches python3.4
347+
c.Jump(vm.JUMP_FORWARD, endif)
348+
c.Label(orelse)
349+
for _, stmt := range node.Orelse {
350+
c.Stmt(stmt)
351+
}
352+
c.Label(endif)
323353
case *ast.With:
324354
// Items []*WithItem
325355
// Body []Stmt

compile/compile_data_test.go

+69-1
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ var compileTestData = []struct {
11491149
Name: "<module>",
11501150
Firstlineno: 1,
11511151
Lnotab: "",
1152-
}, " 1 0 LOAD_CONST 0 (<code object <lambda> at 0x7fd0bed8ee40, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('<lambda>')\n 6 MAKE_FUNCTION 0\n 9 RETURN_VALUE\n"},
1152+
}, " 1 0 LOAD_CONST 0 (<code object <lambda> at 0x7f643912ce40, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('<lambda>')\n 6 MAKE_FUNCTION 0\n 9 RETURN_VALUE\n"},
11531153
{"pass", "exec", &py.Code{
11541154
Argcount: 0,
11551155
Kwonlyargcount: 0,
@@ -1575,4 +1575,72 @@ var compileTestData = []struct {
15751575
Firstlineno: 1,
15761576
Lnotab: "",
15771577
}, " 1 0 LOAD_NAME 0 (a)\n 3 LOAD_NAME 1 (b)\n 6 RAISE_VARARGS 2\n 9 LOAD_CONST 0 (None)\n 12 RETURN_VALUE\n"},
1578+
{"if a: b = c", "exec", &py.Code{
1579+
Argcount: 0,
1580+
Kwonlyargcount: 0,
1581+
Nlocals: 0,
1582+
Stacksize: 1,
1583+
Flags: 64,
1584+
Code: "\x65\x00\x00\x72\x0f\x00\x65\x01\x00\x5a\x02\x00\x6e\x00\x00\x64\x00\x00\x53",
1585+
Consts: []py.Object{py.None},
1586+
Names: []string{"a", "c", "b"},
1587+
Varnames: []string{},
1588+
Freevars: []string{},
1589+
Cellvars: []string{},
1590+
Filename: "<string>",
1591+
Name: "<module>",
1592+
Firstlineno: 1,
1593+
Lnotab: "\x06\x00",
1594+
}, " 1 0 LOAD_NAME 0 (a)\n 3 POP_JUMP_IF_FALSE 15\n 6 LOAD_NAME 1 (c)\n 9 STORE_NAME 2 (b)\n 12 JUMP_FORWARD 0 (to 15)\n >> 15 LOAD_CONST 0 (None)\n 18 RETURN_VALUE\n"},
1595+
{"if a:\n b = c\nelse:\n c = d\n", "exec", &py.Code{
1596+
Argcount: 0,
1597+
Kwonlyargcount: 0,
1598+
Nlocals: 0,
1599+
Stacksize: 1,
1600+
Flags: 64,
1601+
Code: "\x65\x00\x00\x72\x0f\x00\x65\x01\x00\x5a\x02\x00\x6e\x06\x00\x65\x03\x00\x5a\x01\x00\x64\x00\x00\x53",
1602+
Consts: []py.Object{py.None},
1603+
Names: []string{"a", "c", "b", "d"},
1604+
Varnames: []string{},
1605+
Freevars: []string{},
1606+
Cellvars: []string{},
1607+
Filename: "<string>",
1608+
Name: "<module>",
1609+
Firstlineno: 1,
1610+
Lnotab: "\x06\x01\x09\x02",
1611+
}, " 1 0 LOAD_NAME 0 (a)\n 3 POP_JUMP_IF_FALSE 15\n\n 2 6 LOAD_NAME 1 (c)\n 9 STORE_NAME 2 (b)\n 12 JUMP_FORWARD 6 (to 21)\n\n 4 >> 15 LOAD_NAME 3 (d)\n 18 STORE_NAME 1 (c)\n >> 21 LOAD_CONST 0 (None)\n 24 RETURN_VALUE\n"},
1612+
{"while a:\n b = c", "exec", &py.Code{
1613+
Argcount: 0,
1614+
Kwonlyargcount: 0,
1615+
Nlocals: 0,
1616+
Stacksize: 1,
1617+
Flags: 64,
1618+
Code: "\x78\x10\x00\x65\x00\x00\x72\x12\x00\x65\x01\x00\x5a\x02\x00\x71\x03\x00\x57\x64\x00\x00\x53",
1619+
Consts: []py.Object{py.None},
1620+
Names: []string{"a", "c", "b"},
1621+
Varnames: []string{},
1622+
Freevars: []string{},
1623+
Cellvars: []string{},
1624+
Filename: "<string>",
1625+
Name: "<module>",
1626+
Firstlineno: 1,
1627+
Lnotab: "\x09\x01",
1628+
}, " 1 0 SETUP_LOOP 16 (to 19)\n >> 3 LOAD_NAME 0 (a)\n 6 POP_JUMP_IF_FALSE 18\n\n 2 9 LOAD_NAME 1 (c)\n 12 STORE_NAME 2 (b)\n 15 JUMP_ABSOLUTE 3\n >> 18 POP_BLOCK\n >> 19 LOAD_CONST 0 (None)\n 22 RETURN_VALUE\n"},
1629+
{"while a:\n b = c\nelse:\n b = d\n", "exec", &py.Code{
1630+
Argcount: 0,
1631+
Kwonlyargcount: 0,
1632+
Nlocals: 0,
1633+
Stacksize: 1,
1634+
Flags: 64,
1635+
Code: "\x78\x16\x00\x65\x00\x00\x72\x12\x00\x65\x01\x00\x5a\x02\x00\x71\x03\x00\x57\x65\x03\x00\x5a\x02\x00\x64\x00\x00\x53",
1636+
Consts: []py.Object{py.None},
1637+
Names: []string{"a", "c", "b", "d"},
1638+
Varnames: []string{},
1639+
Freevars: []string{},
1640+
Cellvars: []string{},
1641+
Filename: "<string>",
1642+
Name: "<module>",
1643+
Firstlineno: 1,
1644+
Lnotab: "\x09\x01\x0a\x02",
1645+
}, " 1 0 SETUP_LOOP 22 (to 25)\n >> 3 LOAD_NAME 0 (a)\n 6 POP_JUMP_IF_FALSE 18\n\n 2 9 LOAD_NAME 1 (c)\n 12 STORE_NAME 2 (b)\n 15 JUMP_ABSOLUTE 3\n >> 18 POP_BLOCK\n\n 4 19 LOAD_NAME 3 (d)\n 22 STORE_NAME 2 (b)\n >> 25 LOAD_CONST 0 (None)\n 28 RETURN_VALUE\n"},
15781646
}

compile/make_compile_test.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,13 @@
130130
('''raise''', "exec"),
131131
('''raise a''', "exec"),
132132
('''raise a from b''', "exec"),
133-
133+
# if
134+
('''if a: b = c''', "exec"),
135+
('''if a:\n b = c\nelse:\n c = d\n''', "exec"),
136+
# while
137+
('''while a:\n b = c''', "exec"),
138+
('''while a:\n b = c\nelse:\n b = d\n''', "exec"),
139+
# FIXME break
134140

135141
]
136142

0 commit comments

Comments
 (0)