Skip to content

Commit

Permalink
compile: function definitions without body
Browse files Browse the repository at this point in the history
  • Loading branch information
ncw committed Apr 9, 2015
1 parent a39de11 commit 3079681
Show file tree
Hide file tree
Showing 3 changed files with 313 additions and 2 deletions.
73 changes: 72 additions & 1 deletion compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ func CompileAst(Ast ast.Ast, filename string, flags int, dont_inherit bool) *py.
c.Const(py.None) // FIXME extra None for some reason in Consts
c.Expr(node)
valueOnStack = true
case *ast.FunctionDef:
c.Stmts(node.Body)
default:
panic(py.ExceptionNewf(py.SyntaxError, "Unknown ModuleBase: %v", Ast))
}
Expand Down Expand Up @@ -266,7 +268,76 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
// Body []Stmt
// DecoratorList []Expr
// Returns Expr
panic("FIXME compile: FunctionDef not implemented")
code := CompileAst(node, c.Code.Filename, int(c.Code.Flags)|py.CO_OPTIMIZED|py.CO_NEWLOCALS, false) // FIXME pass on compile args
code.Argcount = int32(len(node.Args.Args))
code.Name = string(node.Name)
code.Kwonlyargcount = int32(len(node.Args.Kwonlyargs))
code.Nlocals = code.Kwonlyargcount + int32(len(node.Args.Args))
if code.Kwonlyargcount > 0 {
code.Flags |= py.CO_VARARGS
}

// Arguments
for _, arg := range node.Args.Args {
code.Varnames = append(code.Varnames, string(arg.Arg))
}
for _, arg := range node.Args.Kwonlyargs {
code.Varnames = append(code.Varnames, string(arg.Arg))
}
if node.Args.Vararg != nil {
code.Nlocals++
code.Varnames = append(code.Varnames, string(node.Args.Vararg.Arg))
}
if node.Args.Kwarg != nil {
code.Nlocals++
code.Varnames = append(code.Varnames, string(node.Args.Kwarg.Arg))
code.Flags |= py.CO_VARKEYWORDS
}

// Defaults
posdefaults := uint32(len(node.Args.Defaults))
for _, expr := range node.Args.Defaults {
c.Expr(expr)
}

// KwDefaults
if len(node.Args.Kwonlyargs) != len(node.Args.KwDefaults) {
panic("differing number of Kwonlyargs to KwDefaults")
}
kwdefaults := uint32(len(node.Args.KwDefaults))
for i := range node.Args.KwDefaults {
c.LoadConst(py.String(node.Args.Kwonlyargs[i].Arg))
c.Expr(node.Args.KwDefaults[i])
}

// Annotations
annotations := py.Tuple{}
addAnnotation := func(args ...*ast.Arg) {
for _, arg := range args {
if arg != nil && arg.Annotation != nil {
c.Expr(arg.Annotation)
annotations = append(annotations, py.String(arg.Arg))
}
}
}
addAnnotation(node.Args.Args...)
addAnnotation(node.Args.Vararg)
addAnnotation(node.Args.Kwonlyargs...)
addAnnotation(node.Args.Kwarg)
if node.Returns != nil {
c.Expr(node.Returns)
annotations = append(annotations, py.String("return"))
}
num_annotations := uint32(len(annotations))
if num_annotations > 0 {
num_annotations++ // include the tuple
c.LoadConst(annotations)
}

