Skip to content

Commit 54f3149

Browse files
committed
compiler: pass, expr statement and assert
1 parent 4826ccc commit 54f3149

File tree

4 files changed

+152
-6
lines changed

4 files changed

+152
-6
lines changed

compile/compile.go

+24-5
Original file line numberDiff line numberDiff line change
@@ -111,24 +111,34 @@ func CompileAst(Ast ast.Ast, filename string, flags int, dont_inherit bool) *py.
111111
c := &compiler{
112112
Code: code,
113113
}
114+
valueOnStack := false
114115
switch node := Ast.(type) {
115116
case *ast.Module:
116117
c.Stmts(node.Body)
117118
case *ast.Interactive:
118119
c.Stmts(node.Body)
119120
case *ast.Expression:
120121
c.Expr(node.Body)
122+
valueOnStack = true
121123
case *ast.Suite:
122124
c.Stmts(node.Body)
123125
case ast.Expr:
124126
// Make None the first constant so lambda can't have a docstring
125127
c.Code.Name = "<lambda>"
126128
c.Const(py.None) // FIXME extra None for some reason in Consts
127129
c.Expr(node)
130+
valueOnStack = true
128131
default:
129132
panic(py.ExceptionNewf(py.SyntaxError, "Unknown ModuleBase: %v", Ast))
130133
}
131-
c.Op(vm.RETURN_VALUE)
134+
if !c.OpCodes.EndsWithReturn() {
135+
// add a return
136+
if !valueOnStack {
137+
// return None if there is nothing on the stack
138+
c.OpArg(vm.LOAD_CONST, c.Const(py.None))
139+
}
140+
c.Op(vm.RETURN_VALUE)
141+
}
132142
code.Code = c.OpCodes.Assemble()
133143
code.Stacksize = int32(c.OpCodes.StackDepth())
134144
return code
@@ -223,7 +233,6 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
223233
// DecoratorList []Expr
224234
// Returns Expr
225235
panic("FIXME compile: FunctionDef not implemented")
226-
_ = node
227236
case *ast.ClassDef:
228237
// Name Identifier
229238
// Bases []Expr
@@ -281,7 +290,16 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
281290
case *ast.Assert:
282291
// Test Expr
283292
// Msg Expr
284-
panic("FIXME compile: Assert not implemented")
293+
label := new(Label)
294+
c.Expr(node.Test)
295+
c.Jump(vm.POP_JUMP_IF_TRUE, label)
296+
c.OpArg(vm.LOAD_GLOBAL, c.Name("AssertionError"))
297+
if node.Msg != nil {
298+
c.Expr(node.Msg)
299+
c.OpArg(vm.CALL_FUNCTION, 1) // 1 positional, 0 keyword pair
300+
}
301+
c.OpArg(vm.RAISE_VARARGS, 1)
302+
c.Label(label)
285303
case *ast.Import:
286304
// Names []*Alias
287305
panic("FIXME compile: Import not implemented")
@@ -298,9 +316,10 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
298316
panic("FIXME compile: Nonlocal not implemented")
299317
case *ast.ExprStmt:
300318
// Value Expr
301-
panic("FIXME compile: ExprStmt not implemented")
319+
c.Expr(node.Value)
320+
c.Op(vm.POP_TOP)
302321
case *ast.Pass:
303-
// No nothing
322+
// Do nothing
304323
case *ast.Break:
305324
panic("FIXME compile: Break not implemented")
306325
case *ast.Continue:

compile/compile_data_test.go

