expr.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. #include "pocketpy/expr.h"
  2. namespace pkpy{
  3. bool CodeEmitContext::is_curr_block_loop() const {
  4. return co->blocks[curr_block_i].type == FOR_LOOP || co->blocks[curr_block_i].type == WHILE_LOOP;
  5. }
  6. void CodeEmitContext::enter_block(CodeBlockType type){
  7. if(type == FOR_LOOP) for_loop_depth++;
  8. co->blocks.push_back(CodeBlock(
  9. type, curr_block_i, for_loop_depth, (int)co->codes.size()
  10. ));
  11. curr_block_i = co->blocks.size()-1;
  12. }
  13. void CodeEmitContext::exit_block(){
  14. auto curr_type = co->blocks[curr_block_i].type;
  15. if(curr_type == FOR_LOOP) for_loop_depth--;
  16. co->blocks[curr_block_i].end = co->codes.size();
  17. curr_block_i = co->blocks[curr_block_i].parent;
  18. if(curr_block_i < 0) FATAL_ERROR();
  19. if(curr_type == FOR_LOOP){
  20. // add a no op here to make block check work
  21. emit(OP_NO_OP, BC_NOARG, BC_KEEPLINE);
  22. }
  23. }
  24. // clear the expression stack and generate bytecode
  25. void CodeEmitContext::emit_expr(){
  26. if(s_expr.size() != 1){
  27. throw std::runtime_error("s_expr.size() != 1\n" + _log_s_expr());
  28. }
  29. Expr_ expr = s_expr.popx();
  30. expr->emit(this);
  31. }
  32. std::string CodeEmitContext::_log_s_expr(){
  33. std::stringstream ss;
  34. for(auto& e: s_expr.data()) ss << e->str() << " ";
  35. return ss.str();
  36. }
  37. int CodeEmitContext::emit(Opcode opcode, int arg, int line) {
  38. co->codes.push_back(
  39. Bytecode{(uint16_t)opcode, (uint16_t)curr_block_i, arg}
  40. );
  41. co->lines.push_back(line);
  42. int i = co->codes.size() - 1;
  43. if(line==BC_KEEPLINE){
  44. if(i>=1) co->lines[i] = co->lines[i-1];
  45. else co->lines[i] = 1;
  46. }
  47. return i;
  48. }
  49. void CodeEmitContext::patch_jump(int index) {
  50. int target = co->codes.size();
  51. co->codes[index].arg = target;
  52. }
  53. bool CodeEmitContext::add_label(StrName name){
  54. if(co->labels.contains(name)) return false;
  55. co->labels.set(name, co->codes.size());
  56. return true;
  57. }
  58. int CodeEmitContext::add_varname(StrName name){
  59. int index = co->varnames_inv.try_get(name);
  60. if(index >= 0) return index;
  61. co->varnames.push_back(name);
  62. index = co->varnames.size() - 1;
  63. co->varnames_inv.set(name, index);
  64. return index;
  65. }
  66. int CodeEmitContext::add_const(PyObject* v){
  67. // simple deduplication, only works for int/float
  68. for(int i=0; i<co->consts.size(); i++){
  69. if(co->consts[i] == v) return i;
  70. }
  71. co->consts.push_back(v);
  72. return co->consts.size() - 1;
  73. }
  74. int CodeEmitContext::add_func_decl(FuncDecl_ decl){
  75. co->func_decls.push_back(decl);
  76. return co->func_decls.size() - 1;
  77. }
  78. void NameExpr::emit(CodeEmitContext* ctx) {
  79. int index = ctx->co->varnames_inv.try_get(name);
  80. if(scope == NAME_LOCAL && index >= 0){
  81. ctx->emit(OP_LOAD_FAST, index, line);
  82. }else{
  83. Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
  84. // we cannot determine the scope when calling exec()/eval()
  85. if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
  86. ctx->emit(op, StrName(name).index, line);
  87. }
  88. }
  89. bool NameExpr::emit_del(CodeEmitContext* ctx) {
  90. switch(scope){
  91. case NAME_LOCAL:
  92. ctx->emit(OP_DELETE_FAST, ctx->add_varname(name), line);
  93. break;
  94. case NAME_GLOBAL:
  95. ctx->emit(OP_DELETE_GLOBAL, StrName(name).index, line);
  96. break;
  97. case NAME_GLOBAL_UNKNOWN:
  98. ctx->emit(OP_DELETE_NAME, StrName(name).index, line);
  99. break;
  100. default: FATAL_ERROR(); break;
  101. }
  102. return true;
  103. }
  104. bool NameExpr::emit_store(CodeEmitContext* ctx) {
  105. if(ctx->is_compiling_class){
  106. int index = StrName(name).index;
  107. ctx->emit(OP_STORE_CLASS_ATTR, index, line);
  108. return true;
  109. }
  110. switch(scope){
  111. case NAME_LOCAL:
  112. ctx->emit(OP_STORE_FAST, ctx->add_varname(name), line);
  113. break;
  114. case NAME_GLOBAL:
  115. ctx->emit(OP_STORE_GLOBAL, StrName(name).index, line);
  116. break;
  117. case NAME_GLOBAL_UNKNOWN:
  118. ctx->emit(OP_STORE_NAME, StrName(name).index, line);
  119. break;
  120. default: FATAL_ERROR(); break;
  121. }
  122. return true;
  123. }
  124. void InvertExpr::emit(CodeEmitContext* ctx) {
  125. child->emit(ctx);
  126. ctx->emit(OP_UNARY_INVERT, BC_NOARG, line);
  127. }
  128. void StarredExpr::emit(CodeEmitContext* ctx) {
  129. child->emit(ctx);
  130. ctx->emit(OP_UNARY_STAR, level, line);
  131. }
  132. bool StarredExpr::emit_store(CodeEmitContext* ctx) {
  133. if(level != 1) return false;
  134. // simply proxy to child
  135. return child->emit_store(ctx);
  136. }
  137. void NotExpr::emit(CodeEmitContext* ctx) {
  138. child->emit(ctx);
  139. ctx->emit(OP_UNARY_NOT, BC_NOARG, line);
  140. }
  141. void AndExpr::emit(CodeEmitContext* ctx) {
  142. lhs->emit(ctx);
  143. int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
  144. rhs->emit(ctx);
  145. ctx->patch_jump(patch);
  146. }
  147. void OrExpr::emit(CodeEmitContext* ctx) {
  148. lhs->emit(ctx);
  149. int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
  150. rhs->emit(ctx);
  151. ctx->patch_jump(patch);
  152. }
  153. void Literal0Expr::emit(CodeEmitContext* ctx){
  154. switch (token) {
  155. case TK("None"): ctx->emit(OP_LOAD_NONE, BC_NOARG, line); break;
  156. case TK("True"): ctx->emit(OP_LOAD_TRUE, BC_NOARG, line); break;
  157. case TK("False"): ctx->emit(OP_LOAD_FALSE, BC_NOARG, line); break;
  158. case TK("..."): ctx->emit(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
  159. default: FATAL_ERROR();
  160. }
  161. }
  162. void LongExpr::emit(CodeEmitContext* ctx) {
  163. VM* vm = ctx->vm;
  164. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
  165. ctx->emit(OP_BUILD_LONG, BC_NOARG, line);
  166. }
  167. std::string LiteralExpr::str() const{
  168. if(std::holds_alternative<i64>(value)){
  169. return std::to_string(std::get<i64>(value));
  170. }
  171. if(std::holds_alternative<f64>(value)){
  172. return std::to_string(std::get<f64>(value));
  173. }
  174. if(std::holds_alternative<Str>(value)){
  175. Str s = std::get<Str>(value).escape();
  176. return s.str();
  177. }
  178. FATAL_ERROR();
  179. }
  180. void LiteralExpr::emit(CodeEmitContext* ctx) {
  181. VM* vm = ctx->vm;
  182. PyObject* obj = nullptr;
  183. if(std::holds_alternative<i64>(value)){
  184. i64 _val = std::get<i64>(value);
  185. if(_val >= INT16_MIN && _val <= INT16_MAX){
  186. ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
  187. return;
  188. }
  189. obj = VAR(_val);
  190. }
  191. if(std::holds_alternative<f64>(value)){
  192. obj = VAR(std::get<f64>(value));
  193. }
  194. if(std::holds_alternative<Str>(value)){
  195. obj = VAR(std::get<Str>(value));
  196. }
  197. if(obj == nullptr) FATAL_ERROR();
  198. ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
  199. }
  200. void NegatedExpr::emit(CodeEmitContext* ctx){
  201. VM* vm = ctx->vm;
  202. // if child is a int of float, do constant folding
  203. if(child->is_literal()){
  204. LiteralExpr* lit = static_cast<LiteralExpr*>(child.get());
  205. if(std::holds_alternative<i64>(lit->value)){
  206. i64 _val = -std::get<i64>(lit->value);
  207. if(_val >= INT16_MIN && _val <= INT16_MAX){
  208. ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
  209. }else{
  210. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
  211. }
  212. return;
  213. }
  214. if(std::holds_alternative<f64>(lit->value)){
  215. PyObject* obj = VAR(-std::get<f64>(lit->value));
  216. ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
  217. return;
  218. }
  219. }
  220. child->emit(ctx);
  221. ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
  222. }
  223. void SliceExpr::emit(CodeEmitContext* ctx){
  224. if(start){
  225. start->emit(ctx);
  226. }else{
  227. ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
  228. }
  229. if(stop){
  230. stop->emit(ctx);
  231. }else{
  232. ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
  233. }
  234. if(step){
  235. step->emit(ctx);
  236. }else{
  237. ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
  238. }
  239. ctx->emit(OP_BUILD_SLICE, BC_NOARG, line);
  240. }
  241. void DictItemExpr::emit(CodeEmitContext* ctx) {
  242. if(is_starred()){
  243. PK_ASSERT(key == nullptr);
  244. value->emit(ctx);
  245. }else{
  246. value->emit(ctx);
  247. key->emit(ctx); // reverse order
  248. ctx->emit(OP_BUILD_TUPLE, 2, line);
  249. }
  250. }
  251. bool TupleExpr::emit_store(CodeEmitContext* ctx) {
  252. // TOS is an iterable
  253. // items may contain StarredExpr, we should check it
  254. int starred_i = -1;
  255. for(int i=0; i<items.size(); i++){
  256. if(!items[i]->is_starred()) continue;
  257. if(starred_i == -1) starred_i = i;
  258. else return false; // multiple StarredExpr not allowed
  259. }
  260. if(starred_i == -1){
  261. Bytecode& prev = ctx->co->codes.back();
  262. if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()){
  263. // build tuple and unpack it is meaningless
  264. prev.op = OP_NO_OP;
  265. prev.arg = BC_NOARG;
  266. }else{
  267. ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
  268. }
  269. }else{
  270. // starred assignment target must be in a tuple
  271. if(items.size() == 1) return false;
  272. // starred assignment target must be the last one (differ from cpython)
  273. if(starred_i != items.size()-1) return false;
  274. // a,*b = [1,2,3]
  275. // stack is [1,2,3] -> [1,[2,3]]
  276. ctx->emit(OP_UNPACK_EX, items.size()-1, line);
  277. }
  278. // do reverse emit
  279. for(int i=items.size()-1; i>=0; i--){
  280. bool ok = items[i]->emit_store(ctx);
  281. if(!ok) return false;
  282. }
  283. return true;
  284. }
  285. bool TupleExpr::emit_del(CodeEmitContext* ctx){
  286. for(auto& e: items){
  287. bool ok = e->emit_del(ctx);
  288. if(!ok) return false;
  289. }
  290. return true;
  291. }
  292. void CompExpr::emit(CodeEmitContext* ctx){
  293. ctx->emit(op0(), 0, line);
  294. iter->emit(ctx);
  295. ctx->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
  296. ctx->enter_block(FOR_LOOP);
  297. ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
  298. bool ok = vars->emit_store(ctx);
  299. // this error occurs in `vars` instead of this line, but...nevermind
  300. PK_ASSERT(ok); // TODO: raise a SyntaxError instead
  301. if(cond){
  302. cond->emit(ctx);
  303. int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
  304. expr->emit(ctx);
  305. ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
  306. ctx->patch_jump(patch);
  307. }else{
  308. expr->emit(ctx);
  309. ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
  310. }
  311. ctx->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
  312. ctx->exit_block();
  313. }
  314. void FStringExpr::_load_simple_expr(CodeEmitContext* ctx, Str expr){
  315. // TODO: pre compile this into a function
  316. int dot = expr.index(".");
  317. if(dot < 0){
  318. ctx->emit(OP_LOAD_NAME, StrName(expr.sv()).index, line);
  319. }else{
  320. StrName name(expr.substr(0, dot).sv());
  321. StrName attr(expr.substr(dot+1).sv());
  322. ctx->emit(OP_LOAD_NAME, name.index, line);
  323. ctx->emit(OP_LOAD_ATTR, attr.index, line);
  324. }
  325. }
  326. void FStringExpr::emit(CodeEmitContext* ctx){
  327. VM* vm = ctx->vm;
  328. static const std::regex pattern(R"(\{(.*?)\})");
  329. std::cregex_iterator begin(src.begin(), src.end(), pattern);
  330. std::cregex_iterator end;
  331. int size = 0;
  332. int i = 0;
  333. for(auto it = begin; it != end; it++) {
  334. std::cmatch m = *it;
  335. if (i < m.position()) {
  336. Str literal = src.substr(i, m.position() - i);
  337. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
  338. size++;
  339. }
  340. Str expr = m[1].str();
  341. int conon = expr.index(":");
  342. if(conon >= 0){
  343. _load_simple_expr(ctx, expr.substr(0, conon));
  344. Str spec = expr.substr(conon+1);
  345. ctx->emit(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
  346. }else{
  347. _load_simple_expr(ctx, expr);
  348. }
  349. size++;
  350. i = (int)(m.position() + m.length());
  351. }
  352. if (i < src.length()) {
  353. Str literal = src.substr(i, src.length() - i);
  354. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
  355. size++;
  356. }
  357. ctx->emit(OP_BUILD_STRING, size, line);
  358. }
  359. void SubscrExpr::emit(CodeEmitContext* ctx){
  360. a->emit(ctx);
  361. b->emit(ctx);
  362. ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line);
  363. }
  364. bool SubscrExpr::emit_del(CodeEmitContext* ctx){
  365. a->emit(ctx);
  366. b->emit(ctx);
  367. ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line);
  368. return true;
  369. }
  370. bool SubscrExpr::emit_store(CodeEmitContext* ctx){
  371. a->emit(ctx);
  372. b->emit(ctx);
  373. ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line);
  374. return true;
  375. }
  376. void AttribExpr::emit(CodeEmitContext* ctx){
  377. a->emit(ctx);
  378. int index = StrName(b).index;
  379. ctx->emit(OP_LOAD_ATTR, index, line);
  380. }
  381. bool AttribExpr::emit_del(CodeEmitContext* ctx) {
  382. a->emit(ctx);
  383. int index = StrName(b).index;
  384. ctx->emit(OP_DELETE_ATTR, index, line);
  385. return true;
  386. }
  387. bool AttribExpr::emit_store(CodeEmitContext* ctx){
  388. a->emit(ctx);
  389. int index = StrName(b).index;
  390. ctx->emit(OP_STORE_ATTR, index, line);
  391. return true;
  392. }
  393. void AttribExpr::emit_method(CodeEmitContext* ctx) {
  394. a->emit(ctx);
  395. int index = StrName(b).index;
  396. ctx->emit(OP_LOAD_METHOD, index, line);
  397. }
  398. void CallExpr::emit(CodeEmitContext* ctx) {
  399. bool vargs = false;
  400. bool vkwargs = false;
  401. for(auto& arg: args) if(arg->is_starred()) vargs = true;
  402. for(auto& item: kwargs) if(item.second->is_starred()) vkwargs = true;
  403. // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
  404. if(callable->is_attrib()){
  405. auto p = static_cast<AttribExpr*>(callable.get());
  406. p->emit_method(ctx); // OP_LOAD_METHOD
  407. }else{
  408. callable->emit(ctx);
  409. ctx->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
  410. }
  411. if(vargs || vkwargs){
  412. for(auto& item: args) item->emit(ctx);
  413. ctx->emit(OP_BUILD_TUPLE_UNPACK, (int)args.size(), line);
  414. if(!kwargs.empty()){
  415. for(auto& item: kwargs){
  416. if(item.second->is_starred()){
  417. if(item.second->star_level() != 2) FATAL_ERROR();
  418. item.second->emit(ctx);
  419. }else{
  420. // k=v
  421. int index = ctx->add_const(py_var(ctx->vm, item.first));
  422. ctx->emit(OP_LOAD_CONST, index, line);
  423. item.second->emit(ctx);
  424. ctx->emit(OP_BUILD_TUPLE, 2, line);
  425. }
  426. }
  427. ctx->emit(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
  428. ctx->emit(OP_CALL_TP, 1, line);
  429. }else{
  430. ctx->emit(OP_CALL_TP, 0, line);
  431. }
  432. }else{
  433. // vectorcall protocal
  434. for(auto& item: args) item->emit(ctx);
  435. for(auto& item: kwargs){
  436. int index = StrName(item.first.sv()).index;
  437. ctx->emit(OP_LOAD_INTEGER, index, line);
  438. item.second->emit(ctx);
  439. }
  440. int KWARGC = (int)kwargs.size();
  441. int ARGC = (int)args.size();
  442. ctx->emit(OP_CALL, (KWARGC<<16)|ARGC, line);
  443. }
  444. }
  445. bool BinaryExpr::is_compare() const {
  446. switch(op){
  447. case TK("<"): case TK("<="): case TK("=="):
  448. case TK("!="): case TK(">"): case TK(">="): return true;
  449. default: return false;
  450. }
  451. }
  452. void BinaryExpr::_emit_compare(CodeEmitContext* ctx, std::vector<int>& jmps){
  453. if(lhs->is_compare()){
  454. static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
  455. }else{
  456. lhs->emit(ctx); // [a]
  457. }
  458. rhs->emit(ctx); // [a, b]
  459. ctx->emit(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
  460. ctx->emit(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
  461. switch(op){
  462. case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
  463. case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
  464. case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
  465. case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
  466. case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
  467. case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
  468. default: UNREACHABLE();
  469. }
  470. // [b, RES]
  471. int index = ctx->emit(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
  472. jmps.push_back(index);
  473. }
  474. void BinaryExpr::emit(CodeEmitContext* ctx) {
  475. std::vector<int> jmps;
  476. if(is_compare() && lhs->is_compare()){
  477. // (a < b) < c
  478. static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
  479. // [b, RES]
  480. }else{
  481. // (1 + 2) < c
  482. lhs->emit(ctx);
  483. }
  484. rhs->emit(ctx);
  485. switch (op) {
  486. case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
  487. case TK("-"): ctx->emit(OP_BINARY_SUB, BC_NOARG, line); break;
  488. case TK("*"): ctx->emit(OP_BINARY_MUL, BC_NOARG, line); break;
  489. case TK("/"): ctx->emit(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
  490. case TK("//"): ctx->emit(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
  491. case TK("%"): ctx->emit(OP_BINARY_MOD, BC_NOARG, line); break;
  492. case TK("**"): ctx->emit(OP_BINARY_POW, BC_NOARG, line); break;
  493. case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
  494. case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
  495. case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
  496. case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
  497. case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
  498. case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
  499. case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break;
  500. case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break;
  501. case TK("is"): ctx->emit(OP_IS_OP, 0, line); break;
  502. case TK("is not"): ctx->emit(OP_IS_OP, 1, line); break;
  503. case TK("<<"): ctx->emit(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
  504. case TK(">>"): ctx->emit(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
  505. case TK("&"): ctx->emit(OP_BITWISE_AND, BC_NOARG, line); break;
  506. case TK("|"): ctx->emit(OP_BITWISE_OR, BC_NOARG, line); break;
  507. case TK("^"): ctx->emit(OP_BITWISE_XOR, BC_NOARG, line); break;
  508. case TK("@"): ctx->emit(OP_BINARY_MATMUL, BC_NOARG, line); break;
  509. default: FATAL_ERROR();
  510. }
  511. for(int i: jmps) ctx->patch_jump(i);
  512. }
  513. void TernaryExpr::emit(CodeEmitContext* ctx){
  514. cond->emit(ctx);
  515. int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
  516. true_expr->emit(ctx);
  517. int patch_2 = ctx->emit(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
  518. ctx->patch_jump(patch);
  519. false_expr->emit(ctx);
  520. ctx->patch_jump(patch_2);
  521. }
  522. } // namespace pkpy