abstract.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. /**
  2. * @namespace Sk.abstr
  3. *
  4. */
  5. Sk.abstr = {};
  6. //
  7. // Number
  8. //
  9. Sk.abstr.typeName = function (v) {
  10. var vtypename;
  11. if (v.tp$name !== undefined) {
  12. vtypename = v.tp$name;
  13. } else {
  14. vtypename = "<invalid type>";
  15. }
  16. return vtypename;
  17. };
  18. Sk.abstr.binop_type_error = function (v, w, name) {
  19. var vtypename = Sk.abstr.typeName(v),
  20. wtypename = Sk.abstr.typeName(w);
  21. throw new Sk.builtin.TypeError("unsupported operand type(s) for " + name + ": '" + vtypename + "' and '" + wtypename + "'");
  22. };
  23. Sk.abstr.unop_type_error = function (v, name) {
  24. var vtypename = Sk.abstr.typeName(v),
  25. uop = {
  26. "UAdd" : "+",
  27. "USub" : "-",
  28. "Invert": "~"
  29. }[name];
  30. throw new Sk.builtin.TypeError("bad operand type for unary " + uop + ": '" + vtypename + "'");
  31. };
  32. /**
  33. * lookup and return the LHS object slot function method. This coudl be either a builtin slot function or a dunder method defined by the user.
  34. * @param obj
  35. * @param name
  36. * @returns {Object|null|undefined}
  37. * @private
  38. */
  39. Sk.abstr.boNameToSlotFuncLhs_ = function (obj, name) {
  40. if (obj === null) {
  41. return undefined;
  42. }
  43. switch (name) {
  44. case "Add":
  45. return obj.nb$add ? obj.nb$add : obj["__add__"];
  46. case "Sub":
  47. return obj.nb$subtract ? obj.nb$subtract : obj["__sub__"];
  48. case "Mult":
  49. return obj.nb$multiply ? obj.nb$multiply : obj["__mul__"];
  50. case "Div":
  51. return obj.nb$divide ? obj.nb$divide : obj["__div__"];
  52. case "FloorDiv":
  53. return obj.nb$floor_divide ? obj.nb$floor_divide : obj["__floordiv__"];
  54. case "Mod":
  55. return obj.nb$remainder ? obj.nb$remainder : obj["__mod__"];
  56. case "DivMod":
  57. return obj.nb$divmod ? obj.nb$divmod : obj["__divmod__"];
  58. case "Pow":
  59. return obj.nb$power ? obj.nb$power : obj["__pow__"];
  60. case "LShift":
  61. return obj.nb$lshift ? obj.nb$lshift : obj["__lshift__"];
  62. case "RShift":
  63. return obj.nb$rshift ? obj.nb$rshift : obj["__rshift__"];
  64. case "BitAnd":
  65. return obj.nb$and ? obj.nb$and : obj["__and__"];
  66. case "BitXor":
  67. return obj.nb$xor ? obj.nb$xor : obj["__xor__"];
  68. case "BitOr":
  69. return obj.nb$or ? obj.nb$or : obj["__or__"];
  70. }
  71. };
  72. Sk.abstr.boNameToSlotFuncRhs_ = function (obj, name) {
  73. if (obj === null) {
  74. return undefined;
  75. }
  76. switch (name) {
  77. case "Add":
  78. return obj.nb$reflected_add ? obj.nb$reflected_add : obj["__radd__"];
  79. case "Sub":
  80. return obj.nb$reflected_subtract ? obj.nb$reflected_subtract : obj["__rsub__"];
  81. case "Mult":
  82. return obj.nb$reflected_multiply ? obj.nb$reflected_multiply : obj["__rmul__"];
  83. case "Div":
  84. return obj.nb$reflected_divide ? obj.nb$reflected_divide : obj["__rdiv__"];
  85. case "FloorDiv":
  86. return obj.nb$reflected_floor_divide ? obj.nb$reflected_floor_divide : obj["__rfloordiv__"];
  87. case "Mod":
  88. return obj.nb$reflected_remainder ? obj.nb$reflected_remainder : obj["__rmod__"];
  89. case "DivMod":
  90. return obj.nb$reflected_divmod ? obj.nb$reflected_divmod : obj["__rdivmod__"];
  91. case "Pow":
  92. return obj.nb$reflected_power ? obj.nb$reflected_power : obj["__rpow__"];
  93. case "LShift":
  94. return obj.nb$reflected_lshift ? obj.nb$reflected_lshift : obj["__rlshift__"];
  95. case "RShift":
  96. return obj.nb$reflected_rshift ? obj.nb$reflected_rshift : obj["__rrshift__"];
  97. case "BitAnd":
  98. return obj.nb$reflected_and ? obj.nb$reflected_and : obj["__rand__"];
  99. case "BitXor":
  100. return obj.nb$reflected_xor ? obj.nb$reflected_xor : obj["__rxor__"];
  101. case "BitOr":
  102. return obj.nb$reflected_or ? obj.nb$reflected_or : obj["__ror__"];
  103. }
  104. };
  105. Sk.abstr.iboNameToSlotFunc_ = function (obj, name) {
  106. switch (name) {
  107. case "Add":
  108. return obj.nb$inplace_add ? obj.nb$inplace_add : obj["__iadd__"];
  109. case "Sub":
  110. return obj.nb$inplace_subtract ? obj.nb$inplace_subtract : obj["__isub__"];
  111. case "Mult":
  112. return obj.nb$inplace_multiply ? obj.nb$inplace_multiply : obj["__imul__"];
  113. case "Div":
  114. return obj.nb$inplace_divide ? obj.nb$inplace_divide : obj["__idiv__"];
  115. case "FloorDiv":
  116. return obj.nb$inplace_floor_divide ? obj.nb$inplace_floor_divide : obj["__ifloordiv__"];
  117. case "Mod":
  118. return obj.nb$inplace_remainder;
  119. case "Pow":
  120. return obj.nb$inplace_power;
  121. case "LShift":
  122. return obj.nb$inplace_lshift ? obj.nb$inplace_lshift : obj["__ilshift__"];
  123. case "RShift":
  124. return obj.nb$inplace_rshift ? obj.nb$inplace_rshift : obj["__irshift__"];
  125. case "BitAnd":
  126. return obj.nb$inplace_and;
  127. case "BitOr":
  128. return obj.nb$inplace_or;
  129. case "BitXor":
  130. return obj.nb$inplace_xor ? obj.nb$inplace_xor : obj["__ixor__"];
  131. }
  132. };
  133. Sk.abstr.uoNameToSlotFunc_ = function (obj, name) {
  134. if (obj === null) {
  135. return undefined;
  136. }
  137. switch (name) {
  138. case "USub":
  139. return obj.nb$negative ? obj.nb$negative : obj["__neg__"];
  140. case "UAdd":
  141. return obj.nb$positive ? obj.nb$positive : obj["__pos__"];
  142. case "Invert":
  143. return obj.nb$invert ? obj.nb$invert : obj["__invert__"];
  144. }
  145. };
  146. Sk.abstr.binary_op_ = function (v, w, opname) {
  147. var wop;
  148. var ret;
  149. var vop;
  150. // All Python inheritance is now enforced with Javascript inheritance
  151. // (see Sk.abstr.setUpInheritance). This checks if w's type is a strict
  152. // subclass of v's type
  153. var w_is_subclass = w.constructor.prototype instanceof v.constructor;
  154. // From the Python 2.7 docs:
  155. //
  156. // "If the right operand’s type is a subclass of the left operand’s type and
  157. // that subclass provides the reflected method for the operation, this
  158. // method will be called before the left operand’s non-reflected method.
  159. // This behavior allows subclasses to override their ancestors’ operations."
  160. //
  161. // -- https://docs.python.org/2/reference/datamodel.html#index-92
  162. if (w_is_subclass) {
  163. wop = Sk.abstr.boNameToSlotFuncRhs_(w, opname);
  164. if (wop !== undefined) {
  165. if (wop.call) {
  166. ret = wop.call(w, v);
  167. } else {
  168. ret = Sk.misceval.callsim(wop, w, v);
  169. }
  170. if (ret !== undefined && ret !== Sk.builtin.NotImplemented.NotImplemented$) {
  171. return ret;
  172. }
  173. }
  174. }
  175. vop = Sk.abstr.boNameToSlotFuncLhs_(v, opname);
  176. if (vop !== undefined) {
  177. if (vop.call) {
  178. ret = vop.call(v, w);
  179. } else {
  180. ret = Sk.misceval.callsim(vop, v, w);
  181. }
  182. if (ret !== undefined && ret !== Sk.builtin.NotImplemented.NotImplemented$) {
  183. return ret;
  184. }
  185. }
  186. // Don't retry RHS if failed above
  187. if (!w_is_subclass) {
  188. wop = Sk.abstr.boNameToSlotFuncRhs_(w, opname);
  189. if (wop !== undefined) {
  190. if (wop.call) {
  191. ret = wop.call(w, v);
  192. } else {
  193. ret = Sk.misceval.callsim(wop, w, v);
  194. }
  195. if (ret !== undefined && ret !== Sk.builtin.NotImplemented.NotImplemented$) {
  196. return ret;
  197. }
  198. }
  199. }
  200. Sk.abstr.binop_type_error(v, w, opname);
  201. };
  202. Sk.abstr.binary_iop_ = function (v, w, opname) {
  203. var wop;
  204. var ret;
  205. var vop = Sk.abstr.iboNameToSlotFunc_(v, opname);
  206. if (vop !== undefined) {
  207. if (vop.call) {
  208. ret = vop.call(v, w);
  209. } else { // assume that vop is an __xxx__ type method
  210. ret = Sk.misceval.callsim(vop, v, w);
  211. }
  212. if (ret !== undefined && ret !== Sk.builtin.NotImplemented.NotImplemented$) {
  213. return ret;
  214. }
  215. }
  216. // If there wasn't an in-place operation, fall back to the binop
  217. return Sk.abstr.binary_op_(v, w, opname);
  218. };
  219. Sk.abstr.unary_op_ = function (v, opname) {
  220. var ret;
  221. var vop = Sk.abstr.uoNameToSlotFunc_(v, opname);
  222. if (vop !== undefined) {
  223. if (vop.call) {
  224. ret = vop.call(v);
  225. } else { // assume that vop is an __xxx__ type method
  226. ret = Sk.misceval.callsim(vop, v); // added to be like not-in-place... is this okay?
  227. }
  228. if (ret !== undefined) {
  229. return ret;
  230. }
  231. }
  232. Sk.abstr.unop_type_error(v, opname);
  233. };
  234. //
  235. // handle upconverting a/b from number to long if op causes too big/small a
  236. // result, or if either of the ops are already longs
  237. Sk.abstr.numOpAndPromote = function (a, b, opfn) {
  238. var tmp;
  239. var ans;
  240. if (a === null || b === null) {
  241. return undefined;
  242. }
  243. if (typeof a === "number" && typeof b === "number") {
  244. ans = opfn(a, b);
  245. // todo; handle float Removed RNL (bugs in lng, and it should be a question of precision, not magnitude -- this was just wrong)
  246. if ((ans > Sk.builtin.int_.threshold$ || ans < -Sk.builtin.int_.threshold$) && Math.floor(ans) === ans) {
  247. return [Sk.builtin.lng.fromInt$(a), Sk.builtin.lng.fromInt$(b)];
  248. } else {
  249. return ans;
  250. }
  251. } else if (a === undefined || b === undefined) {
  252. throw new Sk.builtin.NameError("Undefined variable in expression");
  253. }
  254. if (a.constructor === Sk.builtin.lng) {
  255. return [a, b];
  256. } else if ((a.constructor === Sk.builtin.int_ ||
  257. a.constructor === Sk.builtin.float_) &&
  258. b.constructor === Sk.builtin.complex) {
  259. // special case of upconverting nmber and complex
  260. // can we use here the Sk.builtin.checkComplex() method?
  261. tmp = new Sk.builtin.complex(a);
  262. return [tmp, b];
  263. } else if (a.constructor === Sk.builtin.int_ ||
  264. a.constructor === Sk.builtin.float_) {
  265. return [a, b];
  266. } else if (typeof a === "number") {
  267. tmp = Sk.builtin.assk$(a);
  268. return [tmp, b];
  269. } else {
  270. return undefined;
  271. }
  272. };
  273. Sk.abstr.boNumPromote_ = {
  274. "Add" : function (a, b) {
  275. return a + b;
  276. },
  277. "Sub" : function (a, b) {
  278. return a - b;
  279. },
  280. "Mult" : function (a, b) {
  281. return a * b;
  282. },
  283. "Mod" : function (a, b) {
  284. var m;
  285. if (b === 0) {
  286. throw new Sk.builtin.ZeroDivisionError("division or modulo by zero");
  287. }
  288. m = a % b;
  289. return ((m * b) < 0 ? (m + b) : m);
  290. },
  291. "Div" : function (a, b) {
  292. if (b === 0) {
  293. throw new Sk.builtin.ZeroDivisionError("division or modulo by zero");
  294. } else {
  295. return a / b;
  296. }
  297. },
  298. "FloorDiv": function (a, b) {
  299. if (b === 0) {
  300. throw new Sk.builtin.ZeroDivisionError("division or modulo by zero");
  301. } else {
  302. return Math.floor(a / b);
  303. } // todo; wrong? neg?
  304. },
  305. "Pow" : Math.pow,
  306. "BitAnd" : function (a, b) {
  307. var m = a & b;
  308. if (m < 0) {
  309. m = m + 4294967296; // convert back to unsigned
  310. }
  311. return m;
  312. },
  313. "BitOr" : function (a, b) {
  314. var m = a | b;
  315. if (m < 0) {
  316. m = m + 4294967296; // convert back to unsigned
  317. }
  318. return m;
  319. },
  320. "BitXor" : function (a, b) {
  321. var m = a ^ b;
  322. if (m < 0) {
  323. m = m + 4294967296; // convert back to unsigned
  324. }
  325. return m;
  326. },
  327. "LShift" : function (a, b) {
  328. var m;
  329. if (b < 0) {
  330. throw new Sk.builtin.ValueError("negative shift count");
  331. }
  332. m = a << b;
  333. if (m > a) {
  334. return m;
  335. } else {
  336. // Fail, this will get recomputed with longs
  337. return a * Math.pow(2, b);
  338. }
  339. },
  340. "RShift" : function (a, b) {
  341. var m;
  342. if (b < 0) {
  343. throw new Sk.builtin.ValueError("negative shift count");
  344. }
  345. m = a >> b;
  346. if ((a > 0) && (m < 0)) {
  347. // fix incorrect sign extension
  348. m = m & (Math.pow(2, 32 - b) - 1);
  349. }
  350. return m;
  351. }
  352. };
  353. Sk.abstr.numberBinOp = function (v, w, op) {
  354. var tmp;
  355. var numPromoteFunc = Sk.abstr.boNumPromote_[op];
  356. if (numPromoteFunc !== undefined) {
  357. tmp = Sk.abstr.numOpAndPromote(v, w, numPromoteFunc);
  358. if (typeof tmp === "number") {
  359. return tmp;
  360. } else if (tmp !== undefined && tmp.constructor === Sk.builtin.int_) {
  361. return tmp;
  362. } else if (tmp !== undefined && tmp.constructor === Sk.builtin.float_) {
  363. return tmp;
  364. } else if (tmp !== undefined && tmp.constructor === Sk.builtin.lng) {
  365. return tmp;
  366. } else if (tmp !== undefined) {
  367. v = tmp[0];
  368. w = tmp[1];
  369. }
  370. }
  371. return Sk.abstr.binary_op_(v, w, op);
  372. };
  373. goog.exportSymbol("Sk.abstr.numberBinOp", Sk.abstr.numberBinOp);
  374. Sk.abstr.numberInplaceBinOp = function (v, w, op) {
  375. var tmp;
  376. var numPromoteFunc = Sk.abstr.boNumPromote_[op];
  377. if (numPromoteFunc !== undefined) {
  378. tmp = Sk.abstr.numOpAndPromote(v, w, numPromoteFunc);
  379. if (typeof tmp === "number") {
  380. return tmp;
  381. } else if (tmp !== undefined && tmp.constructor === Sk.builtin.int_) {
  382. return tmp;
  383. } else if (tmp !== undefined && tmp.constructor === Sk.builtin.float_) {
  384. return tmp;
  385. } else if (tmp !== undefined && tmp.constructor === Sk.builtin.lng) {
  386. return tmp;
  387. } else if (tmp !== undefined) {
  388. v = tmp[0];
  389. w = tmp[1];
  390. }
  391. }
  392. return Sk.abstr.binary_iop_(v, w, op);
  393. };
  394. goog.exportSymbol("Sk.abstr.numberInplaceBinOp", Sk.abstr.numberInplaceBinOp);
  395. Sk.abstr.numberUnaryOp = function (v, op) {
  396. var value;
  397. if (op === "Not") {
  398. return Sk.misceval.isTrue(v) ? Sk.builtin.bool.false$ : Sk.builtin.bool.true$;
  399. } else if (v instanceof Sk.builtin.bool) {
  400. value = Sk.builtin.asnum$(v);
  401. if (op === "USub") {
  402. return new Sk.builtin.int_(-value);
  403. }
  404. if (op === "UAdd") {
  405. return new Sk.builtin.int_(value);
  406. }
  407. if (op === "Invert") {
  408. return new Sk.builtin.int_(~value);
  409. }
  410. } else {
  411. if (op === "USub" && v.nb$negative) {
  412. return v.nb$negative();
  413. }
  414. if (op === "UAdd" && v.nb$positive) {
  415. return v.nb$positive();
  416. }
  417. if (op === "Invert" && v.nb$invert) {
  418. return v.nb$invert();
  419. }
  420. }
  421. return Sk.abstr.unary_op_(v, op);
  422. };
  423. goog.exportSymbol("Sk.abstr.numberUnaryOp", Sk.abstr.numberUnaryOp);
  424. //
  425. // Sequence
  426. //
  427. Sk.abstr.fixSeqIndex_ = function (seq, i) {
  428. i = Sk.builtin.asnum$(i);
  429. if (i < 0 && seq.sq$length) {
  430. i += seq.sq$length();
  431. }
  432. return i;
  433. };
  434. /**
  435. * @param {*} seq
  436. * @param {*} ob
  437. * @param {boolean=} canSuspend
  438. */
  439. Sk.abstr.sequenceContains = function (seq, ob, canSuspend) {
  440. var seqtypename;
  441. var special;
  442. var r;
  443. if (seq.sq$contains) {
  444. return seq.sq$contains(ob);
  445. }
  446. /**
  447. * Look for special method and call it, we have to distinguish between built-ins and
  448. * python objects
  449. */
  450. special = Sk.abstr.lookupSpecial(seq, "__contains__");
  451. if (special != null) {
  452. // method on builtin, provide this arg
  453. return Sk.misceval.isTrue(Sk.misceval.callsim(special, seq, ob));
  454. }
  455. if (!Sk.builtin.checkIterable(seq)) {
  456. seqtypename = Sk.abstr.typeName(seq);
  457. throw new Sk.builtin.TypeError("argument of type '" + seqtypename + "' is not iterable");
  458. }
  459. r = Sk.misceval.iterFor(Sk.abstr.iter(seq), function(i) {
  460. if (Sk.misceval.richCompareBool(i, ob, "Eq")) {
  461. return new Sk.misceval.Break(true);
  462. } else {
  463. return false;
  464. }
  465. }, false);
  466. return canSuspend ? r : Sk.misceval.retryOptionalSuspensionOrThrow(r);
  467. };
  468. Sk.abstr.sequenceConcat = function (seq1, seq2) {
  469. var seq1typename;
  470. if (seq1.sq$concat) {
  471. return seq1.sq$concat(seq2);
  472. }
  473. seq1typename = Sk.abstr.typeName(seq1);
  474. throw new Sk.builtin.TypeError("'" + seq1typename + "' object can't be concatenated");
  475. };
  476. Sk.abstr.sequenceGetIndexOf = function (seq, ob) {
  477. var seqtypename;
  478. var i, it;
  479. var index;
  480. if (seq.index) {
  481. return Sk.misceval.callsim(seq.index, seq, ob);
  482. }
  483. if (Sk.builtin.checkIterable(seq)) {
  484. index = 0;
  485. for (it = Sk.abstr.iter(seq), i = it.tp$iternext();
  486. i !== undefined; i = it.tp$iternext()) {
  487. if (Sk.misceval.richCompareBool(ob, i, "Eq")) {
  488. return new Sk.builtin.int_(index);
  489. }
  490. index += 1;
  491. }
  492. throw new Sk.builtin.ValueError("sequence.index(x): x not in sequence");
  493. }
  494. seqtypename = Sk.abstr.typeName(seq);
  495. throw new Sk.builtin.TypeError("argument of type '" + seqtypename + "' is not iterable");
  496. };
  497. Sk.abstr.sequenceGetCountOf = function (seq, ob) {
  498. var seqtypename;
  499. var i, it;
  500. var count;
  501. if (seq.count) {
  502. return Sk.misceval.callsim(seq.count, seq, ob);
  503. }
  504. if (Sk.builtin.checkIterable(seq)) {
  505. count = 0;
  506. for (it = Sk.abstr.iter(seq), i = it.tp$iternext();
  507. i !== undefined; i = it.tp$iternext()) {
  508. if (Sk.misceval.richCompareBool(ob, i, "Eq")) {
  509. count += 1;
  510. }
  511. }
  512. return new Sk.builtin.int_(count);
  513. }
  514. seqtypename = Sk.abstr.typeName(seq);
  515. throw new Sk.builtin.TypeError("argument of type '" + seqtypename + "' is not iterable");
  516. };
  517. Sk.abstr.sequenceGetItem = function (seq, i, canSuspend) {
  518. var seqtypename;
  519. if (seq.mp$subscript) {
  520. return seq.mp$subscript(i);
  521. }
  522. seqtypename = Sk.abstr.typeName(seq);
  523. throw new Sk.builtin.TypeError("'" + seqtypename + "' object is unsubscriptable");
  524. };
  525. Sk.abstr.sequenceSetItem = function (seq, i, x, canSuspend) {
  526. var seqtypename;
  527. if (seq.mp$ass_subscript) {
  528. return seq.mp$ass_subscript(i, x);
  529. }
  530. seqtypename = Sk.abstr.typeName(seq);
  531. throw new Sk.builtin.TypeError("'" + seqtypename + "' object does not support item assignment");
  532. };
  533. Sk.abstr.sequenceDelItem = function (seq, i) {
  534. var seqtypename;
  535. if (seq.sq$del_item) {
  536. i = Sk.abstr.fixSeqIndex_(seq, i);
  537. seq.sq$del_item(i);
  538. return;
  539. }
  540. seqtypename = Sk.abstr.typeName(seq);
  541. throw new Sk.builtin.TypeError("'" + seqtypename + "' object does not support item deletion");
  542. };
  543. Sk.abstr.sequenceRepeat = function (f, seq, n) {
  544. var ntypename;
  545. var count;
  546. n = Sk.builtin.asnum$(n);
  547. count = Sk.misceval.asIndex(n);
  548. if (count === undefined) {
  549. ntypename = Sk.abstr.typeName(n);
  550. throw new Sk.builtin.TypeError("can't multiply sequence by non-int of type '" + ntypename + "'");
  551. }
  552. return f.call(seq, n);
  553. };
  554. Sk.abstr.sequenceGetSlice = function (seq, i1, i2) {
  555. var seqtypename;
  556. if (seq.sq$slice) {
  557. i1 = Sk.abstr.fixSeqIndex_(seq, i1);
  558. i2 = Sk.abstr.fixSeqIndex_(seq, i2);
  559. return seq.sq$slice(i1, i2);
  560. } else if (seq.mp$subscript) {
  561. return seq.mp$subscript(new Sk.builtin.slice(i1, i2));
  562. }
  563. seqtypename = Sk.abstr.typeName(seq);
  564. throw new Sk.builtin.TypeError("'" + seqtypename + "' object is unsliceable");
  565. };
  566. Sk.abstr.sequenceDelSlice = function (seq, i1, i2) {
  567. var seqtypename;
  568. if (seq.sq$del_slice) {
  569. i1 = Sk.abstr.fixSeqIndex_(seq, i1);
  570. i2 = Sk.abstr.fixSeqIndex_(seq, i2);
  571. seq.sq$del_slice(i1, i2);
  572. return;
  573. }
  574. seqtypename = Sk.abstr.typeName(seq);
  575. throw new Sk.builtin.TypeError("'" + seqtypename + "' doesn't support slice deletion");
  576. };
  577. Sk.abstr.sequenceSetSlice = function (seq, i1, i2, x) {
  578. var seqtypename;
  579. if (seq.sq$ass_slice) {
  580. i1 = Sk.abstr.fixSeqIndex_(seq, i1);
  581. i2 = Sk.abstr.fixSeqIndex_(seq, i2);
  582. seq.sq$ass_slice(i1, i2, x);
  583. } else if (seq.mp$ass_subscript) {
  584. seq.mp$ass_subscript(new Sk.builtin.slice(i1, i2), x);
  585. } else {
  586. seqtypename = Sk.abstr.typeName(seq);
  587. throw new Sk.builtin.TypeError("'" + seqtypename + "' object doesn't support slice assignment");
  588. }
  589. };
  590. // seq - Python object to unpack
  591. // n - JavaScript number of items to unpack
  592. Sk.abstr.sequenceUnpack = function (seq, n) {
  593. var res = [];
  594. var it, i;
  595. if (!Sk.builtin.checkIterable(seq)) {
  596. throw new Sk.builtin.TypeError("'" + Sk.abstr.typeName(seq) + "' object is not iterable");
  597. }
  598. for (it = Sk.abstr.iter(seq), i = it.tp$iternext();
  599. (i !== undefined) && (res.length < n);
  600. i = it.tp$iternext()) {
  601. res.push(i);
  602. }
  603. if (res.length < n) {
  604. throw new Sk.builtin.ValueError("need more than " + res.length + " values to unpack");
  605. }
  606. if (i !== undefined) {
  607. throw new Sk.builtin.ValueError("too many values to unpack");
  608. }
  609. // Return Javascript array of items
  610. return res;
  611. };
  612. //
  613. // Object
  614. //
  615. Sk.abstr.objectFormat = function (obj, format_spec) {
  616. var meth; // PyObject
  617. var result; // PyObject
  618. // If no format_spec is provided, use an empty string
  619. if(format_spec == null) {
  620. format_spec = "";
  621. }
  622. // Find the (unbound!) __format__ method (a borrowed reference)
  623. meth = Sk.abstr.lookupSpecial(obj, "__format__");
  624. if (meth == null) {
  625. throw new Sk.builtin.TypeError("Type " + Sk.abstr.typeName(obj) + "doesn't define __format__");
  626. }
  627. // And call it
  628. result = Sk.misceval.callsim(meth, obj, format_spec);
  629. if (!Sk.builtin.checkString(result)) {
  630. throw new Sk.builtin.TypeError("__format__ must return a str, not " + Sk.abstr.typeName(result));
  631. }
  632. return result;
  633. };
  634. Sk.abstr.objectAdd = function (a, b) {
  635. var btypename;
  636. var atypename;
  637. if (a.nb$add) {
  638. return a.nb$add(b);
  639. }
  640. atypename = Sk.abstr.typeName(a);
  641. btypename = Sk.abstr.typeName(b);
  642. throw new Sk.builtin.TypeError("unsupported operand type(s) for +: '" + atypename + "' and '" + btypename + "'");
  643. };
  644. // in Python 2.6, this behaviour seems to be defined for numbers and bools (converts bool to int)
  645. Sk.abstr.objectNegative = function (obj) {
  646. var objtypename;
  647. var obj_asnum = Sk.builtin.asnum$(obj); // this will also convert bool type to int
  648. if (obj instanceof Sk.builtin.bool) {
  649. obj = new Sk.builtin.int_(obj_asnum);
  650. }
  651. if (obj.nb$negative) {
  652. return obj.nb$negative();
  653. }
  654. objtypename = Sk.abstr.typeName(obj);
  655. throw new Sk.builtin.TypeError("bad operand type for unary -: '" + objtypename + "'");
  656. };
  657. // in Python 2.6, this behaviour seems to be defined for numbers and bools (converts bool to int)
  658. Sk.abstr.objectPositive = function (obj) {
  659. var objtypename = Sk.abstr.typeName(obj);
  660. var obj_asnum = Sk.builtin.asnum$(obj); // this will also convert bool type to int
  661. if (obj instanceof Sk.builtin.bool) {
  662. obj = new Sk.builtin.int_(obj_asnum);
  663. }
  664. if (obj.nb$negative) {
  665. return obj.nb$positive();
  666. }
  667. throw new Sk.builtin.TypeError("bad operand type for unary +: '" + objtypename + "'");
  668. };
  669. Sk.abstr.objectDelItem = function (o, key) {
  670. var otypename;
  671. var keytypename;
  672. var keyValue;
  673. if (o !== null) {
  674. if (o.mp$del_subscript) {
  675. o.mp$del_subscript(key);
  676. return;
  677. }
  678. if (o.sq$ass_item) {
  679. keyValue = Sk.misceval.asIndex(key);
  680. if (keyValue === undefined) {
  681. keytypename = Sk.abstr.typeName(key);
  682. throw new Sk.builtin.TypeError("sequence index must be integer, not '" + keytypename + "'");
  683. }
  684. Sk.abstr.sequenceDelItem(o, keyValue);
  685. return;
  686. }
  687. // if o is a slice do something else...
  688. }
  689. otypename = Sk.abstr.typeName(o);
  690. throw new Sk.builtin.TypeError("'" + otypename + "' object does not support item deletion");
  691. };
  692. goog.exportSymbol("Sk.abstr.objectDelItem", Sk.abstr.objectDelItem);
  693. Sk.abstr.objectGetItem = function (o, key, canSuspend) {
  694. var otypename;
  695. if (o !== null) {
  696. if (o.tp$getitem) {
  697. return o.tp$getitem(key, canSuspend);
  698. } else if (o.mp$subscript) {
  699. return o.mp$subscript(key, canSuspend);
  700. } else if (Sk.misceval.isIndex(key) && o.sq$item) {
  701. return Sk.abstr.sequenceGetItem(o, Sk.misceval.asIndex(key), canSuspend);
  702. }
  703. }
  704. otypename = Sk.abstr.typeName(o);
  705. throw new Sk.builtin.TypeError("'" + otypename + "' does not support indexing");
  706. };
  707. goog.exportSymbol("Sk.abstr.objectGetItem", Sk.abstr.objectGetItem);
  708. Sk.abstr.objectSetItem = function (o, key, v, canSuspend) {
  709. var otypename;
  710. if (o !== null) {
  711. if (o.tp$setitem) {
  712. return o.tp$setitem(key, v, canSuspend);
  713. } else if (o.mp$ass_subscript) {
  714. return o.mp$ass_subscript(key, v, canSuspend);
  715. } else if (Sk.misceval.isIndex(key) && o.sq$ass_item) {
  716. return Sk.abstr.sequenceSetItem(o, Sk.misceval.asIndex(key), v, canSuspend);
  717. }
  718. }
  719. otypename = Sk.abstr.typeName(o);
  720. throw new Sk.builtin.TypeError("'" + otypename + "' does not support item assignment");
  721. };
  722. goog.exportSymbol("Sk.abstr.objectSetItem", Sk.abstr.objectSetItem);
  723. Sk.abstr.gattr = function (obj, nameJS, canSuspend) {
  724. var ret, f;
  725. var objname = Sk.abstr.typeName(obj);
  726. if (obj === null) {
  727. throw new Sk.builtin.AttributeError("'" + objname + "' object has no attribute '" + nameJS + "'");
  728. }
  729. if (obj.tp$getattr !== undefined) {
  730. ret = obj.tp$getattr(nameJS, canSuspend);
  731. }
  732. ret = Sk.misceval.chain(ret, function(r) {
  733. if (r === undefined) {
  734. throw new Sk.builtin.AttributeError("'" + objname + "' object has no attribute '" + nameJS + "'");
  735. }
  736. return r;
  737. });
  738. return canSuspend ? ret : Sk.misceval.retryOptionalSuspensionOrThrow(ret);
  739. };
  740. goog.exportSymbol("Sk.abstr.gattr", Sk.abstr.gattr);
  741. Sk.abstr.sattr = function (obj, nameJS, data, canSuspend) {
  742. var objname = Sk.abstr.typeName(obj), r, setf;
  743. if (obj === null) {
  744. throw new Sk.builtin.AttributeError("'" + objname + "' object has no attribute '" + nameJS + "'");
  745. }
  746. if (obj.tp$setattr !== undefined) {
  747. return obj.tp$setattr(nameJS, data, canSuspend);
  748. } else {
  749. throw new Sk.builtin.AttributeError("'" + objname + "' object has no attribute '" + nameJS + "'");
  750. }
  751. };
  752. goog.exportSymbol("Sk.abstr.sattr", Sk.abstr.sattr);
  753. Sk.abstr.iternext = function (it, canSuspend) {
  754. return it.tp$iternext(canSuspend);
  755. };
  756. goog.exportSymbol("Sk.abstr.iternext", Sk.abstr.iternext);
  757. /**
  758. * Get the iterator for a Python object This iterator could be one of the following.
  759. * This is the preferred mechanism for consistently getting the correct iterator. You should
  760. * not just use tp$iter because that could lead to incorrect behavior of a user created class.
  761. *
  762. * - tp$iter
  763. * - A user defined `__iter__` method
  764. * - A user defined `__getitem__` method
  765. *
  766. * @param obj
  767. *
  768. * @throws {Sk.builtin.TypeError}
  769. * @returns {Object}
  770. */
  771. Sk.abstr.iter = function(obj) {
  772. var iter;
  773. var getit;
  774. var ret;
  775. /**
  776. * Builds an iterator around classes that have a __getitem__ method.
  777. *
  778. * @constructor
  779. */
  780. var seqIter = function (obj) {
  781. this.idx = 0;
  782. this.myobj = obj;
  783. this.getitem = Sk.abstr.lookupSpecial(obj, "__getitem__");
  784. this.tp$iternext = function () {
  785. var ret;
  786. try {
  787. ret = Sk.misceval.callsim(this.getitem, this.myobj, Sk.ffi.remapToPy(this.idx));
  788. } catch (e) {
  789. if (e instanceof Sk.builtin.IndexError || e instanceof Sk.builtin.StopIteration) {
  790. return undefined;
  791. } else {
  792. throw e;
  793. }
  794. }
  795. this.idx++;
  796. return ret;
  797. };
  798. };
  799. if (obj.tp$getattr) {
  800. iter = Sk.abstr.lookupSpecial(obj,"__iter__");
  801. if (iter) {
  802. ret = Sk.misceval.callsim(iter, obj);
  803. if (ret.tp$iternext) {
  804. return ret;
  805. }
  806. }
  807. }
  808. if (obj.tp$iter) {
  809. try { // catch and ignore not iterable error here.
  810. ret = obj.tp$iter();
  811. if (ret.tp$iternext) {
  812. return ret;
  813. }
  814. } catch (e) { }
  815. }
  816. getit = Sk.abstr.lookupSpecial(obj, "__getitem__");
  817. if (getit) {
  818. // create internal iterobject if __getitem__
  819. return new seqIter(obj);
  820. }
  821. throw new Sk.builtin.TypeError("'" + Sk.abstr.typeName(obj) + "' object is not iterable");
  822. };
  823. goog.exportSymbol("Sk.abstr.iter", Sk.abstr.iter);
  824. /**
  825. * Special method look up. First try getting the method via
  826. * internal dict and getattr. If getattr is not present (builtins)
  827. * try if method is defined on the object itself
  828. *
  829. * @returns {null|Object} Return null if not found or the function
  830. */
  831. Sk.abstr.lookupSpecial = function(op, str) {
  832. var res;
  833. var obtp;
  834. if (op.ob$type) {
  835. obtp = op.ob$type;
  836. } else {
  837. return null;
  838. }
  839. return Sk.builtin.type.typeLookup(obtp, str);
  840. };
  841. goog.exportSymbol("Sk.abstr.lookupSpecial", Sk.abstr.lookupSpecial);
  842. /**
  843. * Mark a class as unhashable and prevent its `__hash__` function from being called.
  844. * @param {function(...[?])} thisClass The class to mark as unhashable.
  845. * @return {undefined}
  846. */
  847. Sk.abstr.markUnhashable = function (thisClass) {
  848. var proto = thisClass.prototype;
  849. proto.__hash__ = Sk.builtin.none.none$;
  850. proto.tp$hash = Sk.builtin.none.none$;
  851. };
  852. /**
  853. * Set up inheritance between two Python classes. This allows only for single
  854. * inheritance -- multiple inheritance is not supported by Javascript.
  855. *
  856. * Javascript's inheritance is prototypal. This means that properties must
  857. * be defined on the superclass' prototype in order for subclasses to inherit
  858. * them.
  859. *
  860. * ```
  861. * Sk.superclass.myProperty # will NOT be inherited
  862. * Sk.superclass.prototype.myProperty # will be inherited
  863. * ```
  864. *
  865. * In order for a class to be subclassable, it must (directly or indirectly)
  866. * inherit from Sk.builtin.object so that it will be properly initialized in
  867. * {@link Sk.doOneTimeInitialization} (in src/import.js). Further, all Python
  868. * builtins should inherit from Sk.builtin.object.
  869. *
  870. * @param {string} childName The Python name of the child (subclass).
  871. * @param {function(...[?])} child The subclass.
  872. * @param {function(...[?])} parent The superclass.
  873. * @return {undefined}
  874. */
  875. Sk.abstr.setUpInheritance = function (childName, child, parent) {
  876. goog.inherits(child, parent);
  877. child.prototype.tp$base = parent;
  878. child.prototype.tp$name = childName;
  879. child.prototype.ob$type = Sk.builtin.type.makeIntoTypeObj(childName, child);
  880. };
  881. /**
  882. * Call the super constructor of the provided class, with the object `self` as
  883. * the `this` value of that constructor. Any arguments passed to this function
  884. * after `self` will be passed as-is to the constructor.
  885. *
  886. * @param {function(...[?])} thisClass The subclass.
  887. * @param {Object} self The instance of the subclas.
  888. * @param {...?} args Arguments to pass to the constructor.
  889. * @return {undefined}
  890. */
  891. Sk.abstr.superConstructor = function (thisClass, self, args) {
  892. var argumentsForConstructor = Array.prototype.slice.call(arguments, 2);
  893. thisClass.prototype.tp$base.apply(self, argumentsForConstructor);
  894. };