expr.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. #include "pocketpy/compiler/expr.hpp"
  2. #include "pocketpy/interpreter/vm.hpp"
  3. namespace pkpy {
  4. inline bool is_identifier(std::string_view s) {
  5. if(s.empty()) return false;
  6. if(!isalpha(s[0]) && s[0] != '_') return false;
  7. for(char c: s)
  8. if(!isalnum(c) && c != '_') return false;
  9. return true;
  10. }
  11. inline bool is_small_int(i64 value) { return value >= INT16_MIN && value <= INT16_MAX; }
  12. int CodeEmitContext::get_loop() const noexcept{
  13. int index = curr_iblock;
  14. while(index >= 0) {
  15. if(co->blocks[index].type == CodeBlockType::FOR_LOOP) break;
  16. if(co->blocks[index].type == CodeBlockType::WHILE_LOOP) break;
  17. index = co->blocks[index].parent;
  18. }
  19. return index;
  20. }
  21. CodeBlock* CodeEmitContext::enter_block(CodeBlockType type) noexcept{
  22. co->blocks.push_back(CodeBlock(type, curr_iblock, (int)co->codes.size()));
  23. curr_iblock = co->blocks.size() - 1;
  24. return &co->blocks[curr_iblock];
  25. }
  26. void CodeEmitContext::exit_block() noexcept{
  27. auto curr_type = co->blocks[curr_iblock].type;
  28. co->blocks[curr_iblock].end = co->codes.size();
  29. curr_iblock = co->blocks[curr_iblock].parent;
  30. assert(curr_iblock >= 0);
  31. if(curr_type == CodeBlockType::FOR_LOOP) {
  32. // add a no op here to make block check work
  33. emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE, true);
  34. }
  35. }
  36. // clear the expression stack and generate bytecode
  37. void CodeEmitContext::emit_expr(bool emit) noexcept{
  38. // assert(s_expr.size() == 1);
  39. Expr* e = s_expr.popx_back();
  40. if(emit) e->emit_(this);
  41. delete_expr(e);
  42. }
  43. void CodeEmitContext::emit_decorators(int count) noexcept{
  44. // [obj]
  45. for(int i=0; i<count; i++) {
  46. Expr* deco = s_expr.popx_back();
  47. deco->emit_(this); // [obj, f]
  48. emit_(OP_ROT_TWO, BC_NOARG, deco->line); // [f, obj]
  49. emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE); // [f, obj, NULL]
  50. emit_(OP_ROT_TWO, BC_NOARG, BC_KEEPLINE); // [obj, NULL, f]
  51. emit_(OP_CALL, 1, deco->line); // [obj]
  52. delete_expr(deco);
  53. }
  54. }
  55. int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) noexcept{
  56. co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
  57. co->lines.push_back(CodeObject::LineInfo{line, is_virtual, curr_iblock});
  58. int i = co->codes.size() - 1;
  59. if(line == BC_KEEPLINE) {
  60. if(i >= 1)
  61. co->lines[i].lineno = co->lines[i - 1].lineno;
  62. else
  63. co->lines[i].lineno = 1;
  64. }
  65. return i;
  66. }
  67. void CodeEmitContext::revert_last_emit_() noexcept{
  68. co->codes.pop_back();
  69. co->lines.pop_back();
  70. }
  71. void CodeEmitContext::try_merge_for_iter_store(int i) noexcept{
  72. // [FOR_ITER, STORE_?, ]
  73. if(co->codes[i].op != OP_FOR_ITER) return;
  74. if(co->codes.size() - i != 2) return;
  75. uint16_t arg = co->codes[i + 1].arg;
  76. if(co->codes[i + 1].op == OP_STORE_FAST) {
  77. revert_last_emit_();
  78. co->codes[i].op = OP_FOR_ITER_STORE_FAST;
  79. co->codes[i].arg = arg;
  80. return;
  81. }
  82. if(co->codes[i + 1].op == OP_STORE_GLOBAL) {
  83. revert_last_emit_();
  84. co->codes[i].op = OP_FOR_ITER_STORE_GLOBAL;
  85. co->codes[i].arg = arg;
  86. return;
  87. }
  88. }
  89. int CodeEmitContext::emit_int(i64 value, int line) noexcept{
  90. if(is_small_int(value)) {
  91. return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line);
  92. } else {
  93. return emit_(OP_LOAD_CONST, add_const(VAR(value)), line);
  94. }
  95. }
  96. void CodeEmitContext::patch_jump(int index) noexcept{
  97. int target = co->codes.size();
  98. co->codes[index].set_signed_arg(target - index);
  99. }
  100. bool CodeEmitContext::add_label(StrName name) noexcept{
  101. if(co->labels.contains(name)) return false;
  102. co->labels.insert(name, co->codes.size());
  103. return true;
  104. }
  105. int CodeEmitContext::add_varname(StrName name) noexcept{
  106. // PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
  107. int index = co->varnames_inv.get(name, -1);
  108. if(index >= 0) return index;
  109. co->varnames.push_back(name);
  110. co->nlocals++;
  111. index = co->varnames.size() - 1;
  112. co->varnames_inv.insert(name, index);
  113. return index;
  114. }
  115. int CodeEmitContext::add_const_string(std::string_view key) noexcept{
  116. int* val = _co_consts_string_dedup_map.try_get(key);
  117. if(val) {
  118. return *val;
  119. } else {
  120. co->consts.push_back(VAR(key));
  121. int index = co->consts.size() - 1;
  122. key = co->consts.back().obj_get<Str>().sv();
  123. _co_consts_string_dedup_map.insert(key, index);
  124. return index;
  125. }
  126. }
  127. int CodeEmitContext::add_const(PyVar v) noexcept{
  128. assert(!is_type(v, VM::tp_str));
  129. // non-string deduplication
  130. int* val = _co_consts_nonstring_dedup_map.try_get(v);
  131. if(val) {
  132. return *val;
  133. } else {
  134. co->consts.push_back(v);
  135. int index = co->consts.size() - 1;
  136. _co_consts_nonstring_dedup_map.insert(v, index);
  137. return index;
  138. }
  139. }
  140. int CodeEmitContext::add_func_decl(FuncDecl_ decl) noexcept{
  141. co->func_decls.push_back(decl);
  142. return co->func_decls.size() - 1;
  143. }
  144. void CodeEmitContext::emit_store_name(NameScope scope, StrName name, int line) noexcept{
  145. switch(scope) {
  146. case NAME_LOCAL: emit_(OP_STORE_FAST, add_varname(name), line); break;
  147. case NAME_GLOBAL: emit_(OP_STORE_GLOBAL, StrName(name).index, line); break;
  148. case NAME_GLOBAL_UNKNOWN: emit_(OP_STORE_NAME, StrName(name).index, line); break;
  149. default: assert(false); break;
  150. }
  151. }
  152. void NameExpr::emit_(CodeEmitContext* ctx) {
  153. int index = ctx->co->varnames_inv.get(name, -1);
  154. if(scope == NAME_LOCAL && index >= 0) {
  155. ctx->emit_(OP_LOAD_FAST, index, line);
  156. } else {
  157. Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
  158. if(ctx->is_compiling_class && scope == NAME_GLOBAL) {
  159. // if we are compiling a class, we should use OP_LOAD_ATTR_GLOBAL instead of OP_LOAD_GLOBAL
  160. // this supports @property.setter
  161. op = OP_LOAD_CLASS_GLOBAL;
  162. // exec()/eval() won't work with OP_LOAD_ATTR_GLOBAL in class body
  163. } else {
  164. // we cannot determine the scope when calling exec()/eval()
  165. if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
  166. }
  167. ctx->emit_(op, StrName(name).index, line);
  168. }
  169. }
  170. bool NameExpr::emit_del(CodeEmitContext* ctx) {
  171. switch(scope) {
  172. case NAME_LOCAL: ctx->emit_(OP_DELETE_FAST, ctx->add_varname(name), line); break;
  173. case NAME_GLOBAL: ctx->emit_(OP_DELETE_GLOBAL, StrName(name).index, line); break;
  174. case NAME_GLOBAL_UNKNOWN: ctx->emit_(OP_DELETE_NAME, StrName(name).index, line); break;
  175. default: assert(false); break;
  176. }
  177. return true;
  178. }
  179. bool NameExpr::emit_store(CodeEmitContext* ctx) {
  180. if(ctx->is_compiling_class) {
  181. ctx->emit_(OP_STORE_CLASS_ATTR, name.index, line);
  182. return true;
  183. }
  184. ctx->emit_store_name(scope, name, line);
  185. return true;
  186. }
  187. void InvertExpr::emit_(CodeEmitContext* ctx) {
  188. child->emit_(ctx);
  189. ctx->emit_(OP_UNARY_INVERT, BC_NOARG, line);
  190. }
  191. void StarredExpr::emit_(CodeEmitContext* ctx) {
  192. child->emit_(ctx);
  193. ctx->emit_(OP_UNARY_STAR, level, line);
  194. }
  195. bool StarredExpr::emit_store(CodeEmitContext* ctx) {
  196. if(level != 1) return false;
  197. // simply proxy to child
  198. return child->emit_store(ctx);
  199. }
  200. void NotExpr::emit_(CodeEmitContext* ctx) {
  201. child->emit_(ctx);
  202. ctx->emit_(OP_UNARY_NOT, BC_NOARG, line);
  203. }
  204. void AndExpr::emit_(CodeEmitContext* ctx) {
  205. lhs->emit_(ctx);
  206. int patch = ctx->emit_(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
  207. rhs->emit_(ctx);
  208. ctx->patch_jump(patch);
  209. }
  210. void OrExpr::emit_(CodeEmitContext* ctx) {
  211. lhs->emit_(ctx);
  212. int patch = ctx->emit_(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
  213. rhs->emit_(ctx);
  214. ctx->patch_jump(patch);
  215. }
  216. void Literal0Expr::emit_(CodeEmitContext* ctx) {
  217. switch(token) {
  218. case TK("None"): ctx->emit_(OP_LOAD_NONE, BC_NOARG, line); break;
  219. case TK("True"): ctx->emit_(OP_LOAD_TRUE, BC_NOARG, line); break;
  220. case TK("False"): ctx->emit_(OP_LOAD_FALSE, BC_NOARG, line); break;
  221. case TK("..."): ctx->emit_(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
  222. default: assert(false);
  223. }
  224. }
  225. void LongExpr::emit_(CodeEmitContext* ctx) {
  226. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(s.sv()), line);
  227. ctx->emit_(OP_BUILD_LONG, BC_NOARG, line);
  228. }
  229. void ImagExpr::emit_(CodeEmitContext* ctx) {
  230. VM* vm = ctx->vm;
  231. ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(value)), line);
  232. ctx->emit_(OP_BUILD_IMAG, BC_NOARG, line);
  233. }
  234. void BytesExpr::emit_(CodeEmitContext* ctx) {
  235. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(s.sv()), line);
  236. ctx->emit_(OP_BUILD_BYTES, BC_NOARG, line);
  237. }
  238. void LiteralExpr::emit_(CodeEmitContext* ctx) {
  239. VM* vm = ctx->vm;
  240. if(std::holds_alternative<i64>(value)) {
  241. i64 _val = std::get<i64>(value);
  242. ctx->emit_int(_val, line);
  243. return;
  244. }
  245. if(std::holds_alternative<f64>(value)) {
  246. f64 _val = std::get<f64>(value);
  247. ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
  248. return;
  249. }
  250. if(std::holds_alternative<Str>(value)) {
  251. std::string_view key = std::get<Str>(value).sv();
  252. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(key), line);
  253. return;
  254. }
  255. }
  256. void NegatedExpr::emit_(CodeEmitContext* ctx) {
  257. VM* vm = ctx->vm;
  258. // if child is a int of float, do constant folding
  259. if(child->is_literal()) {
  260. LiteralExpr* lit = static_cast<LiteralExpr*>(child);
  261. if(std::holds_alternative<i64>(lit->value)) {
  262. i64 _val = -std::get<i64>(lit->value);
  263. ctx->emit_int(_val, line);
  264. return;
  265. }
  266. if(std::holds_alternative<f64>(lit->value)) {
  267. f64 _val = -std::get<f64>(lit->value);
  268. ctx->emit_(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
  269. return;
  270. }
  271. }
  272. child->emit_(ctx);
  273. ctx->emit_(OP_UNARY_NEGATIVE, BC_NOARG, line);
  274. }
  275. void SliceExpr::emit_(CodeEmitContext* ctx) {
  276. if(start) {
  277. start->emit_(ctx);
  278. } else {
  279. ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
  280. }
  281. if(stop) {
  282. stop->emit_(ctx);
  283. } else {
  284. ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
  285. }
  286. if(step) {
  287. step->emit_(ctx);
  288. } else {
  289. ctx->emit_(OP_LOAD_NONE, BC_NOARG, line);
  290. }
  291. ctx->emit_(OP_BUILD_SLICE, BC_NOARG, line);
  292. }
  293. void DictItemExpr::emit_(CodeEmitContext* ctx) {
  294. if(is_starred()) {
  295. assert(key == nullptr);
  296. value->emit_(ctx);
  297. } else {
  298. key->emit_(ctx);
  299. value->emit_(ctx);
  300. ctx->emit_(OP_BUILD_TUPLE, 2, line);
  301. }
  302. }
  303. bool TupleExpr::emit_store(CodeEmitContext* ctx) {
  304. // TOS is an iterable
  305. // items may contain StarredExpr, we should check it
  306. int starred_i = -1;
  307. for(int i = 0; i < items.size(); i++) {
  308. if(!items[i]->is_starred()) continue;
  309. if(starred_i == -1)
  310. starred_i = i;
  311. else
  312. return false; // multiple StarredExpr not allowed
  313. }
  314. if(starred_i == -1) {
  315. Bytecode& prev = ctx->co->codes.back();
  316. if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()) {
  317. // build tuple and unpack it is meaningless
  318. ctx->revert_last_emit_();
  319. } else {
  320. if(prev.op == OP_FOR_ITER) {
  321. prev.op = OP_FOR_ITER_UNPACK;
  322. prev.arg = items.size();
  323. } else {
  324. ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
  325. }
  326. }
  327. } else {
  328. // starred assignment target must be in a tuple
  329. if(items.size() == 1) return false;
  330. // starred assignment target must be the last one (differ from cpython)
  331. if(starred_i != items.size() - 1) return false;
  332. // a,*b = [1,2,3]
  333. // stack is [1,2,3] -> [1,[2,3]]
  334. ctx->emit_(OP_UNPACK_EX, items.size() - 1, line);
  335. }
  336. // do reverse emit
  337. for(int i = items.size() - 1; i >= 0; i--) {
  338. bool ok = items[i]->emit_store(ctx);
  339. if(!ok) return false;
  340. }
  341. return true;
  342. }
  343. bool TupleExpr::emit_del(CodeEmitContext* ctx) {
  344. for(auto& e: items) {
  345. bool ok = e->emit_del(ctx);
  346. if(!ok) return false;
  347. }
  348. return true;
  349. }
  350. void CompExpr::emit_(CodeEmitContext* ctx) {
  351. ctx->emit_(op0, 0, line);
  352. iter->emit_(ctx);
  353. ctx->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
  354. ctx->enter_block(CodeBlockType::FOR_LOOP);
  355. int curr_iblock = ctx->curr_iblock;
  356. int for_codei = ctx->emit_(OP_FOR_ITER, curr_iblock, BC_KEEPLINE);
  357. bool ok = vars->emit_store(ctx);
  358. // this error occurs in `vars` instead of this line, but...nevermind
  359. assert(ok); // this should raise a SyntaxError, but we just assert it
  360. ctx->try_merge_for_iter_store(for_codei);
  361. if(cond) {
  362. cond->emit_(ctx);
  363. int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
  364. expr->emit_(ctx);
  365. ctx->emit_(op1, BC_NOARG, BC_KEEPLINE);
  366. ctx->patch_jump(patch);
  367. } else {
  368. expr->emit_(ctx);
  369. ctx->emit_(op1, BC_NOARG, BC_KEEPLINE);
  370. }
  371. ctx->emit_(OP_LOOP_CONTINUE, curr_iblock, BC_KEEPLINE);
  372. ctx->exit_block();
  373. }
  374. void FStringExpr::_load_simple_expr(CodeEmitContext* ctx, Str expr) {
  375. bool repr = false;
  376. if(expr.size >= 2 && expr.end()[-2] == '!') {
  377. switch(expr.end()[-1]) {
  378. case 'r':
  379. repr = true;
  380. expr = expr.substr(0, expr.size - 2);
  381. break;
  382. case 's':
  383. repr = false;
  384. expr = expr.substr(0, expr.size - 2);
  385. break;
  386. default: break; // nothing happens
  387. }
  388. }
  389. // name or name.name
  390. bool is_fastpath = false;
  391. if(is_identifier(expr.sv())) {
  392. ctx->emit_(OP_LOAD_NAME, StrName(expr.sv()).index, line);
  393. is_fastpath = true;
  394. } else {
  395. int dot = expr.index(".");
  396. if(dot > 0) {
  397. std::string_view a = expr.sv().substr(0, dot);
  398. std::string_view b = expr.sv().substr(dot + 1);
  399. if(is_identifier(a) && is_identifier(b)) {
  400. ctx->emit_(OP_LOAD_NAME, StrName(a).index, line);
  401. ctx->emit_(OP_LOAD_ATTR, StrName(b).index, line);
  402. is_fastpath = true;
  403. }
  404. }
  405. }
  406. if(!is_fastpath) {
  407. int index = ctx->add_const_string(expr.sv());
  408. ctx->emit_(OP_FSTRING_EVAL, index, line);
  409. }
  410. if(repr) { ctx->emit_(OP_REPR, BC_NOARG, line); }
  411. }
  412. static bool is_fmt_valid_char(char c) {
  413. switch(c) {
  414. // clang-format off
  415. case '-': case '=': case '*': case '#': case '@': case '!': case '~':
  416. case '<': case '>': case '^':
  417. case '.': case 'f': case 'd': case 's':
  418. case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
  419. return true;
  420. default: return false;
  421. // clang-format on
  422. }
  423. }
  424. void FStringExpr::emit_(CodeEmitContext* ctx) {
  425. int i = 0; // left index
  426. int j = 0; // right index
  427. int count = 0; // how many string parts
  428. bool flag = false; // true if we are in a expression
  429. while(j < src.size) {
  430. if(flag) {
  431. if(src[j] == '}') {
  432. // add expression
  433. Str expr = src.substr(i, j - i);
  434. // BUG: ':' is not a format specifier in f"{stack[2:]}"
  435. int conon = expr.index(":");
  436. if(conon >= 0) {
  437. Str spec = expr.substr(conon + 1);
  438. // filter some invalid spec
  439. bool ok = true;
  440. for(char c: spec)
  441. if(!is_fmt_valid_char(c)) {
  442. ok = false;
  443. break;
  444. }
  445. if(ok) {
  446. _load_simple_expr(ctx, expr.substr(0, conon));
  447. ctx->emit_(OP_FORMAT_STRING, ctx->add_const_string(spec.sv()), line);
  448. } else {
  449. // ':' is not a spec indicator
  450. _load_simple_expr(ctx, expr);
  451. }
  452. } else {
  453. _load_simple_expr(ctx, expr);
  454. }
  455. flag = false;
  456. count++;
  457. }
  458. } else {
  459. if(src[j] == '{') {
  460. // look at next char
  461. if(j + 1 < src.size && src[j + 1] == '{') {
  462. // {{ -> {
  463. j++;
  464. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string("{"), line);
  465. count++;
  466. } else {
  467. // { -> }
  468. flag = true;
  469. i = j + 1;
  470. }
  471. } else if(src[j] == '}') {
  472. // look at next char
  473. if(j + 1 < src.size && src[j + 1] == '}') {
  474. // }} -> }
  475. j++;
  476. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string("}"), line);
  477. count++;
  478. } else {
  479. // } -> error
  480. // throw std::runtime_error("f-string: unexpected }");
  481. // just ignore
  482. }
  483. } else {
  484. // literal
  485. i = j;
  486. while(j < src.size && src[j] != '{' && src[j] != '}')
  487. j++;
  488. Str literal = src.substr(i, j - i);
  489. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(literal.sv()), line);
  490. count++;
  491. continue; // skip j++
  492. }
  493. }
  494. j++;
  495. }
  496. if(flag) {
  497. // literal
  498. Str literal = src.substr(i, src.size - i);
  499. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(literal.sv()), line);
  500. count++;
  501. }
  502. ctx->emit_(OP_BUILD_STRING, count, line);
  503. }
  504. void SubscrExpr::emit_(CodeEmitContext* ctx) {
  505. lhs->emit_(ctx);
  506. rhs->emit_(ctx);
  507. Bytecode last_bc = ctx->co->codes.back();
  508. if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) {
  509. ctx->revert_last_emit_();
  510. ctx->emit_(OP_LOAD_SUBSCR_FAST, last_bc.arg, line);
  511. } else if(rhs->is_literal() && last_bc.op == OP_LOAD_SMALL_INT) {
  512. ctx->revert_last_emit_();
  513. ctx->emit_(OP_LOAD_SUBSCR_SMALL_INT, last_bc.arg, line);
  514. } else {
  515. ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line);
  516. }
  517. }
  518. bool SubscrExpr::emit_store(CodeEmitContext* ctx) {
  519. lhs->emit_(ctx);
  520. rhs->emit_(ctx);
  521. Bytecode last_bc = ctx->co->codes.back();
  522. if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) {
  523. ctx->revert_last_emit_();
  524. ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line);
  525. } else {
  526. ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
  527. }
  528. return true;
  529. }
  530. void SubscrExpr::emit_inplace(CodeEmitContext* ctx) {
  531. lhs->emit_(ctx);
  532. rhs->emit_(ctx);
  533. ctx->emit_(OP_DUP_TOP_TWO, BC_NOARG, line);
  534. ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line);
  535. }
  536. bool SubscrExpr::emit_store_inplace(CodeEmitContext* ctx) {
  537. // [a, b, val] -> [val, a, b]
  538. ctx->emit_(OP_ROT_THREE, BC_NOARG, line);
  539. ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
  540. return true;
  541. }
  542. bool SubscrExpr::emit_del(CodeEmitContext* ctx) {
  543. lhs->emit_(ctx);
  544. rhs->emit_(ctx);
  545. ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line);
  546. return true;
  547. }
  548. void AttribExpr::emit_(CodeEmitContext* ctx) {
  549. child->emit_(ctx);
  550. ctx->emit_(OP_LOAD_ATTR, name.index, line);
  551. }
  552. bool AttribExpr::emit_del(CodeEmitContext* ctx) {
  553. child->emit_(ctx);
  554. ctx->emit_(OP_DELETE_ATTR, name.index, line);
  555. return true;
  556. }
  557. bool AttribExpr::emit_store(CodeEmitContext* ctx) {
  558. child->emit_(ctx);
  559. ctx->emit_(OP_STORE_ATTR, name.index, line);
  560. return true;
  561. }
  562. void AttribExpr::emit_method(CodeEmitContext* ctx) {
  563. child->emit_(ctx);
  564. ctx->emit_(OP_LOAD_METHOD, name.index, line);
  565. }
  566. void AttribExpr::emit_inplace(CodeEmitContext* ctx) {
  567. child->emit_(ctx);
  568. ctx->emit_(OP_DUP_TOP, BC_NOARG, line);
  569. ctx->emit_(OP_LOAD_ATTR, name.index, line);
  570. }
  571. bool AttribExpr::emit_store_inplace(CodeEmitContext* ctx) {
  572. // [a, val] -> [val, a]
  573. ctx->emit_(OP_ROT_TWO, BC_NOARG, line);
  574. ctx->emit_(OP_STORE_ATTR, name.index, line);
  575. return true;
  576. }
  577. void CallExpr::emit_(CodeEmitContext* ctx) {
  578. bool vargs = false;
  579. bool vkwargs = false;
  580. for(auto& arg: args)
  581. if(arg->is_starred()) vargs = true;
  582. for(auto& item: kwargs)
  583. if(item.second->is_starred()) vkwargs = true;
  584. // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
  585. if(callable->is_attrib()) {
  586. auto p = static_cast<AttribExpr*>(callable);
  587. p->emit_method(ctx); // OP_LOAD_METHOD
  588. } else {
  589. callable->emit_(ctx);
  590. ctx->emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
  591. }
  592. if(vargs || vkwargs) {
  593. for(auto& item: args)
  594. item->emit_(ctx);
  595. ctx->emit_(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
  596. if(!kwargs.empty()) {
  597. for(auto& item: kwargs) {
  598. if(item.second->is_starred()) {
  599. assert(item.second->star_level() == 2);
  600. item.second->emit_(ctx);
  601. } else {
  602. // k=v
  603. int index = ctx->add_const_string(item.first.sv());
  604. ctx->emit_(OP_LOAD_CONST, index, line);
  605. item.second->emit_(ctx);
  606. ctx->emit_(OP_BUILD_TUPLE, 2, line);
  607. }
  608. }
  609. ctx->emit_(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
  610. ctx->emit_(OP_CALL_TP, 1, line);
  611. } else {
  612. ctx->emit_(OP_CALL_TP, 0, line);
  613. }
  614. } else {
  615. // vectorcall protocol
  616. for(auto& item: args)
  617. item->emit_(ctx);
  618. for(auto& item: kwargs) {
  619. i64 _val = StrName(item.first.sv()).index;
  620. ctx->emit_int(_val, line);
  621. item.second->emit_(ctx);
  622. }
  623. int KWARGC = kwargs.size();
  624. int ARGC = args.size();
  625. ctx->emit_(OP_CALL, (KWARGC << 8) | ARGC, line);
  626. }
  627. }
  628. bool BinaryExpr::is_compare() const {
  629. switch(op) {
  630. case TK("<"):
  631. case TK("<="):
  632. case TK("=="):
  633. case TK("!="):
  634. case TK(">"):
  635. case TK(">="): return true;
  636. default: return false;
  637. }
  638. }
  639. void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2<int, 8>& jmps) {
  640. if(lhs->is_compare()) {
  641. static_cast<BinaryExpr*>(lhs)->_emit_compare(ctx, jmps);
  642. } else {
  643. lhs->emit_(ctx); // [a]
  644. }
  645. rhs->emit_(ctx); // [a, b]
  646. ctx->emit_(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
  647. ctx->emit_(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
  648. switch(op) {
  649. case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
  650. case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
  651. case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
  652. case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
  653. case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
  654. case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
  655. default: PK_UNREACHABLE()
  656. }
  657. // [b, RES]
  658. int index = ctx->emit_(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
  659. jmps.push_back(index);
  660. }
  661. void BinaryExpr::emit_(CodeEmitContext* ctx) {
  662. small_vector_2<int, 8> jmps;
  663. if(is_compare() && lhs->is_compare()) {
  664. // (a < b) < c
  665. static_cast<BinaryExpr*>(lhs)->_emit_compare(ctx, jmps);
  666. // [b, RES]
  667. } else {
  668. // (1 + 2) < c
  669. if(inplace) {
  670. lhs->emit_inplace(ctx);
  671. } else {
  672. lhs->emit_(ctx);
  673. }
  674. }
  675. rhs->emit_(ctx);
  676. switch(op) {
  677. case TK("+"): ctx->emit_(OP_BINARY_ADD, BC_NOARG, line); break;
  678. case TK("-"): ctx->emit_(OP_BINARY_SUB, BC_NOARG, line); break;
  679. case TK("*"): ctx->emit_(OP_BINARY_MUL, BC_NOARG, line); break;
  680. case TK("/"): ctx->emit_(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
  681. case TK("//"): ctx->emit_(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
  682. case TK("%"): ctx->emit_(OP_BINARY_MOD, BC_NOARG, line); break;
  683. case TK("**"): ctx->emit_(OP_BINARY_POW, BC_NOARG, line); break;
  684. case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
  685. case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
  686. case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
  687. case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
  688. case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
  689. case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
  690. case TK("in"): ctx->emit_(OP_CONTAINS_OP, 0, line); break;
  691. case TK("not in"): ctx->emit_(OP_CONTAINS_OP, 1, line); break;
  692. case TK("is"): ctx->emit_(OP_IS_OP, BC_NOARG, line); break;
  693. case TK("is not"): ctx->emit_(OP_IS_NOT_OP, BC_NOARG, line); break;
  694. case TK("<<"): ctx->emit_(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
  695. case TK(">>"): ctx->emit_(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
  696. case TK("&"): ctx->emit_(OP_BITWISE_AND, BC_NOARG, line); break;
  697. case TK("|"): ctx->emit_(OP_BITWISE_OR, BC_NOARG, line); break;
  698. case TK("^"): ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break;
  699. case TK("@"): ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break;
  700. default: assert(false);
  701. }
  702. for(int i: jmps)
  703. ctx->patch_jump(i);
  704. }
  705. void TernaryExpr::emit_(CodeEmitContext* ctx) {
  706. cond->emit_(ctx);
  707. int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
  708. true_expr->emit_(ctx);
  709. int patch_2 = ctx->emit_(OP_JUMP_FORWARD, BC_NOARG, true_expr->line);
  710. ctx->patch_jump(patch);
  711. false_expr->emit_(ctx);
  712. ctx->patch_jump(patch_2);
  713. }
  714. } // namespace pkpy