Skip to content

Commit 99c3f74

Browse files
committed
compile: make decorators for functions work
1 parent 7686a57 commit 99c3f74

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

compile/compile.go

+11
Original file line numberDiff line numberDiff line change
@@ -459,10 +459,21 @@ func (c *compiler) compileFunc(Ast ast.Ast, Args *ast.Arguments, DecoratorList [
459459
c.LoadConst(annotations)
460460
}
461461

462+
// Load decorators onto stack
463+
for _, expr := range DecoratorList {
464+
c.Expr(expr)
465+
}
466+
467+
// Make function or closure, leaving it on the stack
462468
posdefaults := uint32(len(Args.Defaults))
463469
kwdefaults := uint32(len(Args.KwDefaults))
464470
args := uint32(posdefaults + (kwdefaults << 8) + (num_annotations << 16))
465471
c.makeClosure(code, args, newC)
472+
473+
// Call decorators
474+
for _ = range DecoratorList {
475+
c.OpArg(vm.CALL_FUNCTION, 1) // 1 positional, 0 keyword pair
476+
}
466477
}
467478

468479
// Compile statement

compile/compile_data_test.go

+115
Original file line numberDiff line numberDiff line change
@@ -2576,4 +2576,119 @@ var compileTestData = []struct {
25762576
Firstlineno: 1,
25772577
Lnotab: "",
25782578
}, nil, ""},
2579+
{"@wrap\ndef fn(o):\n return o", "exec", &py.Code{
2580+
Argcount: 0,
2581+
Kwonlyargcount: 0,
2582+
Nlocals: 0,
2583+
Stacksize: 3,
2584+
Flags: 64,
2585+
Code: "\x65\x00\x00\x64\x00\x00\x64\x01\x00\x84\x00\x00\x83\x01\x00\x5a\x01\x00\x64\x02\x00\x53",
2586+
Consts: []py.Object{&py.Code{
2587+
Argcount: 1,
2588+
Kwonlyargcount: 0,
2589+
Nlocals: 1,
2590+
Stacksize: 1,
2591+
Flags: 67,
2592+
Code: "\x7c\x00\x00\x53",
2593+
Consts: []py.Object{py.None},
2594+
Names: []string{},
2595+
Varnames: []string{"o"},
2596+
Freevars: []string{},
2597+
Cellvars: []string{},
2598+
Filename: "<string>",
2599+
Name: "fn",
2600+
Firstlineno: 1,
2601+
Lnotab: "\x00\x02",
2602+
}, py.String("fn"), py.None},
2603+
Names: []string{"wrap", "fn"},
2604+
Varnames: []string{},
2605+
Freevars: []string{},
2606+
Cellvars: []string{},
2607+
Filename: "<string>",
2608+
Name: "<module>",
2609+
Firstlineno: 1,
2610+
Lnotab: "",
2611+
}, nil, ""},
2612+
{"@wrap1\n@wrap2(\"potato\", 2)\n@wrap3(\"sausage\")\n@wrap4\ndef fn(o):\n return o", "exec", &py.Code{
2613+
Argcount: 0,
2614+
Kwonlyargcount: 0,
2615+
Nlocals: 0,
2616+
Stacksize: 6,
2617+
Flags: 64,
2618+
Code: "\x65\x00\x00\x65\x01\x00\x64\x00\x00\x64\x01\x00\x83\x02\x00\x65\x02\x00\x64\x02\x00\x83\x01\x00\x65\x03\x00\x64\x03\x00\x64\x04\x00\x84\x00\x00\x83\x01\x00\x83\x01\x00\x83\x01\x00\x83\x01\x00\x5a\x04\x00\x64\x05\x00\x53",
2619+
Consts: []py.Object{py.String("potato"), py.Int(2), py.String("sausage"), &py.Code{
2620+
Argcount: 1,
2621+
Kwonlyargcount: 0,
2622+
Nlocals: 1,
2623+
Stacksize: 1,
2624+
Flags: 67,
2625+
Code: "\x7c\x00\x00\x53",
2626+
Consts: []py.Object{py.None},
2627+
Names: []string{},
2628+
Varnames: []string{"o"},
2629+
Freevars: []string{},
2630+
Cellvars: []string{},
2631+
Filename: "<string>",
2632+
Name: "fn",
2633+
Firstlineno: 1,
2634+
Lnotab: "\x00\x05",
2635+
}, py.String("fn"), py.None},
2636+
Names: []string{"wrap1", "wrap2", "wrap3", "wrap4", "fn"},
2637+
Varnames: []string{},
2638+
Freevars: []string{},
2639+
Cellvars: []string{},
2640+
Filename: "<string>",
2641+
Name: "<module>",
2642+
Firstlineno: 1,
2643+
Lnotab: "\x03\x01\x0c\x01\x09\x01",
2644+
}, nil, ""},
2645+
{"def outer(o):\n @wrap1\n @wrap2(\"potato\", o)\n def inner(i):\n return o+i", "exec", &py.Code{
2646+
Argcount: 0,
2647+
Kwonlyargcount: 0,
2648+
Nlocals: 0,
2649+
Stacksize: 2,
2650+
Flags: 64,
2651+
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
2652+
Consts: []py.Object{&py.Code{
2653+
Argcount: 1,
2654+
Kwonlyargcount: 0,
2655+
Nlocals: 2,
2656+
Stacksize: 5,
2657+
Flags: 3,
2658+
Code: "\x74\x00\x00\x74\x01\x00\x64\x01\x00\x88\x00\x00\x83\x02\x00\x87\x00\x00\x66\x01\x00\x64\x02\x00\x64\x03\x00\x86\x00\x00\x83\x01\x00\x83\x01\x00\x7d\x01\x00\x64\x00\x00\x53",
2659+
Consts: []py.Object{py.None, py.String("potato"), &py.Code{
2660+
Argcount: 1,
2661+
Kwonlyargcount: 0,
2662+
Nlocals: 1,
2663+
Stacksize: 2,
2664+
Flags: 19,
2665+
Code: "\x88\x00\x00\x7c\x00\x00\x17\x53",
2666+
Consts: []py.Object{py.None},
2667+
Names: []string{},
2668+
Varnames: []string{"i"},
2669+
Freevars: []string{"o"},
2670+
Cellvars: []string{},
2671+
Filename: "<string>",
2672+
Name: "inner",
2673+
Firstlineno: 2,
2674+
Lnotab: "\x00\x03",
2675+
}, py.String("outer.<locals>.inner")},
2676+
Names: []string{"wrap1", "wrap2"},
2677+
Varnames: []string{"o", "inner"},
2678+
Freevars: []string{},
2679+
Cellvars: []string{"o"},
2680+
Filename: "<string>",
2681+
Name: "outer",
2682+
Firstlineno: 1,
2683+
Lnotab: "\x00\x01\x03\x01",
2684+
}, py.String("outer"), py.None},
2685+
Names: []string{"outer"},
2686+
Varnames: []string{},
2687+
Freevars: []string{},
2688+
Cellvars: []string{},
2689+
Filename: "<string>",
2690+
Name: "<module>",
2691+
Firstlineno: 1,
2692+
Lnotab: "",
2693+
}, nil, ""},
25792694
}

compile/make_compile_test.py

+17
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,23 @@ def inner2(s):
193193
def outer(o):
194194
x = 17
195195
return lambda a,b=42,*args,**kw: a*b*args*kw*x*o''', "exec"),
196+
('''\
197+
@wrap
198+
def fn(o):
199+
return o''', "exec"),
200+
('''\
201+
@wrap1
202+
@wrap2("potato", 2)
203+
@wrap3("sausage")
204+
@wrap4
205+
def fn(o):
206+
return o''', "exec"),
207+
('''\
208+
def outer(o):
209+
@wrap1
210+
@wrap2("potato", o)
211+
def inner(i):
212+
return o+i''', "exec"),
196213
]
197214

198215
def string(s):

0 commit comments

Comments
 (0)