builtins.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. #include "pocketpy/common/str.h"
  2. #include "pocketpy/objects/base.h"
  3. #include "pocketpy/objects/codeobject.h"
  4. #include "pocketpy/pocketpy.h"
  5. #include "pocketpy/common/utils.h"
  6. #include "pocketpy/objects/object.h"
  7. #include "pocketpy/common/sstream.h"
  8. #include "pocketpy/interpreter/vm.h"
  9. #include "pocketpy/common/_generated.h"
  10. #include <math.h>
  11. static bool builtins_exit(int argc, py_Ref argv) {
  12. int code = 0;
  13. if(argc > 1) return TypeError("exit() takes at most 1 argument");
  14. if(argc == 1) {
  15. PY_CHECK_ARG_TYPE(0, tp_int);
  16. code = py_toint(argv);
  17. }
  18. exit(code);
  19. return false;
  20. }
  21. static bool builtins_input(int argc, py_Ref argv) {
  22. if(argc > 1) return TypeError("input() takes at most 1 argument");
  23. const char* prompt = "";
  24. if(argc == 1) {
  25. if(!py_checkstr(argv)) return false;
  26. prompt = py_tostr(argv);
  27. }
  28. py_callbacks()->print(prompt);
  29. c11_sbuf buf;
  30. c11_sbuf__ctor(&buf);
  31. while(true) {
  32. int c = py_callbacks()->getchr();
  33. if(c == '\n' || c == '\r') break;
  34. if(c == EOF) break;
  35. c11_sbuf__write_char(&buf, c);
  36. }
  37. c11_sbuf__py_submit(&buf, py_retval());
  38. return true;
  39. }
  40. static bool builtins_repr(int argc, py_Ref argv) {
  41. PY_CHECK_ARGC(1);
  42. return py_repr(argv);
  43. }
  44. static bool builtins_len(int argc, py_Ref argv) {
  45. PY_CHECK_ARGC(1);
  46. return py_len(argv);
  47. }
  48. static bool builtins_hex(int argc, py_Ref argv) {
  49. PY_CHECK_ARGC(1);
  50. PY_CHECK_ARG_TYPE(0, tp_int);
  51. py_i64 val = py_toint(argv);
  52. if(val == 0) {
  53. py_newstr(py_retval(), "0x0");
  54. return true;
  55. }
  56. c11_sbuf ss;
  57. c11_sbuf__ctor(&ss);
  58. if(val < 0) {
  59. c11_sbuf__write_char(&ss, '-');
  60. val = -val;
  61. }
  62. c11_sbuf__write_cstr(&ss, "0x");
  63. bool non_zero = true;
  64. for(int i = 56; i >= 0; i -= 8) {
  65. unsigned char cpnt = (val >> i) & 0xff;
  66. c11_sbuf__write_hex(&ss, cpnt, non_zero);
  67. if(cpnt != 0) non_zero = false;
  68. }
  69. c11_sbuf__py_submit(&ss, py_retval());
  70. return true;
  71. }
  72. static bool builtins_bin(int argc, py_Ref argv) {
  73. PY_CHECK_ARGC(1);
  74. PY_CHECK_ARG_TYPE(0, tp_int);
  75. py_i64 val = py_toint(argv);
  76. if(val == 0) {
  77. py_newstr(py_retval(), "0b0");
  78. return true;
  79. }
  80. c11_sbuf ss;
  81. c11_sbuf__ctor(&ss);
  82. if(val < 0) {
  83. c11_sbuf__write_char(&ss, '-');
  84. val = -val;
  85. }
  86. c11_sbuf__write_cstr(&ss, "0b");
  87. bool non_zero = true;
  88. for(int i = 63; i >= 0; i--) {
  89. unsigned char bit = (val >> i) & 1;
  90. if(bit != 0) non_zero = false;
  91. if(!non_zero) c11_sbuf__write_char(&ss, bit ? '1' : '0');
  92. }
  93. c11_sbuf__py_submit(&ss, py_retval());
  94. return true;
  95. }
  96. static bool builtins_iter(int argc, py_Ref argv) {
  97. PY_CHECK_ARGC(1);
  98. return py_iter(argv);
  99. }
  100. static bool builtins_next(int argc, py_Ref argv) {
  101. if(argc == 0 || argc > 2) return TypeError("next() takes 1 or 2 arguments");
  102. int res = py_next(argv);
  103. if(res == -1) return false;
  104. if(res) return true;
  105. if(argc == 1) {
  106. // StopIteration stored in py_retval()
  107. return py_raise(py_retval());
  108. } else {
  109. py_assign(py_retval(), py_arg(1));
  110. return true;
  111. }
  112. }
  113. static bool builtins_hash(int argc, py_Ref argv) {
  114. PY_CHECK_ARGC(1);
  115. py_i64 val;
  116. if(!py_hash(argv, &val)) return false;
  117. py_newint(py_retval(), val);
  118. return true;
  119. }
  120. static bool builtins_abs(int argc, py_Ref argv) {
  121. PY_CHECK_ARGC(1);
  122. return pk_callmagic(__abs__, 1, argv);
  123. }
  124. static bool builtins_divmod(int argc, py_Ref argv) {
  125. PY_CHECK_ARGC(2);
  126. return pk_callmagic(__divmod__, 2, argv);
  127. }
  128. static bool builtins_round(int argc, py_Ref argv) {
  129. py_i64 ndigits;
  130. if(argc == 1) {
  131. ndigits = -1;
  132. } else if(argc == 2) {
  133. PY_CHECK_ARG_TYPE(1, tp_int);
  134. ndigits = py_toint(py_arg(1));
  135. if(ndigits < 0) return ValueError("ndigits should be non-negative");
  136. } else {
  137. return TypeError("round() takes 1 or 2 arguments");
  138. }
  139. if(argv->type == tp_int) {
  140. py_assign(py_retval(), py_arg(0));
  141. return true;
  142. } else if(argv->type == tp_float) {
  143. py_f64 x = py_tofloat(py_arg(0));
  144. py_f64 offset = x >= 0 ? 0.5 : -0.5;
  145. if(ndigits == -1) {
  146. py_newint(py_retval(), (py_i64)(x + offset));
  147. return true;
  148. }
  149. py_f64 factor = pow(10, ndigits);
  150. py_newfloat(py_retval(), (py_i64)(x * factor + offset) / factor);
  151. return true;
  152. }
  153. return pk_callmagic(__round__, argc, argv);
  154. }
  155. static bool builtins_print(int argc, py_Ref argv) {
  156. // print(*args, sep=' ', end='\n', flush=False)
  157. py_TValue* args = py_tuple_data(argv);
  158. int length = py_tuple_len(argv);
  159. PY_CHECK_ARG_TYPE(1, tp_str);
  160. PY_CHECK_ARG_TYPE(2, tp_str);
  161. PY_CHECK_ARG_TYPE(3, tp_bool);
  162. c11_sv sep = py_tosv(py_arg(1));
  163. c11_sv end = py_tosv(py_arg(2));
  164. bool flush = py_tobool(py_arg(3));
  165. c11_sbuf buf;
  166. c11_sbuf__ctor(&buf);
  167. for(int i = 0; i < length; i++) {
  168. if(i > 0) c11_sbuf__write_sv(&buf, sep);
  169. if(!py_str(&args[i])) {
  170. c11_sbuf__dtor(&buf);
  171. return false;
  172. }
  173. c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
  174. }
  175. c11_sbuf__write_sv(&buf, end);
  176. c11_string* res = c11_sbuf__submit(&buf);
  177. py_callbacks()->print(res->data);
  178. if(flush) py_callbacks()->flush();
  179. c11_string__delete(res);
  180. py_newnone(py_retval());
  181. return true;
  182. }
  183. static bool builtins_isinstance(int argc, py_Ref argv) {
  184. PY_CHECK_ARGC(2);
  185. if(py_istuple(py_arg(1))) {
  186. int length = py_tuple_len(py_arg(1));
  187. for(int i = 0; i < length; i++) {
  188. py_Ref item = py_tuple_getitem(py_arg(1), i);
  189. if(!py_checktype(item, tp_type)) return false;
  190. if(py_isinstance(py_arg(0), py_totype(item))) {
  191. py_newbool(py_retval(), true);
  192. return true;
  193. }
  194. }
  195. py_newbool(py_retval(), false);
  196. return true;
  197. }
  198. if(!py_checktype(py_arg(1), tp_type)) return false;
  199. py_newbool(py_retval(), py_isinstance(py_arg(0), py_totype(py_arg(1))));
  200. return true;
  201. }
  202. static bool builtins_issubclass(int argc, py_Ref argv) {
  203. PY_CHECK_ARGC(2);
  204. if(!py_checktype(py_arg(0), tp_type)) return false;
  205. if(!py_checktype(py_arg(1), tp_type)) return false;
  206. py_newbool(py_retval(), py_issubclass(py_totype(py_arg(0)), py_totype(py_arg(1))));
  207. return true;
  208. }
  209. static bool builtins_callable(int argc, py_Ref argv) {
  210. PY_CHECK_ARGC(1);
  211. bool res = py_callable(py_arg(0));
  212. py_newbool(py_retval(), res);
  213. return true;
  214. }
  215. static bool builtins_getattr(int argc, py_Ref argv) {
  216. PY_CHECK_ARG_TYPE(1, tp_str);
  217. py_Name name = py_namev(py_tosv(py_arg(1)));
  218. if(argc == 2) {
  219. return py_getattr(py_arg(0), name);
  220. } else if(argc == 3) {
  221. bool ok = py_getattr(py_arg(0), name);
  222. if(!ok && py_matchexc(tp_AttributeError)) {
  223. py_clearexc(NULL);
  224. py_assign(py_retval(), py_arg(2));
  225. return true; // default value
  226. }
  227. return ok;
  228. } else {
  229. return TypeError("getattr() expected 2 or 3 arguments");
  230. }
  231. return true;
  232. }
  233. static bool builtins_setattr(int argc, py_Ref argv) {
  234. PY_CHECK_ARGC(3);
  235. PY_CHECK_ARG_TYPE(1, tp_str);
  236. py_Name name = py_namev(py_tosv(py_arg(1)));
  237. py_newnone(py_retval());
  238. return py_setattr(py_arg(0), name, py_arg(2));
  239. }
  240. static bool builtins_hasattr(int argc, py_Ref argv) {
  241. PY_CHECK_ARGC(2);
  242. PY_CHECK_ARG_TYPE(1, tp_str);
  243. py_Name name = py_namev(py_tosv(py_arg(1)));
  244. bool ok = py_getattr(py_arg(0), name);
  245. if(ok) {
  246. py_newbool(py_retval(), true);
  247. return true;
  248. }
  249. if(py_matchexc(tp_AttributeError)) {
  250. py_clearexc(NULL);
  251. py_newbool(py_retval(), false);
  252. return true;
  253. }
  254. return false;
  255. }
  256. static bool builtins_delattr(int argc, py_Ref argv) {
  257. PY_CHECK_ARGC(2);
  258. PY_CHECK_ARG_TYPE(1, tp_str);
  259. py_Name name = py_namev(py_tosv(py_arg(1)));
  260. py_newnone(py_retval());
  261. return py_delattr(py_arg(0), name);
  262. }
  263. static bool builtins_chr(int argc, py_Ref argv) {
  264. PY_CHECK_ARGC(1);
  265. PY_CHECK_ARG_TYPE(0, tp_int);
  266. uint32_t val = py_toint(py_arg(0));
  267. // convert to utf-8
  268. char utf8[4];
  269. int len = c11__u32_to_u8(val, utf8);
  270. if(len == -1) return ValueError("invalid unicode code point: %d", val);
  271. py_newstrv(py_retval(), (c11_sv){utf8, len});
  272. return true;
  273. }
  274. static bool builtins_ord(int argc, py_Ref argv) {
  275. PY_CHECK_ARGC(1);
  276. PY_CHECK_ARG_TYPE(0, tp_str);
  277. c11_sv sv = py_tosv(py_arg(0));
  278. if(c11_sv__u8_length(sv) != 1) {
  279. return TypeError("ord() expected a character, but string of length %d found",
  280. c11_sv__u8_length(sv));
  281. }
  282. int u8bytes = c11__u8_header(sv.data[0], true);
  283. if(u8bytes == 0) return ValueError("invalid utf-8 char: %c", sv.data[0]);
  284. int value = c11__u8_value(u8bytes, sv.data);
  285. py_newint(py_retval(), value);
  286. return true;
  287. }
  288. static bool builtins_id(int argc, py_Ref argv) {
  289. PY_CHECK_ARGC(1);
  290. if(argv->is_ptr) {
  291. py_newint(py_retval(), (intptr_t)argv->_obj);
  292. } else {
  293. py_newnone(py_retval());
  294. }
  295. return true;
  296. }
  297. static bool builtins_globals(int argc, py_Ref argv) {
  298. PY_CHECK_ARGC(0);
  299. py_newglobals(py_retval());
  300. return true;
  301. }
  302. static bool builtins_locals(int argc, py_Ref argv) {
  303. PY_CHECK_ARGC(0);
  304. py_newlocals(py_retval());
  305. return true;
  306. }
  307. static void pk_push_special_locals() {
  308. py_Frame* frame = pk_current_vm->top_frame;
  309. if(!frame) {
  310. py_pushnil();
  311. return;
  312. }
  313. if(frame->is_locals_special) {
  314. py_push(frame->locals);
  315. } else {
  316. py_StackRef out = py_pushtmp();
  317. out->type = tp_locals;
  318. out->is_ptr = false;
  319. out->extra = 0;
  320. // this is a weak reference
  321. // which will expire when the frame is destroyed
  322. out->_ptr = frame;
  323. }
  324. }
  325. static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) {
  326. switch(argc) {
  327. case 1: {
  328. py_newglobals(py_pushtmp());
  329. pk_push_special_locals();
  330. break;
  331. }
  332. case 2: {
  333. // globals
  334. if(py_isnone(py_arg(1))) {
  335. py_newglobals(py_pushtmp());
  336. } else {
  337. py_push(py_arg(1));
  338. }
  339. // locals
  340. py_pushnil();
  341. break;
  342. }
  343. case 3: {
  344. // globals
  345. if(py_isnone(py_arg(1))) {
  346. py_newglobals(py_pushtmp());
  347. } else {
  348. py_push(py_arg(1));
  349. }
  350. // locals
  351. if(py_isnone(py_arg(2))) {
  352. py_pushnil();
  353. } else {
  354. py_push(py_arg(2));
  355. }
  356. break;
  357. }
  358. default: return TypeError("%s() takes at most 3 arguments", title);
  359. }
  360. if(py_isstr(argv)) {
  361. bool ok = py_compile(py_tostr(argv), "<string>", mode, true);
  362. if(!ok) return false;
  363. py_push(py_retval());
  364. } else if(py_istype(argv, tp_code)) {
  365. py_push(argv);
  366. } else {
  367. return TypeError("%s() expected 'str' or 'code', got '%t'", title, argv->type);
  368. }
  369. py_Frame* frame = pk_current_vm->top_frame;
  370. // [globals, locals, code]
  371. CodeObject* code = py_touserdata(py_peek(-1));
  372. if(code->src->is_dynamic) {
  373. bool ok = pk_execdyn(code, frame ? frame->module : NULL, py_peek(-3), py_peek(-2));
  374. py_shrink(3);
  375. return ok;
  376. } else {
  377. if(argc != 1) {
  378. return ValueError(
  379. "code object is not dynamic, `globals` and `locals` must not be specified");
  380. }
  381. bool ok = pk_exec(code, frame ? frame->module : NULL);
  382. py_shrink(3);
  383. return ok;
  384. }
  385. }
  386. static bool builtins_exec(int argc, py_Ref argv) {
  387. bool ok = _builtins_execdyn("exec", argc, argv, EXEC_MODE);
  388. py_newnone(py_retval());
  389. return ok;
  390. }
  391. static bool builtins_eval(int argc, py_Ref argv) {
  392. return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
  393. }
  394. static bool builtins_compile(int argc, py_Ref argv) {
  395. PY_CHECK_ARGC(3);
  396. for(int i = 0; i < 3; i++) {
  397. if(!py_checktype(py_arg(i), tp_str)) return false;
  398. }
  399. const char* source = py_tostr(py_arg(0));
  400. const char* filename = py_tostr(py_arg(1));
  401. const char* mode = py_tostr(py_arg(2));
  402. enum py_CompileMode compile_mode;
  403. if(strcmp(mode, "exec") == 0) {
  404. compile_mode = EXEC_MODE;
  405. } else if(strcmp(mode, "eval") == 0) {
  406. compile_mode = EVAL_MODE;
  407. } else if(strcmp(mode, "single") == 0) {
  408. compile_mode = SINGLE_MODE;
  409. } else {
  410. return ValueError("compile() mode must be 'exec', 'eval', or 'single'");
  411. }
  412. return py_compile(source, filename, compile_mode, true);
  413. }
  414. static bool builtins__import__(int argc, py_Ref argv) {
  415. PY_CHECK_ARGC(1);
  416. PY_CHECK_ARG_TYPE(0, tp_str);
  417. int res = py_import(py_tostr(argv));
  418. if(res == -1) return false;
  419. if(res) return true;
  420. return ImportError("module '%s' not found", py_tostr(argv));
  421. }
  422. static bool NoneType__repr__(int argc, py_Ref argv) {
  423. py_newstr(py_retval(), "None");
  424. return true;
  425. }
  426. static bool ellipsis__repr__(int argc, py_Ref argv) {
  427. py_newstr(py_retval(), "...");
  428. return true;
  429. }
  430. static bool NotImplementedType__repr__(int argc, py_Ref argv) {
  431. py_newstr(py_retval(), "NotImplemented");
  432. return true;
  433. }
  434. py_GlobalRef pk_builtins__register() {
  435. py_GlobalRef builtins = py_newmodule("builtins");
  436. py_bindfunc(builtins, "exit", builtins_exit);
  437. py_bindfunc(builtins, "input", builtins_input);
  438. py_bindfunc(builtins, "repr", builtins_repr);
  439. py_bindfunc(builtins, "len", builtins_len);
  440. py_bindfunc(builtins, "hex", builtins_hex);
  441. py_bindfunc(builtins, "bin", builtins_bin);
  442. py_bindfunc(builtins, "iter", builtins_iter);
  443. py_bindfunc(builtins, "next", builtins_next);
  444. py_bindfunc(builtins, "hash", builtins_hash);
  445. py_bindfunc(builtins, "abs", builtins_abs);
  446. py_bindfunc(builtins, "divmod", builtins_divmod);
  447. py_bindfunc(builtins, "round", builtins_round);
  448. py_bind(builtins, "print(*args, sep=' ', end='\\n', flush=False)", builtins_print);
  449. py_bindfunc(builtins, "isinstance", builtins_isinstance);
  450. py_bindfunc(builtins, "issubclass", builtins_issubclass);
  451. py_bindfunc(builtins, "callable", builtins_callable);
  452. py_bindfunc(builtins, "getattr", builtins_getattr);
  453. py_bindfunc(builtins, "setattr", builtins_setattr);
  454. py_bindfunc(builtins, "hasattr", builtins_hasattr);
  455. py_bindfunc(builtins, "delattr", builtins_delattr);
  456. py_bindfunc(builtins, "chr", builtins_chr);
  457. py_bindfunc(builtins, "ord", builtins_ord);
  458. py_bindfunc(builtins, "id", builtins_id);
  459. py_bindfunc(builtins, "globals", builtins_globals);
  460. py_bindfunc(builtins, "locals", builtins_locals);
  461. py_bindfunc(builtins, "exec", builtins_exec);
  462. py_bindfunc(builtins, "eval", builtins_eval);
  463. py_bindfunc(builtins, "compile", builtins_compile);
  464. py_bindfunc(builtins, "__import__", builtins__import__);
  465. // some patches
  466. py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
  467. py_setdict(py_tpobject(tp_NoneType), __hash__, py_None());
  468. py_bindmagic(tp_ellipsis, __repr__, ellipsis__repr__);
  469. py_setdict(py_tpobject(tp_ellipsis), __hash__, py_None());
  470. py_bindmagic(tp_NotImplementedType, __repr__, NotImplementedType__repr__);
  471. py_setdict(py_tpobject(tp_NotImplementedType), __hash__, py_None());
  472. return builtins;
  473. }
  474. void function__gc_mark(void* ud, c11_vector* p_stack) {
  475. Function* func = ud;
  476. if(func->globals) pk__mark_value(func->globals);
  477. if(func->closure) {
  478. NameDict* dict = func->closure;
  479. for(int i = 0; i < dict->capacity; i++) {
  480. NameDict_KV* kv = &dict->items[i];
  481. if(kv->key == NULL) continue;
  482. pk__mark_value(&kv->value);
  483. }
  484. }
  485. FuncDecl__gc_mark(func->decl, p_stack);
  486. }
  487. static bool function__doc__(int argc, py_Ref argv) {
  488. PY_CHECK_ARGC(1);
  489. Function* func = py_touserdata(py_arg(0));
  490. if(func->decl->docstring) {
  491. py_newstr(py_retval(), func->decl->docstring);
  492. } else {
  493. py_newnone(py_retval());
  494. }
  495. return true;
  496. }
  497. static bool function__name__(int argc, py_Ref argv) {
  498. PY_CHECK_ARGC(1);
  499. Function* func = py_touserdata(py_arg(0));
  500. py_newstr(py_retval(), func->decl->code.name->data);
  501. return true;
  502. }
  503. static bool function__repr__(int argc, py_Ref argv) {
  504. // <function f at 0x10365b9c0>
  505. PY_CHECK_ARGC(1);
  506. Function* func = py_touserdata(py_arg(0));
  507. c11_sbuf buf;
  508. c11_sbuf__ctor(&buf);
  509. c11_sbuf__write_cstr(&buf, "<function ");
  510. c11_sbuf__write_cstr(&buf, func->decl->code.name->data);
  511. c11_sbuf__write_cstr(&buf, " at ");
  512. c11_sbuf__write_ptr(&buf, func);
  513. c11_sbuf__write_char(&buf, '>');
  514. c11_sbuf__py_submit(&buf, py_retval());
  515. return true;
  516. }
  517. py_Type pk_function__register() {
  518. py_Type type =
  519. pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
  520. py_bindproperty(type, "__doc__", function__doc__, NULL);
  521. py_bindproperty(type, "__name__", function__name__, NULL);
  522. py_bindmagic(type, __repr__, function__repr__);
  523. return type;
  524. }
  525. static bool nativefunc__repr__(int argc, py_Ref argv) {
  526. PY_CHECK_ARGC(1);
  527. py_newstr(py_retval(), "<nativefunc object>");
  528. return true;
  529. }
  530. py_Type pk_nativefunc__register() {
  531. py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true);
  532. py_bindmagic(type, __repr__, nativefunc__repr__);
  533. return type;
  534. }
  535. static bool super__new__(int argc, py_Ref argv) {
  536. py_Type class_arg = 0;
  537. py_Frame* frame = pk_current_vm->top_frame;
  538. py_Ref self_arg = NULL;
  539. if(argc == 1) {
  540. // super()
  541. if(!frame->is_locals_special) {
  542. py_TValue* callable = frame->p0;
  543. if(callable->type == tp_boundmethod) callable = py_getslot(frame->p0, 1);
  544. if(callable->type == tp_function) {
  545. Function* func = py_touserdata(callable);
  546. if(func->clazz != NULL) {
  547. class_arg = ((py_TypeInfo*)PyObject__userdata(func->clazz))->index;
  548. if(frame->co->nlocals > 0) { self_arg = &frame->locals[0]; }
  549. }
  550. }
  551. }
  552. if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments");
  553. if(self_arg->type == tp_type) {
  554. // f(cls, ...)
  555. class_arg = pk_typeinfo(class_arg)->base;
  556. if(class_arg == 0) return RuntimeError("super(): base class is invalid");
  557. py_assign(py_retval(), py_tpobject(class_arg));
  558. return true;
  559. }
  560. } else if(argc == 3) {
  561. // super(type[T], obj)
  562. PY_CHECK_ARG_TYPE(1, tp_type);
  563. class_arg = py_totype(py_arg(1));
  564. self_arg = py_arg(2);
  565. if(!py_isinstance(self_arg, class_arg)) {
  566. return TypeError("super(type, obj): obj must be an instance of type");
  567. }
  568. } else {
  569. return TypeError("super() takes 0 or 2 arguments");
  570. }
  571. class_arg = pk_typeinfo(class_arg)->base;
  572. if(class_arg == 0) return RuntimeError("super(): base class is invalid");
  573. py_Type* p_class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type));
  574. *p_class_arg = class_arg;
  575. py_setslot(py_retval(), 0, self_arg);
  576. return true;
  577. }
  578. py_Type pk_super__register() {
  579. py_Type type = pk_newtype("super", tp_object, NULL, NULL, false, true);
  580. py_bindmagic(type, __new__, super__new__);
  581. return type;
  582. }