expr.cpp 26 KB

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