+103-1
Original file line numberDiff line numberDiff line change
@@ -1149,5 +1149,107 @@ var compileTestData = []struct {
11491149
Name: "<module>",
11501150
Firstlineno: 1,
11511151
Lnotab: "",
1152-
}, " 1 0 LOAD_CONST 0 (<code object <lambda> at 0x7f70f3cb5e40, 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 0x7fb0bc2ece40, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('<lambda>')\n 6 MAKE_FUNCTION 0\n 9 RETURN_VALUE\n"},
1153+
{"pass", "exec", &py.Code{
1154+
Argcount: 0,
1155+
Kwonlyargcount: 0,
1156+
Nlocals: 0,
1157+
Stacksize: 1,
1158+
Flags: 64,
1159+
Code: "\x64\x00\x00\x53",
1160+
Consts: []py.Object{py.None},
1161+
Names: []string{},
1162+
Varnames: []string{},
1163+
Freevars: []string{},
1164+
Cellvars: []string{},
1165+
Filename: "<string>",
1166+
Name: "<module>",
1167+
Firstlineno: 1,
1168+
Lnotab: "",
1169+
}, " 1 0 LOAD_CONST 0 (None)\n 3 RETURN_VALUE\n"},
1170+
{"(a+b)", "exec", &py.Code{
1171+
Argcount: 0,
1172+
Kwonlyargcount: 0,
1173+
Nlocals: 0,
1174+
Stacksize: 2,
1175+
Flags: 64,
1176+
Code: "\x65\x00\x00\x65\x01\x00\x17\x01\x64\x00\x00\x53",
1177+
Consts: []py.Object{py.None},
1178+
Names: []string{"a", "b"},
1179+
Varnames: []string{},
1180+
Freevars: []string{},
1181+
Cellvars: []string{},
1182+
Filename: "<string>",
1183+
Name: "<module>",
1184+
Firstlineno: 1,
1185+
Lnotab: "",
1186+
}, " 1 0 LOAD_NAME 0 (a)\n 3 LOAD_NAME 1 (b)\n 6 BINARY_ADD\n 7 POP_TOP\n 8 LOAD_CONST 0 (None)\n 11 RETURN_VALUE\n"},
1187+
{"assert a, \"hello\"", "exec", &py.Code{
1188+
Argcount: 0,
1189+
Kwonlyargcount: 0,
1190+
Nlocals: 0,
1191+
Stacksize: 2,
1192+
Flags: 64,
1193+
Code: "\x65\x00\x00\x73\x12\x00\x74\x01\x00\x64\x00\x00\x83\x01\x00\x82\x01\x00\x64\x01\x00\x53",
1194+
Consts: []py.Object{py.String("hello"), py.None},
1195+
Names: []string{"a", "AssertionError"},
1196+
Varnames: []string{},
1197+
Freevars: []string{},
1198+
Cellvars: []string{},
1199+
Filename: "<string>",
1200+
Name: "<module>",
1201+
Firstlineno: 1,
1202+
Lnotab: "",
1203+
}, " 1 0 LOAD_NAME 0 (a)\n 3 POP_JUMP_IF_TRUE 18\n 6 LOAD_GLOBAL 1 (AssertionError)\n 9 LOAD_CONST 0 ('hello')\n 12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)\n 15 RAISE_VARARGS 1\n >> 18 LOAD_CONST 1 (None)\n 21 RETURN_VALUE\n"},
1204+
{"assert 1, 2", "exec", &py.Code{
1205+
Argcount: 0,
1206+
Kwonlyargcount: 0,
1207+
Nlocals: 0,
1208+
Stacksize: 2,
1209+
Flags: 64,
1210+
Code: "\x64\x00\x00\x73\x12\x00\x74\x00\x00\x64\x01\x00\x83\x01\x00\x82\x01\x00\x64\x02\x00\x53",
1211+
Consts: []py.Object{py.Int(1), py.Int(2), py.None},
1212+
Names: []string{"AssertionError"},
1213+
Varnames: []string{},
1214+
Freevars: []string{},
1215+
Cellvars: []string{},
1216+
Filename: "<string>",
1217+
Name: "<module>",
1218+
Firstlineno: 1,
1219+
Lnotab: "",
1220+
}, " 1 0 LOAD_CONST 0 (1)\n 3 POP_JUMP_IF_TRUE 18\n 6 LOAD_GLOBAL 0 (AssertionError)\n 9 LOAD_CONST 1 (2)\n 12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)\n 15 RAISE_VARARGS 1\n >> 18 LOAD_CONST 2 (None)\n 21 RETURN_VALUE\n"},
1221+
{"assert a", "exec", &py.Code{
1222+
Argcount: 0,
1223+
Kwonlyargcount: 0,
1224+
Nlocals: 0,
1225+
Stacksize: 1,
1226+
Flags: 64,
1227+
Code: "\x65\x00\x00\x73\x0c\x00\x74\x01\x00\x82\x01\x00\x64\x00\x00\x53",
1228+
Consts: []py.Object{py.None},
1229+
Names: []string{"a", "AssertionError"},
1230+
Varnames: []string{},
1231+
Freevars: []string{},
1232+
Cellvars: []string{},
1233+
Filename: "<string>",
1234+
Name: "<module>",
1235+
Firstlineno: 1,
1236+
Lnotab: "",
1237+
}, " 1 0 LOAD_NAME 0 (a)\n 3 POP_JUMP_IF_TRUE 12\n 6 LOAD_GLOBAL 1 (AssertionError)\n 9 RAISE_VARARGS 1\n >> 12 LOAD_CONST 0 (None)\n 15 RETURN_VALUE\n"},
1238+
{"assert 1", "exec", &py.Code{
1239+
Argcount: 0,
1240+
Kwonlyargcount: 0,
1241+
Nlocals: 0,
1242+
Stacksize: 1,
1243+
Flags: 64,
1244+
Code: "\x64\x00\x00\x73\x0c\x00\x74\x00\x00\x82\x01\x00\x64\x01\x00\x53",
1245+
Consts: []py.Object{py.Int(1), py.None},
1246+
Names: []string{"AssertionError"},
1247+
Varnames: []string{},
1248+
Freevars: []string{},
1249+
Cellvars: []string{},
1250+
Filename: "<string>",
1251+
Name: "<module>",
1252+
Firstlineno: 1,
1253+
Lnotab: "",
1254+
}, " 1 0 LOAD_CONST 0 (1)\n 3 POP_JUMP_IF_TRUE 12\n 6 LOAD_GLOBAL 0 (AssertionError)\n 9 RAISE_VARARGS 1\n >> 12 LOAD_CONST 1 (None)\n 15 RETURN_VALUE\n"},
11531255
}

