Skip to content

Commit 0707033

Browse files
committed
Add a few more opcodes
1 parent 5fce7b9 commit 0707033

File tree

3 files changed

+37
-18
lines changed

3 files changed

+37
-18
lines changed

byterun/pyobj.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ def set(self, value):
142142
class Frame(object):
143143
def __init__(self, f_code, f_globals, f_locals, f_closure, f_back):
144144
self.f_code = f_code
145-
self.py36_opcodes = list(dis.get_instructions(self.f_code)) \
146-
if six.PY3 and sys.version_info.minor >= 6 else None
145+
if sys.version_info[:2] >= (3, 4):
146+
self.opcodes = list(dis.get_instructions(self.f_code))
147147
self.f_globals = f_globals
148148
self.f_locals = f_locals
149149
self.f_back = f_back

byterun/pyvm2.py

+34-15
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ def parse_byte_and_args(self):
171171
In Python3.6 the format is 2 bytes per instruction."""
172172
f = self.frame
173173
opoffset = f.f_lasti
174-
if f.py36_opcodes:
175-
currentOp = f.py36_opcodes[opoffset]
174+
if sys.version_info >= (3, 6):
175+
currentOp = f.opcodes[opoffset]
176176
byteCode = currentOp.opcode
177177
byteName = currentOp.opname
178178
else:
@@ -181,7 +181,7 @@ def parse_byte_and_args(self):
181181
f.f_lasti += 1
182182
arg = None
183183
arguments = []
184-
if f.py36_opcodes and byteCode == dis.EXTENDED_ARG:
184+
if sys.version_info >= (3, 6) and byteCode == dis.EXTENDED_ARG:
185185
# Prefixes any opcode which has an argument too big to fit into the
186186
# default two bytes. ext holds two additional bytes which, taken
187187
# together with the subsequent opcode’s argument, comprise a
@@ -191,7 +191,7 @@ def parse_byte_and_args(self):
191191
# Lib/dis.py:_unpack_opargs
192192
return self.parse_byte_and_args()
193193
if byteCode >= dis.HAVE_ARGUMENT:
194-
if f.py36_opcodes:
194+
if sys.version_info >= (3, 6):
195195
intArg = currentOp.arg
196196
else:
197197
arg = f.f_code.co_code[f.f_lasti:f.f_lasti+2]
@@ -208,12 +208,12 @@ def parse_byte_and_args(self):
208208
elif byteCode in dis.hasname:
209209
arg = f.f_code.co_names[intArg]
210210
elif byteCode in dis.hasjrel:
211-
if f.py36_opcodes:
211+
if sys.version_info >= (3, 6):
212212
arg = f.f_lasti + intArg//2
213213
else:
214214
arg = f.f_lasti + intArg
215215
elif byteCode in dis.hasjabs:
216-
if f.py36_opcodes:
216+
if sys.version_info >= (3, 6):
217217
arg = intArg//2
218218
else:
219219
arg = intArg
@@ -598,30 +598,49 @@ def byte_BUILD_TUPLE_UNPACK_WITH_CALL(self, count):
598598
# This is similar to BUILD_TUPLE_UNPACK, but is used for f(*x, *y, *z)
599599
# call syntax. The stack item at position count + 1 should be the
600600
# corresponding callable f.
601-
self.byte_BUILD_TUPLE_UNPACK(count)
602-
601+
self.build_container_flat(count, tuple)
603602

604603
def byte_BUILD_TUPLE_UNPACK(self, count):
605604
# Pops count iterables from the stack, joins them in a single tuple,
606605
# and pushes the result. Implements iterable unpacking in
607606
# tuple displays (*x, *y, *z).
608-
elts = self.popn(count)
609-
self.push(tuple(e for l in elts for e in l))
607+
self.build_container_flat(count, tuple)
610608

611609
def byte_BUILD_TUPLE(self, count):
612-
elts = self.popn(count)
613-
self.push(tuple(elts))
610+
self.build_container(count, tuple)
614611

615612
def byte_BUILD_LIST_UNPACK(self, count):
613+
# This is similar to BUILD_TUPLE_UNPACK, but a list instead of tuple.
614+
# Implements iterable unpacking in list displays [*x, *y, *z].
615+
self.build_container_flat(count, list)
616+
617+
def byte_BUILD_SET_UNPACK(self, count):
618+
# This is similar to BUILD_TUPLE_UNPACK, but a set instead of tuple.
619+
# Implements iterable unpacking in set displays {*x, *y, *z}.
620+
self.build_container_flat(count, set)
621+
622+
def byte_BUILD_MAP_UNPACK(self, count):
623+
# Pops count mappings from the stack, merges them to a single dict,
624+
# and pushes the result. Implements dictionary unpacking in dictionary
625+
# displays {**x, **y, **z}.
626+
self.build_container(count, dict)
627+
628+
def byte_BUILD_MAP_UNPACK_WITH_CALL(self, count):
629+
self.build_container(count, dict)
630+
631+
def build_container_flat(self, count, container_fn) :
632+
elts = self.popn(count)
633+
self.push(container_fn(e for l in elts for e in l))
634+
635+
def build_container(self, count, container_fn) :
616636
elts = self.popn(count)
617-
self.push([e for l in elts for e in l])
637+
self.push(container_fn(elts))
618638

619639
def byte_BUILD_LIST(self, count):
620640
elts = self.popn(count)
621641
self.push(elts)
622642

623643
def byte_BUILD_SET(self, count):
624-
# TODO: Not documented in Py2 docs.
625644
elts = self.popn(count)
626645
self.push(set(elts))
627646

@@ -636,7 +655,7 @@ def byte_BUILD_CONST_KEY_MAP(self, count):
636655

637656
def byte_BUILD_MAP(self, count):
638657
# Pushes a new dictionary on to stack.
639-
if sys.version_info[:2] < (3, 5):
658+
if sys.version_info < (3, 5):
640659
self.push({})
641660
return
642661
# Pop 2*count items so that

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# and then run "tox" from this directory.
55

66
[tox]
7-
envlist = py27, py33, py36
7+
envlist = py27, py33, py34, py36
88

99
[testenv]
1010
commands =

0 commit comments

Comments
 (0)