expr.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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. void BytesExpr::emit(CodeEmitContext* ctx) {
  168. VM* vm = ctx->vm;
  169. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(s)), line);
  170. ctx->emit(OP_BUILD_BYTES, BC_NOARG, line);
  171. }
  172. void LiteralExpr::emit(CodeEmitContext* ctx) {
  173. VM* vm = ctx->vm;
  174. PyObject* obj = nullptr;
  175. if(std::holds_alternative<i64>(value)){
  176. i64 _val = std::get<i64>(value);
  177. if(_val >= INT16_MIN && _val <= INT16_MAX){
  178. ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
  179. return;
  180. }
  181. obj = VAR(_val);
  182. }
  183. if(std::holds_alternative<f64>(value)){
  184. obj = VAR(std::get<f64>(value));
  185. }
  186. if(std::holds_alternative<Str>(value)){
  187. obj = VAR(std::get<Str>(value));
  188. }
  189. if(obj == nullptr) FATAL_ERROR();
  190. ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
  191. }
  192. void NegatedExpr::emit(CodeEmitContext* ctx){
  193. VM* vm = ctx->vm;
  194. // if child is a int of float, do constant folding
  195. if(child->is_literal()){
  196. LiteralExpr* lit = static_cast<LiteralExpr*>(child.get());
  197. if(std::holds_alternative<i64>(lit->value)){
  198. i64 _val = -std::get<i64>(lit->value);
  199. if(_val >= INT16_MIN && _val <= INT16_MAX){
  200. ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
  201. }else{
  202. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
  203. }
  204. return;
  205. }
  206. if(std::holds_alternative<f64>(lit->value)){
  207. PyObject* obj = VAR(-std::get<f64>(lit->value));
  208. ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
  209. return;
  210. }
  211. }
  212. child->emit(ctx);
  213. ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
  214. }
  215. void SliceExpr::emit(CodeEmitContext* ctx){
  216. if(start){
  217. start->emit(ctx);
  218. }else{
  219. ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
  220. }
  221. if(stop){
  222. stop->emit(ctx);
  223. }else{
  224. ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
  225. }
  226. if(step){
  227. step->emit(ctx);
  228. }else{
  229. ctx->emit(OP_LOAD_NONE, BC_NOARG, line);
  230. }
  231. ctx->emit(OP_BUILD_SLICE, BC_NOARG, line);
  232. }
  233. void DictItemExpr::emit(CodeEmitContext* ctx) {
  234. if(is_starred()){
  235. PK_ASSERT(key == nullptr);
  236. value->emit(ctx);
  237. }else{
  238. value->emit(ctx);
  239. key->emit(ctx); // reverse order
  240. ctx->emit(OP_BUILD_TUPLE, 2, line);
  241. }
  242. }
  243. bool TupleExpr::emit_store(CodeEmitContext* ctx) {
  244. // TOS is an iterable
  245. // items may contain StarredExpr, we should check it
  246. int starred_i = -1;
  247. for(int i=0; i<items.size(); i++){
  248. if(!items[i]->is_starred()) continue;
  249. if(starred_i == -1) starred_i = i;
  250. else return false; // multiple StarredExpr not allowed
  251. }
  252. if(starred_i == -1){
  253. Bytecode& prev = ctx->co->codes.back();
  254. if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()){
  255. // build tuple and unpack it is meaningless
  256. prev.op = OP_NO_OP;
  257. prev.arg = BC_NOARG;
  258. }else{
  259. ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
  260. }
  261. }else{
  262. // starred assignment target must be in a tuple
  263. if(items.size() == 1) return false;
  264. // starred assignment target must be the last one (differ from cpython)
  265. if(starred_i != items.size()-1) return false;
  266. // a,*b = [1,2,3]
  267. // stack is [1,2,3] -> [1,[2,3]]
  268. ctx->emit(OP_UNPACK_EX, items.size()-1, line);
  269. }
  270. // do reverse emit
  271. for(int i=items.size()-1; i>=0; i--){
  272. bool ok = items[i]->emit_store(ctx);
  273. if(!ok) return false;
  274. }
  275. return true;
  276. }
  277. bool TupleExpr::emit_del(CodeEmitContext* ctx){
  278. for(auto& e: items){
  279. bool ok = e->emit_del(ctx);
  280. if(!ok) return false;
  281. }
  282. return true;
  283. }
  284. void CompExpr::emit(CodeEmitContext* ctx){
  285. ctx->emit(op0(), 0, line);
  286. iter->emit(ctx);
  287. ctx->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
  288. ctx->enter_block(FOR_LOOP);
  289. ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
  290. bool ok = vars->emit_store(ctx);
  291. // this error occurs in `vars` instead of this line, but...nevermind
  292. PK_ASSERT(ok); // TODO: raise a SyntaxError instead
  293. if(cond){
  294. cond->emit(ctx);
  295. int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
  296. expr->emit(ctx);
  297. ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
  298. ctx->patch_jump(patch);
  299. }else{
  300. expr->emit(ctx);
  301. ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
  302. }
  303. ctx->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
  304. ctx->exit_block();
  305. }
  306. void FStringExpr::_load_simple_expr(CodeEmitContext* ctx, Str expr){
  307. // name or name.name
  308. std::regex pattern(R"(^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*){0,1}$)");
  309. if(std::regex_match(expr.str(), pattern)){
  310. int dot = expr.index(".");
  311. if(dot < 0){
  312. ctx->emit(OP_LOAD_NAME, StrName(expr.sv()).index, line);
  313. }else{
  314. StrName name(expr.substr(0, dot).sv());
  315. StrName attr(expr.substr(dot+1).sv());
  316. ctx->emit(OP_LOAD_NAME, name.index, line);
  317. ctx->emit(OP_LOAD_ATTR, attr.index, line);
  318. }
  319. }else{
  320. int index = ctx->add_const(py_var(ctx->vm, expr));
  321. ctx->emit(OP_LOAD_CONST, index, line);
  322. ctx->emit(OP_EVAL, BC_NOARG, line);
  323. }
  324. }
  325. void FStringExpr::emit(CodeEmitContext* ctx){
  326. VM* vm = ctx->vm;
  327. PK_LOCAL_STATIC const std::regex pattern(R"(\{(.*?)\})");
  328. std::cregex_iterator begin(src.begin(), src.end(), pattern);
  329. std::cregex_iterator end;
  330. int size = 0;
  331. int i = 0;
  332. for(auto it = begin; it != end; it++) {
  333. std::cmatch m = *it;
  334. if (i < m.position()) {
  335. Str literal = src.substr(i, m.position() - i);
  336. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
  337. size++;
  338. }
  339. Str expr = m[1].str();
  340. int conon = expr.index(":");
  341. if(conon >= 0){
  342. _load_simple_expr(ctx, expr.substr(0, conon));
  343. Str spec = expr.substr(conon+1);
  344. ctx->emit(OP_FORMAT_STRING, ctx->add_const(VAR(spec)), line);
  345. }else{
  346. _load_simple_expr(ctx, expr);
  347. }
  348. size++;
  349. i = (int)(m.position() + m.length());
  350. }
  351. if (i < src.length()) {
  352. Str literal = src.substr(i, src.length() - i);
  353. ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(literal)), line);
  354. size++;
  355. }
  356. ctx->emit(OP_BUILD_STRING, size, line);
  357. }
  358. void SubscrExpr::emit(CodeEmitContext* ctx){
  359. a->emit(ctx);
  360. b->emit(ctx);
  361. ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line);
  362. }
  363. bool SubscrExpr::emit_del(CodeEmitContext* ctx){
  364. a->emit(ctx);
  365. b->emit(ctx);
  366. ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line);
  367. return true;
  368. }
  369. bool SubscrExpr::emit_store(CodeEmitContext* ctx){
  370. a->emit(ctx);
  371. b->emit(ctx);
  372. ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line);
  373. return true;
  374. }
  375. void AttribExpr::emit(CodeEmitContext* ctx){
  376. a->emit(ctx);
  377. int index = StrName(b).index;
  378. ctx->emit(OP_LOAD_ATTR, index, line);
  379. }
  380. bool AttribExpr::emit_del(CodeEmitContext* ctx) {
  381. a->emit(ctx);
  382. int index = StrName(b).index;
  383. ctx->emit(OP_DELETE_ATTR, index, line);
  384. return true;
  385. }
  386. bool AttribExpr::emit_store(CodeEmitContext* ctx){
  387. a->emit(ctx);
  388. int index = StrName(b).index;
  389. ctx->emit(OP_STORE_ATTR, index, line);
  390. return true;
  391. }
  392. void AttribExpr::emit_method(CodeEmitContext* ctx) {
  393. a->emit(ctx);
  394. int index = StrName(b).index;
  395. ctx->emit(OP_LOAD_METHOD, index, line);
  396. }
  397. void CallExpr::emit(CodeEmitContext* ctx) {
  398. bool vargs = false;
  399. bool vkwargs = false;
  400. for(auto& arg: args) if(arg->is_starred()) vargs = true;
  401. for(auto& item: kwargs) if(item.second->is_starred()) vkwargs = true;
  402. // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
  403. if(callable->is_attrib()){
  404. auto p = static_cast<AttribExpr*>(callable.get());
  405. p->emit_method(ctx); // OP_LOAD_METHOD
  406. }else{
  407. callable->emit(ctx);
  408. ctx->emit(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
  409. }
  410. if(vargs || vkwargs){
  411. for(auto& item: args) item->emit(ctx);
  412. ctx->emit(OP_BUILD_TUPLE_UNPACK, (int)args.size(), line);
  413. if(!kwargs.empty()){
  414. for(auto& item: kwargs){
  415. if(item.second->is_starred()){
  416. if(item.second->star_level() != 2) FATAL_ERROR();
  417. item.second->emit(ctx);
  418. }else{
  419. // k=v
  420. int index = ctx->add_const(py_var(ctx->vm, item.first));
  421. ctx->emit(OP_LOAD_CONST, index, line);
  422. item.second->emit(ctx);
  423. ctx->emit(OP_BUILD_TUPLE, 2, line);
  424. }
  425. }
  426. ctx->emit(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
  427. ctx->emit(OP_CALL_TP, 1, line);
  428. }else{
  429. ctx->emit(OP_CALL_TP, 0, line);
  430. }
  431. }else{
  432. // vectorcall protocal
  433. for(auto& item: args) item->emit(ctx);
  434. for(auto& item: kwargs){
  435. int index = StrName(item.first.sv()).index;
  436. ctx->emit(OP_LOAD_INTEGER, index, line);
  437. item.second->emit(ctx);
  438. }
  439. int KWARGC = (int)kwargs.size();
  440. int ARGC = (int)args.size();
  441. ctx->emit(OP_CALL, (KWARGC<<16)|ARGC, line);
  442. }
  443. }
  444. bool BinaryExpr::is_compare() const {
  445. switch(op){
  446. case TK("<"): case TK("<="): case TK("=="):
  447. case TK("!="): case TK(">"): case TK(">="): return true;
  448. default: return false;
  449. }
  450. }
  451. void BinaryExpr::_emit_compare(CodeEmitContext* ctx, std::vector<int>& jmps){
  452. if(lhs->is_compare()){
  453. static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
  454. }else{
  455. lhs->emit(ctx); // [a]
  456. }
  457. rhs->emit(ctx); // [a, b]
  458. ctx->emit(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
  459. ctx->emit(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
  460. switch(op){
  461. case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
  462. case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
  463. case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
  464. case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
  465. case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
  466. case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
  467. default: UNREACHABLE();
  468. }
  469. // [b, RES]
  470. int index = ctx->emit(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
  471. jmps.push_back(index);
  472. }
  473. void BinaryExpr::emit(CodeEmitContext* ctx) {
  474. std::vector<int> jmps;
  475. if(is_compare() && lhs->is_compare()){
  476. // (a < b) < c
  477. static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
  478. // [b, RES]
  479. }else{
  480. // (1 + 2) < c
  481. lhs->emit(ctx);
  482. }
  483. rhs->emit(ctx);
  484. switch (op) {
  485. case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
  486. case TK("-"): ctx->emit(OP_BINARY_SUB, BC_NOARG, line); break;
  487. case TK("*"): ctx->emit(OP_BINARY_MUL, BC_NOARG, line); break;
  488. case TK("/"): ctx->emit(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
  489. case TK("//"): ctx->emit(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
  490. case TK("%"): ctx->emit(OP_BINARY_MOD, BC_NOARG, line); break;
  491. case TK("**"): ctx->emit(OP_BINARY_POW, BC_NOARG, line); break;
  492. case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
  493. case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
  494. case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
  495. case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
  496. case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
  497. case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
  498. case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break;
  499. case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break;
  500. case TK("is"): ctx->emit(OP_IS_OP, 0, line); break;
  501. case TK("is not"): ctx->emit(OP_IS_OP, 1, line); break;
  502. case TK("<<"): ctx->emit(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
  503. case TK(">>"): ctx->emit(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
  504. case TK("&"): ctx->emit(OP_BITWISE_AND, BC_NOARG, line); break;
  505. case TK("|"): ctx->emit(OP_BITWISE_OR, BC_NOARG, line); break;
  506. case TK("^"): ctx->emit(OP_BITWISE_XOR, BC_NOARG, line); break;
  507. case TK("@"): ctx->emit(OP_BINARY_MATMUL, BC_NOARG, line); break;
  508. default: FATAL_ERROR();
  509. }
  510. for(int i: jmps) ctx->patch_jump(i);
  511. }
  512. void TernaryExpr::emit(CodeEmitContext* ctx){
  513. cond->emit(ctx);
  514. int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
  515. true_expr->emit(ctx);
  516. int patch_2 = ctx->emit(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
  517. ctx->patch_jump(patch);
  518. false_expr->emit(ctx);
  519. ctx->patch_jump(patch_2);
  520. }
  521. } // namespace pkpy