Skip to content

Commit abdccce

Browse files
committed
compile,py: fix closure
1 parent 7102b79 commit abdccce

File tree

6 files changed

+125
-32
lines changed

6 files changed

+125
-32
lines changed

compile/compile.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018 The go-python Authors. All rights reserved.
1+
// Copyright 2023 The go-python Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

@@ -214,12 +214,16 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
214214
panic("suite should not be possible")
215215
case *ast.Lambda:
216216
// Make None the first constant as lambda can't have a docstring
217+
code.Argcount = int32(len(node.Args.Args))
218+
code.Kwonlyargcount = int32(len(node.Args.Kwonlyargs))
217219
c.Const(py.None)
218220
code.Name = "<lambda>"
219221
c.setQualname()
220222
c.Expr(node.Body)
221223
valueOnStack = true
222224
case *ast.FunctionDef:
225+
code.Argcount = int32(len(node.Args.Args))
226+
code.Kwonlyargcount = int32(len(node.Args.Kwonlyargs))
223227
code.Name = string(node.Name)
224228
c.setQualname()
225229
c.Stmts(c.docString(node.Body, true))
@@ -295,10 +299,23 @@ func (c *compiler) compileAst(Ast ast.Ast, filename string, futureFlags int, don
295299
}
296300
c.Op(vm.RETURN_VALUE)
297301
}
298-
code.Code = c.OpCodes.Assemble()
299-
code.Stacksize = int32(c.OpCodes.StackDepth())
300-
code.Nlocals = int32(len(code.Varnames))
301-
code.Lnotab = string(c.OpCodes.Lnotab())
302+
c.Code = py.MakeCode(
303+
code.Argcount,
304+
code.Kwonlyargcount,
305+
int32(len(code.Varnames)),
306+
int32(c.OpCodes.StackDepth()),
307+
code.Flags,
308+
c.OpCodes.Assemble(),
309+
code.Consts,
310+
code.Names,
311+
code.Varnames,
312+
code.Freevars,
313+
code.Cellvars,
314+
filename,
315+
code.Name,
316+
code.Firstlineno,
317+
string(c.OpCodes.Lnotab()),
318+
)
302319
return nil
303320
}
304321

py/code.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018 The go-python Authors. All rights reserved.
1+
// Copyright 2023 The go-python Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

@@ -112,8 +112,6 @@ func NewCode(argcount int32, kwonlyargcount int32,
112112
filename_ Object, name_ Object, firstlineno int32,
113113
lnotab_ Object) *Code {
114114

115-
var cell2arg []byte
116-
117115
// Type assert the objects
118116
consts := consts_.(Tuple)
119117
namesTuple := names_.(Tuple)
@@ -154,7 +152,6 @@ func NewCode(argcount int32, kwonlyargcount int32,
154152
// return nil;
155153
// }
156154

157-
n_cellvars := len(cellvars)
158155
intern_strings(namesTuple)
159156
intern_strings(varnamesTuple)
160157
intern_strings(freevarsTuple)
@@ -167,6 +164,38 @@ func NewCode(argcount int32, kwonlyargcount int32,
167164
}
168165
}
169166
}
167+
168+
return MakeCode(argcount,
169+
kwonlyargcount,
170+
nlocals,
171+
stacksize,
172+
flags,
173+
code,
174+
consts,
175+
names,
176+
varnames,
177+
freevars,
178+
cellvars,
179+
filename,
180+
name,
181+
firstlineno,
182+
lnotab)
183+
}
184+
185+
// Make a new code object
186+
func MakeCode(argcount int32, kwonlyargcount int32,
187+
nlocals int32, stacksize int32, flags int32,
188+
code string, consts_ Object, names []string,
189+
varnames []string, freevars []string, cellvars []string,
190+
filename string, name string, firstlineno int32,
191+
lnotab string) *Code {
192+
193+
var cell2arg []byte
194+
195+
// Type assert the objects
196+
consts := consts_.(Tuple)
197+
198+
n_cellvars := len(cellvars)
170199
/* Create mapping between cells and arguments if needed. */
171200
if n_cellvars != 0 {
172201
total_args := argcount + kwonlyargcount

vm/tests/class.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,16 @@ def method1(self, x):
4747
c = x()
4848
assert c.method1(1) == 2
4949

50-
# FIXME doesn't work
51-
# doc="CLASS_DEREF2"
52-
# def classderef2(x):
53-
# class DeRefTest:
54-
# VAR = x
55-
# def method1(self, x):
56-
# "method1"
57-
# return self.VAR+x
58-
# return DeRefTest
59-
# x = classderef2(1)
60-
# c = x()
61-
# assert c.method1(1) == 2
50+
doc="CLASS_DEREF2"
51+
def classderef2(x):
52+
class DeRefTest:
53+
VAR = x
54+
def method1(self, x):
55+
"method1"
56+
return self.VAR+x
57+
return DeRefTest
58+
x = classderef2(1)
59+
c = x()
60+
assert c.method1(1) == 2
6261

6362
doc="finished"

vm/tests/functions.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@ def fn2(x,y=1):
2222

2323
# Closure
2424

25-
# FIXME something wrong with closures over function arguments...
26-
# doc="counter3"
27-
# def counter3(x):
28-
# def inc():
29-
# nonlocal x
30-
# x += 1
31-
# return x
32-
# return inc
33-
# fn3 = counter3(1)
34-
# assert fn3() == 2
35-
# assert fn3() == 3
25+
doc="counter3"
26+
def counter3(x):
27+
def inc():
28+
nonlocal x
29+
x += 1
30+
return x
31+
return inc
32+
fn3 = counter3(1)
33+
assert fn3() == 2
34+
assert fn3() == 3
3635

3736
doc="counter4"
3837
def counter4(initial):

vm/tests2/closure.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# temp file
2+
3+
doc="closure"
4+
def closure(x):
5+
def inc():
6+
nonlocal x
7+
x += 1
8+
return x
9+
return inc
10+
fn3 = closure(1)
11+
assert fn3() == 2
12+
assert fn3() == 3
13+
14+
doc="CLASS_DEREF2"
15+
def classderef2(x):
16+
class DeRefTest:
17+
VAR = x
18+
def method1(self, x):
19+
"method1"
20+
return self.VAR+x
21+
return DeRefTest
22+
x = classderef2(1)
23+
c = x()
24+
assert c.method1(1) == 2
25+
26+
doc="decorator"
27+
28+
def decorator(func):
29+
def warp(*args, **kwargs):
30+
print('before called')
31+
func(*args, **kwargs)
32+
print('after called')
33+
return warp
34+
35+
@decorator
36+
def func():
37+
print('my called')
38+
39+
func()
40+
# before called
41+
# my called
42+
# after called
43+
44+
doc="finished"

vm/vm_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ func TestVm(t *testing.T) {
1919
pytest.RunTests(t, "tests")
2020
}
2121

22+
func TestVm2(t *testing.T) {
23+
// TODO(wetor) temp test
24+
pytest.RunTests(t, "tests2")
25+
}
26+
2227
func BenchmarkVM(b *testing.B) {
2328
pytest.RunBenchmarks(b, "benchmarks")
2429
}

0 commit comments

Comments
 (0)