expr.cpp 27 KB

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