pocketpy.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. #pragma once
  2. #include "vm.h"
  3. #include "compiler.h"
  4. #define PK_VERSION "0.2.0"
  5. #define BIND_NUM_ARITH_OPT(name, op) \
  6. _vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, Frame* frame, PyVarList args){ \
  7. if(!vm->isIntOrFloat(args[0], args[1])) \
  8. vm->typeError("unsupported operand type(s) for " #op ); \
  9. if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){ \
  10. return vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])); \
  11. }else{ \
  12. return vm->PyFloat(vm->numToFloat(args[0]) op vm->numToFloat(args[1])); \
  13. } \
  14. });
  15. #define BIND_NUM_LOGICAL_OPT(name, op, fallback) \
  16. _vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, Frame* frame, PyVarList args){ \
  17. if(!vm->isIntOrFloat(args[0], args[1])){ \
  18. if constexpr(fallback) return vm->PyBool(args[0] op args[1]); \
  19. vm->typeError("unsupported operand type(s) for " #op ); \
  20. } \
  21. return vm->PyBool(vm->numToFloat(args[0]) op vm->numToFloat(args[1])); \
  22. });
  23. void __initializeBuiltinFunctions(VM* _vm) {
  24. BIND_NUM_ARITH_OPT(__add__, +)
  25. BIND_NUM_ARITH_OPT(__sub__, -)
  26. BIND_NUM_ARITH_OPT(__mul__, *)
  27. BIND_NUM_LOGICAL_OPT(__lt__, <, false)
  28. BIND_NUM_LOGICAL_OPT(__le__, <=, false)
  29. BIND_NUM_LOGICAL_OPT(__gt__, >, false)
  30. BIND_NUM_LOGICAL_OPT(__ge__, >=, false)
  31. BIND_NUM_LOGICAL_OPT(__eq__, ==, true)
  32. #undef BIND_NUM_ARITH_OPT
  33. #undef BIND_NUM_LOGICAL_OPT
  34. _vm->bindBuiltinFunc("print", [](VM* vm, Frame* frame, PyVarList args) {
  35. for (auto& arg : args){
  36. _Str s = vm->PyStr_AS_C(vm->asStr(arg)) + " ";
  37. vm->_stdout(s.c_str());
  38. }
  39. vm->_stdout("\n");
  40. return vm->None;
  41. });
  42. _vm->bindBuiltinFunc("eval", [](VM* vm, Frame* frame, PyVarList args) {
  43. vm->__checkArgSize(args, 1);
  44. const _Str& expr = vm->PyStr_AS_C(args[0]);
  45. _Code code = compile(vm, expr.c_str(), "<eval>", EVAL_MODE);
  46. if(code == nullptr) return vm->None;
  47. return vm->_exec(code, frame->_module, frame->f_locals);
  48. });
  49. _vm->bindBuiltinFunc("isinstance", [](VM* vm, Frame* frame, PyVarList args) {
  50. vm->__checkArgSize(args, 2);
  51. return vm->PyBool(vm->isInstance(args[0], args[1]));
  52. });
  53. _vm->bindBuiltinFunc("repr", [](VM* vm, Frame* frame, PyVarList args) {
  54. vm->__checkArgSize(args, 1);
  55. return vm->asRepr(args[0]);
  56. });
  57. _vm->bindBuiltinFunc("hash", [](VM* vm, Frame* frame, PyVarList args) {
  58. vm->__checkArgSize(args, 1);
  59. return vm->PyInt(vm->hash(args[0]));
  60. });
  61. _vm->bindBuiltinFunc("chr", [](VM* vm, Frame* frame, PyVarList args) {
  62. vm->__checkArgSize(args, 1);
  63. _Int i = vm->PyInt_AS_C(args[0]);
  64. if (i < 0 || i > 128) vm->valueError("chr() arg not in range(128)");
  65. return vm->PyStr(_Str(1, (char)i));
  66. });
  67. _vm->bindBuiltinFunc("ord", [](VM* vm, Frame* frame, PyVarList args) {
  68. vm->__checkArgSize(args, 1);
  69. _Str s = vm->PyStr_AS_C(args[0]);
  70. if (s.size() != 1) vm->typeError("ord() expected an ASCII character");
  71. return vm->PyInt((_Int)s[0]);
  72. });
  73. _vm->bindBuiltinFunc("dir", [](VM* vm, Frame* frame, PyVarList args) {
  74. vm->__checkArgSize(args, 1);
  75. PyVarList ret;
  76. for (auto& [k, _] : args[0]->attribs) ret.push_back(vm->PyStr(k));
  77. return vm->PyList(ret);
  78. });
  79. _vm->bindMethod("object", "__repr__", [](VM* vm, Frame* frame, PyVarList args) {
  80. PyVar _self = args[0];
  81. _Str s = "<" + _self->getTypeName() + " object at " + std::to_string((uintptr_t)_self.get()) + ">";
  82. return vm->PyStr(s);
  83. });
  84. _vm->bindMethod("type", "__new__", [](VM* vm, Frame* frame, PyVarList args) {
  85. vm->__checkArgSize(args, 1);
  86. return args[0]->attribs[__class__];
  87. });
  88. _vm->bindMethod("range", "__new__", [](VM* vm, Frame* frame, PyVarList args) {
  89. _Range r;
  90. switch (args.size()) {
  91. case 1: r.stop = vm->PyInt_AS_C(args[0]); break;
  92. case 2: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); break;
  93. case 3: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); r.step = vm->PyInt_AS_C(args[2]); break;
  94. default: vm->typeError("expected 1-3 arguments, but got " + std::to_string(args.size()));
  95. }
  96. return vm->PyRange(r);
  97. });
  98. _vm->bindMethod("range", "__iter__", [](VM* vm, Frame* frame, PyVarList args) {
  99. vm->__checkType(args[0], vm->_tp_range);
  100. auto iter = std::make_shared<RangeIterator>(vm, args[0]);
  101. return vm->PyIter(iter);
  102. });
  103. _vm->bindMethod("NoneType", "__repr__", [](VM* vm, Frame* frame, PyVarList args) {
  104. return vm->PyStr("None");
  105. });
  106. _vm->bindMethodMulti({"int", "float"}, "__truediv__", [](VM* vm, Frame* frame, PyVarList args) {
  107. if(!vm->isIntOrFloat(args[0], args[1]))
  108. vm->typeError("unsupported operand type(s) for " "/" );
  109. _Float rhs = vm->numToFloat(args[1]);
  110. if (rhs == 0) vm->zeroDivisionError();
  111. return vm->PyFloat(vm->numToFloat(args[0]) / rhs);
  112. });
  113. _vm->bindMethodMulti({"int", "float"}, "__pow__", [](VM* vm, Frame* frame, PyVarList args) {
  114. if(!vm->isIntOrFloat(args[0], args[1]))
  115. vm->typeError("unsupported operand type(s) for " "**" );
  116. if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){
  117. return vm->PyInt((_Int)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
  118. }else{
  119. return vm->PyFloat((_Float)pow(vm->numToFloat(args[0]), vm->numToFloat(args[1])));
  120. }
  121. });
  122. /************ PyInt ************/
  123. _vm->bindMethod("int", "__new__", [](VM* vm, Frame* frame, PyVarList args) {
  124. if(args.size() == 0) return vm->PyInt(0);
  125. vm->__checkArgSize(args, 1);
  126. if (args[0]->isType(vm->_tp_int)) return args[0];
  127. if (args[0]->isType(vm->_tp_float)) return vm->PyInt((_Int)vm->PyFloat_AS_C(args[0]));
  128. if (args[0]->isType(vm->_tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0);
  129. if (args[0]->isType(vm->_tp_str)) {
  130. const _Str& s = vm->PyStr_AS_C(args[0]);
  131. try{
  132. _Int val = std::stoll(s.str());
  133. return vm->PyInt(val);
  134. }catch(std::invalid_argument&){
  135. vm->valueError("invalid literal for int(): '" + s + "'");
  136. }
  137. }
  138. vm->typeError("int() argument must be a int, float, bool or str");
  139. return vm->None;
  140. });
  141. _vm->bindMethod("int", "__floordiv__", [](VM* vm, Frame* frame, PyVarList args) {
  142. if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int))
  143. vm->typeError("unsupported operand type(s) for " "//" );
  144. _Int rhs = vm->PyInt_AS_C(args[1]);
  145. if(rhs == 0) vm->zeroDivisionError();
  146. return vm->PyInt(vm->PyInt_AS_C(args[0]) / rhs);
  147. });
  148. _vm->bindMethod("int", "__mod__", [](VM* vm, Frame* frame, PyVarList args) {
  149. if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int))
  150. vm->typeError("unsupported operand type(s) for " "%" );
  151. return vm->PyInt(vm->PyInt_AS_C(args[0]) % vm->PyInt_AS_C(args[1]));
  152. });
  153. _vm->bindMethod("int", "__neg__", [](VM* vm, Frame* frame, PyVarList args) {
  154. if(!args[0]->isType(vm->_tp_int))
  155. vm->typeError("unsupported operand type(s) for " "-" );
  156. return vm->PyInt(-1 * vm->PyInt_AS_C(args[0]));
  157. });
  158. _vm->bindMethod("int", "__repr__", [](VM* vm, Frame* frame, PyVarList args) {
  159. return vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0])));
  160. });
  161. /************ PyFloat ************/
  162. _vm->bindMethod("float", "__new__", [](VM* vm, Frame* frame, PyVarList args) {
  163. if(args.size() == 0) return vm->PyFloat(0.0);
  164. vm->__checkArgSize(args, 1);
  165. if (args[0]->isType(vm->_tp_int)) return vm->PyFloat((_Float)vm->PyInt_AS_C(args[0]));
  166. if (args[0]->isType(vm->_tp_float)) return args[0];
  167. if (args[0]->isType(vm->_tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0);
  168. if (args[0]->isType(vm->_tp_str)) {
  169. const _Str& s = vm->PyStr_AS_C(args[0]);
  170. if(s == "inf") return vm->PyFloat(_FLOAT_INF_POS);
  171. if(s == "-inf") return vm->PyFloat(_FLOAT_INF_NEG);
  172. try{
  173. _Float val = std::stod(s.str());
  174. return vm->PyFloat(val);
  175. }catch(std::invalid_argument&){
  176. vm->valueError("invalid literal for float(): '" + s + "'");
  177. }
  178. }
  179. vm->typeError("float() argument must be a int, float, bool or str");
  180. return vm->None;
  181. });
  182. _vm->bindMethod("float", "__neg__", [](VM* vm, Frame* frame, PyVarList args) {
  183. return vm->PyFloat(-1.0 * vm->PyFloat_AS_C(args[0]));
  184. });
  185. _vm->bindMethod("float", "__repr__", [](VM* vm, Frame* frame, PyVarList args) {
  186. _Float val = vm->PyFloat_AS_C(args[0]);
  187. if(std::isinf(val) || std::isnan(val)) return vm->PyStr(std::to_string(val));
  188. _StrStream ss;
  189. ss << std::setprecision(std::numeric_limits<_Float>::max_digits10-1) << val;
  190. std::string s = ss.str();
  191. if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0";
  192. return vm->PyStr(s);
  193. });
  194. /************ PyString ************/
  195. _vm->bindMethod("str", "__new__", [](VM* vm, Frame* frame, PyVarList args) {
  196. vm->__checkArgSize(args, 1);
  197. return vm->asStr(args[0]);
  198. });
  199. _vm->bindMethod("str", "__add__", [](VM* vm, Frame* frame, PyVarList args) {
  200. if(!args[0]->isType(vm->_tp_str) || !args[1]->isType(vm->_tp_str))
  201. vm->typeError("unsupported operand type(s) for " "+" );
  202. const _Str& lhs = vm->PyStr_AS_C(args[0]);
  203. const _Str& rhs = vm->PyStr_AS_C(args[1]);
  204. return vm->PyStr(lhs + rhs);
  205. });
  206. _vm->bindMethod("str", "__len__", [](VM* vm, Frame* frame, PyVarList args) {
  207. const _Str& _self = vm->PyStr_AS_C(args[0]);
  208. return vm->PyInt(_self.u8_length());
  209. });
  210. _vm->bindMethod("str", "__contains__", [](VM* vm, Frame* frame, PyVarList args) {
  211. const _Str& _self = vm->PyStr_AS_C(args[0]);
  212. const _Str& _other = vm->PyStr_AS_C(args[1]);
  213. return vm->PyBool(_self.str().find(_other.str()) != _Str::npos);
  214. });
  215. _vm->bindMethod("str", "__str__", [](VM* vm, Frame* frame, PyVarList args) {
  216. return args[0]; // str is immutable
  217. });
  218. _vm->bindMethod("str", "__iter__", [](VM* vm, Frame* frame, PyVarList args) {
  219. auto it = std::make_shared<StringIterator>(vm, args[0]);
  220. return vm->PyIter(it);
  221. });
  222. _vm->bindMethod("str", "__repr__", [](VM* vm, Frame* frame, PyVarList args) {
  223. const _Str& _self = vm->PyStr_AS_C(args[0]);
  224. // we just do a simple repr here, no escaping
  225. return vm->PyStr("'" + _self.str() + "'");
  226. });
  227. _vm->bindMethod("str", "__eq__", [](VM* vm, Frame* frame, PyVarList args) {
  228. if(args[0]->isType(vm->_tp_str) && args[1]->isType(vm->_tp_str))
  229. return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1]));
  230. return vm->PyBool(args[0] == args[1]); // fallback
  231. });
  232. _vm->bindMethod("str", "__getitem__", [](VM* vm, Frame* frame, PyVarList args) {
  233. const _Str& _self (vm->PyStr_AS_C(args[0]));
  234. if(args[1]->isType(vm->_tp_slice)){
  235. _Slice s = vm->PySlice_AS_C(args[1]);
  236. s.normalize(_self.u8_length());
  237. return vm->PyStr(_self.u8_substr(s.start, s.stop));
  238. }
  239. int _index = vm->PyInt_AS_C(args[1]);
  240. _index = vm->normalizedIndex(_index, _self.u8_length());
  241. return vm->PyStr(_self.u8_getitem(_index));
  242. });
  243. _vm->bindMethod("str", "__gt__", [](VM* vm, Frame* frame, PyVarList args) {
  244. const _Str& _self (vm->PyStr_AS_C(args[0]));
  245. const _Str& _obj (vm->PyStr_AS_C(args[1]));
  246. return vm->PyBool(_self > _obj);
  247. });
  248. _vm->bindMethod("str", "__lt__", [](VM* vm, Frame* frame, PyVarList args) {
  249. const _Str& _self (vm->PyStr_AS_C(args[0]));
  250. const _Str& _obj (vm->PyStr_AS_C(args[1]));
  251. return vm->PyBool(_self < _obj);
  252. });
  253. _vm->bindMethod("str", "upper", [](VM* vm, Frame* frame, PyVarList args) {
  254. vm->__checkArgSize(args, 1, true);
  255. const _Str& _self (vm->PyStr_AS_C(args[0]));
  256. _StrStream ss;
  257. for(auto c : _self.str()) ss << (char)toupper(c);
  258. return vm->PyStr(ss);
  259. });
  260. _vm->bindMethod("str", "lower", [](VM* vm, Frame* frame, PyVarList args) {
  261. vm->__checkArgSize(args, 1, true);
  262. const _Str& _self (vm->PyStr_AS_C(args[0]));
  263. _StrStream ss;
  264. for(auto c : _self.str()) ss << (char)tolower(c);
  265. return vm->PyStr(ss);
  266. });
  267. _vm->bindMethod("str", "replace", [](VM* vm, Frame* frame, PyVarList args) {
  268. vm->__checkArgSize(args, 3, true);
  269. const _Str& _self = vm->PyStr_AS_C(args[0]);
  270. const _Str& _old = vm->PyStr_AS_C(args[1]);
  271. const _Str& _new = vm->PyStr_AS_C(args[2]);
  272. std::string _copy = _self.str();
  273. // replace all occurences of _old with _new in _copy
  274. size_t pos = 0;
  275. while ((pos = _copy.find(_old.str(), pos)) != std::string::npos) {
  276. _copy.replace(pos, _old.str().length(), _new.str());
  277. pos += _new.str().length();
  278. }
  279. return vm->PyStr(_copy);
  280. });
  281. _vm->bindMethod("str", "startswith", [](VM* vm, Frame* frame, PyVarList args) {
  282. vm->__checkArgSize(args, 2, true);
  283. const _Str& _self = vm->PyStr_AS_C(args[0]);
  284. const _Str& _prefix = vm->PyStr_AS_C(args[1]);
  285. return vm->PyBool(_self.str().find(_prefix.str()) == 0);
  286. });
  287. _vm->bindMethod("str", "endswith", [](VM* vm, Frame* frame, PyVarList args) {
  288. vm->__checkArgSize(args, 2, true);
  289. const _Str& _self = vm->PyStr_AS_C(args[0]);
  290. const _Str& _suffix = vm->PyStr_AS_C(args[1]);
  291. return vm->PyBool(_self.str().rfind(_suffix.str()) == _self.str().length() - _suffix.str().length());
  292. });
  293. _vm->bindMethod("str", "join", [](VM* vm, Frame* frame, PyVarList args) {
  294. vm->__checkArgSize(args, 2, true);
  295. const _Str& _self = vm->PyStr_AS_C(args[0]);
  296. const PyVarList& _list = vm->PyList_AS_C(args[1]);
  297. _StrStream ss;
  298. for(int i = 0; i < _list.size(); i++){
  299. if(i > 0) ss << _self;
  300. ss << vm->PyStr_AS_C(vm->asStr(_list[i]));
  301. }
  302. return vm->PyStr(ss);
  303. });
  304. /************ PyList ************/
  305. _vm->bindMethod("list", "__iter__", [](VM* vm, Frame* frame, PyVarList args) {
  306. vm->__checkType(args[0], vm->_tp_list);
  307. auto iter = std::make_shared<VectorIterator>(vm, args[0]);
  308. return vm->PyIter(iter);
  309. });
  310. _vm->bindMethod("list", "append", [](VM* vm, Frame* frame, PyVarList args) {
  311. vm->__checkArgSize(args, 2, true);
  312. PyVarList& _self = vm->PyList_AS_C(args[0]);
  313. _self.push_back(args[1]);
  314. return vm->None;
  315. });
  316. _vm->bindMethod("list", "insert", [](VM* vm, Frame* frame, PyVarList args) {
  317. vm->__checkArgSize(args, 3, true);
  318. PyVarList& _self = vm->PyList_AS_C(args[0]);
  319. int _index = vm->PyInt_AS_C(args[1]);
  320. _index = vm->normalizedIndex(_index, _self.size());
  321. _self.insert(_self.begin() + _index, args[2]);
  322. return vm->None;
  323. });
  324. _vm->bindMethod("list", "clear", [](VM* vm, Frame* frame, PyVarList args) {
  325. vm->__checkArgSize(args, 1, true);
  326. vm->PyList_AS_C(args[0]).clear();
  327. return vm->None;
  328. });
  329. _vm->bindMethod("list", "copy", [](VM* vm, Frame* frame, PyVarList args) {
  330. vm->__checkArgSize(args, 1, true);
  331. return vm->PyList(vm->PyList_AS_C(args[0]));
  332. });
  333. _vm->bindMethod("list", "pop", [](VM* vm, Frame* frame, PyVarList args) {
  334. vm->__checkArgSize(args, 1, true);
  335. PyVarList& _self = vm->PyList_AS_C(args[0]);
  336. if(_self.empty()) vm->indexError("pop from empty list");
  337. PyVar ret = _self.back();
  338. _self.pop_back();
  339. return ret;
  340. });
  341. _vm->bindMethod("list", "__add__", [](VM* vm, Frame* frame, PyVarList args) {
  342. const PyVarList& _self = vm->PyList_AS_C(args[0]);
  343. const PyVarList& _obj = vm->PyList_AS_C(args[1]);
  344. PyVarList _new_list = _self;
  345. _new_list.insert(_new_list.end(), _obj.begin(), _obj.end());
  346. return vm->PyList(_new_list);
  347. });
  348. _vm->bindMethod("list", "__len__", [](VM* vm, Frame* frame, PyVarList args) {
  349. const PyVarList& _self = vm->PyList_AS_C(args[0]);
  350. return vm->PyInt(_self.size());
  351. });
  352. _vm->bindMethod("list", "__getitem__", [](VM* vm, Frame* frame, PyVarList args) {
  353. const PyVarList& _self = vm->PyList_AS_C(args[0]);
  354. if(args[1]->isType(vm->_tp_slice)){
  355. _Slice s = vm->PySlice_AS_C(args[1]);
  356. s.normalize(_self.size());
  357. PyVarList _new_list;
  358. for(int i = s.start; i < s.stop; i++)
  359. _new_list.push_back(_self[i]);
  360. return vm->PyList(_new_list);
  361. }
  362. int _index = vm->PyInt_AS_C(args[1]);
  363. _index = vm->normalizedIndex(_index, _self.size());
  364. return _self[_index];
  365. });
  366. _vm->bindMethod("list", "__setitem__", [](VM* vm, Frame* frame, PyVarList args) {
  367. PyVarList& _self = vm->PyList_AS_C(args[0]);
  368. int _index = vm->PyInt_AS_C(args[1]);
  369. _index = vm->normalizedIndex(_index, _self.size());
  370. _self[_index] = args[2];
  371. return vm->None;
  372. });
  373. _vm->bindMethod("list", "__delitem__", [](VM* vm, Frame* frame, PyVarList args) {
  374. PyVarList& _self = vm->PyList_AS_C(args[0]);
  375. int _index = vm->PyInt_AS_C(args[1]);
  376. _index = vm->normalizedIndex(_index, _self.size());
  377. _self.erase(_self.begin() + _index);
  378. return vm->None;
  379. });
  380. /************ PyTuple ************/
  381. _vm->bindMethod("tuple", "__new__", [](VM* vm, Frame* frame, PyVarList args) {
  382. vm->__checkArgSize(args, 1);
  383. PyVarList _list = vm->PyList_AS_C(vm->call(frame, vm->builtins->attribs["list"], args));
  384. return vm->PyTuple(_list);
  385. });
  386. _vm->bindMethod("tuple", "__iter__", [](VM* vm, Frame* frame, PyVarList args) {
  387. vm->__checkType(args[0], vm->_tp_tuple);
  388. auto iter = std::make_shared<VectorIterator>(vm, args[0]);
  389. return vm->PyIter(iter);
  390. });
  391. _vm->bindMethod("tuple", "__len__", [](VM* vm, Frame* frame, PyVarList args) {
  392. const PyVarList& _self = vm->PyTuple_AS_C(args[0]);
  393. return vm->PyInt(_self.size());
  394. });
  395. _vm->bindMethod("tuple", "__getitem__", [](VM* vm, Frame* frame, PyVarList args) {
  396. const PyVarList& _self = vm->PyTuple_AS_C(args[0]);
  397. int _index = vm->PyInt_AS_C(args[1]);
  398. _index = vm->normalizedIndex(_index, _self.size());
  399. return _self[_index];
  400. });
  401. /************ PyBool ************/
  402. _vm->bindMethod("bool", "__repr__", [](VM* vm, Frame* frame, PyVarList args) {
  403. bool val = vm->PyBool_AS_C(args[0]);
  404. return vm->PyStr(val ? "True" : "False");
  405. });
  406. _vm->bindMethod("bool", "__eq__", [](VM* vm, Frame* frame, PyVarList args) {
  407. return vm->PyBool(args[0] == args[1]);
  408. });
  409. }
  410. void __runCodeBuiltins(VM* vm, const char* src){
  411. _Code code = compile(vm, src, "builtins.py");
  412. if(code != nullptr) vm->exec(code, vm->builtins);
  413. }
  414. #include "builtins.h"
  415. #ifdef _WIN32
  416. #define __EXPORT __declspec(dllexport)
  417. #elif __APPLE__
  418. #define __EXPORT __attribute__((visibility("default"))) __attribute__((used))
  419. #else
  420. #define __EXPORT
  421. #endif
  422. void __addModuleTime(VM* vm){
  423. PyVar mod = vm->newModule("time");
  424. vm->bindFunc(mod, "time", [](VM* vm, Frame* frame, PyVarList args) {
  425. auto now = std::chrono::high_resolution_clock::now();
  426. return vm->PyFloat(std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count() / 1000000.0);
  427. });
  428. }
  429. void __addModuleSys(VM* vm){
  430. PyVar mod = vm->newModule("sys");
  431. vm->bindFunc(mod, "getrefcount", [](VM* vm, Frame* frame, PyVarList args) {
  432. vm->__checkArgSize(args, 1);
  433. return vm->PyInt(args[0].use_count());
  434. });
  435. vm->setAttr(mod, "version", vm->PyStr(PK_VERSION));
  436. }
  437. extern "C" {
  438. __EXPORT
  439. VM* createVM(PrintFn _stdout, PrintFn _stderr){
  440. VM* vm = new VM();
  441. __initializeBuiltinFunctions(vm);
  442. __runCodeBuiltins(vm, __BUILTINS_CODE);
  443. __addModuleSys(vm);
  444. __addModuleTime(vm);
  445. vm->_stdout = _stdout;
  446. vm->_stderr = _stderr;
  447. return vm;
  448. }
  449. __EXPORT
  450. void destroyVM(VM* vm){
  451. delete vm;
  452. }
  453. __EXPORT
  454. void exec(VM* vm, const char* source){
  455. _Code code = compile(vm, source, "main.py");
  456. if(code != nullptr) vm->exec(code);
  457. }
  458. __EXPORT
  459. void registerModule(VM* vm, const char* name, const char* source){
  460. _Code code = compile(vm, source, name + _Str(".py"));
  461. if(code != nullptr){
  462. PyVar _m = vm->newModule(name);
  463. vm->exec(code, _m);
  464. }
  465. }
  466. }