OILS / opy / _regtest / src / opy / byterun / pyvm2.py View on Github | oilshell.org

1066 lines, 792 significant
1"""A pure-Python Python bytecode interpreter."""
2# Based on:
3# pyvm2 by Paul Swartz (z3p), from http://www.twistedmatrix.com/users/z3p/
4
5from __future__ import print_function, division
6import dis
7import inspect
8import linecache
9import logging
10import operator
11import sys
12import types
13
14import six
15from six.moves import reprlib
16
17PY3, PY2 = six.PY3, not six.PY3
18
19from pyobj import Frame, Block, Method, Function, Generator
20
21log = logging.getLogger(__name__)
22
23# Create a repr that won't overflow.
24repr_obj = reprlib.Repr()
25repr_obj.maxother = 120
26repper = repr_obj.repr
27
28
29class VirtualMachineError(Exception):
30 """For raising errors in the operation of the VM."""
31 pass
32
33
34class VirtualMachine(object):
35 def __init__(self):
36 # The call stack of frames.
37 self.frames = []
38 # The current frame.
39 self.frame = None
40 self.return_value = None
41 self.last_exception = None
42
43 def top(self):
44 """Return the value at the top of the stack, with no changes."""
45 return self.frame.stack[-1]
46
47 def pop(self, i=0):
48 """Pop a value from the stack.
49
50 Default to the top of the stack, but `i` can be a count from the top
51 instead.
52
53 """
54 return self.frame.stack.pop(-1-i)
55
56 def push(self, *vals):
57 """Push values onto the value stack."""
58 self.frame.stack.extend(vals)
59
60 def popn(self, n):
61 """Pop a number of values from the value stack.
62
63 A list of `n` values is returned, the deepest value first.
64
65 """
66 if n:
67 ret = self.frame.stack[-n:]
68 self.frame.stack[-n:] = []
69 return ret
70 else:
71 return []
72
73 def peek(self, n):
74 """Get a value `n` entries down in the stack, without changing the stack."""
75 return self.frame.stack[-n]
76
77 def jump(self, jump):
78 """Move the bytecode pointer to `jump`, so it will execute next."""
79 self.frame.f_lasti = jump
80
81 def push_block(self, type, handler=None, level=None):
82 if level is None:
83 level = len(self.frame.stack)
84 self.frame.block_stack.append(Block(type, handler, level))
85
86 def pop_block(self):
87 return self.frame.block_stack.pop()
88
89 def make_frame(self, code, callargs={}, f_globals=None, f_locals=None):
90 log.info("make_frame: code=%r, callargs=%s" % (code, repper(callargs)))
91 if f_globals is not None:
92 f_globals = f_globals
93 if f_locals is None:
94 f_locals = f_globals
95 elif self.frames:
96 f_globals = self.frame.f_globals
97 f_locals = {}
98 else:
99 f_globals = f_locals = {
100 '__builtins__': __builtins__,
101 '__name__': '__main__',
102 '__doc__': None,
103 '__package__': None,
104 }
105 f_locals.update(callargs)
106 frame = Frame(code, f_globals, f_locals, self.frame)
107 return frame
108
109 def push_frame(self, frame):
110 self.frames.append(frame)
111 self.frame = frame
112
113 def pop_frame(self):
114 self.frames.pop()
115 if self.frames:
116 self.frame = self.frames[-1]
117 else:
118 self.frame = None
119
120 def print_frames(self):
121 """Print the call stack, for debugging."""
122 for f in self.frames:
123 filename = f.f_code.co_filename
124 lineno = f.line_number()
125 print(' File "%s", line %d, in %s' % (
126 filename, lineno, f.f_code.co_name
127 ))
128 linecache.checkcache(filename)
129 line = linecache.getline(filename, lineno, f.f_globals)
130 if line:
131 print(' ' + line.strip())
132
133 def resume_frame(self, frame):
134 frame.f_back = self.frame
135 val = self.run_frame(frame)
136 frame.f_back = None
137 return val
138
139 def run_code(self, code, f_globals=None, f_locals=None):
140 frame = self.make_frame(code, f_globals=f_globals, f_locals=f_locals)
141 val = self.run_frame(frame)
142 # Check some invariants
143 if self.frames: # pragma: no cover
144 raise VirtualMachineError("Frames left over!")
145 if self.frame and self.frame.stack: # pragma: no cover
146 raise VirtualMachineError("Data left on stack! %r" % self.frame.stack)
147
148 return val
149
150 def unwind_block(self, block):
151 if block.type == 'except-handler':
152 offset = 3
153 else:
154 offset = 0
155
156 while len(self.frame.stack) > block.level + offset:
157 self.pop()
158
159 if block.type == 'except-handler':
160 tb, value, exctype = self.popn(3)
161 self.last_exception = exctype, value, tb
162
163 def parse_byte_and_args(self):
164 """ Parse 1 - 3 bytes of bytecode into
165 an instruction and optionally arguments."""
166 f = self.frame
167 opoffset = f.f_lasti
168 byteCode = ord(f.f_code.co_code[opoffset])
169 f.f_lasti += 1
170 byteName = dis.opname[byteCode]
171 arg = None
172 arguments = []
173 if byteCode >= dis.HAVE_ARGUMENT:
174 arg = f.f_code.co_code[f.f_lasti:f.f_lasti+2]
175 f.f_lasti += 2
176 intArg = ord(arg[0]) + (ord(arg[1]) << 8)
177 if byteCode in dis.hasconst:
178 arg = f.f_code.co_consts[intArg]
179 elif byteCode in dis.hasfree:
180 if intArg < len(f.f_code.co_cellvars):
181 arg = f.f_code.co_cellvars[intArg]
182 else:
183 var_idx = intArg - len(f.f_code.co_cellvars)
184 arg = f.f_code.co_freevars[var_idx]
185 elif byteCode in dis.hasname:
186 arg = f.f_code.co_names[intArg]
187 elif byteCode in dis.hasjrel:
188 arg = f.f_lasti + intArg
189 elif byteCode in dis.hasjabs:
190 arg = intArg
191 elif byteCode in dis.haslocal:
192 arg = f.f_code.co_varnames[intArg]
193 else:
194 arg = intArg
195 arguments = [arg]
196
197 return byteName, arguments, opoffset
198
199 def log(self, byteName, arguments, opoffset):
200 """ Log arguments, block stack, and data stack for each opcode."""
201 op = "%d: %s" % (opoffset, byteName)
202 if arguments:
203 op += " %r" % (arguments[0],)
204 indent = " "*(len(self.frames)-1)
205 stack_rep = repper(self.frame.stack)
206 block_stack_rep = repper(self.frame.block_stack)
207
208 log.info(" %sdata: %s" % (indent, stack_rep))
209 log.info(" %sblks: %s" % (indent, block_stack_rep))
210 log.info("%s%s" % (indent, op))
211
212 def dispatch(self, byteName, arguments):
213 """ Dispatch by bytename to the corresponding methods.
214 Exceptions are caught and set on the virtual machine."""
215 why = None
216 try:
217 if byteName.startswith('UNARY_'):
218 self.unaryOperator(byteName[6:])
219 elif byteName.startswith('BINARY_'):
220 self.binaryOperator(byteName[7:])
221 elif byteName.startswith('INPLACE_'):
222 self.inplaceOperator(byteName[8:])
223 elif 'SLICE+' in byteName:
224 self.sliceOperator(byteName)
225 else:
226 # dispatch
227 bytecode_fn = getattr(self, 'byte_%s' % byteName, None)
228 if not bytecode_fn: # pragma: no cover
229 raise VirtualMachineError(
230 "unknown bytecode type: %s" % byteName
231 )
232 why = bytecode_fn(*arguments)
233
234 except:
235 # deal with exceptions encountered while executing the op.
236 self.last_exception = sys.exc_info()[:2] + (None,)
237 log.info("Caught exception during execution")
238 why = 'exception'
239
240 return why
241
242 def manage_block_stack(self, why):
243 """ Manage a frame's block stack.
244 Manipulate the block stack and data stack for looping,
245 exception handling, or returning."""
246 assert why != 'yield'
247
248 block = self.frame.block_stack[-1]
249 if block.type == 'loop' and why == 'continue':
250 self.jump(self.return_value)
251 why = None
252 return why
253
254 self.pop_block()
255 self.unwind_block(block)
256
257 if block.type == 'loop' and why == 'break':
258 why = None
259 self.jump(block.handler)
260 return why
261
262 if PY2:
263 if (
264 block.type == 'finally' or
265 (block.type == 'setup-except' and why == 'exception') or
266 block.type == 'with'
267 ):
268 if why == 'exception':
269 exctype, value, tb = self.last_exception
270 self.push(tb, value, exctype)
271 else:
272 if why in ('return', 'continue'):
273 self.push(self.return_value)
274 self.push(why)
275
276 why = None
277 self.jump(block.handler)
278 return why
279
280 elif PY3:
281 if (
282 why == 'exception' and
283 block.type in ['setup-except', 'finally']
284 ):
285 self.push_block('except-handler')
286 exctype, value, tb = self.last_exception
287 self.push(tb, value, exctype)
288 # PyErr_Normalize_Exception goes here
289 self.push(tb, value, exctype)
290 why = None
291 self.jump(block.handler)
292 return why
293
294 elif block.type == 'finally':
295 if why in ('return', 'continue'):
296 self.push(self.return_value)
297 self.push(why)
298
299 why = None
300 self.jump(block.handler)
301 return why
302
303 return why
304
305
306 def run_frame(self, frame):
307 """Run a frame until it returns (somehow).
308
309 Exceptions are raised, the return value is returned.
310
311 """
312 self.push_frame(frame)
313 num_ticks = 0
314 while True:
315 num_ticks += 1
316 byteName, arguments, opoffset = self.parse_byte_and_args()
317 if log.isEnabledFor(logging.INFO):
318 self.log(byteName, arguments, opoffset)
319
320 # When unwinding the block stack, we need to keep track of why we
321 # are doing it.
322 why = self.dispatch(byteName, arguments)
323 if why == 'exception':
324 # TODO: ceval calls PyTraceBack_Here, not sure what that does.
325 pass
326
327 if why == 'reraise':
328 why = 'exception'
329
330 if why != 'yield':
331 while why and frame.block_stack:
332 # Deal with any block management we need to do.
333 why = self.manage_block_stack(why)
334
335 if why:
336 break
337
338 # TODO: handle generator exception state
339
340 self.pop_frame()
341
342 if why == 'exception':
343 # Hm there is no third traceback part of the tuple?
344 #print('GOT', self.last_exception)
345 six.reraise(*self.last_exception)
346 # How to raise with_traceback? Is that Python 3 only?
347 #raise self.last_exception
348
349 #print('num_ticks: %d' % num_ticks)
350 return self.return_value
351
352 ## Stack manipulation
353
354 def byte_LOAD_CONST(self, const):
355 self.push(const)
356
357 def byte_POP_TOP(self):
358 self.pop()
359
360 def byte_DUP_TOP(self):
361 self.push(self.top())
362
363 def byte_DUP_TOPX(self, count):
364 items = self.popn(count)
365 for i in [1, 2]:
366 self.push(*items)
367
368 def byte_DUP_TOP_TWO(self):
369 # Py3 only
370 a, b = self.popn(2)
371 self.push(a, b, a, b)
372
373 def byte_ROT_TWO(self):
374 a, b = self.popn(2)
375 self.push(b, a)
376
377 def byte_ROT_THREE(self):
378 a, b, c = self.popn(3)
379 self.push(c, a, b)
380
381 def byte_ROT_FOUR(self):
382 a, b, c, d = self.popn(4)
383 self.push(d, a, b, c)
384
385 ## Names
386
387 def byte_LOAD_NAME(self, name):
388 frame = self.frame
389 if name in frame.f_locals:
390 val = frame.f_locals[name]
391 elif name in frame.f_globals:
392 val = frame.f_globals[name]
393 elif name in frame.f_builtins:
394 val = frame.f_builtins[name]
395 else:
396 raise NameError("name '%s' is not defined" % name)
397 self.push(val)
398
399 def byte_STORE_NAME(self, name):
400 self.frame.f_locals[name] = self.pop()
401
402 def byte_DELETE_NAME(self, name):
403 del self.frame.f_locals[name]
404
405 def byte_LOAD_FAST(self, name):
406 if name in self.frame.f_locals:
407 val = self.frame.f_locals[name]
408 else:
409 raise UnboundLocalError(
410 "local variable '%s' referenced before assignment" % name
411 )
412 self.push(val)
413
414 def byte_STORE_FAST(self, name):
415 self.frame.f_locals[name] = self.pop()
416
417 def byte_DELETE_FAST(self, name):
418 del self.frame.f_locals[name]
419
420 def byte_LOAD_GLOBAL(self, name):
421 f = self.frame
422 if name in f.f_globals:
423 val = f.f_globals[name]
424 elif name in f.f_builtins:
425 val = f.f_builtins[name]
426 else:
427 raise NameError("global name '%s' is not defined" % name)
428 self.push(val)
429
430 def byte_STORE_GLOBAL(self, name):
431 f = self.frame
432 f.f_globals[name] = self.pop()
433
434 def byte_LOAD_DEREF(self, name):
435 self.push(self.frame.cells[name].get())
436
437 def byte_STORE_DEREF(self, name):
438 self.frame.cells[name].set(self.pop())
439
440 def byte_LOAD_LOCALS(self):
441 self.push(self.frame.f_locals)
442
443 ## Operators
444
445 UNARY_OPERATORS = {
446 'POSITIVE': operator.pos,
447 'NEGATIVE': operator.neg,
448 'NOT': operator.not_,
449 'CONVERT': repr,
450 'INVERT': operator.invert,
451 }
452
453 def unaryOperator(self, op):
454 x = self.pop()
455 self.push(self.UNARY_OPERATORS[op](x))
456
457 BINARY_OPERATORS = {
458 'POWER': pow,
459 'MULTIPLY': operator.mul,
460 'DIVIDE': getattr(operator, 'div', lambda x, y: None),
461 'FLOOR_DIVIDE': operator.floordiv,
462 'TRUE_DIVIDE': operator.truediv,
463 'MODULO': operator.mod,
464 'ADD': operator.add,
465 'SUBTRACT': operator.sub,
466 'SUBSCR': operator.getitem,
467 'LSHIFT': operator.lshift,
468 'RSHIFT': operator.rshift,
469 'AND': operator.and_,
470 'XOR': operator.xor,
471 'OR': operator.or_,
472 }
473
474 def binaryOperator(self, op):
475 x, y = self.popn(2)
476 self.push(self.BINARY_OPERATORS[op](x, y))
477
478 def inplaceOperator(self, op):
479 x, y = self.popn(2)
480 if op == 'POWER':
481 x **= y
482 elif op == 'MULTIPLY':
483 x *= y
484 elif op in ['DIVIDE', 'FLOOR_DIVIDE']:
485 x //= y
486 elif op == 'TRUE_DIVIDE':
487 x /= y
488 elif op == 'MODULO':
489 x %= y
490 elif op == 'ADD':
491 x += y
492 elif op == 'SUBTRACT':
493 x -= y
494 elif op == 'LSHIFT':
495 x <<= y
496 elif op == 'RSHIFT':
497 x >>= y
498 elif op == 'AND':
499 x &= y
500 elif op == 'XOR':
501 x ^= y
502 elif op == 'OR':
503 x |= y
504 else: # pragma: no cover
505 raise VirtualMachineError("Unknown in-place operator: %r" % op)
506 self.push(x)
507
508 def sliceOperator(self, op):
509 start = 0
510 end = None # we will take this to mean end
511 op, count = op[:-2], int(op[-1])
512 if count == 1:
513 start = self.pop()
514 elif count == 2:
515 end = self.pop()
516 elif count == 3:
517 end = self.pop()
518 start = self.pop()
519 l = self.pop()
520 if end is None:
521 end = len(l)
522 if op.startswith('STORE_'):
523 l[start:end] = self.pop()
524 elif op.startswith('DELETE_'):
525 del l[start:end]
526 else:
527 self.push(l[start:end])
528
529 COMPARE_OPERATORS = [
530 operator.lt,
531 operator.le,
532 operator.eq,
533 operator.ne,
534 operator.gt,
535 operator.ge,
536 lambda x, y: x in y,
537 lambda x, y: x not in y,
538 lambda x, y: x is y,
539 lambda x, y: x is not y,
540 lambda x, y: issubclass(x, Exception) and issubclass(x, y),
541 ]
542
543 def byte_COMPARE_OP(self, opnum):
544 x, y = self.popn(2)
545 self.push(self.COMPARE_OPERATORS[opnum](x, y))
546
547 ## Attributes and indexing
548
549 def byte_LOAD_ATTR(self, attr):
550 obj = self.pop()
551 val = getattr(obj, attr)
552 self.push(val)
553
554 def byte_STORE_ATTR(self, name):
555 val, obj = self.popn(2)
556 setattr(obj, name, val)
557
558 def byte_DELETE_ATTR(self, name):
559 obj = self.pop()
560 delattr(obj, name)
561
562 def byte_STORE_SUBSCR(self):
563 val, obj, subscr = self.popn(3)
564 obj[subscr] = val
565
566 def byte_DELETE_SUBSCR(self):
567 obj, subscr = self.popn(2)
568 del obj[subscr]
569
570 ## Building
571
572 def byte_BUILD_TUPLE(self, count):
573 elts = self.popn(count)
574 self.push(tuple(elts))
575
576 def byte_BUILD_LIST(self, count):
577 elts = self.popn(count)
578 self.push(elts)
579
580 def byte_BUILD_SET(self, count):
581 # TODO: Not documented in Py2 docs.
582 elts = self.popn(count)
583 self.push(set(elts))
584
585 def byte_BUILD_MAP(self, size):
586 # size is ignored.
587 self.push({})
588
589 def byte_STORE_MAP(self):
590 the_map, val, key = self.popn(3)
591 the_map[key] = val
592 self.push(the_map)
593
594 def byte_UNPACK_SEQUENCE(self, count):
595 seq = self.pop()
596 for x in reversed(seq):
597 self.push(x)
598
599 def byte_BUILD_SLICE(self, count):
600 if count == 2:
601 x, y = self.popn(2)
602 self.push(slice(x, y))
603 elif count == 3:
604 x, y, z = self.popn(3)
605 self.push(slice(x, y, z))
606 else: # pragma: no cover
607 raise VirtualMachineError("Strange BUILD_SLICE count: %r" % count)
608
609 def byte_LIST_APPEND(self, count):
610 val = self.pop()
611 the_list = self.peek(count)
612 the_list.append(val)
613
614 def byte_SET_ADD(self, count):
615 val = self.pop()
616 the_set = self.peek(count)
617 the_set.add(val)
618
619 def byte_MAP_ADD(self, count):
620 val, key = self.popn(2)
621 the_map = self.peek(count)
622 the_map[key] = val
623
624 ## Printing
625
626 if 0: # Only used in the interactive interpreter, not in modules.
627 def byte_PRINT_EXPR(self):
628 print(self.pop())
629
630 def byte_PRINT_ITEM(self):
631 item = self.pop()
632 self.print_item(item)
633
634 def byte_PRINT_ITEM_TO(self):
635 to = self.pop()
636 item = self.pop()
637 self.print_item(item, to)
638
639 def byte_PRINT_NEWLINE(self):
640 self.print_newline()
641
642 def byte_PRINT_NEWLINE_TO(self):
643 to = self.pop()
644 self.print_newline(to)
645
646 def print_item(self, item, to=None):
647 if to is None:
648 to = sys.stdout
649 if to.softspace:
650 print(" ", end="", file=to)
651 to.softspace = 0
652 print(item, end="", file=to)
653 if isinstance(item, str):
654 if (not item) or (not item[-1].isspace()) or (item[-1] == " "):
655 to.softspace = 1
656 else:
657 to.softspace = 1
658
659 def print_newline(self, to=None):
660 if to is None:
661 to = sys.stdout
662 print("", file=to)
663 to.softspace = 0
664
665 ## Jumps
666
667 def byte_JUMP_FORWARD(self, jump):
668 self.jump(jump)
669
670 def byte_JUMP_ABSOLUTE(self, jump):
671 self.jump(jump)
672
673 if 0: # Not in py2.7
674 def byte_JUMP_IF_TRUE(self, jump):
675 val = self.top()
676 if val:
677 self.jump(jump)
678
679 def byte_JUMP_IF_FALSE(self, jump):
680 val = self.top()
681 if not val:
682 self.jump(jump)
683
684 def byte_POP_JUMP_IF_TRUE(self, jump):
685 val = self.pop()
686 if val:
687 self.jump(jump)
688
689 def byte_POP_JUMP_IF_FALSE(self, jump):
690 val = self.pop()
691 if not val:
692 self.jump(jump)
693
694 def byte_JUMP_IF_TRUE_OR_POP(self, jump):
695 val = self.top()
696 if val:
697 self.jump(jump)
698 else:
699 self.pop()
700
701 def byte_JUMP_IF_FALSE_OR_POP(self, jump):
702 val = self.top()
703 if not val:
704 self.jump(jump)
705 else:
706 self.pop()
707
708 ## Blocks
709
710 def byte_SETUP_LOOP(self, dest):
711 self.push_block('loop', dest)
712
713 def byte_GET_ITER(self):
714 self.push(iter(self.pop()))
715
716 def byte_FOR_ITER(self, jump):
717 iterobj = self.top()
718 try:
719 v = next(iterobj)
720 self.push(v)
721 except StopIteration:
722 self.pop()
723 self.jump(jump)
724
725 def byte_BREAK_LOOP(self):
726 return 'break'
727
728 def byte_CONTINUE_LOOP(self, dest):
729 # This is a trick with the return value.
730 # While unrolling blocks, continue and return both have to preserve
731 # state as the finally blocks are executed. For continue, it's
732 # where to jump to, for return, it's the value to return. It gets
733 # pushed on the stack for both, so continue puts the jump destination
734 # into return_value.
735 self.return_value = dest
736 return 'continue'
737
738 def byte_SETUP_EXCEPT(self, dest):
739 self.push_block('setup-except', dest)
740
741 def byte_SETUP_FINALLY(self, dest):
742 self.push_block('finally', dest)
743
744 def byte_END_FINALLY(self):
745 v = self.pop()
746 if isinstance(v, str):
747 why = v
748 if why in ('return', 'continue'):
749 self.return_value = self.pop()
750 if why == 'silenced': # PY3
751 block = self.pop_block()
752 assert block.type == 'except-handler'
753 self.unwind_block(block)
754 why = None
755 elif v is None:
756 why = None
757 elif issubclass(v, BaseException):
758 exctype = v
759 val = self.pop()
760 tb = self.pop()
761 self.last_exception = (exctype, val, tb)
762 why = 'reraise'
763 else: # pragma: no cover
764 raise VirtualMachineError("Confused END_FINALLY")
765 return why
766
767 def byte_POP_BLOCK(self):
768 self.pop_block()
769
770 if PY2:
771 def byte_RAISE_VARARGS(self, argc):
772 # NOTE: the dis docs are completely wrong about the order of the
773 # operands on the stack!
774 exctype = val = tb = None
775 if argc == 0:
776 exctype, val, tb = self.last_exception
777 elif argc == 1:
778 exctype = self.pop()
779 elif argc == 2:
780 val = self.pop()
781 exctype = self.pop()
782 elif argc == 3:
783 tb = self.pop()
784 val = self.pop()
785 exctype = self.pop()
786
787 # There are a number of forms of "raise", normalize them somewhat.
788 if isinstance(exctype, BaseException):
789 val = exctype
790 exctype = type(val)
791
792 self.last_exception = (exctype, val, tb)
793
794 if tb:
795 return 'reraise'
796 else:
797 return 'exception'
798
799 elif PY3:
800 def byte_RAISE_VARARGS(self, argc):
801 cause = exc = None
802 if argc == 2:
803 cause = self.pop()
804 exc = self.pop()
805 elif argc == 1:
806 exc = self.pop()
807 return self.do_raise(exc, cause)
808
809 def do_raise(self, exc, cause):
810 if exc is None: # reraise
811 exc_type, val, tb = self.last_exception
812 if exc_type is None:
813 return 'exception' # error
814 else:
815 return 'reraise'
816
817 elif type(exc) == type:
818 # As in `raise ValueError`
819 exc_type = exc
820 val = exc() # Make an instance.
821 elif isinstance(exc, BaseException):
822 # As in `raise ValueError('foo')`
823 exc_type = type(exc)
824 val = exc
825 else:
826 return 'exception' # error
827
828 # If you reach this point, you're guaranteed that
829 # val is a valid exception instance and exc_type is its class.
830 # Now do a similar thing for the cause, if present.
831 if cause:
832 if type(cause) == type:
833 cause = cause()
834 elif not isinstance(cause, BaseException):
835 return 'exception' # error
836
837 val.__cause__ = cause
838
839 self.last_exception = exc_type, val, val.__traceback__
840 return 'exception'
841
842 def byte_POP_EXCEPT(self):
843 block = self.pop_block()
844 if block.type != 'except-handler':
845 raise Exception("popped block is not an except handler")
846 self.unwind_block(block)
847
848 def byte_SETUP_WITH(self, dest):
849 ctxmgr = self.pop()
850 self.push(ctxmgr.__exit__)
851 ctxmgr_obj = ctxmgr.__enter__()
852 if PY2:
853 self.push_block('with', dest)
854 elif PY3:
855 self.push_block('finally', dest)
856 self.push(ctxmgr_obj)
857
858 def byte_WITH_CLEANUP(self):
859 # The code here does some weird stack manipulation: the exit function
860 # is buried in the stack, and where depends on what's on top of it.
861 # Pull out the exit function, and leave the rest in place.
862 v = w = None
863 u = self.top()
864 if u is None:
865 exit_func = self.pop(1)
866 elif isinstance(u, str):
867 if u in ('return', 'continue'):
868 exit_func = self.pop(2)
869 else:
870 exit_func = self.pop(1)
871 u = None
872 elif issubclass(u, BaseException):
873 if PY2:
874 w, v, u = self.popn(3)
875 exit_func = self.pop()
876 self.push(w, v, u)
877 elif PY3:
878 w, v, u = self.popn(3)
879 tp, exc, tb = self.popn(3)
880 exit_func = self.pop()
881 self.push(tp, exc, tb)
882 self.push(None)
883 self.push(w, v, u)
884 block = self.pop_block()
885 assert block.type == 'except-handler'
886 self.push_block(block.type, block.handler, block.level-1)
887 else: # pragma: no cover
888 raise VirtualMachineError("Confused WITH_CLEANUP")
889 exit_ret = exit_func(u, v, w)
890 err = (u is not None) and bool(exit_ret)
891 if err:
892 # An error occurred, and was suppressed
893 if PY2:
894 self.popn(3)
895 self.push(None)
896 elif PY3:
897 self.push('silenced')
898
899 ## Functions
900
901 def byte_MAKE_FUNCTION(self, argc):
902 if PY3:
903 name = self.pop()
904 else:
905 name = None
906 code = self.pop()
907 defaults = self.popn(argc)
908 globs = self.frame.f_globals
909 fn = Function(name, code, globs, defaults, None, self)
910 self.push(fn)
911
912 def byte_LOAD_CLOSURE(self, name):
913 self.push(self.frame.cells[name])
914
915 def byte_MAKE_CLOSURE(self, argc):
916 if PY3:
917 # TODO: the py3 docs don't mention this change.
918 name = self.pop()
919 else:
920 name = None
921 closure, code = self.popn(2)
922 defaults = self.popn(argc)
923 globs = self.frame.f_globals
924 fn = Function(name, code, globs, defaults, closure, self)
925 self.push(fn)
926
927 def byte_CALL_FUNCTION(self, arg):
928 return self.call_function(arg, [], {})
929
930 def byte_CALL_FUNCTION_VAR(self, arg):
931 args = self.pop()
932 return self.call_function(arg, args, {})
933
934 def byte_CALL_FUNCTION_KW(self, arg):
935 kwargs = self.pop()
936 return self.call_function(arg, [], kwargs)
937
938 def byte_CALL_FUNCTION_VAR_KW(self, arg):
939 args, kwargs = self.popn(2)
940 return self.call_function(arg, args, kwargs)
941
942 def call_function(self, arg, args, kwargs):
943 lenKw, lenPos = divmod(arg, 256)
944 namedargs = {}
945 for i in range(lenKw):
946 key, val = self.popn(2)
947 namedargs[key] = val
948 namedargs.update(kwargs)
949 posargs = self.popn(lenPos)
950 posargs.extend(args)
951
952 func = self.pop()
953 frame = self.frame
954 if hasattr(func, 'im_func'):
955 # Methods get self as an implicit first parameter.
956 if func.im_self:
957 posargs.insert(0, func.im_self)
958 # The first parameter must be the correct type.
959 if not isinstance(posargs[0], func.im_class):
960 raise TypeError(
961 'unbound method %s() must be called with %s instance '
962 'as first argument (got %s instance instead)' % (
963 func.im_func.func_name,
964 func.im_class.__name__,
965 type(posargs[0]).__name__,
966 )
967 )
968 func = func.im_func
969
970 # BUG FIX: The callable must be a pyobj.Function, not a native Python
971 # function (types.FunctionType). The latter will be executed using the
972 # HOST CPython interpreter rather than the byterun interpreter.
973
974 # Cases:
975 # 1. builtin functions like int(). We want to use the host here.
976 # 2. User-defined functions from this module. These are created with
977 # MAKE_FUNCTION, which properly turns them into pyobj.Function.
978 # 3. User-defined function from another module. These are created with
979 # __import__, which yields a native function.
980
981 if isinstance(func, types.FunctionType):
982 defaults = func.func_defaults or ()
983 byterun_func = Function(
984 func.func_name, func.func_code, func.func_globals,
985 defaults, func.func_closure, self)
986 else:
987 byterun_func = func
988
989 retval = byterun_func(*posargs, **namedargs)
990 self.push(retval)
991
992 def byte_RETURN_VALUE(self):
993 self.return_value = self.pop()
994 if self.frame.generator:
995 self.frame.generator.finished = True
996 return "return"
997
998 def byte_YIELD_VALUE(self):
999 self.return_value = self.pop()
1000 return "yield"
1001
1002 def byte_YIELD_FROM(self):
1003 u = self.pop()
1004 x = self.top()
1005
1006 try:
1007 if not isinstance(x, Generator) or u is None:
1008 # Call next on iterators.
1009 retval = next(x)
1010 else:
1011 retval = x.send(u)
1012 self.return_value = retval
1013 except StopIteration as e:
1014 self.pop()
1015 self.push(e.value)
1016 else:
1017 # YIELD_FROM decrements f_lasti, so that it will be called
1018 # repeatedly until a StopIteration is raised.
1019 self.jump(self.frame.f_lasti - 1)
1020 # Returning "yield" prevents the block stack cleanup code
1021 # from executing, suspending the frame in its current state.
1022 return "yield"
1023
1024 ## Importing
1025
1026 def byte_IMPORT_NAME(self, name):
1027 level, fromlist = self.popn(2)
1028 frame = self.frame
1029 mod = __import__(name, frame.f_globals, frame.f_locals, fromlist, level)
1030 #print('-- IMPORTED %s -> %s' % (name, mod))
1031 self.push(mod)
1032
1033 def byte_IMPORT_STAR(self):
1034 # TODO: this doesn't use __all__ properly.
1035 mod = self.pop()
1036 for attr in dir(mod):
1037 if attr[0] != '_':
1038 self.frame.f_locals[attr] = getattr(mod, attr)
1039
1040 def byte_IMPORT_FROM(self, name):
1041 mod = self.top()
1042 self.push(getattr(mod, name))
1043
1044 ## And the rest...
1045
1046 def byte_EXEC_STMT(self):
1047 stmt, globs, locs = self.popn(3)
1048 six.exec_(stmt, globs, locs)
1049
1050 if PY2:
1051 def byte_BUILD_CLASS(self):
1052 name, bases, methods = self.popn(3)
1053 self.push(type(name, bases, methods))
1054
1055
1056 elif PY3:
1057 def byte_LOAD_BUILD_CLASS(self):
1058 # New in py3
1059 self.push(__build_class__)
1060
1061 def byte_STORE_LOCALS(self):
1062 self.frame.f_locals = self.pop()
1063
1064 if 0: # Not in py2.7
1065 def byte_SET_LINENO(self, lineno):
1066 self.frame.f_lineno = lineno