expr.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  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. int CodeEmitContext::get_loop() const {
  10. int index = curr_block_i;
  11. while(index >= 0){
  12. if(co->blocks[index].type == CodeBlockType::FOR_LOOP) break;
  13. if(co->blocks[index].type == CodeBlockType::WHILE_LOOP) break;
  14. index = co->blocks[index].parent;
  15. }
  16. return index;
  17. }
  18. CodeBlock* CodeEmitContext::enter_block(CodeBlockType type){
  19. if(type==CodeBlockType::FOR_LOOP || type==CodeBlockType::CONTEXT_MANAGER) base_stack_size++;
  20. co->blocks.push_back(CodeBlock(
  21. type, curr_block_i, base_stack_size, (int)co->codes.size()
  22. ));
  23. curr_block_i = co->blocks.size()-1;
  24. return &co->blocks[curr_block_i];
  25. }
  26. void CodeEmitContext::exit_block(){
  27. auto curr_type = co->blocks[curr_block_i].type;
  28. if(curr_type == CodeBlockType::FOR_LOOP || curr_type==CodeBlockType::CONTEXT_MANAGER) base_stack_size--;
  29. co->blocks[curr_block_i].end = co->codes.size();
  30. curr_block_i = co->blocks[curr_block_i].parent;
  31. if(curr_block_i < 0) PK_FATAL_ERROR();
  32. if(curr_type == CodeBlockType::FOR_LOOP){
  33. // add a no op here to make block check work
  34. emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE, true);
  35. }
  36. }
  37. // clear the expression stack and generate bytecode
  38. void CodeEmitContext::emit_expr(){
  39. if(s_expr.size() != 1) throw std::runtime_error("s_expr.size() != 1");
  40. Expr_ expr = s_expr.popx();
  41. expr->emit_(this);
  42. }
  43. int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) {
  44. co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
  45. co->iblocks.push_back(curr_block_i);
  46. co->lines.push_back(CodeObject::LineInfo{line, is_virtual});
  47. int i = co->codes.size() - 1;
  48. if(line == BC_KEEPLINE){
  49. if(i >= 1) co->lines[i].lineno = co->lines[i-1].lineno;
  50. else co->lines[i].lineno = 1;
  51. }
  52. return i;
  53. }
  54. void CodeEmitContext::revert_last_emit_(){
  55. co->codes.pop_back();
  56. co->iblocks.pop_back();
  57. co->lines.pop_back();
  58. }
  59. void CodeEmitContext::try_merge_for_iter_store(int i){
  60. // [FOR_ITER, STORE_?, ]
  61. if(co->codes[i].op != OP_FOR_ITER) return;
  62. if(co->codes.size() - i != 2) return;
  63. uint16_t arg = co->codes[i+1].arg;
  64. if(co->codes[i+1].op == OP_STORE_FAST){
  65. revert_last_emit_();
  66. co->codes[i].op = OP_FOR_ITER_STORE_FAST;
  67. co->codes[i].arg = arg;
  68. return;
  69. }
  70. if(co->codes[i+1].op == OP_STORE_GLOBAL){
  71. revert_last_emit_();
  72. co->codes[i].op = OP_FOR_ITER_STORE_GLOBAL;
  73. co->codes[i].arg = arg;
  74. return;
  75. }
  76. }
  77. int CodeEmitContext::emit_int(i64 value, int line){
  78. if(value >= 0 && value <= 16){
  79. uint8_t op = OP_LOAD_INT_0 + (uint8_t)value;
  80. return emit_((Opcode)op, BC_NOARG, 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].arg = target;
  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(PyObject* 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. prev.op = OP_NO_OP;
  321. prev.arg = BC_NOARG;
  322. }else{
  323. ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
  324. }
  325. }else{
  326. // starred assignment target must be in a tuple
  327. if(items.size() == 1) return false;
  328. // starred assignment target must be the last one (differ from cpython)
  329. if(starred_i != items.size()-1) return false;
  330. // a,*b = [1,2,3]
  331. // stack is [1,2,3] -> [1,[2,3]]
  332. ctx->emit_(OP_UNPACK_EX, items.size()-1, line);
  333. }
  334. // do reverse emit
  335. for(int i=items.size()-1; i>=0; i--){
  336. bool ok = items[i]->emit_store(ctx);
  337. if(!ok) return false;
  338. }
  339. return true;
  340. }
  341. bool TupleExpr::emit_del(CodeEmitContext* ctx){
  342. for(auto& e: items){
  343. bool ok = e->emit_del(ctx);
  344. if(!ok) return false;
  345. }
  346. return true;
  347. }
  348. void CompExpr::emit_(CodeEmitContext* ctx){
  349. ctx->emit_(op0(), 0, line);
  350. iter->emit_(ctx);
  351. ctx->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
  352. ctx->enter_block(CodeBlockType::FOR_LOOP);
  353. int for_codei = ctx->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
  354. bool ok = vars->emit_store(ctx);
  355. // this error occurs in `vars` instead of this line, but...nevermind
  356. if(!ok) throw std::runtime_error("SyntaxError");
  357. ctx->try_merge_for_iter_store(for_codei);
  358. if(cond){
  359. cond->emit_(ctx);
  360. int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
  361. expr->emit_(ctx);
  362. ctx->emit_(op1(), BC_NOARG, BC_KEEPLINE);
  363. ctx->patch_jump(patch);
  364. }else{
  365. expr->emit_(ctx);
  366. ctx->emit_(op1(), BC_NOARG, BC_KEEPLINE);
  367. }
  368. ctx->emit_(OP_LOOP_CONTINUE, ctx->get_loop(), BC_KEEPLINE);
  369. ctx->exit_block();
  370. }
  371. void FStringExpr::_load_simple_expr(CodeEmitContext* ctx, Str expr){
  372. bool repr = false;
  373. if(expr.size>=2 && expr.end()[-2]=='!'){
  374. switch(expr.end()[-1]){
  375. case 'r': repr = true; expr = expr.substr(0, expr.size-2); break;
  376. case 's': repr = false; expr = expr.substr(0, expr.size-2); break;
  377. default: break; // nothing happens
  378. }
  379. }
  380. // name or name.name
  381. bool is_fastpath = false;
  382. if(is_identifier(expr.sv())){
  383. ctx->emit_(OP_LOAD_NAME, StrName(expr.sv()).index, line);
  384. is_fastpath = true;
  385. }else{
  386. int dot = expr.index(".");
  387. if(dot > 0){
  388. std::string_view a = expr.sv().substr(0, dot);
  389. std::string_view b = expr.sv().substr(dot+1);
  390. if(is_identifier(a) && is_identifier(b)){
  391. ctx->emit_(OP_LOAD_NAME, StrName(a).index, line);
  392. ctx->emit_(OP_LOAD_ATTR, StrName(b).index, line);
  393. is_fastpath = true;
  394. }
  395. }
  396. }
  397. if(!is_fastpath){
  398. int index = ctx->add_const_string(expr.sv());
  399. ctx->emit_(OP_FSTRING_EVAL, index, line);
  400. }
  401. if(repr){
  402. ctx->emit_(OP_REPR, BC_NOARG, line);
  403. }
  404. }
  405. void FStringExpr::emit_(CodeEmitContext* ctx){
  406. int i = 0; // left index
  407. int j = 0; // right index
  408. int count = 0; // how many string parts
  409. bool flag = false; // true if we are in a expression
  410. const char* fmt_valid_chars = "0-=*#@!~" "<>^" ".fds" "0123456789";
  411. PK_LOCAL_STATIC const std::set<char> fmt_valid_char_set(fmt_valid_chars, fmt_valid_chars + strlen(fmt_valid_chars));
  412. while(j < src.size){
  413. if(flag){
  414. if(src[j] == '}'){
  415. // add expression
  416. Str expr = src.substr(i, j-i);
  417. // BUG: ':' is not a format specifier in f"{stack[2:]}"
  418. int conon = expr.index(":");
  419. if(conon >= 0){
  420. Str spec = expr.substr(conon+1);
  421. // filter some invalid spec
  422. bool ok = true;
  423. for(char c: spec) if(!fmt_valid_char_set.count(c)){ ok = false; break; }
  424. if(ok){
  425. _load_simple_expr(ctx, expr.substr(0, conon));
  426. ctx->emit_(OP_FORMAT_STRING, ctx->add_const_string(spec.sv()), line);
  427. }else{
  428. // ':' is not a spec indicator
  429. _load_simple_expr(ctx, expr);
  430. }
  431. }else{
  432. _load_simple_expr(ctx, expr);
  433. }
  434. flag = false;
  435. count++;
  436. }
  437. }else{
  438. if(src[j] == '{'){
  439. // look at next char
  440. if(j+1 < src.size && src[j+1] == '{'){
  441. // {{ -> {
  442. j++;
  443. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string("{"), line);
  444. count++;
  445. }else{
  446. // { -> }
  447. flag = true;
  448. i = j+1;
  449. }
  450. }else if(src[j] == '}'){
  451. // look at next char
  452. if(j+1 < src.size && src[j+1] == '}'){
  453. // }} -> }
  454. j++;
  455. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string("}"), line);
  456. count++;
  457. }else{
  458. // } -> error
  459. // throw std::runtime_error("f-string: unexpected }");
  460. // just ignore
  461. }
  462. }else{
  463. // literal
  464. i = j;
  465. while(j < src.size && src[j] != '{' && src[j] != '}') j++;
  466. Str literal = src.substr(i, j-i);
  467. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(literal.sv()), line);
  468. count++;
  469. continue; // skip j++
  470. }
  471. }
  472. j++;
  473. }
  474. if(flag){
  475. // literal
  476. Str literal = src.substr(i, src.size-i);
  477. ctx->emit_(OP_LOAD_CONST, ctx->add_const_string(literal.sv()), line);
  478. count++;
  479. }
  480. ctx->emit_(OP_BUILD_STRING, count, line);
  481. }
  482. void SubscrExpr::emit_(CodeEmitContext* ctx){
  483. a->emit_(ctx);
  484. b->emit_(ctx);
  485. ctx->emit_(OP_LOAD_SUBSCR, BC_NOARG, line);
  486. }
  487. bool SubscrExpr::emit_del(CodeEmitContext* ctx){
  488. a->emit_(ctx);
  489. b->emit_(ctx);
  490. ctx->emit_(OP_DELETE_SUBSCR, BC_NOARG, line);
  491. return true;
  492. }
  493. bool SubscrExpr::emit_store(CodeEmitContext* ctx){
  494. a->emit_(ctx);
  495. b->emit_(ctx);
  496. ctx->emit_(OP_STORE_SUBSCR, BC_NOARG, line);
  497. return true;
  498. }
  499. void AttribExpr::emit_(CodeEmitContext* ctx){
  500. a->emit_(ctx);
  501. ctx->emit_(OP_LOAD_ATTR, b.index, line);
  502. }
  503. bool AttribExpr::emit_del(CodeEmitContext* ctx) {
  504. a->emit_(ctx);
  505. ctx->emit_(OP_DELETE_ATTR, b.index, line);
  506. return true;
  507. }
  508. bool AttribExpr::emit_store(CodeEmitContext* ctx){
  509. a->emit_(ctx);
  510. ctx->emit_(OP_STORE_ATTR, b.index, line);
  511. return true;
  512. }
  513. void AttribExpr::emit_method(CodeEmitContext* ctx) {
  514. a->emit_(ctx);
  515. ctx->emit_(OP_LOAD_METHOD, b.index, line);
  516. }
  517. void CallExpr::emit_(CodeEmitContext* ctx) {
  518. bool vargs = false;
  519. bool vkwargs = false;
  520. for(auto& arg: args) if(arg->is_starred()) vargs = true;
  521. for(auto& item: kwargs) if(item.second->is_starred()) vkwargs = true;
  522. // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
  523. if(callable->is_attrib()){
  524. auto p = static_cast<AttribExpr*>(callable.get());
  525. p->emit_method(ctx); // OP_LOAD_METHOD
  526. }else{
  527. callable->emit_(ctx);
  528. ctx->emit_(OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
  529. }
  530. if(vargs || vkwargs){
  531. for(auto& item: args) item->emit_(ctx);
  532. ctx->emit_(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
  533. if(!kwargs.empty()){
  534. for(auto& item: kwargs){
  535. if(item.second->is_starred()){
  536. PK_ASSERT(item.second->star_level() == 2)
  537. item.second->emit_(ctx);
  538. }else{
  539. // k=v
  540. int index = ctx->add_const_string(item.first.sv());
  541. ctx->emit_(OP_LOAD_CONST, index, line);
  542. item.second->emit_(ctx);
  543. ctx->emit_(OP_BUILD_TUPLE, 2, line);
  544. }
  545. }
  546. ctx->emit_(OP_BUILD_DICT_UNPACK, (int)kwargs.size(), line);
  547. ctx->emit_(OP_CALL_TP, 1, line);
  548. }else{
  549. ctx->emit_(OP_CALL_TP, 0, line);
  550. }
  551. }else{
  552. // vectorcall protocol
  553. for(auto& item: args) item->emit_(ctx);
  554. for(auto& item: kwargs){
  555. i64 _val = StrName(item.first.sv()).index;
  556. ctx->emit_int(_val, line);
  557. item.second->emit_(ctx);
  558. }
  559. int KWARGC = kwargs.size();
  560. int ARGC = args.size();
  561. ctx->emit_(OP_CALL, (KWARGC<<8)|ARGC, line);
  562. }
  563. }
  564. bool BinaryExpr::is_compare() const {
  565. switch(op){
  566. case TK("<"): case TK("<="): case TK("=="):
  567. case TK("!="): case TK(">"): case TK(">="): return true;
  568. default: return false;
  569. }
  570. }
  571. void BinaryExpr::_emit_compare(CodeEmitContext* ctx, pod_vector<int>& jmps){
  572. if(lhs->is_compare()){
  573. static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
  574. }else{
  575. lhs->emit_(ctx); // [a]
  576. }
  577. rhs->emit_(ctx); // [a, b]
  578. ctx->emit_(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
  579. ctx->emit_(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
  580. switch(op){
  581. case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
  582. case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
  583. case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
  584. case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
  585. case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
  586. case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
  587. default: PK_UNREACHABLE()
  588. }
  589. // [b, RES]
  590. int index = ctx->emit_(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
  591. jmps.push_back(index);
  592. }
  593. void BinaryExpr::emit_(CodeEmitContext* ctx) {
  594. pod_vector<int> jmps;
  595. if(is_compare() && lhs->is_compare()){
  596. // (a < b) < c
  597. static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
  598. // [b, RES]
  599. }else{
  600. // (1 + 2) < c
  601. lhs->emit_(ctx);
  602. }
  603. rhs->emit_(ctx);
  604. switch (op) {
  605. case TK("+"): ctx->emit_(OP_BINARY_ADD, BC_NOARG, line); break;
  606. case TK("-"): ctx->emit_(OP_BINARY_SUB, BC_NOARG, line); break;
  607. case TK("*"): ctx->emit_(OP_BINARY_MUL, BC_NOARG, line); break;
  608. case TK("/"): ctx->emit_(OP_BINARY_TRUEDIV, BC_NOARG, line); break;
  609. case TK("//"): ctx->emit_(OP_BINARY_FLOORDIV, BC_NOARG, line); break;
  610. case TK("%"): ctx->emit_(OP_BINARY_MOD, BC_NOARG, line); break;
  611. case TK("**"): ctx->emit_(OP_BINARY_POW, BC_NOARG, line); break;
  612. case TK("<"): ctx->emit_(OP_COMPARE_LT, BC_NOARG, line); break;
  613. case TK("<="): ctx->emit_(OP_COMPARE_LE, BC_NOARG, line); break;
  614. case TK("=="): ctx->emit_(OP_COMPARE_EQ, BC_NOARG, line); break;
  615. case TK("!="): ctx->emit_(OP_COMPARE_NE, BC_NOARG, line); break;
  616. case TK(">"): ctx->emit_(OP_COMPARE_GT, BC_NOARG, line); break;
  617. case TK(">="): ctx->emit_(OP_COMPARE_GE, BC_NOARG, line); break;
  618. case TK("in"): ctx->emit_(OP_CONTAINS_OP, 0, line); break;
  619. case TK("not in"): ctx->emit_(OP_CONTAINS_OP, 1, line); break;
  620. case TK("is"): ctx->emit_(OP_IS_OP, 0, line); break;
  621. case TK("is not"): ctx->emit_(OP_IS_OP, 1, line); break;
  622. case TK("<<"): ctx->emit_(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
  623. case TK(">>"): ctx->emit_(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
  624. case TK("&"): ctx->emit_(OP_BITWISE_AND, BC_NOARG, line); break;
  625. case TK("|"): ctx->emit_(OP_BITWISE_OR, BC_NOARG, line); break;
  626. case TK("^"): ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break;
  627. case TK("@"): ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break;
  628. default: PK_FATAL_ERROR();
  629. }
  630. for(int i: jmps) ctx->patch_jump(i);
  631. }
  632. void TernaryExpr::emit_(CodeEmitContext* ctx){
  633. cond->emit_(ctx);
  634. int patch = ctx->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, cond->line);
  635. true_expr->emit_(ctx);
  636. int patch_2 = ctx->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, true_expr->line);
  637. ctx->patch_jump(patch);
  638. false_expr->emit_(ctx);
  639. ctx->patch_jump(patch_2);
  640. }
  641. } // namespace pkpy