compile/instructions.go

+14
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ done:
5353
return string(out)
5454
}
5555

56+
// EndsWithReturn returns true if the instruction stream ends with a
57+
// RETURN_VALUE
58+
func (is Instructions) EndsWithReturn() bool {
59+
if len(is) == 0 {
60+
return false
61+
}
62+
last := is[len(is)-1]
63+
op, ok := last.(*Op)
64+
if !ok {
65+
return false
66+
}
67+
return op.Op == vm.RETURN_VALUE
68+
}
69+
5670
// Calculate number of arguments for CALL_FUNCTION etc
5771
func nArgs(o uint32) int {
5872
return (int(o) & 0xFF) + 2*((int(o)>>8)&0xFF)

compile/make_compile_test.py

+11
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,17 @@
9494
# lambda
9595
('''lambda: 0''', "eval"),
9696
#('''lambda x: 2*x''', "eval"),
97+
# pass statment
98+
('''pass''', "exec"),
99+
# expr statement
100+
('''(a+b)''', "exec"),
101+
#('''(a+\nb+\nc)\n''', "exec"),
102+
# assert
103+
('''assert a, "hello"''', "exec"),
104+
('''assert 1, 2''', "exec"),
105+
('''assert a''', "exec"),
106+
('''assert 1''', "exec"),
107+
97108
]
98109

99110
def string(s):

0 commit comments

Comments
 (0)