PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/interpreter/pyopcode.py

https://bitbucket.org/kcr/pypy
Python | 1487 lines | 1210 code | 178 blank | 99 comment | 143 complexity | fe6b25b84d1b1b33aa8c0fc40a55a51d MD5 | raw file
Possible License(s): Apache-2.0

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

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