vm.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. #include "pocketpy/vm.h"
  2. namespace pkpy{
  3. VM::VM(bool enable_os) : heap(this), enable_os(enable_os) {
  4. this->vm = this;
  5. this->_c.error = nullptr;
  6. _stdout = [](VM* vm, const char* buf, int size) {
  7. PK_UNUSED(vm);
  8. std::cout.write(buf, size);
  9. };
  10. _stderr = [](VM* vm, const char* buf, int size) {
  11. PK_UNUSED(vm);
  12. std::cerr.write(buf, size);
  13. };
  14. callstack.reserve(8);
  15. _main = nullptr;
  16. _last_exception = nullptr;
  17. _import_handler = [](const Str& name) {
  18. PK_UNUSED(name);
  19. return Bytes();
  20. };
  21. init_builtin_types();
  22. }
  23. PyObject* VM::py_str(PyObject* obj){
  24. const PyTypeInfo* ti = _inst_type_info(obj);
  25. if(ti->m__str__) return ti->m__str__(this, obj);
  26. PyObject* self;
  27. PyObject* f = get_unbound_method(obj, __str__, &self, false);
  28. if(self != PY_NULL) return call_method(self, f);
  29. return py_repr(obj);
  30. }
  31. PyObject* VM::py_repr(PyObject* obj){
  32. const PyTypeInfo* ti = _inst_type_info(obj);
  33. if(ti->m__repr__) return ti->m__repr__(this, obj);
  34. return call_method(obj, __repr__);
  35. }
  36. PyObject* VM::py_json(PyObject* obj){
  37. const PyTypeInfo* ti = _inst_type_info(obj);
  38. if(ti->m__json__) return ti->m__json__(this, obj);
  39. return call_method(obj, __json__);
  40. }
  41. PyObject* VM::py_iter(PyObject* obj){
  42. const PyTypeInfo* ti = _inst_type_info(obj);
  43. if(ti->m__iter__) return ti->m__iter__(this, obj);
  44. PyObject* self;
  45. PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
  46. if(self != PY_NULL) return call_method(self, iter_f);
  47. TypeError(OBJ_NAME(_t(obj)).escape() + " object is not iterable");
  48. return nullptr;
  49. }
  50. FrameId VM::top_frame(){
  51. #if PK_DEBUG_EXTRA_CHECK
  52. if(callstack.empty()) FATAL_ERROR();
  53. #endif
  54. return FrameId(&callstack.data(), callstack.size()-1);
  55. }
  56. void VM::_pop_frame(){
  57. Frame* frame = &callstack.top();
  58. s_data.reset(frame->_sp_base);
  59. callstack.pop();
  60. }
  61. PyObject* VM::find_name_in_mro(PyObject* cls, StrName name){
  62. PyObject* val;
  63. do{
  64. val = cls->attr().try_get(name);
  65. if(val != nullptr) return val;
  66. Type base = _all_types[PK_OBJ_GET(Type, cls)].base;
  67. if(base.index == -1) break;
  68. cls = _all_types[base].obj;
  69. }while(true);
  70. return nullptr;
  71. }
  72. bool VM::isinstance(PyObject* obj, Type cls_t){
  73. Type obj_t = PK_OBJ_GET(Type, _t(obj));
  74. do{
  75. if(obj_t == cls_t) return true;
  76. Type base = _all_types[obj_t].base;
  77. if(base.index == -1) break;
  78. obj_t = base;
  79. }while(true);
  80. return false;
  81. }
  82. PyObject* VM::exec(Str source, Str filename, CompileMode mode, PyObject* _module){
  83. if(_module == nullptr) _module = _main;
  84. try {
  85. CodeObject_ code = compile(source, filename, mode);
  86. #if PK_DEBUG_DIS_EXEC
  87. if(_module == _main) std::cout << disassemble(code) << '\n';
  88. #endif
  89. return _exec(code, _module);
  90. }catch (const Exception& e){
  91. Str sum = e.summary() + "\n";
  92. _stderr(this, sum.data, sum.size);
  93. }
  94. #if !PK_DEBUG_FULL_EXCEPTION
  95. catch (const std::exception& e) {
  96. Str msg = "An std::exception occurred! It could be a bug.\n";
  97. msg = msg + e.what() + "\n";
  98. _stderr(this, msg.data, msg.size);
  99. }
  100. #endif
  101. callstack.clear();
  102. s_data.clear();
  103. return nullptr;
  104. }
  105. void VM::exec(Str source){
  106. exec(source, "main.py", EXEC_MODE);
  107. }
  108. PyObject* VM::eval(Str source){
  109. return exec(source, "<eval>", EVAL_MODE);
  110. }
  111. PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){
  112. PyObject* obj = heap._new<Type>(tp_type, _all_types.size());
  113. const PyTypeInfo& base_info = _all_types[base];
  114. if(!base_info.subclass_enabled){
  115. TypeError(fmt("type ", base_info.name.escape(), " is not `subclass_enabled`"));
  116. }
  117. PyTypeInfo info{
  118. obj,
  119. base,
  120. mod,
  121. name.sv(),
  122. subclass_enabled,
  123. };
  124. if(mod != nullptr) mod->attr().set(name, obj);
  125. _all_types.push_back(info);
  126. return obj;
  127. }
  128. Type VM::_new_type_object(StrName name, Type base) {
  129. PyObject* obj = new_type_object(nullptr, name, base, false);
  130. return PK_OBJ_GET(Type, obj);
  131. }
  132. PyObject* VM::_find_type_object(const Str& type){
  133. PyObject* obj = builtins->attr().try_get(type);
  134. if(obj == nullptr){
  135. for(auto& t: _all_types) if(t.name == type) return t.obj;
  136. throw std::runtime_error(fmt("type not found: ", type));
  137. }
  138. check_non_tagged_type(obj, tp_type);
  139. return obj;
  140. }
  141. Type VM::_type(const Str& type){
  142. PyObject* obj = _find_type_object(type);
  143. return PK_OBJ_GET(Type, obj);
  144. }
  145. PyTypeInfo* VM::_type_info(const Str& type){
  146. PyObject* obj = builtins->attr().try_get(type);
  147. if(obj == nullptr){
  148. for(auto& t: _all_types) if(t.name == type) return &t;
  149. FATAL_ERROR();
  150. }
  151. return &_all_types[PK_OBJ_GET(Type, obj)];
  152. }
  153. PyTypeInfo* VM::_type_info(Type type){
  154. return &_all_types[type];
  155. }
  156. const PyTypeInfo* VM::_inst_type_info(PyObject* obj){
  157. if(is_int(obj)) return &_all_types[tp_int];
  158. if(is_float(obj)) return &_all_types[tp_float];
  159. return &_all_types[obj->type];
  160. }
  161. bool VM::py_equals(PyObject* lhs, PyObject* rhs){
  162. if(lhs == rhs) return true;
  163. const PyTypeInfo* ti = _inst_type_info(lhs);
  164. PyObject* res;
  165. if(ti->m__eq__){
  166. res = ti->m__eq__(this, lhs, rhs);
  167. if(res != vm->NotImplemented) return res == vm->True;
  168. }
  169. res = call_method(lhs, __eq__, rhs);
  170. if(res != vm->NotImplemented) return res == vm->True;
  171. ti = _inst_type_info(rhs);
  172. if(ti->m__eq__){
  173. res = ti->m__eq__(this, rhs, lhs);
  174. if(res != vm->NotImplemented) return res == vm->True;
  175. }
  176. res = call_method(rhs, __eq__, lhs);
  177. if(res != vm->NotImplemented) return res == vm->True;
  178. return false;
  179. }
  180. int VM::normalized_index(int index, int size){
  181. if(index < 0) index += size;
  182. if(index < 0 || index >= size){
  183. IndexError(std::to_string(index) + " not in [0, " + std::to_string(size) + ")");
  184. }
  185. return index;
  186. }
  187. PyObject* VM::py_next(PyObject* obj){
  188. const PyTypeInfo* ti = _inst_type_info(obj);
  189. if(ti->m__next__) return ti->m__next__(this, obj);
  190. return call_method(obj, __next__);
  191. }
  192. PyObject* VM::py_import(Str path, bool throw_err){
  193. if(path.empty()) vm->ValueError("empty module name");
  194. auto f_join = [](const std::vector<std::string_view>& cpnts){
  195. std::stringstream ss;
  196. for(int i=0; i<cpnts.size(); i++){
  197. if(i != 0) ss << ".";
  198. ss << cpnts[i];
  199. }
  200. return Str(ss.str());
  201. };
  202. if(path[0] == '.'){
  203. if(_import_context.pending.empty()){
  204. ImportError("relative import outside of package");
  205. }
  206. Str curr_path = _import_context.pending.back();
  207. bool curr_is_init = _import_context.pending_is_init.back();
  208. // convert relative path to absolute path
  209. std::vector<std::string_view> cpnts = curr_path.split(".");
  210. int prefix = 0; // how many dots in the prefix
  211. for(int i=0; i<path.length(); i++){
  212. if(path[i] == '.') prefix++;
  213. else break;
  214. }
  215. if(prefix > cpnts.size()) ImportError("attempted relative import beyond top-level package");
  216. path = path.substr(prefix); // remove prefix
  217. for(int i=(int)curr_is_init; i<prefix; i++) cpnts.pop_back();
  218. if(!path.empty()) cpnts.push_back(path.sv());
  219. path = f_join(cpnts);
  220. }
  221. // std::cout << "py_import(" << path.escape() << ")" << std::endl;
  222. PK_ASSERT(path.begin()[0] != '.');
  223. PK_ASSERT(path.end()[-1] != '.');
  224. auto path_cpnts = path.split(".");
  225. // check circular import
  226. if(_import_context.pending.size() > 128){
  227. ImportError("maximum recursion depth exceeded while importing");
  228. }
  229. StrName name(path); // path to StrName
  230. PyObject* ext_mod = _modules.try_get(name);
  231. if(ext_mod != nullptr) return ext_mod;
  232. // try import
  233. Str filename = path.replace('.', kPlatformSep) + ".py";
  234. Str source;
  235. bool is_init = false;
  236. auto it = _lazy_modules.find(name);
  237. if(it == _lazy_modules.end()){
  238. Bytes b = _import_handler(filename);
  239. if(!b){
  240. filename = path.replace('.', kPlatformSep).str() + kPlatformSep + "__init__.py";
  241. is_init = true;
  242. b = _import_handler(filename);
  243. }
  244. if(!b){
  245. if(throw_err) ImportError(fmt("module ", path.escape(), " not found"));
  246. else return nullptr;
  247. }
  248. source = Str(b.str());
  249. }else{
  250. source = it->second;
  251. _lazy_modules.erase(it);
  252. }
  253. auto _ = _import_context.scope(path, is_init);
  254. CodeObject_ code = compile(source, filename, EXEC_MODE);
  255. Str name_cpnt = path_cpnts.back();
  256. path_cpnts.pop_back();
  257. PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
  258. _exec(code, new_mod);
  259. new_mod->attr()._try_perfect_rehash();
  260. return new_mod;
  261. }
  262. VM::~VM() {
  263. callstack.clear();
  264. s_data.clear();
  265. _all_types.clear();
  266. _modules.clear();
  267. _lazy_modules.clear();
  268. }
  269. PyObject* VM::py_negate(PyObject* obj){
  270. const PyTypeInfo* ti = _inst_type_info(obj);
  271. if(ti->m__neg__) return ti->m__neg__(this, obj);
  272. return call_method(obj, __neg__);
  273. }
  274. void VM::check_int_or_float(PyObject *obj){
  275. if(!is_tagged(obj)){
  276. TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape());
  277. }
  278. }
  279. bool VM::py_bool(PyObject* obj){
  280. if(is_non_tagged_type(obj, tp_bool)) return obj == True;
  281. if(obj == None) return false;
  282. if(is_int(obj)) return _CAST(i64, obj) != 0;
  283. if(is_float(obj)) return _CAST(f64, obj) != 0.0;
  284. PyObject* self;
  285. PyObject* len_f = get_unbound_method(obj, __len__, &self, false);
  286. if(self != PY_NULL){
  287. PyObject* ret = call_method(self, len_f);
  288. return CAST(i64, ret) > 0;
  289. }
  290. return true;
  291. }
  292. PyObject* VM::py_list(PyObject* it){
  293. auto _lock = heap.gc_scope_lock();
  294. it = py_iter(it);
  295. List list;
  296. PyObject* obj = py_next(it);
  297. while(obj != StopIteration){
  298. list.push_back(obj);
  299. obj = py_next(it);
  300. }
  301. return VAR(std::move(list));
  302. }
  303. void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step){
  304. auto clip = [](int value, int min, int max){
  305. if(value < min) return min;
  306. if(value > max) return max;
  307. return value;
  308. };
  309. if(s.step == None) step = 1;
  310. else step = CAST(int, s.step);
  311. if(step == 0) ValueError("slice step cannot be zero");
  312. if(step > 0){
  313. if(s.start == None){
  314. start = 0;
  315. }else{
  316. start = CAST(int, s.start);
  317. if(start < 0) start += length;
  318. start = clip(start, 0, length);
  319. }
  320. if(s.stop == None){
  321. stop = length;
  322. }else{
  323. stop = CAST(int, s.stop);
  324. if(stop < 0) stop += length;
  325. stop = clip(stop, 0, length);
  326. }
  327. }else{
  328. if(s.start == None){
  329. start = length - 1;
  330. }else{
  331. start = CAST(int, s.start);
  332. if(start < 0) start += length;
  333. start = clip(start, -1, length - 1);
  334. }
  335. if(s.stop == None){
  336. stop = -1;
  337. }else{
  338. stop = CAST(int, s.stop);
  339. if(stop < 0) stop += length;
  340. stop = clip(stop, -1, length - 1);
  341. }
  342. }
  343. }
  344. i64 VM::py_hash(PyObject* obj){
  345. // https://docs.python.org/3.10/reference/datamodel.html#object.__hash__
  346. const PyTypeInfo* ti = _inst_type_info(obj);
  347. if(ti->m__hash__) return ti->m__hash__(this, obj);
  348. PyObject* self;
  349. PyObject* f = get_unbound_method(obj, __hash__, &self, false);
  350. if(f != nullptr){
  351. PyObject* ret = call_method(self, f);
  352. return CAST(i64, ret);
  353. }
  354. // if it is trivial `object`, return PK_BITS
  355. if(ti == &_all_types[tp_object]) return PK_BITS(obj);
  356. // otherwise, we check if it has a custom __eq__ other than object.__eq__
  357. bool has_custom_eq = false;
  358. if(ti->m__eq__) has_custom_eq = true;
  359. else{
  360. f = get_unbound_method(obj, __eq__, &self, false);
  361. has_custom_eq = f != _t(tp_object)->attr(__eq__);
  362. }
  363. if(has_custom_eq){
  364. TypeError(fmt("unhashable type: ", ti->name.escape()));
  365. return 0;
  366. }else{
  367. return PK_BITS(obj);
  368. }
  369. }
  370. PyObject* VM::format(Str spec, PyObject* obj){
  371. if(spec.empty()) return py_str(obj);
  372. char type;
  373. switch(spec.end()[-1]){
  374. case 'f': case 'd': case 's':
  375. type = spec.end()[-1];
  376. spec = spec.substr(0, spec.length() - 1);
  377. break;
  378. default: type = ' '; break;
  379. }
  380. char pad_c = ' ';
  381. for(char c: std::string_view("0-=*#@!~")){
  382. if(spec[0] == c){
  383. pad_c = c;
  384. spec = spec.substr(1);
  385. break;
  386. }
  387. }
  388. char align;
  389. if(spec[0] == '^'){
  390. align = '^';
  391. spec = spec.substr(1);
  392. }else if(spec[0] == '>'){
  393. align = '>';
  394. spec = spec.substr(1);
  395. }else if(spec[0] == '<'){
  396. align = '<';
  397. spec = spec.substr(1);
  398. }else{
  399. if(is_int(obj) || is_float(obj)) align = '>';
  400. else align = '<';
  401. }
  402. int dot = spec.index(".");
  403. int width, precision;
  404. try{
  405. if(dot >= 0){
  406. if(dot == 0){
  407. width = -1;
  408. }else{
  409. width = Number::stoi(spec.substr(0, dot).str());
  410. }
  411. precision = Number::stoi(spec.substr(dot+1).str());
  412. }else{
  413. width = Number::stoi(spec.str());
  414. precision = -1;
  415. }
  416. }catch(...){
  417. ValueError("invalid format specifer");
  418. UNREACHABLE();
  419. }
  420. if(type != 'f' && dot >= 0) ValueError("precision not allowed in the format specifier");
  421. Str ret;
  422. if(type == 'f'){
  423. f64 val = CAST(f64, obj);
  424. if(precision < 0) precision = 6;
  425. std::stringstream ss;
  426. ss << std::fixed << std::setprecision(precision) << val;
  427. ret = ss.str();
  428. }else if(type == 'd'){
  429. ret = std::to_string(CAST(i64, obj));
  430. }else if(type == 's'){
  431. ret = CAST(Str&, obj);
  432. }else{
  433. ret = CAST(Str&, py_str(obj));
  434. }
  435. if(width != -1 && width > ret.length()){
  436. int pad = width - ret.length();
  437. if(align == '>' || align == '<'){
  438. std::string padding(pad, pad_c);
  439. if(align == '>') ret = padding.c_str() + ret;
  440. else ret = ret + padding.c_str();
  441. }else{ // ^
  442. int pad_left = pad / 2;
  443. int pad_right = pad - pad_left;
  444. std::string padding_left(pad_left, pad_c);
  445. std::string padding_right(pad_right, pad_c);
  446. ret = padding_left.c_str() + ret + padding_right.c_str();
  447. }
  448. }
  449. return VAR(ret);
  450. }
  451. PyObject* VM::new_module(Str name, Str package) {
  452. PyObject* obj = heap._new<DummyModule>(tp_module);
  453. obj->attr().set(__name__, VAR(name));
  454. obj->attr().set(__package__, VAR(package));
  455. // we do not allow override in order to avoid memory leak
  456. // it is because Module objects are not garbage collected
  457. if(_modules.contains(name)){
  458. throw std::runtime_error(fmt("module ", name.escape(), " already exists"));
  459. }
  460. // convert to fullname and set it into _modules
  461. if(!package.empty()) name = package + "." + name;
  462. obj->attr().set(__path__, VAR(name));
  463. _modules.set(name, obj);
  464. return obj;
  465. }
  466. static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
  467. std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg);
  468. switch(byte.op){
  469. case OP_LOAD_CONST: case OP_FORMAT_STRING: case OP_IMPORT_PATH:
  470. if(vm != nullptr){
  471. argStr += fmt(" (", CAST(Str, vm->py_repr(co->consts[byte.arg])), ")");
  472. }
  473. break;
  474. case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
  475. case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR:
  476. case OP_BEGIN_CLASS: case OP_RAISE:
  477. case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: case OP_STORE_CLASS_ATTR:
  478. argStr += fmt(" (", StrName(byte.arg).sv(), ")");
  479. break;
  480. case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST: case OP_INC_FAST: case OP_DEC_FAST:
  481. argStr += fmt(" (", co->varnames[byte.arg].sv(), ")");
  482. break;
  483. case OP_LOAD_FUNCTION:
  484. argStr += fmt(" (", co->func_decls[byte.arg]->code->name, ")");
  485. break;
  486. }
  487. return argStr;
  488. }
  489. Str VM::disassemble(CodeObject_ co){
  490. auto pad = [](const Str& s, const int n){
  491. if(s.length() >= n) return s.substr(0, n);
  492. return s + std::string(n - s.length(), ' ');
  493. };
  494. std::vector<int> jumpTargets;
  495. for(auto byte : co->codes){
  496. if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE || byte.op == OP_SHORTCUT_IF_FALSE_OR_POP){
  497. jumpTargets.push_back(byte.arg);
  498. }
  499. }
  500. std::stringstream ss;
  501. int prev_line = -1;
  502. for(int i=0; i<co->codes.size(); i++){
  503. const Bytecode& byte = co->codes[i];
  504. Str line = std::to_string(co->lines[i]);
  505. if(co->lines[i] == prev_line) line = "";
  506. else{
  507. if(prev_line != -1) ss << "\n";
  508. prev_line = co->lines[i];
  509. }
  510. std::string pointer;
  511. if(std::find(jumpTargets.begin(), jumpTargets.end(), i) != jumpTargets.end()){
  512. pointer = "-> ";
  513. }else{
  514. pointer = " ";
  515. }
  516. ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
  517. ss << " " << pad(OP_NAMES[byte.op], 25) << " ";
  518. // ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
  519. std::string argStr = _opcode_argstr(this, byte, co.get());
  520. ss << argStr;
  521. // ss << pad(argStr, 40); // may overflow
  522. // ss << co->blocks[byte.block].type;
  523. if(i != co->codes.size() - 1) ss << '\n';
  524. }
  525. for(auto& decl: co->func_decls){
  526. ss << "\n\n" << "Disassembly of " << decl->code->name << ":\n";
  527. ss << disassemble(decl->code);
  528. }
  529. ss << "\n";
  530. return Str(ss.str());
  531. }
  532. #if PK_DEBUG_CEVAL_STEP
  533. void VM::_log_s_data(const char* title) {
  534. if(_main == nullptr) return;
  535. if(callstack.empty()) return;
  536. std::stringstream ss;
  537. if(title) ss << title << " | ";
  538. std::map<PyObject**, int> sp_bases;
  539. for(Frame& f: callstack.data()){
  540. if(f._sp_base == nullptr) FATAL_ERROR();
  541. sp_bases[f._sp_base] += 1;
  542. }
  543. FrameId frame = top_frame();
  544. int line = frame->co->lines[frame->_ip];
  545. ss << frame->co->name << ":" << line << " [";
  546. for(PyObject** p=s_data.begin(); p!=s_data.end(); p++){
  547. ss << std::string(sp_bases[p], '|');
  548. if(sp_bases[p] > 0) ss << " ";
  549. PyObject* obj = *p;
  550. if(obj == nullptr) ss << "(nil)";
  551. else if(obj == PY_NULL) ss << "NULL";
  552. else if(is_int(obj)) ss << CAST(i64, obj);
  553. else if(is_float(obj)) ss << CAST(f64, obj);
  554. else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape();
  555. else if(obj == None) ss << "None";
  556. else if(obj == True) ss << "True";
  557. else if(obj == False) ss << "False";
  558. else if(is_type(obj, tp_function)){
  559. auto& f = CAST(Function&, obj);
  560. ss << f.decl->code->name << "(...)";
  561. } else if(is_type(obj, tp_type)){
  562. Type t = PK_OBJ_GET(Type, obj);
  563. ss << "<class " + _all_types[t].name.escape() + ">";
  564. } else if(is_type(obj, tp_list)){
  565. auto& t = CAST(List&, obj);
  566. ss << "list(size=" << t.size() << ")";
  567. } else if(is_type(obj, tp_tuple)){
  568. auto& t = CAST(Tuple&, obj);
  569. ss << "tuple(size=" << t.size() << ")";
  570. } else ss << "(" << obj_type_name(this, obj->type) << ")";
  571. ss << ", ";
  572. }
  573. std::string output = ss.str();
  574. if(!s_data.empty()) {
  575. output.pop_back(); output.pop_back();
  576. }
  577. output.push_back(']');
  578. Bytecode byte = frame->co->codes[frame->_ip];
  579. std::cout << output << " " << OP_NAMES[byte.op] << " " << _opcode_argstr(nullptr, byte, frame->co) << std::endl;
  580. }
  581. #endif
  582. void VM::init_builtin_types(){
  583. _all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, nullptr, "object", true});
  584. _all_types.push_back({heap._new<Type>(Type(1), Type(1)), 0, nullptr, "type", false});
  585. tp_object = 0; tp_type = 1;
  586. tp_int = _new_type_object("int");
  587. tp_float = _new_type_object("float");
  588. if(tp_int.index != kTpIntIndex || tp_float.index != kTpFloatIndex) FATAL_ERROR();
  589. tp_bool = _new_type_object("bool");
  590. tp_str = _new_type_object("str");
  591. tp_list = _new_type_object("list");
  592. tp_tuple = _new_type_object("tuple");
  593. tp_slice = _new_type_object("slice");
  594. tp_range = _new_type_object("range");
  595. tp_module = _new_type_object("module");
  596. tp_function = _new_type_object("function");
  597. tp_native_func = _new_type_object("native_func");
  598. tp_bound_method = _new_type_object("bound_method");
  599. tp_super = _new_type_object("super");
  600. tp_exception = _new_type_object("Exception");
  601. tp_bytes = _new_type_object("bytes");
  602. tp_mappingproxy = _new_type_object("mappingproxy");
  603. tp_dict = _new_type_object("dict");
  604. tp_property = _new_type_object("property");
  605. tp_star_wrapper = _new_type_object("_star_wrapper");
  606. this->None = heap._new<Dummy>(_new_type_object("NoneType"));
  607. this->NotImplemented = heap._new<Dummy>(_new_type_object("NotImplementedType"));
  608. this->Ellipsis = heap._new<Dummy>(_new_type_object("ellipsis"));
  609. this->True = heap._new<Dummy>(tp_bool);
  610. this->False = heap._new<Dummy>(tp_bool);
  611. this->StopIteration = heap._new<Dummy>(_new_type_object("StopIterationType"));
  612. this->builtins = new_module("builtins");
  613. // setup public types
  614. builtins->attr().set("type", _t(tp_type));
  615. builtins->attr().set("object", _t(tp_object));
  616. builtins->attr().set("bool", _t(tp_bool));
  617. builtins->attr().set("int", _t(tp_int));
  618. builtins->attr().set("float", _t(tp_float));
  619. builtins->attr().set("str", _t(tp_str));
  620. builtins->attr().set("list", _t(tp_list));
  621. builtins->attr().set("tuple", _t(tp_tuple));
  622. builtins->attr().set("range", _t(tp_range));
  623. builtins->attr().set("bytes", _t(tp_bytes));
  624. builtins->attr().set("dict", _t(tp_dict));
  625. builtins->attr().set("property", _t(tp_property));
  626. builtins->attr().set("StopIteration", StopIteration);
  627. builtins->attr().set("NotImplemented", NotImplemented);
  628. builtins->attr().set("slice", _t(tp_slice));
  629. post_init();
  630. for(int i=0; i<_all_types.size(); i++){
  631. _all_types[i].obj->attr()._try_perfect_rehash();
  632. }
  633. for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash();
  634. this->_main = new_module("__main__");
  635. }
  636. // `heap.gc_scope_lock();` needed before calling this function
  637. void VM::_unpack_as_list(ArgsView args, List& list){
  638. for(PyObject* obj: args){
  639. if(is_non_tagged_type(obj, tp_star_wrapper)){
  640. const StarWrapper& w = _CAST(StarWrapper&, obj);
  641. // maybe this check should be done in the compile time
  642. if(w.level != 1) TypeError("expected level 1 star wrapper");
  643. PyObject* _0 = py_iter(w.obj);
  644. PyObject* _1 = py_next(_0);
  645. while(_1 != StopIteration){
  646. list.push_back(_1);
  647. _1 = py_next(_0);
  648. }
  649. }else{
  650. list.push_back(obj);
  651. }
  652. }
  653. }
  654. // `heap.gc_scope_lock();` needed before calling this function
  655. void VM::_unpack_as_dict(ArgsView args, Dict& dict){
  656. for(PyObject* obj: args){
  657. if(is_non_tagged_type(obj, tp_star_wrapper)){
  658. const StarWrapper& w = _CAST(StarWrapper&, obj);
  659. // maybe this check should be done in the compile time
  660. if(w.level != 2) TypeError("expected level 2 star wrapper");
  661. const Dict& other = CAST(Dict&, w.obj);
  662. dict.update(other);
  663. }else{
  664. const Tuple& t = CAST(Tuple&, obj);
  665. if(t.size() != 2) TypeError("expected tuple of length 2");
  666. dict.set(t[0], t[1]);
  667. }
  668. }
  669. }
  670. void VM::_prepare_py_call(PyObject** buffer, ArgsView args, ArgsView kwargs, const FuncDecl_& decl){
  671. const CodeObject* co = decl->code.get();
  672. int co_nlocals = co->varnames.size();
  673. int decl_argc = decl->args.size();
  674. if(args.size() < decl_argc){
  675. vm->TypeError(fmt(
  676. "expected ", decl_argc, " positional arguments, got ", args.size(),
  677. " (", co->name, ')'
  678. ));
  679. }
  680. int i = 0;
  681. // prepare args
  682. for(int index: decl->args) buffer[index] = args[i++];
  683. // set extra varnames to nullptr
  684. for(int j=i; j<co_nlocals; j++) buffer[j] = PY_NULL;
  685. // prepare kwdefaults
  686. for(auto& kv: decl->kwargs) buffer[kv.key] = kv.value;
  687. // handle *args
  688. if(decl->starred_arg != -1){
  689. ArgsView vargs(args.begin() + i, args.end());
  690. buffer[decl->starred_arg] = VAR(vargs.to_tuple());
  691. i += vargs.size();
  692. }else{
  693. // kwdefaults override
  694. for(auto& kv: decl->kwargs){
  695. if(i >= args.size()) break;
  696. buffer[kv.key] = args[i++];
  697. }
  698. if(i < args.size()) TypeError(fmt("too many arguments", " (", decl->code->name, ')'));
  699. }
  700. PyObject* vkwargs;
  701. if(decl->starred_kwarg != -1){
  702. vkwargs = VAR(Dict(this));
  703. buffer[decl->starred_kwarg] = vkwargs;
  704. }else{
  705. vkwargs = nullptr;
  706. }
  707. for(int j=0; j<kwargs.size(); j+=2){
  708. StrName key(CAST(int, kwargs[j]));
  709. int index = co->varnames_inv.try_get(key);
  710. if(index < 0){
  711. if(vkwargs == nullptr){
  712. TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()"));
  713. }else{
  714. Dict& dict = _CAST(Dict&, vkwargs);
  715. dict.set(VAR(key.sv()), kwargs[j+1]);
  716. }
  717. }else{
  718. buffer[index] = kwargs[j+1];
  719. }
  720. }
  721. }
  722. PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
  723. PyObject** p1 = s_data._sp - KWARGC*2;
  724. PyObject** p0 = p1 - ARGC - 2;
  725. // [callable, <self>, args..., kwargs...]
  726. // ^p0 ^p1 ^_sp
  727. PyObject* callable = p1[-(ARGC + 2)];
  728. bool method_call = p1[-(ARGC + 1)] != PY_NULL;
  729. // handle boundmethod, do a patch
  730. if(is_non_tagged_type(callable, tp_bound_method)){
  731. if(method_call) FATAL_ERROR();
  732. auto& bm = CAST(BoundMethod&, callable);
  733. callable = bm.func; // get unbound method
  734. p1[-(ARGC + 2)] = bm.func;
  735. p1[-(ARGC + 1)] = bm.self;
  736. method_call = true;
  737. // [unbound, self, args..., kwargs...]
  738. }
  739. ArgsView args(p1 - ARGC - int(method_call), p1);
  740. ArgsView kwargs(p1, s_data._sp);
  741. PyObject* buffer[PK_MAX_CO_VARNAMES];
  742. if(is_non_tagged_type(callable, tp_native_func)){
  743. const auto& f = PK_OBJ_GET(NativeFunc, callable);
  744. PyObject* ret;
  745. if(f.decl != nullptr){
  746. int co_nlocals = f.decl->code->varnames.size();
  747. _prepare_py_call(buffer, args, kwargs, f.decl);
  748. // copy buffer back to stack
  749. s_data.reset(args.begin());
  750. for(int j=0; j<co_nlocals; j++) PUSH(buffer[j]);
  751. ret = f.call(vm, ArgsView(s_data._sp - co_nlocals, s_data._sp));
  752. }else{
  753. if(KWARGC != 0) TypeError("old-style native_func does not accept keyword arguments");
  754. f.check_size(this, args);
  755. ret = f.call(this, args);
  756. }
  757. s_data.reset(p0);
  758. return ret;
  759. }
  760. if(is_non_tagged_type(callable, tp_function)){
  761. /*****************_py_call*****************/
  762. // callable must be a `function` object
  763. if(s_data.is_overflow()) StackOverflowError();
  764. const Function& fn = PK_OBJ_GET(Function, callable);
  765. const FuncDecl_& decl = fn.decl;
  766. const CodeObject* co = decl->code.get();
  767. int co_nlocals = co->varnames.size();
  768. _prepare_py_call(buffer, args, kwargs, decl);
  769. if(co->is_generator){
  770. s_data.reset(p0);
  771. return _py_generator(
  772. Frame(&s_data, nullptr, co, fn._module, callable),
  773. ArgsView(buffer, buffer + co_nlocals)
  774. );
  775. }
  776. // copy buffer back to stack
  777. s_data.reset(args.begin());
  778. for(int j=0; j<co_nlocals; j++) PUSH(buffer[j]);
  779. callstack.emplace(&s_data, p0, co, fn._module, callable, FastLocals(co, args.begin()));
  780. if(op_call) return PY_OP_CALL;
  781. return _run_top_frame();
  782. /*****************_py_call*****************/
  783. }
  784. if(is_non_tagged_type(callable, tp_type)){
  785. if(method_call) FATAL_ERROR();
  786. // [type, NULL, args..., kwargs...]
  787. PyObject* new_f = find_name_in_mro(callable, __new__);
  788. PyObject* obj;
  789. #if PK_DEBUG_EXTRA_CHECK
  790. PK_ASSERT(new_f != nullptr);
  791. #endif
  792. if(new_f == cached_object__new__) {
  793. // fast path for object.__new__
  794. Type t = PK_OBJ_GET(Type, callable);
  795. obj= vm->heap.gcnew<DummyInstance>(t);
  796. }else{
  797. PUSH(new_f);
  798. PUSH(PY_NULL);
  799. PUSH(callable); // cls
  800. for(PyObject* o: args) PUSH(o);
  801. for(PyObject* o: kwargs) PUSH(o);
  802. // if obj is not an instance of callable, the behavior is undefined
  803. obj = vectorcall(ARGC+1, KWARGC);
  804. }
  805. // __init__
  806. PyObject* self;
  807. callable = get_unbound_method(obj, __init__, &self, false);
  808. if (self != PY_NULL) {
  809. // replace `NULL` with `self`
  810. p1[-(ARGC + 2)] = callable;
  811. p1[-(ARGC + 1)] = self;
  812. // [init_f, self, args..., kwargs...]
  813. vectorcall(ARGC, KWARGC);
  814. // We just discard the return value of `__init__`
  815. // in cpython it raises a TypeError if the return value is not None
  816. }else{
  817. // manually reset the stack
  818. s_data.reset(p0);
  819. }
  820. return obj;
  821. }
  822. // handle `__call__` overload
  823. PyObject* self;
  824. PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
  825. if(self != PY_NULL){
  826. p1[-(ARGC + 2)] = call_f;
  827. p1[-(ARGC + 1)] = self;
  828. // [call_f, self, args..., kwargs...]
  829. return vectorcall(ARGC, KWARGC, false);
  830. }
  831. TypeError(OBJ_NAME(_t(callable)).escape() + " object is not callable");
  832. return nullptr;
  833. }
  834. // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
  835. PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
  836. PyObject* objtype;
  837. // handle super() proxy
  838. if(is_non_tagged_type(obj, tp_super)){
  839. const Super& super = PK_OBJ_GET(Super, obj);
  840. obj = super.first;
  841. objtype = _t(super.second);
  842. }else{
  843. objtype = _t(obj);
  844. }
  845. PyObject* cls_var = find_name_in_mro(objtype, name);
  846. if(cls_var != nullptr){
  847. // handle descriptor
  848. if(is_non_tagged_type(cls_var, tp_property)){
  849. const Property& prop = _CAST(Property&, cls_var);
  850. return call(prop.getter, obj);
  851. }
  852. }
  853. // handle instance __dict__
  854. if(!is_tagged(obj) && obj->is_attr_valid()){
  855. PyObject* val = obj->attr().try_get(name);
  856. if(val != nullptr) return val;
  857. }
  858. if(cls_var != nullptr){
  859. // bound method is non-data descriptor
  860. if(is_non_tagged_type(cls_var, tp_function) || is_non_tagged_type(cls_var, tp_native_func)){
  861. return VAR(BoundMethod(obj, cls_var));
  862. }
  863. return cls_var;
  864. }
  865. if(is_non_tagged_type(obj, tp_module)){
  866. Str path = CAST(Str&, obj->attr(__path__));
  867. path = path + "." + name.sv();
  868. PyObject* mod = py_import(path, false);
  869. if(mod != nullptr){
  870. obj->attr().set(name, mod);
  871. return mod;
  872. }
  873. }
  874. if(throw_err) AttributeError(obj, name);
  875. return nullptr;
  876. }
  877. // used by OP_LOAD_METHOD
  878. // try to load a unbound method (fallback to `getattr` if not found)
  879. PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err, bool fallback){
  880. *self = PY_NULL;
  881. PyObject* objtype;
  882. // handle super() proxy
  883. if(is_non_tagged_type(obj, tp_super)){
  884. const Super& super = PK_OBJ_GET(Super, obj);
  885. obj = super.first;
  886. objtype = _t(super.second);
  887. }else{
  888. objtype = _t(obj);
  889. }
  890. PyObject* cls_var = find_name_in_mro(objtype, name);
  891. if(fallback){
  892. if(cls_var != nullptr){
  893. // handle descriptor
  894. if(is_non_tagged_type(cls_var, tp_property)){
  895. const Property& prop = _CAST(Property&, cls_var);
  896. return call(prop.getter, obj);
  897. }
  898. }
  899. // handle instance __dict__
  900. if(!is_tagged(obj) && obj->is_attr_valid()){
  901. PyObject* val = obj->attr().try_get(name);
  902. if(val != nullptr) return val;
  903. }
  904. }
  905. if(cls_var != nullptr){
  906. if(is_non_tagged_type(cls_var, tp_function) || is_non_tagged_type(cls_var, tp_native_func)){
  907. *self = obj;
  908. }
  909. return cls_var;
  910. }
  911. if(throw_err) AttributeError(obj, name);
  912. return nullptr;
  913. }
  914. void VM::setattr(PyObject* obj, StrName name, PyObject* value){
  915. PyObject* objtype;
  916. // handle super() proxy
  917. if(is_non_tagged_type(obj, tp_super)){
  918. Super& super = PK_OBJ_GET(Super, obj);
  919. obj = super.first;
  920. objtype = _t(super.second);
  921. }else{
  922. objtype = _t(obj);
  923. }
  924. PyObject* cls_var = find_name_in_mro(objtype, name);
  925. if(cls_var != nullptr){
  926. // handle descriptor
  927. if(is_non_tagged_type(cls_var, tp_property)){
  928. const Property& prop = _CAST(Property&, cls_var);
  929. if(prop.setter != vm->None){
  930. call(prop.setter, obj, value);
  931. }else{
  932. TypeError(fmt("readonly attribute: ", name.escape()));
  933. }
  934. return;
  935. }
  936. }
  937. // handle instance __dict__
  938. if(is_tagged(obj) || !obj->is_attr_valid()) TypeError("cannot set attribute");
  939. obj->attr().set(name, value);
  940. }
  941. PyObject* VM::bind(PyObject* obj, const char* sig, NativeFuncC fn, UserData userdata){
  942. return bind(obj, sig, nullptr, fn, userdata);
  943. }
  944. PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, NativeFuncC fn, UserData userdata){
  945. CodeObject_ co;
  946. try{
  947. // fn(a, b, *c, d=1) -> None
  948. co = compile("def " + Str(sig) + " : pass", "<bind>", EXEC_MODE);
  949. }catch(Exception&){
  950. throw std::runtime_error("invalid signature: " + std::string(sig));
  951. }
  952. if(co->func_decls.size() != 1){
  953. throw std::runtime_error("expected 1 function declaration");
  954. }
  955. FuncDecl_ decl = co->func_decls[0];
  956. decl->signature = Str(sig);
  957. if(docstring != nullptr){
  958. decl->docstring = Str(docstring).strip();
  959. }
  960. PyObject* f_obj = VAR(NativeFunc(fn, decl));
  961. PK_OBJ_GET(NativeFunc, f_obj).set_userdata(userdata);
  962. if(obj != nullptr) obj->attr().set(decl->code->name, f_obj);
  963. return f_obj;
  964. }
  965. PyObject* VM::bind_property(PyObject* obj, Str name, NativeFuncC fget, NativeFuncC fset){
  966. PyObject* _0 = heap.gcnew<NativeFunc>(tp_native_func, fget, 1, false);
  967. PyObject* _1 = vm->None;
  968. if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(tp_native_func, fset, 2, false);
  969. Str signature = name;
  970. int pos = name.index(":");
  971. if(pos > 0) name = name.substr(0, pos).strip();
  972. PyObject* prop = VAR(Property(_0, _1, signature));
  973. obj->attr().set(name, prop);
  974. return prop;
  975. }
  976. void VM::_error(Exception e){
  977. if(callstack.empty()){
  978. e.is_re = false;
  979. throw e;
  980. }
  981. PUSH(VAR(std::move(e)));
  982. _raise();
  983. }
  984. void ManagedHeap::mark() {
  985. for(PyObject* obj: _no_gc) PK_OBJ_MARK(obj);
  986. for(auto& frame : vm->callstack.data()) frame._gc_mark();
  987. for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj);
  988. if(_gc_marker_ex) _gc_marker_ex(vm);
  989. if(vm->_last_exception) PK_OBJ_MARK(vm->_last_exception);
  990. if(vm->_c.error != nullptr) PK_OBJ_MARK(vm->_c.error);
  991. }
  992. Str obj_type_name(VM *vm, Type type){
  993. return vm->_all_types[type].name;
  994. }
  995. void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
  996. PyObject* obj = _t(type);
  997. _all_types[type].m__hash__ = f;
  998. PyObject* nf = bind_method<0>(obj, "__hash__", [](VM* vm, ArgsView args){
  999. i64 ret = lambda_get_userdata<i64(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);
  1000. return VAR(ret);
  1001. });
  1002. PK_OBJ_GET(NativeFunc, nf).set_userdata(f);
  1003. }
  1004. void VM::bind__len__(Type type, i64 (*f)(VM*, PyObject*)){
  1005. PyObject* obj = _t(type);
  1006. _all_types[type].m__len__ = f;
  1007. PyObject* nf = bind_method<0>(obj, "__len__", [](VM* vm, ArgsView args){
  1008. i64 ret = lambda_get_userdata<i64(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);
  1009. return VAR(ret);
  1010. });
  1011. PK_OBJ_GET(NativeFunc, nf).set_userdata(f);
  1012. }
  1013. void Dict::_probe_0(PyObject *key, bool &ok, int &i) const{
  1014. ok = false;
  1015. i64 hash = vm->py_hash(key);
  1016. i = hash & _mask;
  1017. // std::cout << CAST(Str, vm->py_repr(key)) << " " << hash << " " << i << std::endl;
  1018. for(int j=0; j<_capacity; j++) {
  1019. if(_items[i].first != nullptr){
  1020. if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
  1021. }else{
  1022. if(_items[i].second == nullptr) break;
  1023. }
  1024. // https://github.com/python/cpython/blob/3.8/Objects/dictobject.c#L166
  1025. i = ((5*i) + 1) & _mask;
  1026. // std::cout << CAST(Str, vm->py_repr(key)) << " next: " << i << std::endl;
  1027. }
  1028. }
  1029. void Dict::_probe_1(PyObject *key, bool &ok, int &i) const{
  1030. ok = false;
  1031. i = vm->py_hash(key) & _mask;
  1032. while(_items[i].first != nullptr) {
  1033. if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
  1034. // https://github.com/python/cpython/blob/3.8/Objects/dictobject.c#L166
  1035. i = ((5*i) + 1) & _mask;
  1036. }
  1037. }
  1038. void CodeObjectSerializer::write_object(VM *vm, PyObject *obj){
  1039. if(is_int(obj)) write_int(_CAST(i64, obj));
  1040. else if(is_float(obj)) write_float(_CAST(f64, obj));
  1041. else if(is_type(obj, vm->tp_str)) write_str(_CAST(Str&, obj));
  1042. else if(is_type(obj, vm->tp_bool)) write_bool(_CAST(bool, obj));
  1043. else if(obj == vm->None) write_none();
  1044. else if(obj == vm->Ellipsis) write_ellipsis();
  1045. else{
  1046. throw std::runtime_error(fmt(OBJ_NAME(vm->_t(obj)).escape(), " is not serializable"));
  1047. }
  1048. }
  1049. void NativeFunc::check_size(VM* vm, ArgsView args) const{
  1050. if(args.size() != argc && argc != -1) {
  1051. vm->TypeError(fmt("expected ", argc, " arguments, got ", args.size()));
  1052. }
  1053. }
  1054. PyObject* NativeFunc::call(VM *vm, ArgsView args) const {
  1055. return f(vm, args);
  1056. }
  1057. } // namespace pkpy