list.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /**
  2. * @constructor
  3. * @param {Array.<Object>=} L
  4. * @param {boolean=} canSuspend (defaults to true in this case, as list() is used directly from Python)
  5. * @extends Sk.builtin.object
  6. */
  7. Sk.builtin.list = function (L, canSuspend) {
  8. var v, it, thisList;
  9. if (this instanceof Sk.builtin.list) {
  10. canSuspend = canSuspend || false;
  11. } else {
  12. // Default to true in this case, because 'list' gets called directly from Python
  13. return new Sk.builtin.list(L, canSuspend || true);
  14. }
  15. this.__class__ = Sk.builtin.list;
  16. if (L === undefined) {
  17. v = [];
  18. } else if (Object.prototype.toString.apply(L) === "[object Array]") {
  19. v = L;
  20. } else if (Sk.builtin.checkIterable(L)) {
  21. v = [];
  22. it = Sk.abstr.iter(L);
  23. thisList = this;
  24. return (function next(i) {
  25. while(true) {
  26. if (i instanceof Sk.misceval.Suspension) {
  27. return new Sk.misceval.Suspension(next, i);
  28. } else if (i === undefined) {
  29. // done!
  30. thisList.v = v;
  31. return thisList;
  32. } else {
  33. v.push(i);
  34. i = it.tp$iternext(canSuspend);
  35. }
  36. }
  37. })(it.tp$iternext(canSuspend));
  38. } else {
  39. throw new Sk.builtin.TypeError("'" + Sk.abstr.typeName(L)+ "' " +"object is not iterable");
  40. }
  41. this["v"] = this.v = v;
  42. return this;
  43. };
  44. Sk.abstr.setUpInheritance("list", Sk.builtin.list, Sk.builtin.seqtype);
  45. Sk.abstr.markUnhashable(Sk.builtin.list);
  46. Sk.builtin.list.prototype.list_concat_ = function (other) {
  47. // other not a list
  48. var i;
  49. var ret;
  50. if (!other.__class__ || other.__class__ != Sk.builtin.list) {
  51. throw new Sk.builtin.TypeError("can only concatenate list to list");
  52. }
  53. ret = this.v.slice();
  54. for (i = 0; i < other.v.length; ++i) {
  55. ret.push(other.v[i]);
  56. }
  57. return new Sk.builtin.list(ret, false);
  58. };
  59. Sk.builtin.list.prototype.list_extend_ = function (other) {
  60. var it, i;
  61. var newb;
  62. if (!Sk.builtin.checkIterable(other)) {
  63. throw new Sk.builtin.TypeError("'" + Sk.abstr.typeName(other) +
  64. "' object is not iterable");
  65. }
  66. if (this == other) {
  67. // Handle extending list with itself
  68. newb = [];
  69. for (it = Sk.abstr.iter(other), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
  70. newb.push(i);
  71. }
  72. // Concatenate
  73. this.v.push.apply(this.v, newb);
  74. } else {
  75. for (it = Sk.abstr.iter(other), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
  76. this.v.push(i);
  77. }
  78. }
  79. return this;
  80. };
  81. Sk.builtin.list.prototype.list_del_item_ = function (i) {
  82. i = Sk.builtin.asnum$(i);
  83. if (i < 0 || i >= this.v.length) {
  84. throw new Sk.builtin.IndexError("list assignment index out of range");
  85. }
  86. this.list_del_slice_(i, i + 1);
  87. };
  88. Sk.builtin.list.prototype.list_del_slice_ = function (ilow, ihigh) {
  89. var args;
  90. ilow = Sk.builtin.asnum$(ilow);
  91. ihigh = Sk.builtin.asnum$(ihigh);
  92. args = [];
  93. args.unshift(ihigh - ilow);
  94. args.unshift(ilow);
  95. this.v.splice.apply(this.v, args);
  96. };
  97. Sk.builtin.list.prototype.list_ass_item_ = function (i, v) {
  98. i = Sk.builtin.asnum$(i);
  99. if (i < 0 || i >= this.v.length) {
  100. throw new Sk.builtin.IndexError("list assignment index out of range");
  101. }
  102. this.v[i] = v;
  103. };
  104. Sk.builtin.list.prototype.list_ass_slice_ = function (ilow, ihigh, v) {
  105. var args;
  106. ilow = Sk.builtin.asnum$(ilow);
  107. ihigh = Sk.builtin.asnum$(ihigh);
  108. if (Sk.builtin.checkIterable(v)) {
  109. args = new Sk.builtin.list(v, false).v.slice(0);
  110. } else {
  111. throw new Sk.builtin.TypeError("can only assign an iterable");
  112. }
  113. args.unshift(ihigh - ilow);
  114. args.unshift(ilow);
  115. this.v.splice.apply(this.v, args);
  116. };
  117. Sk.builtin.list.prototype["$r"] = function () {
  118. var it, i;
  119. var ret = [];
  120. for (it = Sk.abstr.iter(this), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
  121. if(i === this) {
  122. ret.push("[...]");
  123. } else {
  124. ret.push(Sk.misceval.objectRepr(i).v);
  125. }
  126. }
  127. return new Sk.builtin.str("[" + ret.join(", ") + "]");
  128. };
  129. Sk.builtin.list.prototype.tp$richcompare = function (w, op) {
  130. // todo; can't figure out where cpy handles this silly case (test/run/t96.py)
  131. // perhaps by trapping a stack overflow? otherwise i'm not sure for more
  132. // complicated cases. bleh
  133. //
  134. // if the comparison allows for equality then short-circuit it here
  135. var k;
  136. var i;
  137. var wl;
  138. var vl;
  139. var v;
  140. if (this === w && Sk.misceval.opAllowsEquality(op)) {
  141. return true;
  142. }
  143. // w not a list
  144. if (!w.__class__ || w.__class__ != Sk.builtin.list) {
  145. // shortcuts for eq/not
  146. if (op === "Eq") {
  147. return false;
  148. }
  149. if (op === "NotEq") {
  150. return true;
  151. }
  152. // todo; other types should have an arbitrary order
  153. return false;
  154. }
  155. v = this.v;
  156. w = w.v;
  157. vl = v.length;
  158. wl = w.length;
  159. for (i = 0; i < vl && i < wl; ++i) {
  160. k = Sk.misceval.richCompareBool(v[i], w[i], "Eq");
  161. if (!k) {
  162. break;
  163. }
  164. }
  165. if (i >= vl || i >= wl) {
  166. // no more items to compare, compare sizes
  167. switch (op) {
  168. case "Lt":
  169. return vl < wl;
  170. case "LtE":
  171. return vl <= wl;
  172. case "Eq":
  173. return vl === wl;
  174. case "NotEq":
  175. return vl !== wl;
  176. case "Gt":
  177. return vl > wl;
  178. case "GtE":
  179. return vl >= wl;
  180. default:
  181. goog.asserts.fail();
  182. }
  183. }
  184. // we have an item that's different
  185. // shortcuts for eq/not
  186. if (op === "Eq") {
  187. return false;
  188. }
  189. if (op === "NotEq") {
  190. return true;
  191. }
  192. // or, compare the differing element using the proper operator
  193. return Sk.misceval.richCompareBool(v[i], w[i], op);
  194. };
  195. Sk.builtin.list.prototype.__iter__ = new Sk.builtin.func(function (self) {
  196. Sk.builtin.pyCheckArgs("__iter__", arguments, 0, 0, true, false);
  197. return new Sk.builtin.list_iter_(self);
  198. });
  199. Sk.builtin.list.prototype.tp$iter = function () {
  200. return new Sk.builtin.list_iter_(this);
  201. };
  202. Sk.builtin.list.prototype.sq$length = function () {
  203. return this.v.length;
  204. };
  205. Sk.builtin.list.prototype.sq$concat = Sk.builtin.list.prototype.list_concat_;
  206. Sk.builtin.list.prototype.nb$add = Sk.builtin.list.prototype.list_concat_;
  207. Sk.builtin.list.prototype.nb$inplace_add = Sk.builtin.list.prototype.list_extend_;
  208. Sk.builtin.list.prototype.sq$repeat = function (n) {
  209. var j;
  210. var i;
  211. var ret;
  212. if (!Sk.misceval.isIndex(n)) {
  213. throw new Sk.builtin.TypeError("can't multiply sequence by non-int of type '" + Sk.abstr.typeName(n) + "'");
  214. }
  215. n = Sk.misceval.asIndex(n);
  216. ret = [];
  217. for (i = 0; i < n; ++i) {
  218. for (j = 0; j < this.v.length; ++j) {
  219. ret.push(this.v[j]);
  220. }
  221. }
  222. return new Sk.builtin.list(ret, false);
  223. };
  224. Sk.builtin.list.prototype.nb$multiply = Sk.builtin.list.prototype.sq$repeat;
  225. Sk.builtin.list.prototype.nb$inplace_multiply = function(n) {
  226. var j;
  227. var i;
  228. var len;
  229. if (!Sk.misceval.isIndex(n)) {
  230. throw new Sk.builtin.TypeError("can't multiply sequence by non-int of type '" + Sk.abstr.typeName(n) + "'");
  231. }
  232. // works on list itself --> inplace
  233. n = Sk.misceval.asIndex(n);
  234. len = this.v.length;
  235. for (i = 1; i < n; ++i) {
  236. for (j = 0; j < len; ++j) {
  237. this.v.push(this.v[j]);
  238. }
  239. }
  240. return this;
  241. };
  242. /*
  243. Sk.builtin.list.prototype.sq$item = list_item;
  244. Sk.builtin.list.prototype.sq$slice = list_slice;
  245. */
  246. Sk.builtin.list.prototype.sq$ass_item = Sk.builtin.list.prototype.list_ass_item_;
  247. Sk.builtin.list.prototype.sq$del_item = Sk.builtin.list.prototype.list_del_item_;
  248. Sk.builtin.list.prototype.sq$ass_slice = Sk.builtin.list.prototype.list_ass_slice_;
  249. Sk.builtin.list.prototype.sq$del_slice = Sk.builtin.list.prototype.list_del_slice_;
  250. Sk.builtin.list.prototype.sq$contains = function (item) {
  251. var it, i;
  252. for (it = this.tp$iter(), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
  253. if (Sk.misceval.richCompareBool(i, item, "Eq")) {
  254. return true;
  255. }
  256. }
  257. return false;
  258. };
  259. /*
  260. Sk.builtin.list.prototype.sq$inplace_concat = list_inplace_concat;
  261. Sk.builtin.list.prototype.sq$inplace_repeat = list_inplace_repeat;
  262. */
  263. Sk.builtin.list.prototype.list_subscript_ = function (index) {
  264. var ret;
  265. var i;
  266. if (Sk.misceval.isIndex(index)) {
  267. i = Sk.misceval.asIndex(index);
  268. if (i !== undefined) {
  269. if (i < 0) {
  270. i = this.v.length + i;
  271. }
  272. if (i < 0 || i >= this.v.length) {
  273. throw new Sk.builtin.IndexError("list index out of range");
  274. }
  275. return this.v[i];
  276. }
  277. } else if (index instanceof Sk.builtin.slice) {
  278. ret = [];
  279. index.sssiter$(this, function (i, wrt) {
  280. ret.push(wrt.v[i]);
  281. });
  282. return new Sk.builtin.list(ret, false);
  283. }
  284. throw new Sk.builtin.TypeError("list indices must be integers, not " + Sk.abstr.typeName(index));
  285. };
  286. Sk.builtin.list.prototype.list_ass_subscript_ = function (index, value) {
  287. var i;
  288. var j;
  289. var tosub;
  290. var indices;
  291. if (Sk.misceval.isIndex(index)) {
  292. i = Sk.misceval.asIndex(index);
  293. if (i !== undefined) {
  294. if (i < 0) {
  295. i = this.v.length + i;
  296. }
  297. this.list_ass_item_(i, value);
  298. return;
  299. }
  300. } else if (index instanceof Sk.builtin.slice) {
  301. indices = index.slice_indices_(this.v.length);
  302. if (indices[2] === 1) {
  303. this.list_ass_slice_(indices[0], indices[1], value);
  304. } else {
  305. tosub = [];
  306. index.sssiter$(this, function (i, wrt) {
  307. tosub.push(i);
  308. });
  309. j = 0;
  310. if (tosub.length !== value.v.length) {
  311. throw new Sk.builtin.ValueError("attempt to assign sequence of size " + value.v.length + " to extended slice of size " + tosub.length);
  312. }
  313. for (i = 0; i < tosub.length; ++i) {
  314. this.v.splice(tosub[i], 1, value.v[j]);
  315. j += 1;
  316. }
  317. }
  318. return;
  319. }
  320. throw new Sk.builtin.TypeError("list indices must be integers, not " + Sk.abstr.typeName(index));
  321. };
  322. Sk.builtin.list.prototype.list_del_subscript_ = function (index) {
  323. var offdir;
  324. var dec;
  325. var self;
  326. var indices;
  327. var i;
  328. if (Sk.misceval.isIndex(index)) {
  329. i = Sk.misceval.asIndex(index);
  330. if (i !== undefined) {
  331. if (i < 0) {
  332. i = this.v.length + i;
  333. }
  334. this.list_del_item_(i);
  335. return;
  336. }
  337. } else if (index instanceof Sk.builtin.slice) {
  338. indices = index.slice_indices_(this.v.length);
  339. if (indices[2] === 1) {
  340. this.list_del_slice_(indices[0], indices[1]);
  341. } else {
  342. self = this;
  343. dec = 0; // offset of removal for next index (because we'll have removed, but the iterator is giving orig indices)
  344. offdir = indices[2] > 0 ? 1 : 0;
  345. index.sssiter$(this, function (i, wrt) {
  346. self.v.splice(i - dec, 1);
  347. dec += offdir;
  348. });
  349. }
  350. return;
  351. }
  352. throw new Sk.builtin.TypeError("list indices must be integers, not " + typeof index);
  353. };
  354. Sk.builtin.list.prototype.mp$subscript = Sk.builtin.list.prototype.list_subscript_;
  355. Sk.builtin.list.prototype.mp$ass_subscript = Sk.builtin.list.prototype.list_ass_subscript_;
  356. Sk.builtin.list.prototype.mp$del_subscript = Sk.builtin.list.prototype.list_del_subscript_;
  357. Sk.builtin.list.prototype.__getitem__ = new Sk.builtin.func(function (self, index) {
  358. return Sk.builtin.list.prototype.list_subscript_.call(self, index);
  359. });
  360. /**
  361. * @param {?=} self
  362. * @param {?=} cmp optional
  363. * @param {?=} key optional
  364. * @param {?=} reverse optional
  365. */
  366. Sk.builtin.list.prototype.list_sort_ = function (self, cmp, key, reverse) {
  367. var mucked;
  368. var j;
  369. var keyvalue;
  370. var item;
  371. var i;
  372. var zero;
  373. var timsort;
  374. var has_key = key !== undefined && key !== null;
  375. var has_cmp = cmp !== undefined && cmp !== null;
  376. var rev;
  377. if (reverse === undefined) {
  378. rev = false;
  379. } else if (reverse === Sk.builtin.none.none$) {
  380. throw new Sk.builtin.TypeError("an integer is required");
  381. } else {
  382. rev = Sk.misceval.isTrue(reverse);
  383. }
  384. timsort = new Sk.builtin.timSort(self);
  385. self.v = [];
  386. zero = new Sk.builtin.int_(0);
  387. if (has_key) {
  388. if (has_cmp) {
  389. timsort.lt = function (a, b) {
  390. var res = Sk.misceval.callsim(cmp, a[0], b[0]);
  391. return Sk.misceval.richCompareBool(res, zero, "Lt");
  392. };
  393. } else {
  394. timsort.lt = function (a, b) {
  395. return Sk.misceval.richCompareBool(a[0], b[0], "Lt");
  396. };
  397. }
  398. for (i = 0; i < timsort.listlength; i++) {
  399. item = timsort.list.v[i];
  400. keyvalue = Sk.misceval.callsim(key, item);
  401. timsort.list.v[i] = [keyvalue, item];
  402. }
  403. } else if (has_cmp) {
  404. timsort.lt = function (a, b) {
  405. var res = Sk.misceval.callsim(cmp, a, b);
  406. return Sk.misceval.richCompareBool(res, zero, "Lt");
  407. };
  408. }
  409. if (rev) {
  410. timsort.list.list_reverse_(timsort.list);
  411. }
  412. timsort.sort();
  413. if (rev) {
  414. timsort.list.list_reverse_(timsort.list);
  415. }
  416. if (has_key) {
  417. for (j = 0; j < timsort.listlength; j++) {
  418. item = timsort.list.v[j][1];
  419. timsort.list.v[j] = item;
  420. }
  421. }
  422. mucked = self.sq$length() > 0;
  423. self.v = timsort.list.v;
  424. if (mucked) {
  425. throw new Sk.builtin.OperationError("list modified during sort");
  426. }
  427. return Sk.builtin.none.none$;
  428. };
  429. /**
  430. * @param {Sk.builtin.list=} self optional
  431. **/
  432. Sk.builtin.list.prototype.list_reverse_ = function (self) {
  433. var i;
  434. var newarr;
  435. var old;
  436. var len;
  437. Sk.builtin.pyCheckArgs("reverse", arguments, 1, 1);
  438. len = self.v.length;
  439. old = self.v;
  440. newarr = [];
  441. for (i = len - 1; i > -1; --i) {
  442. newarr.push(old[i]);
  443. }
  444. self["v"] = newarr;
  445. return Sk.builtin.none.none$;
  446. };
  447. //Sk.builtin.list.prototype.__reversed__ = todo;
  448. Sk.builtin.list.prototype["append"] = new Sk.builtin.func(function (self, item) {
  449. Sk.builtin.pyCheckArgs("append", arguments, 2, 2);
  450. self.v.push(item);
  451. return Sk.builtin.none.none$;
  452. });
  453. Sk.builtin.list.prototype["insert"] = new Sk.builtin.func(function (self, i, x) {
  454. Sk.builtin.pyCheckArgs("insert", arguments, 3, 3);
  455. if (!Sk.builtin.checkNumber(i)) {
  456. throw new Sk.builtin.TypeError("an integer is required");
  457. }
  458. i = Sk.builtin.asnum$(i);
  459. if (i < 0) {
  460. i = i + self.v.length;
  461. }
  462. if (i < 0) {
  463. i = 0;
  464. } else if (i > self.v.length) {
  465. i = self.v.length;
  466. }
  467. self.v.splice(i, 0, x);
  468. return Sk.builtin.none.none$;
  469. });
  470. Sk.builtin.list.prototype["extend"] = new Sk.builtin.func(function (self, b) {
  471. Sk.builtin.pyCheckArgs("extend", arguments, 2, 2);
  472. self.list_extend_(b);
  473. return Sk.builtin.none.none$;
  474. });
  475. Sk.builtin.list.prototype["pop"] = new Sk.builtin.func(function (self, i) {
  476. var ret;
  477. Sk.builtin.pyCheckArgs("pop", arguments, 1, 2);
  478. if (i === undefined) {
  479. i = self.v.length - 1;
  480. }
  481. if (!Sk.builtin.checkNumber(i)) {
  482. throw new Sk.builtin.TypeError("an integer is required");
  483. }
  484. i = Sk.builtin.asnum$(i);
  485. if (i < 0) {
  486. i = i + self.v.length;
  487. }
  488. if ((i < 0) || (i >= self.v.length)) {
  489. throw new Sk.builtin.IndexError("pop index out of range");
  490. }
  491. ret = self.v[i];
  492. self.v.splice(i, 1);
  493. return ret;
  494. });
  495. Sk.builtin.list.prototype["remove"] = new Sk.builtin.func(function (self, item) {
  496. var idx;
  497. Sk.builtin.pyCheckArgs("remove", arguments, 2, 2);
  498. idx = Sk.builtin.list.prototype["index"].func_code(self, item);
  499. self.v.splice(Sk.builtin.asnum$(idx), 1);
  500. return Sk.builtin.none.none$;
  501. });
  502. Sk.builtin.list.prototype["index"] = new Sk.builtin.func(function (self, item, start, stop) {
  503. var i;
  504. var obj;
  505. var len;
  506. Sk.builtin.pyCheckArgs("index", arguments, 2, 4);
  507. if (start !== undefined && !Sk.builtin.checkInt(start)) {
  508. throw new Sk.builtin.TypeError("slice indices must be integers");
  509. }
  510. if (stop !== undefined && !Sk.builtin.checkInt(stop)) {
  511. throw new Sk.builtin.TypeError("slice indices must be integers");
  512. }
  513. len = self.v.length;
  514. obj = self.v;
  515. start = (start === undefined) ? 0 : start.v;
  516. if (start < 0) {
  517. start = ((start + len) >= 0) ? start + len : 0;
  518. }
  519. stop = (stop === undefined) ? len : stop.v;
  520. if (stop < 0) {
  521. stop = ((stop + len) >= 0) ? stop + len : 0;
  522. }
  523. for (i = start; i < stop; ++i) {
  524. if (Sk.misceval.richCompareBool(obj[i], item, "Eq")) {
  525. return new Sk.builtin.int_(i);
  526. }
  527. }
  528. throw new Sk.builtin.ValueError("list.index(x): x not in list");
  529. });
  530. Sk.builtin.list.prototype["count"] = new Sk.builtin.func(function (self, item) {
  531. var i;
  532. var count;
  533. var obj;
  534. var len;
  535. Sk.builtin.pyCheckArgs("count", arguments, 2, 2);
  536. len = self.v.length;
  537. obj = self.v;
  538. count = 0;
  539. for (i = 0; i < len; ++i) {
  540. if (Sk.misceval.richCompareBool(obj[i], item, "Eq")) {
  541. count += 1;
  542. }
  543. }
  544. return new Sk.builtin.int_(count);
  545. });
  546. Sk.builtin.list.prototype["reverse"] = new Sk.builtin.func(Sk.builtin.list.prototype.list_reverse_);
  547. Sk.builtin.list.prototype["sort"] = new Sk.builtin.func(Sk.builtin.list.prototype.list_sort_);
  548. // Make sure that key/value variations of lst.sort() work
  549. // See issue 45 on github as to possible alternate approaches to this and
  550. // why this was chosen - csev
  551. Sk.builtin.list.prototype["sort"].func_code["co_varnames"] = ["__self__", "cmp", "key", "reverse"];
  552. goog.exportSymbol("Sk.builtin.list", Sk.builtin.list);
  553. /**
  554. * @constructor
  555. * @param {Object} lst
  556. */
  557. Sk.builtin.list_iter_ = function (lst) {
  558. if (!(this instanceof Sk.builtin.list_iter_)) {
  559. return new Sk.builtin.list_iter_(lst);
  560. }
  561. this.$index = 0;
  562. this.lst = lst.v.slice();
  563. this.sq$length = this.lst.length;
  564. this.tp$iter = this;
  565. this.tp$iternext = function () {
  566. if (this.$index >= this.sq$length) {
  567. return undefined;
  568. }
  569. return this.lst[this.$index++];
  570. };
  571. this.$r = function () {
  572. return new Sk.builtin.str("listiterator");
  573. };
  574. return this;
  575. };
  576. Sk.abstr.setUpInheritance("listiterator", Sk.builtin.list_iter_, Sk.builtin.object);
  577. Sk.builtin.list_iter_.prototype.__class__ = Sk.builtin.list_iter_;
  578. Sk.builtin.list_iter_.prototype.__iter__ = new Sk.builtin.func(function (self) {
  579. return self;
  580. });
  581. Sk.builtin.list_iter_.prototype["next"] = new Sk.builtin.func(function (self) {
  582. var ret = self.tp$iternext();
  583. if (ret === undefined) {
  584. throw new Sk.builtin.StopIteration();
  585. }
  586. return ret;
  587. });