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