c.LoadConst(code)
c.LoadConst(py.String(node.Name))
c.OpArg(vm.MAKE_FUNCTION, posdefaults+(kwdefaults<<8)+(num_annotations<<16))
c.OpArg(vm.STORE_NAME, c.Name(node.Name))
case *ast.ClassDef:
// Name Identifier
// Bases []Expr
Expand Down
233 changes: 232 additions & 1 deletion compile/compile_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ var compileTestData = []struct {
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 (<code object <lambda> at 0x7f94f9f31db0, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('<lambda>')\n 6 MAKE_FUNCTION 0\n 9 RETURN_VALUE\n", nil, ""},
}, " 1 0 LOAD_CONST 0 (<code object <lambda> at 0x7fe734191db0, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('<lambda>')\n 6 MAKE_FUNCTION 0\n 9 RETURN_VALUE\n", nil, ""},
{"pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Expand Down Expand Up @@ -1919,4 +1919,235 @@ var compileTestData = []struct {
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_NAME 0 (f)\n 3 LOAD_NAME 1 (a)\n 6 LOAD_CONST 0 ('d')\n 9 LOAD_NAME 2 (e)\n 12 LOAD_NAME 3 (kwargs)\n 15 CALL_FUNCTION_KW 257 (1 positional, 1 keyword pair)\n 18 RETURN_VALUE\n", nil, ""},
{"def fn(): pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 2,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
Consts: []py.Object{&py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 1,
Flags: 67,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 (<code object fn at 0x7fe7341918a0, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('fn')\n 6 MAKE_FUNCTION 0\n 9 STORE_NAME 0 (fn)\n 12 LOAD_CONST 2 (None)\n 15 RETURN_VALUE\n", nil, ""},
{"def fn(a): pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 2,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
Consts: []py.Object{&py.Code{
Argcount: 1,
Kwonlyargcount: 0,
Nlocals: 1,
Stacksize: 1,
Flags: 67,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{"a"},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 (<code object fn at 0x7fe73567c6f0, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('fn')\n 6 MAKE_FUNCTION 0\n 9 STORE_NAME 0 (fn)\n 12 LOAD_CONST 2 (None)\n 15 RETURN_VALUE\n", nil, ""},
{"def fn(a,b,c): pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 2,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
Consts: []py.Object{&py.Code{
Argcount: 3,
Kwonlyargcount: 0,
Nlocals: 3,
Stacksize: 1,
Flags: 67,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{"a", "b", "c"},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 (<code object fn at 0x7fe734191db0, file \"<string>\", line 1>)\n 3 LOAD_CONST 1 ('fn')\n 6 MAKE_FUNCTION 0\n 9 STORE_NAME 0 (fn)\n 12 LOAD_CONST 2 (None)\n 15 RETURN_VALUE\n", nil, ""},
{"def fn(a,b=1,c=2): pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 4,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x64\x02\x00\x64\x03\x00\x84\x02\x00\x5a\x00\x00\x64\x04\x00\x53",
Consts: []py.Object{py.Int(1), py.Int(2), &py.Code{
Argcount: 3,
Kwonlyargcount: 0,
Nlocals: 3,
Stacksize: 1,
Flags: 67,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{"a", "b", "c"},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 (1)\n 3 LOAD_CONST 1 (2)\n 6 LOAD_CONST 2 (<code object fn at 0x7fe7341b68a0, file \"<string>\", line 1>)\n 9 LOAD_CONST 3 ('fn')\n 12 MAKE_FUNCTION 2\n 15 STORE_NAME 0 (fn)\n 18 LOAD_CONST 4 (None)\n 21 RETURN_VALUE\n", nil, ""},
{"def fn(a,*arg,b=1,c=2): pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 6,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x64\x02\x00\x64\x03\x00\x64\x04\x00\x64\x05\x00\x84\x00\x02\x5a\x00\x00\x64\x06\x00\x53",
Consts: []py.Object{py.String("b"), py.Int(1), py.String("c"), py.Int(2), &py.Code{
Argcount: 1,
Kwonlyargcount: 2,
Nlocals: 4,
Stacksize: 1,
Flags: 71,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{"a", "b", "c", "arg"},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 ('b')\n 3 LOAD_CONST 1 (1)\n 6 LOAD_CONST 2 ('c')\n 9 LOAD_CONST 3 (2)\n 12 LOAD_CONST 4 (<code object fn at 0x7fe7341918a0, file \"<string>\", line 1>)\n 15 LOAD_CONST 5 ('fn')\n 18 MAKE_FUNCTION 512\n 21 STORE_NAME 0 (fn)\n 24 LOAD_CONST 6 (None)\n 27 RETURN_VALUE\n", nil, ""},
{"def fn(a,*arg,b=1,c=2,**kwargs): pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 6,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x64\x02\x00\x64\x03\x00\x64\x04\x00\x64\x05\x00\x84\x00\x02\x5a\x00\x00\x64\x06\x00\x53",
Consts: []py.Object{py.String("b"), py.Int(1), py.String("c"), py.Int(2), &py.Code{
Argcount: 1,
Kwonlyargcount: 2,
Nlocals: 5,
Stacksize: 1,
Flags: 79,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{"a", "b", "c", "arg", "kwargs"},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 ('b')\n 3 LOAD_CONST 1 (1)\n 6 LOAD_CONST 2 ('c')\n 9 LOAD_CONST 3 (2)\n 12 LOAD_CONST 4 (<code object fn at 0x7fe73567c6f0, file \"<string>\", line 1>)\n 15 LOAD_CONST 5 ('fn')\n 18 MAKE_FUNCTION 512\n 21 STORE_NAME 0 (fn)\n 24 LOAD_CONST 6 (None)\n 27 RETURN_VALUE\n", nil, ""},
{"def fn(a:\"a\",*arg:\"arg\",b:\"b\"=1,c:\"c\"=2,**kwargs:\"kw\") -> \"ret\": pass", "exec", &py.Code{
Argcount: 0,
Kwonlyargcount: 0,
Nlocals: 0,
Stacksize: 13,
Flags: 64,
Code: "\x64\x00\x00\x64\x01\x00\x64\x02\x00\x64\x03\x00\x64\x04\x00\x64\x05\x00\x64\x00\x00\x64\x02\x00\x64\x06\x00\x64\x07\x00\x64\x08\x00\x64\x09\x00\x64\x0a\x00\x90\x07\x00\x84\x00\x02\x5a\x00\x00\x64\x0b\x00\x53",
Consts: []py.Object{py.String("b"), py.Int(1), py.String("c"), py.Int(2), py.String("a"), py.String("arg"), py.String("kw"), py.String("ret"), py.Tuple{py.String("a"), py.String("arg"), py.String("b"), py.String("c"), py.String("kwargs"), py.String("return")}, &py.Code{
Argcount: 1,
Kwonlyargcount: 2,
Nlocals: 5,
Stacksize: 1,
Flags: 79,
Code: "\x64\x00\x00\x53",
Consts: []py.Object{py.None},
Names: []string{},
Varnames: []string{"a", "b", "c", "arg", "kwargs"},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "fn",
Firstlineno: 1,
Lnotab: "",
}, py.String("fn"), py.None},
Names: []string{"fn"},
Varnames: []string{},
Freevars: []string{},
Cellvars: []string{},
Filename: "<string>",
Name: "<module>",
Firstlineno: 1,
Lnotab: "",
}, " 1 0 LOAD_CONST 0 ('b')\n 3 LOAD_CONST 1 (1)\n 6 LOAD_CONST 2 ('c')\n 9 LOAD_CONST 3 (2)\n 12 LOAD_CONST 4 ('a')\n 15 LOAD_CONST 5 ('arg')\n 18 LOAD_CONST 0 ('b')\n 21 LOAD_CONST 2 ('c')\n 24 LOAD_CONST 6 ('kw')\n 27 LOAD_CONST 7 ('ret')\n 30 LOAD_CONST 8 (('a', 'arg', 'b', 'c', 'kwargs', 'return'))\n 33 LOAD_CONST 9 (<code object fn at 0x7fe734191db0, file \"<string>\", line 1>)\n 36 LOAD_CONST 10 ('fn')\n 39 EXTENDED_ARG 7\n 42 MAKE_FUNCTION 459264\n 45 STORE_NAME 0 (fn)\n 48 LOAD_CONST 11 (None)\n 51 RETURN_VALUE\n", nil, ""},
}
9 changes: 9 additions & 0 deletions compile/make_compile_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@
('''f(a, b, *args)''', "eval"),
('''f(a, b, *args, d=e, **kwargs)''', "eval"),
('''f(a, d=e, **kwargs)''', "eval"),
# def
('''def fn(): pass''', "exec"),
('''def fn(a): pass''', "exec"),
('''def fn(a,b,c): pass''', "exec"),
('''def fn(a,b=1,c=2): pass''', "exec"),
('''def fn(a,*arg,b=1,c=2): pass''', "exec"),
('''def fn(a,*arg,b=1,c=2,**kwargs): pass''', "exec"),
('''def fn(a:"a",*arg:"arg",b:"b"=1,c:"c"=2,**kwargs:"kw") -> "ret": pass''', "exec"),
#('''def fn(): a+b''', "exec"),

]

Expand Down

0 comments on commit 3079681

Please sign in to comment.