PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/interpreter/pyopcode.py

https://bitbucket.org/kkris/pypy
Python | 1488 lines | 1211 code | 178 blank | 99 comment | 143 complexity | 97d64957a54b253a7f3ebf4d7969eab7 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, 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. if self.space.is_true(self.space.isinstance(w_2, self.space.w_tuple)):
  666. for w_t in self.space.fixedview(w_2):
  667. if self.space.is_true(self.space.isinstance(w_t,
  668. self.space.w_str)):
  669. self.space.warn("catching of string exceptions is "
  670. "deprecated",
  671. self.space.w_DeprecationWarning)
  672. elif self.space.is_true(self.space.isinstance(w_2, self.space.w_str)):
  673. self.space.warn("catching of string exceptions is deprecated",
  674. self.space.w_DeprecationWarning)
  675. return self.space.newbool(self.space.exception_match(w_1, w_2))
  676. def COMPARE_OP(self, testnum, next_instr):
  677. w_2 = self.popvalue()
  678. w_1 = self.popvalue()
  679. w_result = None
  680. for i, attr in unrolling_compare_dispatch_table:
  681. if i == testnum:
  682. w_result = getattr(self, attr)(w_1, w_2)
  683. break
  684. else:
  685. raise BytecodeCorruption, "bad COMPARE_OP oparg"
  686. self.pushvalue(w_result)
  687. def IMPORT_NAME(self, nameindex, next_instr):
  688. space = self.space
  689. w_modulename = self.getname_w(nameindex)
  690. modulename = self.space.str_w(w_modulename)
  691. w_fromlist = self.popvalue()
  692. w_flag = self.popvalue()
  693. try:
  694. if space.int_w(w_flag) == -1:
  695. w_flag = None
  696. except OperationError, e:
  697. if e.async(space):
  698. raise
  699. w_import = self.get_builtin().getdictvalue(space, '__import__')
  700. if w_import is None:
  701. raise OperationError(space.w_ImportError,
  702. space.wrap("__import__ not found"))
  703. w_locals = self.w_locals
  704. if w_locals is None: # CPython does this
  705. w_locals = space.w_None
  706. w_modulename = space.wrap(modulename)
  707. w_globals = self.w_globals
  708. if w_flag is None:
  709. w_obj = space.call_function(w_import, w_modulename, w_globals,
  710. w_locals, w_fromlist)
  711. else:
  712. w_obj = space.call_function(w_import, w_modulename, w_globals,
  713. w_locals, w_fromlist, w_flag)
  714. self.pushvalue(w_obj)
  715. def IMPORT_STAR(self, oparg, next_instr):
  716. w_module = self.popvalue()
  717. w_locals = self.getdictscope()
  718. import_all_from(self.space, w_module, w_locals)
  719. self.setdictscope(w_locals)
  720. def IMPORT_FROM(self, nameindex, next_instr):
  721. w_name = self.getname_w(nameindex)
  722. w_module = self.peekvalue()
  723. try:
  724. w_obj = self.space.getattr(w_module, w_name)
  725. except OperationError, e:
  726. if not e.match(self.space, self.space.w_AttributeError):
  727. raise
  728. raise operationerrfmt(self.space.w_ImportError,
  729. "cannot import name '%s'",
  730. self.space.str_w(w_name))
  731. self.pushvalue(w_obj)
  732. def YIELD_VALUE(self, oparg, next_instr):
  733. raise Yield
  734. def jump_absolute(self, jumpto, ec):
  735. # this function is overridden by pypy.module.pypyjit.interp_jit
  736. check_nonneg(jumpto)
  737. return jumpto
  738. def JUMP_FORWARD(self, jumpby, next_instr):
  739. next_instr += jumpby
  740. return next_instr
  741. def POP_JUMP_IF_FALSE(self, target, next_instr):
  742. w_value = self.popvalue()
  743. if not self.space.is_true(w_value):
  744. return target
  745. return next_instr
  746. def POP_JUMP_IF_TRUE(self, target, next_instr):
  747. w_value = self.popvalue()
  748. if self.space.is_true(w_value):
  749. return target
  750. return next_instr
  751. def JUMP_IF_FALSE_OR_POP(self, target, next_instr):
  752. w_value = self.peekvalue()
  753. if not self.space.is_true(w_value):
  754. return target
  755. self.popvalue()
  756. return next_instr
  757. def JUMP_IF_TRUE_OR_POP(self, target, next_instr):
  758. w_value = self.peekvalue()
  759. if self.space.is_true(w_value):
  760. return target
  761. self.popvalue()
  762. return next_instr
  763. def GET_ITER(self, oparg, next_instr):
  764. w_iterable = self.popvalue()
  765. w_iterator = self.space.iter(w_iterable)
  766. self.pushvalue(w_iterator)
  767. def FOR_ITER(self, jumpby, next_instr):
  768. w_iterator = self.peekvalue()
  769. try:
  770. w_nextitem = self.space.next(w_iterator)
  771. except OperationError, e:
  772. if not e.match(self.space, self.space.w_StopIteration):
  773. raise
  774. # iterator exhausted
  775. self.popvalue()
  776. next_instr += jumpby
  777. else:
  778. self.pushvalue(w_nextitem)
  779. return next_instr
  780. def FOR_LOOP(self, oparg, next_instr):
  781. raise BytecodeCorruption, "old opcode, no longer in use"
  782. def SETUP_LOOP(self, offsettoend, next_instr):
  783. block = LoopBlock(self, next_instr + offsettoend, self.lastblock)
  784. self.lastblock = block
  785. def SETUP_EXCEPT(self, offsettoend, next_instr):
  786. block = ExceptBlock(self, next_instr + offsettoend, self.lastblock)
  787. self.lastblock = block
  788. def SETUP_FINALLY(self, offsettoend, next_instr):
  789. block = FinallyBlock(self, next_instr + offsettoend, self.lastblock)
  790. self.lastblock = block
  791. def SETUP_WITH(self, offsettoend, next_instr):
  792. w_manager = self.peekvalue()
  793. w_enter = self.space.lookup(w_manager, "__enter__")
  794. w_descr = self.space.lookup(w_manager, "__exit__")
  795. if w_enter is None or w_descr is None:
  796. typename = self.space.type(w_manager).getname(self.space)
  797. raise operationerrfmt(self.space.w_AttributeError,
  798. "'%s' object is not a context manager"
  799. " (no __enter__/__exit__ method)", typename)
  800. w_exit = self.space.get(w_descr, w_manager)
  801. self.settopvalue(w_exit)
  802. w_result = self.space.get_and_call_function(w_enter, w_manager)
  803. block = WithBlock(self, next_instr + offsettoend, self.lastblock)
  804. self.lastblock = block
  805. self.pushvalue(w_result)
  806. def WITH_CLEANUP(self, oparg, next_instr):
  807. # see comment in END_FINALLY for stack state
  808. w_unroller = self.popvalue()
  809. w_exitfunc = self.popvalue()
  810. self.pushvalue(w_unroller)
  811. unroller = self.space.interpclass_w(w_unroller)
  812. is_app_exc = (unroller is not None and
  813. isinstance(unroller, SApplicationException))
  814. if is_app_exc:
  815. operr = unroller.operr
  816. self.last_exception = operr
  817. w_traceback = self.space.wrap(operr.get_traceback())
  818. w_suppress = self.call_contextmanager_exit_function(
  819. w_exitfunc,
  820. operr.w_type,
  821. operr.get_w_value(self.space),
  822. w_traceback)
  823. if self.space.is_true(w_suppress):
  824. # __exit__() returned True -> Swallow the exception.
  825. self.settopvalue(self.space.w_None)
  826. else:
  827. self.call_contextmanager_exit_function(
  828. w_exitfunc,
  829. self.space.w_None,
  830. self.space.w_None,
  831. self.space.w_None)
  832. @jit.unroll_safe
  833. def call_function(self, oparg, w_star=None, w_starstar=None):
  834. n_arguments = oparg & 0xff
  835. n_keywords = (oparg>>8) & 0xff
  836. if n_keywords:
  837. keywords = [None] * n_keywords
  838. keywords_w = [None] * n_keywords
  839. while True:
  840. n_keywords -= 1
  841. if n_keywords < 0:
  842. break
  843. w_value = self.popvalue()
  844. w_key = self.popvalue()
  845. key = self.space.str_w(w_key)
  846. keywords[n_keywords] = key
  847. keywords_w[n_keywords] = w_value
  848. else:
  849. keywords = None
  850. keywords_w = None
  851. arguments = self.popvalues(n_arguments)
  852. args = self.argument_factory(arguments, keywords, keywords_w, w_star,
  853. w_starstar)
  854. w_function = self.popvalue()
  855. if self.is_being_profiled and function.is_builtin_code(w_function):
  856. w_result = self.space.call_args_and_c_profile(self, w_function,
  857. args)
  858. else:
  859. w_result = self.space.call_args(w_function, args)
  860. self.pushvalue(w_result)
  861. def CALL_FUNCTION(self, oparg, next_instr):
  862. # XXX start of hack for performance
  863. if (oparg >> 8) & 0xff == 0:
  864. # Only positional arguments
  865. nargs = oparg & 0xff
  866. w_function = self.peekvalue(nargs)
  867. try:
  868. w_result = self.space.call_valuestack(w_function, nargs, self)
  869. finally:
  870. self.dropvalues(nargs + 1)
  871. self.pushvalue(w_result)
  872. # XXX end of hack for performance
  873. else:
  874. # general case
  875. self.call_function(oparg)
  876. def CALL_FUNCTION_VAR(self, oparg, next_instr):
  877. w_varargs = self.popvalue()
  878. self.call_function(oparg, w_varargs)
  879. def CALL_FUNCTION_KW(self, oparg, next_instr):
  880. w_varkw = self.popvalue()
  881. self.call_function(oparg, None, w_varkw)
  882. def CALL_FUNCTION_VAR_KW(self, oparg, next_instr):
  883. w_varkw = self.popvalue()
  884. w_varargs = self.popvalue()
  885. self.call_function(oparg, w_varargs, w_varkw)
  886. def MAKE_FUNCTION(self, numdefaults, next_instr):
  887. w_codeobj = self.popvalue()
  888. codeobj = self.space.interp_w(PyCode, w_codeobj)
  889. defaultarguments = self.popvalues(numdefaults)
  890. fn = function.Function(self.space, codeobj, self.w_globals,
  891. defaultarguments)
  892. self.pushvalue(self.space.wrap(fn))
  893. def BUILD_SLICE(self, numargs, next_instr):
  894. if numargs == 3:
  895. w_step = self.popvalue()
  896. elif numargs == 2:
  897. w_step = self.space.w_None
  898. else:
  899. raise BytecodeCorruption
  900. w_end = self.popvalue()
  901. w_start = self.popvalue()
  902. w_slice = self.space.newslice(w_start, w_end, w_step)
  903. self.pushvalue(w_slice)
  904. def LIST_APPEND(self, oparg, next_instr):
  905. w = self.popvalue()
  906. v = self.peekvalue(oparg - 1)
  907. self.space.call_method(v, 'append', w)
  908. def SET_ADD(self, oparg, next_instr):
  909. w_value = self.popvalue()
  910. w_set = self.peekvalue(oparg - 1)
  911. self.space.call_method(w_set, 'add', w_value)
  912. def MAP_ADD(self, oparg, next_instr):
  913. w_key = self.popvalue()
  914. w_value = self.popvalue()
  915. w_dict = self.peekvalue(oparg - 1)
  916. self.space.setitem(w_dict, w_key, w_value)
  917. def SET_LINENO(self, lineno, next_instr):
  918. pass
  919. # overridden by faster version in the standard object space.
  920. LOOKUP_METHOD = LOAD_ATTR
  921. CALL_METHOD = CALL_FUNCTION
  922. def MISSING_OPCODE(self, oparg, next_instr):
  923. ofs = self.last_instr
  924. c = self.pycode.co_code[ofs]
  925. name = self.pycode.co_name
  926. raise BytecodeCorruption("unknown opcode, ofs=%d, code=%d, name=%s" %
  927. (ofs, ord(c), name) )
  928. STOP_CODE = MISSING_OPCODE
  929. def BUILD_MAP(self, itemcount, next_instr):
  930. w_dict = self.space.newdict()
  931. self.pushvalue(w_dict)
  932. @jit.unroll_safe
  933. def BUILD_SET(self, itemcount, next_instr):
  934. w_set = self.space.newset()
  935. for i in range(itemcount):
  936. w_item = self.popvalue()
  937. self.space.call_method(w_set, 'add', w_item)
  938. self.pushvalue(w_set)
  939. def STORE_MAP(self, oparg, next_instr):
  940. w_key = self.popvalue()
  941. w_value = self.popvalue()
  942. w_dict = self.peekvalue()
  943. self.space.setitem(w_dict, w_key, w_value)
  944. class __extend__(pyframe.CPythonFrame):
  945. def JUMP_IF_FALSE(self, stepby, next_instr):
  946. w_cond = self.peekvalue()
  947. if not self.space.is_true(w_cond):
  948. next_instr += stepby
  949. return next_instr
  950. def JUMP_IF_TRUE(self, stepby, next_instr):
  951. w_cond = self.peekvalue()
  952. if self.space.is_true(w_cond):
  953. next_instr += stepby
  954. return next_instr
  955. def BUILD_MAP(self, itemcount, next_instr):
  956. if sys.version_info >= (2, 6):
  957. # We could pre-allocate a dict here
  958. # but for the moment this code is not translated.
  959. pass
  960. else:
  961. if itemcount != 0:
  962. raise BytecodeCorruption
  963. w_dict = self.space.newdict()
  964. self.pushvalue(w_dict)
  965. def STORE_MAP(self, zero, next_instr):
  966. if sys.version_info >= (2, 6):
  967. w_key = self.popvalue()
  968. w_value = self.popvalue()
  969. w_dict = self.peekvalue()
  970. self.space.setitem(w_dict, w_key, w_value)
  971. else:
  972. raise BytecodeCorruption
  973. def LIST_APPEND(self, oparg, next_instr):
  974. w = self.popvalue()
  975. if sys.version_info < (2, 7):
  976. v = self.popvalue()
  977. else:
  978. v = self.peekvalue(oparg - 1)
  979. self.space.call_method(v, 'append', w)
  980. ### ____________________________________________________________ ###
  981. class ExitFrame(Exception):
  982. pass
  983. class Return(ExitFrame):
  984. """Raised when exiting a frame via a 'return' statement."""
  985. class Yield(ExitFrame):
  986. """Raised when exiting a frame via a 'yield' statement."""
  987. class RaiseWithExplicitTraceback(Exception):
  988. """Raised at interp-level by a 0- or 3-arguments 'raise' statement."""
  989. def __init__(self, operr):
  990. self.operr = operr
  991. ### Frame Blocks ###
  992. class SuspendedUnroller(Wrappable):
  993. """Abstract base class for interpreter-level objects that
  994. instruct the interpreter to change the control flow and the
  995. block stack.
  996. The concrete subclasses correspond to the various values WHY_XXX
  997. values of the why_code enumeration in ceval.c:
  998. WHY_NOT, OK, not this one :-)
  999. WHY_EXCEPTION, SApplicationException
  1000. WHY_RERAISE, implemented differently, see Reraise
  1001. WHY_RETURN, SReturnValue
  1002. WHY_BREAK, SBreakLoop
  1003. WHY_CONTINUE, SContinueLoop
  1004. WHY_YIELD not needed
  1005. """
  1006. _immutable_ = True
  1007. def nomoreblocks(self):
  1008. raise BytecodeCorruption("misplaced bytecode - should not return")
  1009. class SReturnValue(SuspendedUnroller):
  1010. """Signals a 'return' statement.
  1011. Argument is the wrapped object to return."""
  1012. _immutable_ = True
  1013. kind = 0x01
  1014. def __init__(self, w_returnvalue):
  1015. self.w_returnvalue = w_returnvalue
  1016. def nomoreblocks(self):
  1017. return self.w_returnvalue
  1018. class SApplicationException(SuspendedUnroller):
  1019. """Signals an application-level exception
  1020. (i.e. an OperationException)."""
  1021. _immutable_ = True
  1022. kind = 0x02
  1023. def __init__(self, operr):
  1024. self.operr = operr
  1025. def nomoreblocks(self):
  1026. raise RaiseWithExplicitTraceback(self.operr)
  1027. class SBreakLoop(SuspendedUnroller):
  1028. """Signals a 'break' statement."""
  1029. _immutable_ = True
  1030. kind = 0x04
  1031. SBreakLoop.singleton = SBreakLoop()
  1032. class SContinueLoop(SuspendedUnroller):
  1033. """Signals a 'continue' statement.
  1034. Argument is the bytecode position of the beginning of the loop."""
  1035. _immutable_ = True
  1036. kind = 0x08
  1037. def __init__(self, jump_to):
  1038. self.jump_to = jump_to
  1039. class FrameBlock(object):
  1040. """Abstract base class for frame blocks from the blockstack,
  1041. used by the SETUP_XXX and POP_BLOCK opcodes."""
  1042. _immutable_ = True
  1043. def __init__(self, frame, handlerposition, previous):
  1044. self.handlerposition = handlerposition
  1045. self.valuestackdepth = frame.valuestackdepth
  1046. self.previous = previous # this makes a linked list of blocks
  1047. def __eq__(self, other):
  1048. return (self.__class__ is other.__class__ and
  1049. self.handlerposition == other.handlerposition and
  1050. self.valuestackdepth == other.valuestackdepth)
  1051. def __ne__(self, other):
  1052. return not (self == other)
  1053. def __hash__(self):
  1054. return hash((self.handlerposition, self.valuestackdepth))
  1055. def cleanupstack(self, frame):
  1056. frame.dropvaluesuntil(self.valuestackdepth)
  1057. def cleanup(self, frame):
  1058. "Clean up a frame when we normally exit the block."
  1059. self.cleanupstack(frame)
  1060. # internal pickling interface, not using the standard protocol
  1061. def _get_state_(self, space):
  1062. w = space.wrap
  1063. return space.newtuple([w(self._opname), w(self.handlerposition),
  1064. w(self.valuestackdepth)])
  1065. def handle(self, frame, unroller):
  1066. """ Purely abstract method
  1067. """
  1068. raise NotImplementedError
  1069. class LoopBlock(FrameBlock):
  1070. """A loop block. Stores the end-of-loop pointer in case of 'break'."""
  1071. _immutable_ = True
  1072. _opname = 'SETUP_LOOP'
  1073. handling_mask = SBreakLoop.kind | SContinueLoop.kind
  1074. def handle(self, frame, unroller):
  1075. if isinstance(unroller, SContinueLoop):
  1076. # re-push the loop block without cleaning up the value stack,
  1077. # and jump to the beginning of the loop, stored in the
  1078. # exception's argument
  1079. frame.append_block(self)
  1080. jumpto = unroller.jump_to
  1081. ec = frame.space.getexecutioncontext()
  1082. return r_uint(frame.jump_absolute(jumpto, ec))
  1083. else:
  1084. # jump to the end of the loop
  1085. self.cleanupstack(frame)
  1086. return r_uint(self.handlerposition)
  1087. class ExceptBlock(FrameBlock):
  1088. """An try:except: block. Stores the position of the exception handler."""
  1089. _immutable_ = True
  1090. _opname = 'SETUP_EXCEPT'
  1091. handling_mask = SApplicationException.kind
  1092. def handle(self, frame, unroller):
  1093. # push the exception to the value stack for inspection by the
  1094. # exception handler (the code after the except:)
  1095. self.cleanupstack(frame)
  1096. assert isinstance(unroller, SApplicationException)
  1097. operationerr = unroller.operr
  1098. operationerr.normalize_exception(frame.space)
  1099. # the stack setup is slightly different than in CPython:
  1100. # instead of the traceback, we store the unroller object,
  1101. # wrapped.
  1102. frame.pushvalue(frame.space.wrap(unroller))
  1103. frame.pushvalue(operationerr.get_w_value(frame.space))
  1104. frame.pushvalue(operationerr.w_type)
  1105. frame.last_exception = operationerr
  1106. return r_uint(self.handlerposition) # jump to the handler
  1107. class FinallyBlock(FrameBlock):
  1108. """A try:finally: block. Stores the position of the exception handler."""
  1109. _immutable_ = True
  1110. _opname = 'SETUP_FINALLY'
  1111. handling_mask = -1 # handles every kind of SuspendedUnroller
  1112. def handle(self, frame, unroller):
  1113. # any abnormal reason for unrolling a finally: triggers the end of
  1114. # the block unrolling and the entering the finally: handler.
  1115. # see comments in cleanup().
  1116. self.cleanupstack(frame)
  1117. frame.pushvalue(frame.space.wrap(unroller))
  1118. return r_uint(self.handlerposition) # jump to the handler
  1119. class WithBlock(FinallyBlock):
  1120. _immutable_ = True
  1121. def handle(self, frame, unroller):
  1122. if isinstance(unroller, SApplicationException):
  1123. unroller.operr.normalize_exception(frame.space)
  1124. return FinallyBlock.handle(self, frame, unroller)
  1125. block_classes = {'SETUP_LOOP': LoopBlock,
  1126. 'SETUP_EXCEPT': ExceptBlock,
  1127. 'SETUP_FINALLY': FinallyBlock,
  1128. 'SETUP_WITH': WithBlock,
  1129. }
  1130. ### helpers written

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