PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/interpreter/pyopcode.py

https://bitbucket.org/varialus/jyjy
Python | 1538 lines | 1296 code | 164 blank | 78 comment | 152 complexity | 955eb8c675811bb15565dee1b1b15ac8 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. """
  2. Implementation of a part of the standard Python opcodes.
  3. The rest, dealing with variables in optimized ways, is in nestedscope.py.
  4. """
  5. import sys
  6. from pypy.interpreter.error import OperationError, operationerrfmt
  7. from pypy.interpreter.baseobjspace import Wrappable
  8. from pypy.interpreter import gateway, function, eval, pyframe, pytraceback
  9. from pypy.interpreter.pycode import PyCode
  10. from pypy.tool.sourcetools import func_with_new_name
  11. from pypy.rlib.objectmodel import we_are_translated
  12. from pypy.rlib import jit, rstackovf
  13. from pypy.rlib.rarithmetic import r_uint, intmask
  14. from pypy.rlib.unroll import unrolling_iterable
  15. from pypy.rlib.debug import check_nonneg
  16. from pypy.tool.stdlib_opcode import (bytecode_spec,
  17. unrolling_all_opcode_descs)
  18. def unaryoperation(operationname):
  19. """NOT_RPYTHON"""
  20. def opimpl(self, *ignored):
  21. operation = getattr(self.space, operationname)
  22. w_1 = self.popvalue()
  23. w_result = operation(w_1)
  24. self.pushvalue(w_result)
  25. opimpl.unaryop = operationname
  26. return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname)
  27. def binaryoperation(operationname):
  28. """NOT_RPYTHON"""
  29. def opimpl(self, *ignored):
  30. operation = getattr(self.space, operationname)
  31. w_2 = self.popvalue()
  32. w_1 = self.popvalue()
  33. w_result = operation(w_1, w_2)
  34. self.pushvalue(w_result)
  35. opimpl.binop = operationname
  36. return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname)
  37. compare_dispatch_table = [
  38. "cmp_lt", # "<"
  39. "cmp_le", # "<="
  40. "cmp_eq", # "=="
  41. "cmp_ne", # "!="
  42. "cmp_gt", # ">"
  43. "cmp_ge", # ">="
  44. "cmp_in",
  45. "cmp_not_in",
  46. "cmp_is",
  47. "cmp_is_not",
  48. "cmp_exc_match",
  49. ]
  50. unrolling_compare_dispatch_table = unrolling_iterable(
  51. enumerate(compare_dispatch_table))
  52. class __extend__(pyframe.PyFrame):
  53. """A PyFrame that knows about interpretation of standard Python opcodes
  54. minus the ones related to nested scopes."""
  55. # for logbytecode:
  56. last_opcode = -1
  57. bytecode_spec = bytecode_spec
  58. opcode_method_names = bytecode_spec.method_names
  59. opcodedesc = bytecode_spec.opcodedesc
  60. opdescmap = bytecode_spec.opdescmap
  61. HAVE_ARGUMENT = bytecode_spec.HAVE_ARGUMENT
  62. ### opcode dispatch ###
  63. def dispatch(self, pycode, next_instr, ec):
  64. # For the sequel, force 'next_instr' to be unsigned for performance
  65. next_instr = r_uint(next_instr)
  66. co_code = pycode.co_code
  67. try:
  68. while True:
  69. next_instr = self.handle_bytecode(co_code, next_instr, ec)
  70. except ExitFrame:
  71. return self.popvalue()
  72. def handle_bytecode(self, co_code, next_instr, ec):
  73. try:
  74. next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  75. except OperationError, operr:
  76. next_instr = self.handle_operation_error(ec, operr)
  77. except Reraise:
  78. operr = self.last_exception
  79. next_instr = self.handle_operation_error(ec, operr,
  80. attach_tb=False)
  81. except RaiseWithExplicitTraceback, e:
  82. next_instr = self.handle_operation_error(ec, e.operr,
  83. attach_tb=False)
  84. except KeyboardInterrupt:
  85. next_instr = self.handle_asynchronous_error(ec,
  86. self.space.w_KeyboardInterrupt)
  87. except MemoryError:
  88. next_instr = self.handle_asynchronous_error(ec,
  89. self.space.w_MemoryError)
  90. except rstackovf.StackOverflow, e:
  91. rstackovf.check_stack_overflow()
  92. w_err = self.space.prebuilt_recursion_error
  93. next_instr = self.handle_operation_error(ec, w_err)
  94. return next_instr
  95. def handle_asynchronous_error(self, ec, w_type, w_value=None):
  96. # catch asynchronous exceptions and turn them
  97. # into OperationErrors
  98. if w_value is None:
  99. w_value = self.space.w_None
  100. operr = OperationError(w_type, w_value)
  101. return self.handle_operation_error(ec, operr)
  102. def handle_operation_error(self, ec, operr, attach_tb=True):
  103. if attach_tb:
  104. if 1:
  105. # xxx this is a hack. It allows bytecode_trace() to
  106. # call a signal handler which raises, and catch the
  107. # raised exception immediately. See test_alarm_raise in
  108. # pypy/module/signal/test/test_signal.py. Without the
  109. # next four lines, if an external call (like
  110. # socket.accept()) is interrupted by a signal, it raises
  111. # an exception carrying EINTR which arrives here,
  112. # entering the next "except" block -- but the signal
  113. # handler is then called on the next call to
  114. # dispatch_bytecode(), causing the real exception to be
  115. # raised after the exception handler block was popped.
  116. try:
  117. trace = self.w_f_trace
  118. if trace is not None:
  119. self.w_f_trace = None
  120. try:
  121. ec.bytecode_trace_after_exception(self)
  122. finally:
  123. if trace is not None:
  124. self.w_f_trace = trace
  125. except OperationError, e:
  126. operr = e
  127. pytraceback.record_application_traceback(
  128. self.space, operr, self, self.last_instr)
  129. ec.exception_trace(self, operr)
  130. block = self.unrollstack(SApplicationException.kind)
  131. if block is None:
  132. # no handler found for the OperationError
  133. if we_are_translated():
  134. raise operr
  135. else:
  136. # try to preserve the CPython-level traceback
  137. import sys
  138. tb = sys.exc_info()[2]
  139. raise OperationError, operr, tb
  140. else:
  141. unroller = SApplicationException(operr)
  142. next_instr = block.handle(self, unroller)
  143. return next_instr
  144. def call_contextmanager_exit_function(self, w_func, w_typ, w_val, w_tb):
  145. return self.space.call_function(w_func, w_typ, w_val, w_tb)
  146. @jit.unroll_safe
  147. def dispatch_bytecode(self, co_code, next_instr, ec):
  148. space = self.space
  149. while True:
  150. self.last_instr = intmask(next_instr)
  151. if not jit.we_are_jitted():
  152. ec.bytecode_trace(self)
  153. next_instr = r_uint(self.last_instr)
  154. opcode = ord(co_code[next_instr])
  155. next_instr += 1
  156. if space.config.objspace.logbytecodes:
  157. space.bytecodecounts[opcode] += 1
  158. try:
  159. probs = space.bytecodetransitioncount[self.last_opcode]
  160. except KeyError:
  161. probs = space.bytecodetransitioncount[self.last_opcode] = {}
  162. probs[opcode] = probs.get(opcode, 0) + 1
  163. self.last_opcode = opcode
  164. if opcode >= self.HAVE_ARGUMENT:
  165. lo = ord(co_code[next_instr])
  166. hi = ord(co_code[next_instr+1])
  167. next_instr += 2
  168. oparg = (hi * 256) | lo
  169. else:
  170. oparg = 0
  171. while opcode == self.opcodedesc.EXTENDED_ARG.index:
  172. opcode = ord(co_code[next_instr])
  173. if opcode < self.HAVE_ARGUMENT:
  174. raise BytecodeCorruption
  175. lo = ord(co_code[next_instr+1])
  176. hi = ord(co_code[next_instr+2])
  177. next_instr += 3
  178. oparg = (oparg * 65536) | (hi * 256) | lo
  179. if opcode == self.opcodedesc.RETURN_VALUE.index:
  180. w_returnvalue = self.popvalue()
  181. block = self.unrollstack(SReturnValue.kind)
  182. if block is None:
  183. self.pushvalue(w_returnvalue) # XXX ping pong
  184. raise Return
  185. else:
  186. unroller = SReturnValue(w_returnvalue)
  187. next_instr = block.handle(self, unroller)
  188. return next_instr # now inside a 'finally' block
  189. if opcode == self.opcodedesc.END_FINALLY.index:
  190. unroller = self.end_finally()
  191. if isinstance(unroller, SuspendedUnroller):
  192. # go on unrolling the stack
  193. block = self.unrollstack(unroller.kind)
  194. if block is None:
  195. w_result = unroller.nomoreblocks()
  196. self.pushvalue(w_result)
  197. raise Return
  198. else:
  199. next_instr = block.handle(self, unroller)
  200. return next_instr
  201. if opcode == self.opcodedesc.JUMP_ABSOLUTE.index:
  202. return self.jump_absolute(oparg, next_instr, ec)
  203. if we_are_translated():
  204. for opdesc in unrolling_all_opcode_descs:
  205. # static checks to skip this whole case if necessary
  206. if opdesc.bytecode_spec is not self.bytecode_spec:
  207. continue
  208. if not opdesc.is_enabled(space):
  209. continue
  210. if opdesc.methodname in (
  211. 'EXTENDED_ARG', 'RETURN_VALUE',
  212. 'END_FINALLY', 'JUMP_ABSOLUTE'):
  213. continue # opcodes implemented above
  214. if opcode == opdesc.index:
  215. # dispatch to the opcode method
  216. meth = getattr(self, opdesc.methodname)
  217. res = meth(oparg, next_instr)
  218. # !! warning, for the annotator the next line is not
  219. # comparing an int and None - you can't do that.
  220. # Instead, it's constant-folded to either True or False
  221. if res is not None:
  222. next_instr = res
  223. break
  224. else:
  225. self.MISSING_OPCODE(oparg, next_instr)
  226. else: # when we are not translated, a list lookup is much faster
  227. methodname = self.opcode_method_names[opcode]
  228. try:
  229. meth = getattr(self, methodname)
  230. except AttributeError:
  231. raise BytecodeCorruption("unimplemented opcode, ofs=%d, "
  232. "code=%d, name=%s" %
  233. (self.last_instr, opcode,
  234. methodname))
  235. try:
  236. res = meth(oparg, next_instr)
  237. except Exception:
  238. if 0:
  239. import dis, sys
  240. print "*** %s at offset %d (%s)" % (sys.exc_info()[0],
  241. self.last_instr,
  242. methodname)
  243. try:
  244. dis.dis(co_code)
  245. except:
  246. pass
  247. raise
  248. if res is not None:
  249. next_instr = res
  250. if jit.we_are_jitted():
  251. return next_instr
  252. @jit.unroll_safe
  253. def unrollstack(self, unroller_kind):
  254. while self.blockstack_non_empty():
  255. block = self.pop_block()
  256. if (block.handling_mask & unroller_kind) != 0:
  257. return block
  258. block.cleanupstack(self)
  259. self.frame_finished_execution = True # for generators
  260. return None
  261. def unrollstack_and_jump(self, unroller):
  262. block = self.unrollstack(unroller.kind)
  263. if block is None:
  264. raise BytecodeCorruption("misplaced bytecode - should not return")
  265. return block.handle(self, unroller)
  266. ### accessor functions ###
  267. def getlocalvarname(self, index):
  268. return self.getcode().co_varnames[index]
  269. def getconstant_w(self, index):
  270. return self.getcode().co_consts_w[index]
  271. def getname_u(self, index):
  272. return self.space.str_w(self.getcode().co_names_w[index])
  273. def getname_w(self, index):
  274. return self.getcode().co_names_w[index]
  275. ################################################################
  276. ## Implementation of the "operational" opcodes
  277. ## See also nestedscope.py for the rest.
  278. ##
  279. def NOP(self, oparg, next_instr):
  280. # annotation-time check: if it fails, it means that the decoding
  281. # of oparg failed to produce an integer which is annotated as non-neg
  282. check_nonneg(oparg)
  283. def LOAD_FAST(self, varindex, next_instr):
  284. # access a local variable directly
  285. w_value = self.locals_stack_w[varindex]
  286. if w_value is None:
  287. self._load_fast_failed(varindex)
  288. self.pushvalue(w_value)
  289. LOAD_FAST._always_inline_ = True
  290. def _load_fast_failed(self, varindex):
  291. varname = self.getlocalvarname(varindex)
  292. message = "local variable '%s' referenced before assignment"
  293. raise operationerrfmt(self.space.w_UnboundLocalError, message, varname)
  294. _load_fast_failed._dont_inline_ = True
  295. def LOAD_CONST(self, constindex, next_instr):
  296. w_const = self.getconstant_w(constindex)
  297. self.pushvalue(w_const)
  298. def STORE_FAST(self, varindex, next_instr):
  299. w_newvalue = self.popvalue()
  300. assert w_newvalue is not None
  301. self.locals_stack_w[varindex] = w_newvalue
  302. def POP_TOP(self, oparg, next_instr):
  303. self.popvalue()
  304. def ROT_TWO(self, oparg, next_instr):
  305. w_1 = self.popvalue()
  306. w_2 = self.popvalue()
  307. self.pushvalue(w_1)
  308. self.pushvalue(w_2)
  309. def ROT_THREE(self, oparg, next_instr):
  310. w_1 = self.popvalue()
  311. w_2 = self.popvalue()
  312. w_3 = self.popvalue()
  313. self.pushvalue(w_1)
  314. self.pushvalue(w_3)
  315. self.pushvalue(w_2)
  316. def ROT_FOUR(self, oparg, next_instr):
  317. w_1 = self.popvalue()
  318. w_2 = self.popvalue()
  319. w_3 = self.popvalue()
  320. w_4 = self.popvalue()
  321. self.pushvalue(w_1)
  322. self.pushvalue(w_4)
  323. self.pushvalue(w_3)
  324. self.pushvalue(w_2)
  325. def DUP_TOP(self, oparg, next_instr):
  326. w_1 = self.peekvalue()
  327. self.pushvalue(w_1)
  328. def DUP_TOPX(self, itemcount, next_instr):
  329. assert 1 <= itemcount <= 5, "limitation of the current interpreter"
  330. self.dupvalues(itemcount)
  331. UNARY_POSITIVE = unaryoperation("pos")
  332. UNARY_NEGATIVE = unaryoperation("neg")
  333. UNARY_NOT = unaryoperation("not_")
  334. UNARY_CONVERT = unaryoperation("repr")
  335. UNARY_INVERT = unaryoperation("invert")
  336. def BINARY_POWER(self, oparg, next_instr):
  337. w_2 = self.popvalue()
  338. w_1 = self.popvalue()
  339. w_result = self.space.pow(w_1, w_2, self.space.w_None)
  340. self.pushvalue(w_result)
  341. BINARY_MULTIPLY = binaryoperation("mul")
  342. BINARY_TRUE_DIVIDE = binaryoperation("truediv")
  343. BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
  344. BINARY_DIVIDE = binaryoperation("div")
  345. # XXX BINARY_DIVIDE must fall back to BINARY_TRUE_DIVIDE with -Qnew
  346. BINARY_MODULO = binaryoperation("mod")
  347. BINARY_ADD = binaryoperation("add")
  348. BINARY_SUBTRACT = binaryoperation("sub")
  349. BINARY_SUBSCR = binaryoperation("getitem")
  350. BINARY_LSHIFT = binaryoperation("lshift")
  351. BINARY_RSHIFT = binaryoperation("rshift")
  352. BINARY_AND = binaryoperation("and_")
  353. BINARY_XOR = binaryoperation("xor")
  354. BINARY_OR = binaryoperation("or_")
  355. def INPLACE_POWER(self, oparg, next_instr):
  356. w_2 = self.popvalue()
  357. w_1 = self.popvalue()
  358. w_result = self.space.inplace_pow(w_1, w_2)
  359. self.pushvalue(w_result)
  360. INPLACE_MULTIPLY = binaryoperation("inplace_mul")
  361. INPLACE_TRUE_DIVIDE = binaryoperation("inplace_truediv")
  362. INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
  363. INPLACE_DIVIDE = binaryoperation("inplace_div")
  364. # XXX INPLACE_DIVIDE must fall back to INPLACE_TRUE_DIVIDE with -Qnew
  365. INPLACE_MODULO = binaryoperation("inplace_mod")
  366. INPLACE_ADD = binaryoperation("inplace_add")
  367. INPLACE_SUBTRACT = binaryoperation("inplace_sub")
  368. INPLACE_LSHIFT = binaryoperation("inplace_lshift")
  369. INPLACE_RSHIFT = binaryoperation("inplace_rshift")
  370. INPLACE_AND = binaryoperation("inplace_and")
  371. INPLACE_XOR = binaryoperation("inplace_xor")
  372. INPLACE_OR = binaryoperation("inplace_or")
  373. def slice(self, w_start, w_end):
  374. w_obj = self.popvalue()
  375. w_result = self.space.getslice(w_obj, w_start, w_end)
  376. self.pushvalue(w_result)
  377. def SLICE_0(self, oparg, next_instr):
  378. self.slice(self.space.w_None, self.space.w_None)
  379. def SLICE_1(self, oparg, next_instr):
  380. w_start = self.popvalue()
  381. self.slice(w_start, self.space.w_None)
  382. def SLICE_2(self, oparg, next_instr):
  383. w_end = self.popvalue()
  384. self.slice(self.space.w_None, w_end)
  385. def SLICE_3(self, oparg, next_instr):
  386. w_end = self.popvalue()
  387. w_start = self.popvalue()
  388. self.slice(w_start, w_end)
  389. def storeslice(self, w_start, w_end):
  390. w_obj = self.popvalue()
  391. w_newvalue = self.popvalue()
  392. self.space.setslice(w_obj, w_start, w_end, w_newvalue)
  393. def STORE_SLICE_0(self, oparg, next_instr):
  394. self.storeslice(self.space.w_None, self.space.w_None)
  395. def STORE_SLICE_1(self, oparg, next_instr):
  396. w_start = self.popvalue()
  397. self.storeslice(w_start, self.space.w_None)
  398. def STORE_SLICE_2(self, oparg, next_instr):
  399. w_end = self.popvalue()
  400. self.storeslice(self.space.w_None, w_end)
  401. def STORE_SLICE_3(self, oparg, next_instr):
  402. w_end = self.popvalue()
  403. w_start = self.popvalue()
  404. self.storeslice(w_start, w_end)
  405. def deleteslice(self, w_start, w_end):
  406. w_obj = self.popvalue()
  407. self.space.delslice(w_obj, w_start, w_end)
  408. def DELETE_SLICE_0(self, oparg, next_instr):
  409. self.deleteslice(self.space.w_None, self.space.w_None)
  410. def DELETE_SLICE_1(self, oparg, next_instr):
  411. w_start = self.popvalue()
  412. self.deleteslice(w_start, self.space.w_None)
  413. def DELETE_SLICE_2(self, oparg, next_instr):
  414. w_end = self.popvalue()
  415. self.deleteslice(self.space.w_None, w_end)
  416. def DELETE_SLICE_3(self, oparg, next_instr):
  417. w_end = self.popvalue()
  418. w_start = self.popvalue()
  419. self.deleteslice(w_start, w_end)
  420. def STORE_SUBSCR(self, oparg, next_instr):
  421. "obj[subscr] = newvalue"
  422. w_subscr = self.popvalue()
  423. w_obj = self.popvalue()
  424. w_newvalue = self.popvalue()
  425. self.space.setitem(w_obj, w_subscr, w_newvalue)
  426. def DELETE_SUBSCR(self, oparg, next_instr):
  427. "del obj[subscr]"
  428. w_subscr = self.popvalue()
  429. w_obj = self.popvalue()
  430. self.space.delitem(w_obj, w_subscr)
  431. def PRINT_EXPR(self, oparg, next_instr):
  432. w_expr = self.popvalue()
  433. print_expr(self.space, w_expr)
  434. def PRINT_ITEM_TO(self, oparg, next_instr):
  435. w_stream = self.popvalue()
  436. w_item = self.popvalue()
  437. if self.space.is_w(w_stream, self.space.w_None):
  438. w_stream = sys_stdout(self.space) # grumble grumble special cases
  439. print_item_to(self.space, w_item, w_stream)
  440. def PRINT_ITEM(self, oparg, next_instr):
  441. w_item = self.popvalue()
  442. print_item(self.space, w_item)
  443. def PRINT_NEWLINE_TO(self, oparg, next_instr):
  444. w_stream = self.popvalue()
  445. if self.space.is_w(w_stream, self.space.w_None):
  446. w_stream = sys_stdout(self.space) # grumble grumble special cases
  447. print_newline_to(self.space, w_stream)
  448. def PRINT_NEWLINE(self, oparg, next_instr):
  449. print_newline(self.space)
  450. def BREAK_LOOP(self, oparg, next_instr):
  451. return self.unrollstack_and_jump(SBreakLoop.singleton)
  452. def CONTINUE_LOOP(self, startofloop, next_instr):
  453. unroller = SContinueLoop(startofloop)
  454. return self.unrollstack_and_jump(unroller)
  455. @jit.unroll_safe
  456. def RAISE_VARARGS(self, nbargs, next_instr):
  457. space = self.space
  458. if nbargs == 0:
  459. frame = self
  460. ec = self.space.getexecutioncontext()
  461. while frame:
  462. if frame.last_exception is not None:
  463. operror = ec._convert_exc(frame.last_exception)
  464. break
  465. frame = frame.f_backref()
  466. else:
  467. raise OperationError(space.w_TypeError,
  468. space.wrap("raise: no active exception to re-raise"))
  469. # re-raise, no new traceback obj will be attached
  470. self.last_exception = operror
  471. raise Reraise
  472. w_value = w_traceback = space.w_None
  473. if nbargs >= 3:
  474. w_traceback = self.popvalue()
  475. if nbargs >= 2:
  476. w_value = self.popvalue()
  477. if 1:
  478. w_type = self.popvalue()
  479. operror = OperationError(w_type, w_value)
  480. operror.normalize_exception(space)
  481. if not space.full_exceptions or space.is_w(w_traceback, space.w_None):
  482. # common case
  483. raise operror
  484. else:
  485. msg = "raise: arg 3 must be a traceback or None"
  486. tb = pytraceback.check_traceback(space, w_traceback, msg)
  487. operror.set_traceback(tb)
  488. # special 3-arguments raise, no new traceback obj will be attached
  489. raise RaiseWithExplicitTraceback(operror)
  490. def LOAD_LOCALS(self, oparg, next_instr):
  491. self.pushvalue(self.w_locals)
  492. def EXEC_STMT(self, oparg, next_instr):
  493. w_locals = self.popvalue()
  494. w_globals = self.popvalue()
  495. w_prog = self.popvalue()
  496. ec = self.space.getexecutioncontext()
  497. flags = ec.compiler.getcodeflags(self.pycode)
  498. w_compile_flags = self.space.wrap(flags)
  499. w_resulttuple = prepare_exec(self.space, self.space.wrap(self), w_prog,
  500. w_globals, w_locals,
  501. w_compile_flags,
  502. self.space.wrap(self.get_builtin()),
  503. self.space.gettypeobject(PyCode.typedef))
  504. w_prog, w_globals, w_locals = self.space.fixedview(w_resulttuple, 3)
  505. plain = (self.w_locals is not None and
  506. self.space.is_w(w_locals, self.w_locals))
  507. if plain:
  508. w_locals = self.getdictscope()
  509. co = self.space.interp_w(eval.Code, w_prog)
  510. co.exec_code(self.space, w_globals, w_locals)
  511. if plain:
  512. self.setdictscope(w_locals)
  513. def POP_BLOCK(self, oparg, next_instr):
  514. block = self.pop_block()
  515. block.cleanup(self) # the block knows how to clean up the value stack
  516. def end_finally(self):
  517. # unlike CPython, there are two statically distinct cases: the
  518. # END_FINALLY might be closing an 'except' block or a 'finally'
  519. # block. In the first case, the stack contains three items:
  520. # [exception type we are now handling]
  521. # [exception value we are now handling]
  522. # [wrapped SApplicationException]
  523. # In the case of a finally: block, the stack contains only one
  524. # item (unlike CPython which can have 1, 2 or 3 items):
  525. # [wrapped subclass of SuspendedUnroller]
  526. w_top = self.popvalue()
  527. # the following logic is a mess for the flow objspace,
  528. # so we hide it specially in the space :-/
  529. if self.space._check_constant_interp_w_or_w_None(SuspendedUnroller, w_top):
  530. # case of a finally: block
  531. unroller = self.space.interpclass_w(w_top)
  532. return unroller
  533. else:
  534. # case of an except: block. We popped the exception type
  535. self.popvalue() # Now we pop the exception value
  536. unroller = self.space.interpclass_w(self.popvalue())
  537. assert unroller is not None
  538. return unroller
  539. def BUILD_CLASS(self, oparg, next_instr):
  540. w_methodsdict = self.popvalue()
  541. w_bases = self.popvalue()
  542. w_name = self.popvalue()
  543. w_metaclass = find_metaclass(self.space, w_bases,
  544. w_methodsdict, self.w_globals,
  545. self.space.wrap(self.get_builtin()))
  546. w_newclass = self.space.call_function(w_metaclass, w_name,
  547. w_bases, w_methodsdict)
  548. self.pushvalue(w_newclass)
  549. def STORE_NAME(self, varindex, next_instr):
  550. varname = self.getname_u(varindex)
  551. w_newvalue = self.popvalue()
  552. self.space.setitem_str(self.w_locals, varname, w_newvalue)
  553. def DELETE_NAME(self, varindex, next_instr):
  554. w_varname = self.getname_w(varindex)
  555. try:
  556. self.space.delitem(self.w_locals, w_varname)
  557. except OperationError, e:
  558. # catch KeyErrors and turn them into NameErrors
  559. if not e.match(self.space, self.space.w_KeyError):
  560. raise
  561. message = "name '%s' is not defined"
  562. raise operationerrfmt(self.space.w_NameError, message,
  563. self.space.str_w(w_varname))
  564. def UNPACK_SEQUENCE(self, itemcount, next_instr):
  565. w_iterable = self.popvalue()
  566. items = self.space.fixedview_unroll(w_iterable, itemcount)
  567. self.pushrevvalues(itemcount, items)
  568. def STORE_ATTR(self, nameindex, next_instr):
  569. "obj.attributename = newvalue"
  570. w_attributename = self.getname_w(nameindex)
  571. w_obj = self.popvalue()
  572. w_newvalue = self.popvalue()
  573. self.space.setattr(w_obj, w_attributename, w_newvalue)
  574. def DELETE_ATTR(self, nameindex, next_instr):
  575. "del obj.attributename"
  576. w_attributename = self.getname_w(nameindex)
  577. w_obj = self.popvalue()
  578. self.space.delattr(w_obj, w_attributename)
  579. def STORE_GLOBAL(self, nameindex, next_instr):
  580. varname = self.getname_u(nameindex)
  581. w_newvalue = self.popvalue()
  582. self.space.setitem_str(self.w_globals, varname, w_newvalue)
  583. def DELETE_GLOBAL(self, nameindex, next_instr):
  584. w_varname = self.getname_w(nameindex)
  585. self.space.delitem(self.w_globals, w_varname)
  586. def LOAD_NAME(self, nameindex, next_instr):
  587. if self.w_locals is not self.w_globals:
  588. w_varname = self.getname_w(nameindex)
  589. w_value = self.space.finditem(self.w_locals, w_varname)
  590. if w_value is not None:
  591. self.pushvalue(w_value)
  592. return
  593. self.LOAD_GLOBAL(nameindex, next_instr) # fall-back
  594. def _load_global(self, varname):
  595. w_value = self.space.finditem_str(self.w_globals, varname)
  596. if w_value is None:
  597. # not in the globals, now look in the built-ins
  598. w_value = self.get_builtin().getdictvalue(self.space, varname)
  599. if w_value is None:
  600. self._load_global_failed(varname)
  601. return w_value
  602. _load_global._always_inline_ = True
  603. def _load_global_failed(self, varname):
  604. message = "global name '%s' is not defined"
  605. raise operationerrfmt(self.space.w_NameError, message, varname)
  606. _load_global_failed._dont_inline_ = True
  607. def LOAD_GLOBAL(self, nameindex, next_instr):
  608. self.pushvalue(self._load_global(self.getname_u(nameindex)))
  609. LOAD_GLOBAL._always_inline_ = True
  610. def DELETE_FAST(self, varindex, next_instr):
  611. if self.locals_stack_w[varindex] is None:
  612. varname = self.getlocalvarname(varindex)
  613. message = "local variable '%s' referenced before assignment"
  614. raise operationerrfmt(self.space.w_UnboundLocalError, message,
  615. varname)
  616. self.locals_stack_w[varindex] = None
  617. def BUILD_TUPLE(self, itemcount, next_instr):
  618. items = self.popvalues(itemcount)
  619. w_tuple = self.space.newtuple(items)
  620. self.pushvalue(w_tuple)
  621. def BUILD_LIST(self, itemcount, next_instr):
  622. items = self.popvalues_mutable(itemcount)
  623. w_list = self.space.newlist(items)
  624. self.pushvalue(w_list)
  625. def BUILD_LIST_FROM_ARG(self, _, next_instr):
  626. # this is a little dance, because list has to be before the
  627. # value
  628. last_val = self.popvalue()
  629. try:
  630. lgt = self.space.len_w(last_val)
  631. except OperationError, e:
  632. if e.async(self.space):
  633. raise
  634. lgt = 0 # oh well
  635. self.pushvalue(self.space.newlist([], sizehint=lgt))
  636. self.pushvalue(last_val)
  637. def LOAD_ATTR(self, nameindex, next_instr):
  638. "obj.attributename"
  639. w_obj = self.popvalue()
  640. if (self.space.config.objspace.std.withmapdict
  641. and not jit.we_are_jitted()):
  642. from pypy.objspace.std.mapdict import LOAD_ATTR_caching
  643. w_value = LOAD_ATTR_caching(self.getcode(), w_obj, nameindex)
  644. else:
  645. w_attributename = self.getname_w(nameindex)
  646. w_value = self.space.getattr(w_obj, w_attributename)
  647. self.pushvalue(w_value)
  648. LOAD_ATTR._always_inline_ = True
  649. def cmp_lt(self, w_1, w_2):
  650. return self.space.lt(w_1, w_2)
  651. def cmp_le(self, w_1, w_2):
  652. return self.space.le(w_1, w_2)
  653. def cmp_eq(self, w_1, w_2):
  654. return self.space.eq(w_1, w_2)
  655. def cmp_ne(self, w_1, w_2):
  656. return self.space.ne(w_1, w_2)
  657. def cmp_gt(self, w_1, w_2):
  658. return self.space.gt(w_1, w_2)
  659. def cmp_ge(self, w_1, w_2):
  660. return self.space.ge(w_1, w_2)
  661. def cmp_in(self, w_1, w_2):
  662. return self.space.contains(w_2, w_1)
  663. def cmp_not_in(self, w_1, w_2):
  664. return self.space.not_(self.space.contains(w_2, w_1))
  665. def cmp_is(self, w_1, w_2):
  666. return self.space.is_(w_1, w_2)
  667. def cmp_is_not(self, w_1, w_2):
  668. return self.space.not_(self.space.is_(w_1, w_2))
  669. @jit.unroll_safe
  670. def cmp_exc_match(self, w_1, w_2):
  671. if self.space.is_true(self.space.isinstance(w_2, self.space.w_tuple)):
  672. for w_t in self.space.fixedview(w_2):
  673. if self.space.is_true(self.space.isinstance(w_t,
  674. self.space.w_str)):
  675. self.space.warn("catching of string exceptions is "
  676. "deprecated",
  677. self.space.w_DeprecationWarning)
  678. elif self.space.is_true(self.space.isinstance(w_2, self.space.w_str)):
  679. self.space.warn("catching of string exceptions is deprecated",
  680. self.space.w_DeprecationWarning)
  681. return self.space.newbool(self.space.exception_match(w_1, w_2))
  682. def COMPARE_OP(self, testnum, next_instr):
  683. w_2 = self.popvalue()
  684. w_1 = self.popvalue()
  685. w_result = None
  686. for i, attr in unrolling_compare_dispatch_table:
  687. if i == testnum:
  688. w_result = getattr(self, attr)(w_1, w_2)
  689. break
  690. else:
  691. raise BytecodeCorruption, "bad COMPARE_OP oparg"
  692. self.pushvalue(w_result)
  693. def IMPORT_NAME(self, nameindex, next_instr):
  694. space = self.space
  695. w_modulename = self.getname_w(nameindex)
  696. modulename = self.space.str_w(w_modulename)
  697. w_fromlist = self.popvalue()
  698. w_flag = self.popvalue()
  699. try:
  700. if space.int_w(w_flag) == -1:
  701. w_flag = None
  702. except OperationError, e:
  703. if e.async(space):
  704. raise
  705. w_import = self.get_builtin().getdictvalue(space, '__import__')
  706. if w_import is None:
  707. raise OperationError(space.w_ImportError,
  708. space.wrap("__import__ not found"))
  709. w_locals = self.w_locals
  710. if w_locals is None: # CPython does this
  711. w_locals = space.w_None
  712. w_modulename = space.wrap(modulename)
  713. w_globals = self.w_globals
  714. if w_flag is None:
  715. w_obj = space.call_function(w_import, w_modulename, w_globals,
  716. w_locals, w_fromlist)
  717. else:
  718. w_obj = space.call_function(w_import, w_modulename, w_globals,
  719. w_locals, w_fromlist, w_flag)
  720. self.pushvalue(w_obj)
  721. def IMPORT_STAR(self, oparg, next_instr):
  722. w_module = self.popvalue()
  723. w_locals = self.getdictscope()
  724. import_all_from(self.space, w_module, w_locals)
  725. self.setdictscope(w_locals)
  726. def IMPORT_FROM(self, nameindex, next_instr):
  727. w_name = self.getname_w(nameindex)
  728. w_module = self.peekvalue()
  729. try:
  730. w_obj = self.space.getattr(w_module, w_name)
  731. except OperationError, e:
  732. if not e.match(self.space, self.space.w_AttributeError):
  733. raise
  734. raise operationerrfmt(self.space.w_ImportError,
  735. "cannot import name '%s'",
  736. self.space.str_w(w_name))
  737. self.pushvalue(w_obj)
  738. def YIELD_VALUE(self, oparg, next_instr):
  739. raise Yield
  740. def jump_absolute(self, jumpto, next_instr, ec):
  741. check_nonneg(jumpto)
  742. return jumpto
  743. def JUMP_FORWARD(self, jumpby, next_instr):
  744. next_instr += jumpby
  745. return next_instr
  746. def POP_JUMP_IF_FALSE(self, target, next_instr):
  747. w_value = self.popvalue()
  748. if not self.space.is_true(w_value):
  749. return target
  750. return next_instr
  751. def POP_JUMP_IF_TRUE(self, target, next_instr):
  752. w_value = self.popvalue()
  753. if self.space.is_true(w_value):
  754. return target
  755. return next_instr
  756. def JUMP_IF_FALSE_OR_POP(self, target, next_instr):
  757. w_value = self.peekvalue()
  758. if not self.space.is_true(w_value):
  759. return target
  760. self.popvalue()
  761. return next_instr
  762. def JUMP_IF_TRUE_OR_POP(self, target, next_instr):
  763. w_value = self.peekvalue()
  764. if self.space.is_true(w_value):
  765. return target
  766. self.popvalue()
  767. return next_instr
  768. def GET_ITER(self, oparg, next_instr):
  769. w_iterable = self.popvalue()
  770. w_iterator = self.space.iter(w_iterable)
  771. self.pushvalue(w_iterator)
  772. def FOR_ITER(self, jumpby, next_instr):
  773. w_iterator = self.peekvalue()
  774. try:
  775. w_nextitem = self.space.next(w_iterator)
  776. except OperationError, e:
  777. if not e.match(self.space, self.space.w_StopIteration):
  778. raise
  779. # iterator exhausted
  780. self.popvalue()
  781. next_instr += jumpby
  782. else:
  783. self.pushvalue(w_nextitem)
  784. return next_instr
  785. def FOR_LOOP(self, oparg, next_instr):
  786. raise BytecodeCorruption, "old opcode, no longer in use"
  787. def SETUP_LOOP(self, offsettoend, next_instr):
  788. block = LoopBlock(self, next_instr + offsettoend, self.lastblock)
  789. self.lastblock = block
  790. def SETUP_EXCEPT(self, offsettoend, next_instr):
  791. block = ExceptBlock(self, next_instr + offsettoend, self.lastblock)
  792. self.lastblock = block
  793. def SETUP_FINALLY(self, offsettoend, next_instr):
  794. block = FinallyBlock(self, next_instr + offsettoend, self.lastblock)
  795. self.lastblock = block
  796. def SETUP_WITH(self, offsettoend, next_instr):
  797. w_manager = self.peekvalue()
  798. w_enter = self.space.lookup(w_manager, "__enter__")
  799. w_descr = self.space.lookup(w_manager, "__exit__")
  800. if w_enter is None or w_descr is None:
  801. typename = self.space.type(w_manager).getname(self.space)
  802. raise operationerrfmt(self.space.w_AttributeError,
  803. "'%s' object is not a context manager"
  804. " (no __enter__/__exit__ method)", typename)
  805. w_exit = self.space.get(w_descr, w_manager)
  806. self.settopvalue(w_exit)
  807. w_result = self.space.get_and_call_function(w_enter, w_manager)
  808. block = WithBlock(self, next_instr + offsettoend, self.lastblock)
  809. self.lastblock = block
  810. self.pushvalue(w_result)
  811. def WITH_CLEANUP(self, oparg, next_instr):
  812. # see comment in END_FINALLY for stack state
  813. # This opcode changed a lot between CPython versions
  814. if (self.pycode.magic >= 0xa0df2ef
  815. # Implementation since 2.7a0: 62191 (introduce SETUP_WITH)
  816. or self.pycode.magic >= 0xa0df2d1):
  817. # implementation since 2.6a1: 62161 (WITH_CLEANUP optimization)
  818. w_unroller = self.popvalue()
  819. w_exitfunc = self.popvalue()
  820. self.pushvalue(w_unroller)
  821. elif self.pycode.magic >= 0xa0df28c:
  822. # Implementation since 2.5a0: 62092 (changed WITH_CLEANUP opcode)
  823. w_exitfunc = self.popvalue()
  824. w_unroller = self.peekvalue(0)
  825. else:
  826. raise NotImplementedError("WITH_CLEANUP for CPython <= 2.4")
  827. unroller = self.space.interpclass_w(w_unroller)
  828. is_app_exc = (unroller is not None and
  829. isinstance(unroller, SApplicationException))
  830. if is_app_exc:
  831. operr = unroller.operr
  832. w_traceback = self.space.wrap(operr.get_traceback())
  833. w_suppress = self.call_contextmanager_exit_function(
  834. w_exitfunc,
  835. operr.w_type,
  836. operr.get_w_value(self.space),
  837. w_traceback)
  838. if self.space.is_true(w_suppress):
  839. # __exit__() returned True -> Swallow the exception.
  840. self.settopvalue(self.space.w_None)
  841. else:
  842. self.call_contextmanager_exit_function(
  843. w_exitfunc,
  844. self.space.w_None,
  845. self.space.w_None,
  846. self.space.w_None)
  847. @jit.unroll_safe
  848. def call_function(self, oparg, w_star=None, w_starstar=None):
  849. n_arguments = oparg & 0xff
  850. n_keywords = (oparg>>8) & 0xff
  851. if n_keywords:
  852. keywords = [None] * n_keywords
  853. keywords_w = [None] * n_keywords
  854. while True:
  855. n_keywords -= 1
  856. if n_keywords < 0:
  857. break
  858. w_value = self.popvalue()
  859. w_key = self.popvalue()
  860. key = self.space.str_w(w_key)
  861. keywords[n_keywords] = key
  862. keywords_w[n_keywords] = w_value
  863. else:
  864. keywords = None
  865. keywords_w = None
  866. arguments = self.popvalues(n_arguments)
  867. args = self.argument_factory(arguments, keywords, keywords_w, w_star,
  868. w_starstar)
  869. w_function = self.popvalue()
  870. if self.is_being_profiled and function.is_builtin_code(w_function):
  871. w_result = self.space.call_args_and_c_profile(self, w_function,
  872. args)
  873. else:
  874. w_result = self.space.call_args(w_function, args)
  875. self.pushvalue(w_result)
  876. def CALL_FUNCTION(self, oparg, next_instr):
  877. # XXX start of hack for performance
  878. if (oparg >> 8) & 0xff == 0:
  879. # Only positional arguments
  880. nargs = oparg & 0xff
  881. w_function = self.peekvalue(nargs)
  882. try:
  883. w_result = self.space.call_valuestack(w_function, nargs, self)
  884. finally:
  885. self.dropvalues(nargs + 1)
  886. self.pushvalue(w_result)
  887. # XXX end of hack for performance
  888. else:
  889. # general case
  890. self.call_function(oparg)
  891. def CALL_FUNCTION_VAR(self, oparg, next_instr):
  892. w_varargs = self.popvalue()
  893. self.call_function(oparg, w_varargs)
  894. def CALL_FUNCTION_KW(self, oparg, next_instr):
  895. w_varkw = self.popvalue()
  896. self.call_function(oparg, None, w_varkw)
  897. def CALL_FUNCTION_VAR_KW(self, oparg, next_instr):
  898. w_varkw = self.popvalue()
  899. w_varargs = self.popvalue()
  900. self.call_function(oparg, w_varargs, w_varkw)
  901. def MAKE_FUNCTION(self, numdefaults, next_instr):
  902. w_codeobj = self.popvalue()
  903. codeobj = self.space.interp_w(PyCode, w_codeobj)
  904. defaultarguments = self.popvalues(numdefaults)
  905. fn = function.Function(self.space, codeobj, self.w_globals,
  906. defaultarguments)
  907. self.pushvalue(self.space.wrap(fn))
  908. def BUILD_SLICE(self, numargs, next_instr):
  909. if numargs == 3:
  910. w_step = self.popvalue()
  911. elif numargs == 2:
  912. w_step = self.space.w_None
  913. else:
  914. raise BytecodeCorruption
  915. w_end = self.popvalue()
  916. w_start = self.popvalue()
  917. w_slice = self.space.newslice(w_start, w_end, w_step)
  918. self.pushvalue(w_slice)
  919. def LIST_APPEND(self, oparg, next_instr):
  920. w = self.popvalue()
  921. v = self.peekvalue(oparg - 1)
  922. self.space.call_method(v, 'append', w)
  923. def SET_ADD(self, oparg, next_instr):
  924. w_value = self.popvalue()
  925. w_set = self.peekvalue(oparg - 1)
  926. self.space.call_method(w_set, 'add', w_value)
  927. def MAP_ADD(self, oparg, next_instr):
  928. w_key = self.popvalue()
  929. w_value = self.popvalue()
  930. w_dict = self.peekvalue(oparg - 1)
  931. self.space.setitem(w_dict, w_key, w_value)
  932. def SET_LINENO(self, lineno, next_instr):
  933. pass
  934. # overridden by faster version in the standard object space.
  935. LOOKUP_METHOD = LOAD_ATTR
  936. CALL_METHOD = CALL_FUNCTION
  937. def MISSING_OPCODE(self, oparg, next_instr):
  938. ofs = self.last_instr
  939. c = self.pycode.co_code[ofs]
  940. name = self.pycode.co_name
  941. raise BytecodeCorruption("unknown opcode, ofs=%d, code=%d, name=%s" %
  942. (ofs, ord(c), name) )
  943. STOP_CODE = MISSING_OPCODE
  944. def BUILD_MAP(self, itemcount, next_instr):
  945. w_dict = self.space.newdict()
  946. self.pushvalue(w_dict)
  947. @jit.unroll_safe
  948. def BUILD_SET(self, itemcount, next_instr):
  949. w_set = self.space.newset()
  950. for i in range(itemcount):
  951. w_item = self.popvalue()
  952. self.space.call_method(w_set, 'add', w_item)
  953. self.pushvalue(w_set)
  954. def STORE_MAP(self, oparg, next_instr):
  955. w_key = self.popvalue()
  956. w_value = self.popvalue()
  957. w_dict = self.peekvalue()
  958. self.space.setitem(w_dict, w_key, w_value)
  959. class __extend__(pyframe.CPythonFrame):
  960. def JUMP_IF_FALSE(self, stepby, next_instr):
  961. w_cond = self.peekvalue()
  962. if not self.space.is_true(w_cond):
  963. next_instr += stepby
  964. return next_instr
  965. def JUMP_IF_TRUE(self, stepby, next_instr):
  966. w_cond = self.peekvalue()
  967. if self.space.is_true(w_cond):
  968. next_instr += stepby
  969. return next_instr
  970. def BUILD_MAP(self, itemcount, next_instr):
  971. if sys.version_info >= (2, 6):
  972. # We could pre-allocate a dict here
  973. # but for the moment this code is not translated.
  974. pass
  975. else:
  976. if itemcount != 0:
  977. raise BytecodeCorruption
  978. w_dict = self.space.newdict()
  979. self.pushvalue(w_dict)
  980. def STORE_MAP(self, zero, next_instr):
  981. if sys.version_info >= (2, 6):
  982. w_key = self.popvalue()
  983. w_value = self.popvalue()
  984. w_dict = self.peekvalue()
  985. self.space.setitem(w_dict, w_key, w_value)
  986. else:
  987. raise BytecodeCorruption
  988. def LIST_APPEND(self, oparg, next_instr):
  989. w = self.popvalue()
  990. if sys.version_info < (2, 7):
  991. v = self.popvalue()
  992. else:
  993. v = self.peekvalue(oparg - 1)
  994. self.space.call_method(v, 'append', w)
  995. ### ____________________________________________________________ ###
  996. class ExitFrame(Exception):
  997. pass
  998. class Return(ExitFrame):
  999. """Raised when exiting a frame via a 'return' statement."""
  1000. class Yield(ExitFrame):
  1001. """Raised when exiting a frame via a 'yield' statement."""
  1002. class Reraise(Exception):
  1003. """Raised at interp-level by a bare 'raise' statement."""
  1004. class RaiseWithExplicitTraceback(Exception):
  1005. """Raised at interp-level by a 3-arguments 'raise' statement."""
  1006. def __init__(self, operr):
  1007. self.operr = operr
  1008. class BytecodeCorruption(Exception):
  1009. """Detected bytecode corruption. Never caught; it's an error."""
  1010. ### Frame Blocks ###
  1011. class SuspendedUnroller(Wrappable):
  1012. """Abstract base class for interpreter-level objects that
  1013. instruct the interpreter to change the control flow and the
  1014. block stack.
  1015. The concrete subclasses correspond to the various values WHY_XXX
  1016. values of the why_code enumeration in ceval.c:
  1017. WHY_NOT, OK, not this one :-)
  1018. WHY_EXCEPTION, SApplicationException
  1019. WHY_RERAISE, implemented differently, see Reraise
  1020. WHY_RETURN, SReturnValue
  1021. WHY_BREAK, SBreakLoop
  1022. WHY_CONTINUE, SContinueLoop
  1023. WHY_YIELD not needed
  1024. """
  1025. _immutable_ = True
  1026. def nomoreblocks(self):
  1027. raise BytecodeCorruption("misplaced bytecode - should not return")
  1028. # NB. for the flow object space, the state_(un)pack_variables methods
  1029. # give a way to "pickle" and "unpickle" the SuspendedUnroller by
  1030. # enumerating the Variables it contains.
  1031. class SReturnValue(SuspendedUnroller):
  1032. """Signals a 'return' statement.
  1033. Argument is the wrapped object to return."""
  1034. _immutable_ = True
  1035. kind = 0x01
  1036. def __init__(self, w_returnvalue):
  1037. self.w_returnvalue = w_returnvalue
  1038. def nomoreblocks(self):
  1039. return self.w_returnvalue
  1040. def state_unpack_variables(self, space):
  1041. return [self.w_returnvalue]
  1042. def state_pack_variables(space, w_returnvalue):
  1043. return SReturnValue(w_returnvalue)
  1044. state_pack_variables = staticmethod(state_pack_variables)
  1045. class SApplicationException(SuspendedUnroller):
  1046. """Signals an application-level exception
  1047. (i.e. an OperationException)."""
  1048. _immutable_ = True
  1049. kind = 0x02
  1050. def __init__(self, operr):
  1051. self.operr = operr
  1052. def nomoreblocks(self):
  1053. raise RaiseWithExplicitTraceback(self.operr)
  1054. def state_unpack_variables(self, space):
  1055. return [self.operr.w_type, self.operr.get_w_value(space)]
  1056. def state_pack_variables(space, w_type, w_value):
  1057. return SApplicationException(OperationError(w_type, w_value))
  1058. state_pack_variables = staticmethod(state_pack_variables)
  1059. class SBreakLoop(SuspendedUnroller):
  1060. """Signals a 'break' statement."""
  1061. _immutable_ = True
  1062. kind = 0x04
  1063. def state_unpack_variables(self, space):
  1064. return []
  1065. def state_pack_variables(space):
  1066. return SBreakLoop.singleton
  1067. state_pack_variables = staticmethod(state_pack_variables)
  1068. SBreakLoop.singleton = SBreakLoop()
  1069. class SContinueLoop(SuspendedUnroller):
  1070. """Signals a 'continue' statement.
  1071. Argument is the bytecode position of the beginning of the loop."""
  1072. _immutable_ = True
  1073. kind = 0x08
  1074. def __init__(self, jump_to):
  1075. self.jump_to = jump_to
  1076. def state_unpack_variables(self, space):
  1077. return [space.wrap(self.jump_to)]
  1078. def state_pack_variables(space, w_jump_to):
  1079. return SContinueLoop(space.int_w(w_jump_to))
  1080. state_pack_variables = staticmethod(state_pack_variables)
  1081. class FrameBlock(object):
  1082. """Abstract base class for frame blocks from the blockstack,
  1083. used by the SETUP_XXX and POP_BLOCK opcodes."""
  1084. _immutable_ = True
  1085. def __init__(self, frame, handlerposition, previous):
  1086. self.handlerposition = handlerposition
  1087. self.valuestackdepth = frame.valuestackdepth
  1088. self.previous = previous # this makes a linked list of blocks
  1089. def __eq__(self, other):
  1090. return (self.__class__ is other.__class__ and
  1091. self.handlerposition == other.handlerposition and
  1092. self.valuestackdepth == other.valuestackdepth)
  1093. def __ne__(self, other):
  1094. return not (self == other)
  1095. def __hash__(self):
  1096. return hash((self.handlerposition, self.valuestackdepth))
  1097. def cleanupstack(self, frame):
  1098. frame.dropvaluesuntil(self.valuestackdepth)
  1099. def cleanup(self, frame):
  1100. "Clean up a frame when we normally exit the block."
  1101. self.cleanupstack(frame)
  1102. # internal pickling interface, not using the standard protocol
  1103. def _get_state_(self, space):
  1104. w = space.wrap
  1105. return space.newtuple([w(self._opname), w(self.handlerposition),
  1106. w(self.valuestackdepth)])
  1107. def handle(self, frame, unroller):
  1108. """ Purely abstract method
  1109. """
  1110. raise NotImplementedError
  1111. class LoopBlock(FrameBlock):
  1112. """A loop block. Stores the end-of-loop pointer in case of 'break'."""
  1113. _immutable_ = True
  1114. _opname = 'SETUP_LOOP'
  1115. handling_mask = SBreakLoop.kind | SContinueLoop.kind
  1116. def handle(self, frame, unroller):
  1117. if isinstance(unroller, SContinueLoop):
  1118. # re-push the loop block without cleaning up the value stack,
  1119. # and jump to the beginning of the loop, stored in the
  1120. # exception's argument
  1121. frame.append_block(self)
  1122. return r_uint(unroller.jump_to)
  1123. else:
  1124. # jump to the end of the loop
  1125. self.cleanupstack(frame)
  1126. return r_uint(self.handlerposition)
  1127. class ExceptBlock(FrameBlock):
  1128. """An try:except: block. Stores the position of the exception handler."""
  1129. _immutable_ = True
  1130. _opname = 'SETUP_EXCEPT'
  1131. handl

Large files files are truncated, but you can click here to view the full file