expr.cpp 25 KB

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