Skip to content

Commit ae2d3c2

Browse files
author
rocky
committed
Something weird happened...
Some code in byteop3{3,5} got deleted. Reinstate that.
1 parent 3e08206 commit ae2d3c2

File tree

3 files changed

+128
-20
lines changed

3 files changed

+128
-20
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ dist: clean
3636

3737
#: Remove .pyc files
3838
clean_pyc:
39-
( cd x-python && $(RM) -f *.pyc */*.pyc )
39+
( cd xpython && $(RM) -f *.pyc */*.pyc )
40+
( cd tests && $(RM) -f *.pyc */*.pyc )
4041

4142
#: Create source tarball
4243
sdist:

xpython/byteop/byteop33.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import print_function, division
44

55

6+
from xpython.pyobj import Function
67
from xpython.byteop.byteop27 import ByteOp27
78
from xpython.byteop.byteop25 import ByteOp25
89

@@ -27,6 +28,55 @@ def __init__(self, vm):
2728
self.vm = vm
2829
self.version = 3.3
2930

31+
# Changed from 2.7
32+
# 3.3 has kwdefaults that aren't allowed in 2.7
33+
def MAKE_FUNCTION(self, argc):
34+
"""
35+
Pushes a new function object on the stack. From bottom to top, the consumed stack must consist of:
36+
37+
* argc & 0xFF default argument objects in positional order
38+
* (argc >> 8) & 0xFF pairs of name and default argument, with the name just below the object on the stack, for keyword-only parameters
39+
* (argc >> 16) & 0x7FFF parameter annotation objects
40+
* a tuple listing the parameter names for the annotations (only if there are ony annotation objects)
41+
* the code associated with the function (at TOS1)
42+
* the qualified name of the function (at TOS)
43+
"""
44+
rest, default_count = divmod(argc, 256)
45+
annotate_count, kw_default_count = divmod(rest, 256)
46+
47+
name = self.vm.pop()
48+
code = self.vm.pop()
49+
if annotate_count:
50+
annotate_names = self.vm.pop()
51+
# annotate count includes +1 for the above names
52+
annotate_objects = self.vm.popn(annotate_count - 1)
53+
n = len(annotate_names)
54+
assert n == len(annotate_objects)
55+
annotations = {annotate_names[i]:annotate_objects[i] for i in range(n)}
56+
else:
57+
annotations = {}
58+
59+
if kw_default_count:
60+
kw_default_pairs = self.vm.popn(2 * kw_default_count)
61+
kwdefaults = dict(kw_default_pairs[i:i+2] for i in range(0, len(kw_default_pairs), 2))
62+
else:
63+
kwdefaults = {}
64+
65+
if default_count:
66+
defaults = self.vm.popn(default_count)
67+
else:
68+
defaults = tuple()
69+
70+
globs = self.vm.frame.f_globals
71+
72+
fn = Function(name, code, globs, defaults,
73+
closure=None,
74+
vm = self.vm,
75+
kwdefaults=kwdefaults,
76+
annotations=annotations)
77+
fn.version = self.version
78+
self.vm.push(fn)
79+
3080
# Order of function here is the same as in:
3181
# https://docs.python.org/3.3/library/dis.html#python-bytecode-instructions
3282

xpython/byteop/byteop35.py

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
"""
33
from __future__ import print_function, division
44

5-
import inspect
6-
import types
7-
85
from xpython.byteop.byteop25 import ByteOp25
96
from xpython.byteop.byteop33 import ByteOp33
107
from xpython.byteop.byteop34 import ByteOp34
@@ -77,31 +74,91 @@ def BUILD_MAP_UNPACK_WITH_CALL(self, oparg):
7774
mappings, the relative position of the corresponding callable
7875
f is encoded in the second byte of oparg.
7976
"""
80-
arg, count = divmod(arg, 256)
77+
arg, count = divmod(oparg, 256)
8178
elts = self.vm.popn(count)
8279
kwargs = {k:v for m in elts for k, v in m.items()}
8380
# FIXME: This is probably not right
8481
self.vm.call_function(arg, 0, kwargs)
8582

8683

87-
def GET_AITER(self):
88-
raise self.VirtualMachineError("GET_AITER not implemented yet")
84+
def GET_AITER(self):
85+
raise self.VirtualMachineError("GET_AITER not implemented yet")
86+
87+
def GET_ANEXT(self):
88+
raise self.VirtualMachineError("GET_ANEXT not implemented yet")
89+
90+
def BEFORE_ASYNC_WITH(self):
91+
raise self.VirtualMachineError("BEFORE_ASYNC_WITH not implemented yet")
92+
return
8993

90-
def GET_ANEXT(self):
91-
raise self.VirtualMachineError("GET_ANEXT not implemented yet")
94+
def GET_YIELD_FROM_ITER(self):
95+
raise self.VirtualMachineError("GET_YIELD_FROM_ITER not implemented yet")
9296

93-
def BEFORE_ASYNC_WITH(self):
94-
raise self.VirtualMachineError("BEFORE_ASYNC_WITH not implemented yet")
95-
return
97+
def GET_AWAITABLE(self):
98+
raise self.VirtualMachineError("GET_AWAITABLE not implemented yet")
9699

97-
def GET_YIELD_FROM_ITER(self):
98-
raise self.VirtualMachineError("GET_YIELD_FROM_ITER not implemented yet")
100+
def WITH_CLEANUP_START(self):
101+
"""Cleans up the stack when a with statement block exits.
99102
100-
def GET_AWAITABLE(self):
101-
raise self.VirtualMachineError("GET_AWAITABLE not implemented yet")
103+
TOS is the context manager’s __exit__() bound method. Below
104+
TOS are 1–3 values indicating how/why the finally clause was
105+
entered:
102106
103-
def WITH_CLEANUP_START(self):
104-
raise self.VirtualMachineError("WITH_CLEANUP_START not implemented yet")
107+
* SECOND = None
108+
* (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval
109+
* SECOND = WHY_*; no retval below it
110+
* (SECOND, THIRD, FOURTH) = exc_info()
105111
106-
def WITH_CLEANUP_FINISH(self):
107-
raise self.VirtualMachineError("WITH_CLEANUP_FINISH not implemented yet")
112+
In the last case, TOS(SECOND, THIRD, FOURTH) is called,
113+
otherwise TOS(None, None, None). Pushes SECOND and result of the call
114+
to the stack. Cleans up the stack when a `with` statement block
115+
exits. TOS is the context manager's `__exit__()` bound method.
116+
"""
117+
second = third = fourth = None
118+
TOS = self.vm.top()
119+
if TOS is None:
120+
exit_func = self.vm.pop(1)
121+
elif isinstance(TOS, str):
122+
# FIXME: This code does something funky with pushing "continue"
123+
# See the comment under CONTINUE_LOOP.
124+
# jump addresses on the frame stack. As a result, we need to
125+
# set up here something to make END_FINALLY work and remove
126+
# the jump address. This means that the comment or semantics
127+
# described above isn't strictly correct.
128+
if TOS in ("return", "continue"):
129+
exit_func = self.vm.pop(2)
130+
second = TOS
131+
else:
132+
exit_func = self.vm.pop(1)
133+
second = None
134+
elif issubclass(TOS, BaseException):
135+
fourth, third, second = self.vm.popn(3)
136+
tp, exc, tb = self.vm.popn(3)
137+
self.vm.push(None)
138+
self.vm.push(fourth, third, second)
139+
block = self.vm.pop_block()
140+
assert block.type == "except-handler"
141+
self.vm.push_block(block.type, block.handler, block.level - 1)
142+
else:
143+
pass
144+
exit_ret = exit_func(second, third, fourth)
145+
self.vm.push(exit_ret)
146+
self.vm.push(second)
147+
148+
def WITH_CLEANUP_FINISH(self):
149+
"""Pops exception type and result of "exit" function call from the stack.
150+
151+
If the stack represents an exception, and the function call
152+
returns a ‘true’ value, this information is "zapped" and
153+
replaced with a single WHY_SILENCED to prevent END_FINALLY
154+
from re-raising the exception. (But non-local gotos will still
155+
be resumed.)
156+
"""
157+
# FIXME: Not sure what this is supposed to be
158+
exit_ret = self.vm.pop(1)
159+
if bool(exit_ret):
160+
# An error occurred, and was suppressed
161+
self.vm.push("silenced")
162+
else:
163+
self.vm.pop(1)
164+
pass

0 commit comments

Comments
 (0)