ceval.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. #pragma once
  2. #include "common.h"
  3. #include "namedict.h"
  4. #include "vm.h"
  5. namespace pkpy{
  6. inline PyObject* VM::_run_top_frame(){
  7. DEF_SNAME(add);
  8. DEF_SNAME(set);
  9. DEF_SNAME(__enter__);
  10. DEF_SNAME(__exit__);
  11. DEF_SNAME(__doc__);
  12. FrameId frame = top_frame();
  13. const int base_id = frame.index;
  14. bool need_raise = false;
  15. // shared registers
  16. PyObject *_0, *_1, *_2;
  17. const PyTypeInfo* _ti;
  18. StrName _name;
  19. while(true){
  20. #if DEBUG_EXTRA_CHECK
  21. if(frame.index < base_id) FATAL_ERROR();
  22. #endif
  23. try{
  24. if(need_raise){ need_raise = false; _raise(); }
  25. /**********************************************************************/
  26. /* NOTE:
  27. * Be aware of accidental gc!
  28. * DO NOT leave any strong reference of PyObject* in the C stack
  29. */
  30. {
  31. #define DISPATCH_OP_CALL() { frame = top_frame(); goto __NEXT_FRAME; }
  32. __NEXT_FRAME:
  33. Bytecode byte = frame->next_bytecode();
  34. // cache
  35. const CodeObject* co = frame->co;
  36. const auto& co_consts = co->consts;
  37. const auto& co_blocks = co->blocks;
  38. #if PK_ENABLE_COMPUTED_GOTO
  39. static void* OP_LABELS[] = {
  40. #define OPCODE(name) &&CASE_OP_##name,
  41. #include "opcodes.h"
  42. #undef OPCODE
  43. };
  44. #define DISPATCH() { byte = frame->next_bytecode(); goto *OP_LABELS[byte.op];}
  45. #define TARGET(op) CASE_OP_##op:
  46. goto *OP_LABELS[byte.op];
  47. #else
  48. #define TARGET(op) case OP_##op:
  49. #define DISPATCH() { byte = frame->next_bytecode(); goto __NEXT_STEP;}
  50. __NEXT_STEP:;
  51. #if DEBUG_CEVAL_STEP
  52. _log_s_data();
  53. #endif
  54. #if DEBUG_CEVAL_STEP_MIN
  55. std::cout << OP_NAMES[byte.op] << std::endl;
  56. #endif
  57. switch (byte.op)
  58. {
  59. #endif
  60. TARGET(NO_OP) DISPATCH();
  61. /*****************************************/
  62. TARGET(POP_TOP) POP(); DISPATCH();
  63. TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
  64. TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
  65. TARGET(PRINT_EXPR)
  66. if(TOP() != None){
  67. _stdout(this, CAST(Str&, py_repr(TOP())));
  68. _stdout(this, "\n");
  69. }
  70. POP();
  71. DISPATCH();
  72. /*****************************************/
  73. TARGET(LOAD_CONST)
  74. heap._auto_collect();
  75. PUSH(co_consts[byte.arg]);
  76. DISPATCH();
  77. TARGET(LOAD_NONE) PUSH(None); DISPATCH();
  78. TARGET(LOAD_TRUE) PUSH(True); DISPATCH();
  79. TARGET(LOAD_FALSE) PUSH(False); DISPATCH();
  80. TARGET(LOAD_INTEGER) PUSH(VAR(byte.arg)); DISPATCH();
  81. TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH();
  82. TARGET(LOAD_FUNCTION) {
  83. FuncDecl_ decl = co->func_decls[byte.arg];
  84. bool is_simple = decl->starred_arg==-1 && decl->kwargs.size()==0 && !decl->code->is_generator;
  85. int argc = decl->args.size();
  86. PyObject* obj;
  87. if(decl->nested){
  88. obj = VAR(Function({decl, is_simple, argc, frame->_module, frame->_locals.to_namedict()}));
  89. }else{
  90. obj = VAR(Function({decl, is_simple, argc, frame->_module}));
  91. }
  92. PUSH(obj);
  93. } DISPATCH();
  94. TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH();
  95. /*****************************************/
  96. TARGET(LOAD_FAST) {
  97. heap._auto_collect();
  98. _0 = frame->_locals[byte.arg];
  99. if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]);
  100. PUSH(_0);
  101. } DISPATCH();
  102. TARGET(LOAD_NAME)
  103. heap._auto_collect();
  104. _name = StrName(byte.arg);
  105. _0 = frame->_locals.try_get(_name);
  106. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  107. _0 = frame->f_closure_try_get(_name);
  108. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  109. _0 = frame->f_globals().try_get(_name);
  110. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  111. _0 = vm->builtins->attr().try_get(_name);
  112. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  113. vm->NameError(_name);
  114. DISPATCH();
  115. TARGET(LOAD_NONLOCAL) {
  116. heap._auto_collect();
  117. _name = StrName(byte.arg);
  118. _0 = frame->f_closure_try_get(_name);
  119. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  120. _0 = frame->f_globals().try_get(_name);
  121. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  122. _0 = vm->builtins->attr().try_get(_name);
  123. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  124. vm->NameError(_name);
  125. DISPATCH();
  126. } DISPATCH();
  127. TARGET(LOAD_GLOBAL)
  128. heap._auto_collect();
  129. _name = StrName(byte.arg);
  130. _0 = frame->f_globals().try_get(_name);
  131. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  132. _0 = vm->builtins->attr().try_get(_name);
  133. if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
  134. vm->NameError(_name);
  135. DISPATCH();
  136. TARGET(LOAD_ATTR)
  137. TOP() = getattr(TOP(), StrName(byte.arg));
  138. DISPATCH();
  139. TARGET(LOAD_METHOD)
  140. TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
  141. PUSH(_0);
  142. DISPATCH();
  143. TARGET(LOAD_SUBSCR)
  144. _1 = POPX(); // b
  145. _0 = TOP(); // a
  146. _ti = _inst_type_info(_0);
  147. if(_ti->m__getitem__){
  148. TOP() = _ti->m__getitem__(this, _0, _1);
  149. }else{
  150. TOP() = call_method(_0, __getitem__, _1);
  151. }
  152. DISPATCH();
  153. TARGET(STORE_FAST)
  154. frame->_locals[byte.arg] = POPX();
  155. DISPATCH();
  156. TARGET(STORE_NAME)
  157. _name = StrName(byte.arg);
  158. _0 = POPX();
  159. if(frame->_callable != nullptr){
  160. bool ok = frame->_locals.try_set(_name, _0);
  161. if(!ok) vm->NameError(_name);
  162. }else{
  163. frame->f_globals().set(_name, _0);
  164. }
  165. DISPATCH();
  166. TARGET(STORE_GLOBAL)
  167. frame->f_globals().set(StrName(byte.arg), POPX());
  168. DISPATCH();
  169. TARGET(STORE_ATTR) {
  170. _0 = TOP(); // a
  171. _1 = SECOND(); // val
  172. setattr(_0, StrName(byte.arg), _1);
  173. STACK_SHRINK(2);
  174. } DISPATCH();
  175. TARGET(STORE_SUBSCR)
  176. _2 = POPX(); // b
  177. _1 = POPX(); // a
  178. _0 = POPX(); // val
  179. _ti = _inst_type_info(_1);
  180. if(_ti->m__setitem__){
  181. _ti->m__setitem__(this, _1, _2, _0);
  182. }else{
  183. call_method(_1, __setitem__, _2, _0);
  184. }
  185. DISPATCH();
  186. TARGET(DELETE_FAST)
  187. _0 = frame->_locals[byte.arg];
  188. if(_0 == nullptr) vm->NameError(co->varnames[byte.arg]);
  189. frame->_locals[byte.arg] = nullptr;
  190. DISPATCH();
  191. TARGET(DELETE_NAME)
  192. _name = StrName(byte.arg);
  193. if(frame->_callable != nullptr){
  194. if(!frame->_locals.contains(_name)) vm->NameError(_name);
  195. frame->_locals.erase(_name);
  196. }else{
  197. if(!frame->f_globals().contains(_name)) vm->NameError(_name);
  198. frame->f_globals().erase(_name);
  199. }
  200. DISPATCH();
  201. TARGET(DELETE_GLOBAL)
  202. _name = StrName(byte.arg);
  203. if(frame->f_globals().contains(_name)){
  204. frame->f_globals().erase(_name);
  205. }else{
  206. NameError(_name);
  207. }
  208. DISPATCH();
  209. TARGET(DELETE_ATTR)
  210. _0 = POPX();
  211. _name = StrName(byte.arg);
  212. if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute");
  213. if(!_0->attr().contains(_name)) AttributeError(_0, _name);
  214. _0->attr().erase(_name);
  215. DISPATCH();
  216. TARGET(DELETE_SUBSCR)
  217. _1 = POPX();
  218. _0 = POPX();
  219. _ti = _inst_type_info(_0);
  220. if(_ti->m__delitem__){
  221. _ti->m__delitem__(this, _0, _1);
  222. }else{
  223. call_method(_0, __delitem__, _1);
  224. }
  225. DISPATCH();
  226. /*****************************************/
  227. TARGET(BUILD_LIST)
  228. _0 = VAR(STACK_VIEW(byte.arg).to_list());
  229. STACK_SHRINK(byte.arg);
  230. PUSH(_0);
  231. DISPATCH();
  232. TARGET(BUILD_DICT)
  233. if(byte.arg == 0){
  234. PUSH(VAR(Dict(this)));
  235. DISPATCH();
  236. }
  237. _0 = VAR(STACK_VIEW(byte.arg).to_list());
  238. _0 = call(_t(tp_dict), _0);
  239. STACK_SHRINK(byte.arg);
  240. PUSH(_0);
  241. DISPATCH();
  242. TARGET(BUILD_SET)
  243. _0 = VAR(STACK_VIEW(byte.arg).to_list());
  244. _0 = call(builtins->attr(set), _0);
  245. STACK_SHRINK(byte.arg);
  246. PUSH(_0);
  247. DISPATCH();
  248. TARGET(BUILD_SLICE)
  249. _2 = POPX(); // step
  250. _1 = POPX(); // stop
  251. _0 = POPX(); // start
  252. PUSH(VAR(Slice(_0, _1, _2)));
  253. DISPATCH();
  254. TARGET(BUILD_TUPLE)
  255. _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
  256. STACK_SHRINK(byte.arg);
  257. PUSH(_0);
  258. DISPATCH();
  259. TARGET(BUILD_STRING) {
  260. std::stringstream ss;
  261. ArgsView view = STACK_VIEW(byte.arg);
  262. for(PyObject* obj : view) ss << CAST(Str&, py_str(obj));
  263. STACK_SHRINK(byte.arg);
  264. PUSH(VAR(ss.str()));
  265. } DISPATCH();
  266. /*****************************************/
  267. #define PREDICT_INT_OP(op) \
  268. if(is_both_int(TOP(), SECOND())){ \
  269. _1 = POPX(); \
  270. _0 = TOP(); \
  271. TOP() = VAR(_CAST(i64, _0) op _CAST(i64, _1)); \
  272. DISPATCH(); \
  273. }
  274. #define BINARY_OP_SPECIAL(func) \
  275. _1 = POPX(); \
  276. _0 = TOP(); \
  277. _ti = _inst_type_info(_0); \
  278. if(_ti->m##func){ \
  279. TOP() = VAR(_ti->m##func(this, _0, _1)); \
  280. }else{ \
  281. TOP() = call_method(_0, func, _1); \
  282. }
  283. TARGET(BINARY_TRUEDIV)
  284. if(is_tagged(SECOND())){
  285. f64 lhs = num_to_float(SECOND());
  286. f64 rhs = num_to_float(TOP());
  287. POP();
  288. TOP() = VAR(lhs / rhs);
  289. DISPATCH();
  290. }
  291. BINARY_OP_SPECIAL(__truediv__);
  292. DISPATCH();
  293. TARGET(BINARY_POW)
  294. BINARY_OP_SPECIAL(__pow__);
  295. DISPATCH();
  296. TARGET(BINARY_ADD)
  297. PREDICT_INT_OP(+);
  298. BINARY_OP_SPECIAL(__add__);
  299. DISPATCH()
  300. TARGET(BINARY_SUB)
  301. PREDICT_INT_OP(-);
  302. BINARY_OP_SPECIAL(__sub__);
  303. DISPATCH()
  304. TARGET(BINARY_MUL)
  305. BINARY_OP_SPECIAL(__mul__);
  306. DISPATCH()
  307. TARGET(BINARY_FLOORDIV)
  308. PREDICT_INT_OP(/);
  309. BINARY_OP_SPECIAL(__floordiv__);
  310. DISPATCH()
  311. TARGET(BINARY_MOD)
  312. PREDICT_INT_OP(%);
  313. BINARY_OP_SPECIAL(__mod__);
  314. DISPATCH()
  315. TARGET(COMPARE_LT)
  316. BINARY_OP_SPECIAL(__lt__);
  317. DISPATCH()
  318. TARGET(COMPARE_LE)
  319. BINARY_OP_SPECIAL(__le__);
  320. DISPATCH()
  321. TARGET(COMPARE_EQ)
  322. _1 = POPX();
  323. _0 = TOP();
  324. TOP() = VAR(py_equals(_0, _1));
  325. DISPATCH()
  326. TARGET(COMPARE_NE)
  327. _1 = POPX();
  328. _0 = TOP();
  329. TOP() = VAR(py_not_equals(_0, _1));
  330. DISPATCH()
  331. TARGET(COMPARE_GT)
  332. BINARY_OP_SPECIAL(__gt__);
  333. DISPATCH()
  334. TARGET(COMPARE_GE)
  335. BINARY_OP_SPECIAL(__ge__);
  336. DISPATCH()
  337. TARGET(BITWISE_LSHIFT)
  338. PREDICT_INT_OP(<<);
  339. BINARY_OP_SPECIAL(__lshift__);
  340. DISPATCH()
  341. TARGET(BITWISE_RSHIFT)
  342. PREDICT_INT_OP(>>);
  343. BINARY_OP_SPECIAL(__rshift__);
  344. DISPATCH()
  345. TARGET(BITWISE_AND)
  346. PREDICT_INT_OP(&);
  347. BINARY_OP_SPECIAL(__and__);
  348. DISPATCH()
  349. TARGET(BITWISE_OR)
  350. PREDICT_INT_OP(|);
  351. BINARY_OP_SPECIAL(__or__);
  352. DISPATCH()
  353. TARGET(BITWISE_XOR)
  354. PREDICT_INT_OP(^);
  355. BINARY_OP_SPECIAL(__xor__);
  356. DISPATCH()
  357. TARGET(BINARY_MATMUL)
  358. BINARY_OP_SPECIAL(__matmul__);
  359. DISPATCH();
  360. #undef BINARY_OP_SPECIAL
  361. #undef PREDICT_INT_OP
  362. TARGET(IS_OP)
  363. _1 = POPX(); // rhs
  364. _0 = TOP(); // lhs
  365. if(byte.arg == 1){
  366. TOP() = VAR(_0 != _1);
  367. }else{
  368. TOP() = VAR(_0 == _1);
  369. }
  370. DISPATCH();
  371. TARGET(CONTAINS_OP)
  372. // a in b -> b __contains__ a
  373. _ti = _inst_type_info(TOP());
  374. if(_ti->m__contains__){
  375. _0 = VAR(_ti->m__contains__(this, TOP(), SECOND()));
  376. }else{
  377. _0 = call_method(TOP(), __contains__, SECOND());
  378. }
  379. POP();
  380. if(byte.arg == 1){
  381. TOP() = VAR(!CAST(bool, _0));
  382. }else{
  383. TOP() = VAR(CAST(bool, _0));
  384. }
  385. DISPATCH();
  386. /*****************************************/
  387. TARGET(JUMP_ABSOLUTE)
  388. frame->jump_abs(byte.arg);
  389. DISPATCH();
  390. TARGET(POP_JUMP_IF_FALSE)
  391. if(!py_bool(POPX())) frame->jump_abs(byte.arg);
  392. DISPATCH();
  393. TARGET(JUMP_IF_TRUE_OR_POP)
  394. if(py_bool(TOP()) == true) frame->jump_abs(byte.arg);
  395. else POP();
  396. DISPATCH();
  397. TARGET(JUMP_IF_FALSE_OR_POP)
  398. if(py_bool(TOP()) == false) frame->jump_abs(byte.arg);
  399. else POP();
  400. DISPATCH();
  401. TARGET(LOOP_CONTINUE)
  402. frame->jump_abs(co_blocks[byte.block].start);
  403. DISPATCH();
  404. TARGET(LOOP_BREAK)
  405. frame->jump_abs_break(co_blocks[byte.block].end);
  406. DISPATCH();
  407. TARGET(GOTO) {
  408. _name = StrName(byte.arg);
  409. int index = co->labels.try_get(_name);
  410. if(index < 0) _error("KeyError", fmt("label ", _name.escape(), " not found"));
  411. frame->jump_abs_break(index);
  412. } DISPATCH();
  413. /*****************************************/
  414. TARGET(BEGIN_CALL)
  415. PUSH(PY_BEGIN_CALL);
  416. DISPATCH();
  417. TARGET(CALL)
  418. _0 = vectorcall(
  419. byte.arg & 0xFFFF, // ARGC
  420. (byte.arg>>16) & 0xFFFF, // KWARGC
  421. true
  422. );
  423. if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
  424. PUSH(_0);
  425. DISPATCH();
  426. TARGET(RETURN_VALUE)
  427. _0 = POPX();
  428. _pop_frame();
  429. if(frame.index == base_id){ // [ frameBase<- ]
  430. return _0;
  431. }else{
  432. frame = top_frame();
  433. PUSH(_0);
  434. goto __NEXT_FRAME;
  435. }
  436. TARGET(YIELD_VALUE)
  437. return PY_OP_YIELD;
  438. /*****************************************/
  439. TARGET(LIST_APPEND)
  440. _0 = POPX();
  441. CAST(List&, SECOND()).push_back(_0);
  442. DISPATCH();
  443. TARGET(DICT_ADD) {
  444. _0 = POPX();
  445. Tuple& t = CAST(Tuple&, _0);
  446. call_method(SECOND(), __setitem__, t[0], t[1]);
  447. } DISPATCH();
  448. TARGET(SET_ADD)
  449. _0 = POPX();
  450. call_method(SECOND(), add, _0);
  451. DISPATCH();
  452. /*****************************************/
  453. TARGET(UNARY_NEGATIVE)
  454. TOP() = py_negate(TOP());
  455. DISPATCH();
  456. TARGET(UNARY_NOT)
  457. TOP() = VAR(!py_bool(TOP()));
  458. DISPATCH();
  459. /*****************************************/
  460. TARGET(GET_ITER)
  461. TOP() = py_iter(TOP());
  462. DISPATCH();
  463. TARGET(FOR_ITER)
  464. _0 = PyIterNext(TOP());
  465. if(_0 != StopIteration){
  466. PUSH(_0);
  467. }else{
  468. frame->jump_abs_break(co_blocks[byte.block].end);
  469. }
  470. DISPATCH();
  471. /*****************************************/
  472. TARGET(IMPORT_NAME) {
  473. StrName name(byte.arg);
  474. PyObject* ext_mod = _modules.try_get(name);
  475. if(ext_mod == nullptr){
  476. Str source;
  477. auto it = _lazy_modules.find(name);
  478. if(it == _lazy_modules.end()){
  479. Bytes b = _read_file_cwd(fmt(name, ".py"));
  480. if(!b) _error("ImportError", fmt("module ", name.escape(), " not found"));
  481. source = Str(b.str());
  482. }else{
  483. source = it->second;
  484. _lazy_modules.erase(it);
  485. }
  486. CodeObject_ code = compile(source, Str(name.sv())+".py", EXEC_MODE);
  487. PyObject* new_mod = new_module(name);
  488. _exec(code, new_mod);
  489. new_mod->attr()._try_perfect_rehash();
  490. PUSH(new_mod);
  491. }else{
  492. PUSH(ext_mod);
  493. }
  494. } DISPATCH();
  495. TARGET(IMPORT_STAR)
  496. _0 = POPX();
  497. for(auto& [name, value]: _0->attr().items()){
  498. std::string_view s = name.sv();
  499. if(s.empty() || s[0] == '_') continue;
  500. frame->f_globals().set(name, value);
  501. }
  502. DISPATCH();
  503. /*****************************************/
  504. TARGET(UNPACK_SEQUENCE)
  505. TARGET(UNPACK_EX) {
  506. auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
  507. _0 = py_iter(POPX());
  508. for(int i=0; i<byte.arg; i++){
  509. _1 = PyIterNext(_0);
  510. if(_1 == StopIteration) ValueError("not enough values to unpack");
  511. PUSH(_1);
  512. }
  513. // handle extra items
  514. if(byte.op == OP_UNPACK_EX){
  515. List extras;
  516. while(true){
  517. _1 = PyIterNext(_0);
  518. if(_1 == StopIteration) break;
  519. extras.push_back(_1);
  520. }
  521. PUSH(VAR(extras));
  522. }else{
  523. if(PyIterNext(_0) != StopIteration) ValueError("too many values to unpack");
  524. }
  525. } DISPATCH();
  526. TARGET(UNPACK_UNLIMITED) {
  527. auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
  528. _0 = py_iter(POPX());
  529. _1 = PyIterNext(_0);
  530. while(_1 != StopIteration){
  531. PUSH(_1);
  532. _1 = PyIterNext(_0);
  533. }
  534. } DISPATCH();
  535. /*****************************************/
  536. TARGET(BEGIN_CLASS)
  537. _name = StrName(byte.arg);
  538. _0 = POPX(); // super
  539. if(_0 == None) _0 = _t(tp_object);
  540. check_non_tagged_type(_0, tp_type);
  541. _1 = new_type_object(frame->_module, _name, OBJ_GET(Type, _0));
  542. PUSH(_1);
  543. DISPATCH();
  544. TARGET(END_CLASS)
  545. _0 = POPX();
  546. _0->attr()._try_perfect_rehash();
  547. DISPATCH();
  548. TARGET(STORE_CLASS_ATTR)
  549. _name = StrName(byte.arg);
  550. _0 = POPX();
  551. TOP()->attr().set(_name, _0);
  552. DISPATCH();
  553. /*****************************************/
  554. // TODO: using "goto" inside with block may cause __exit__ not called
  555. TARGET(WITH_ENTER)
  556. call_method(POPX(), __enter__);
  557. DISPATCH();
  558. TARGET(WITH_EXIT)
  559. call_method(POPX(), __exit__);
  560. DISPATCH();
  561. /*****************************************/
  562. TARGET(ASSERT) {
  563. _0 = TOP();
  564. Str msg;
  565. if(is_type(_0, tp_tuple)){
  566. auto& t = CAST(Tuple&, _0);
  567. if(t.size() != 2) ValueError("assert tuple must have 2 elements");
  568. _0 = t[0];
  569. msg = CAST(Str&, py_str(t[1]));
  570. }
  571. bool ok = py_bool(_0);
  572. POP();
  573. if(!ok) _error("AssertionError", msg);
  574. } DISPATCH();
  575. TARGET(EXCEPTION_MATCH) {
  576. const auto& e = CAST(Exception&, TOP());
  577. _name = StrName(byte.arg);
  578. PUSH(VAR(e.match_type(_name)));
  579. } DISPATCH();
  580. TARGET(RAISE) {
  581. _0 = POPX();
  582. Str msg = _0 == None ? "" : CAST(Str, py_str(_0));
  583. _error(StrName(byte.arg), msg);
  584. } DISPATCH();
  585. TARGET(RE_RAISE) _raise(); DISPATCH();
  586. /*****************************************/
  587. TARGET(SETUP_DOCSTRING)
  588. TOP()->attr().set(__doc__, co_consts[byte.arg]);
  589. DISPATCH();
  590. TARGET(FORMAT_STRING) {
  591. _0 = POPX();
  592. const Str& spec = CAST(Str&, co_consts[byte.arg]);
  593. PUSH(format(spec, _0));
  594. } DISPATCH();
  595. #if !PK_ENABLE_COMPUTED_GOTO
  596. #if DEBUG_EXTRA_CHECK
  597. default: throw std::runtime_error(fmt(OP_NAMES[byte.op], " is not implemented"));
  598. #else
  599. default: UNREACHABLE();
  600. #endif
  601. }
  602. #endif
  603. }
  604. #undef DISPATCH
  605. #undef TARGET
  606. #undef DISPATCH_OP_CALL
  607. /**********************************************************************/
  608. UNREACHABLE();
  609. }catch(HandledException& e){
  610. continue;
  611. }catch(UnhandledException& e){
  612. PyObject* obj = POPX();
  613. Exception& _e = CAST(Exception&, obj);
  614. _e.st_push(frame->snapshot());
  615. _pop_frame();
  616. if(callstack.empty()){
  617. #if DEBUG_FULL_EXCEPTION
  618. std::cerr << _e.summary() << std::endl;
  619. #endif
  620. throw _e;
  621. }
  622. frame = top_frame();
  623. PUSH(obj);
  624. if(frame.index < base_id) throw ToBeRaisedException();
  625. need_raise = true;
  626. }catch(ToBeRaisedException& e){
  627. need_raise = true;
  628. }
  629. }
  630. }
  631. #undef TOP
  632. #undef SECOND
  633. #undef THIRD
  634. #undef PEEK
  635. #undef STACK_SHRINK
  636. #undef PUSH
  637. #undef POP
  638. #undef POPX
  639. #undef STACK_VIEW
  640. #undef DISPATCH
  641. #undef TARGET
  642. #undef DISPATCH_OP_CALL
  643. } // namespace pkpy