| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /**
- * @constructor
- * @param {Array.<Object>|Object} L
- */
- Sk.builtin.tuple = function (L) {
- var it, i;
- if (!(this instanceof Sk.builtin.tuple)) {
- return new Sk.builtin.tuple(L);
- }
- if (L === undefined) {
- L = [];
- }
- if (Object.prototype.toString.apply(L) === "[object Array]") {
- this.v = L;
- } else {
- if (Sk.builtin.checkIterable(L)) {
- this.v = [];
- for (it = Sk.abstr.iter(L), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
- this.v.push(i);
- }
- } else {
- throw new Sk.builtin.TypeError("expecting Array or iterable");
- }
- }
- this.__class__ = Sk.builtin.tuple;
- this["v"] = this.v;
- return this;
- };
- Sk.abstr.setUpInheritance("tuple", Sk.builtin.tuple, Sk.builtin.seqtype);
- Sk.builtin.tuple.prototype["$r"] = function () {
- var ret;
- var i;
- var bits;
- if (this.v.length === 0) {
- return new Sk.builtin.str("()");
- }
- bits = [];
- for (i = 0; i < this.v.length; ++i) {
- bits[i] = Sk.misceval.objectRepr(this.v[i]).v;
- }
- ret = bits.join(", ");
- if (this.v.length === 1) {
- ret += ",";
- }
- return new Sk.builtin.str("(" + ret + ")");
- };
- Sk.builtin.tuple.prototype.mp$subscript = function (index) {
- var ret;
- var i;
- if (Sk.misceval.isIndex(index)) {
- i = Sk.misceval.asIndex(index);
- if (i !== undefined) {
- if (i < 0) {
- i = this.v.length + i;
- }
- if (i < 0 || i >= this.v.length) {
- throw new Sk.builtin.IndexError("tuple index out of range");
- }
- return this.v[i];
- }
- } else if (index instanceof Sk.builtin.slice) {
- ret = [];
- index.sssiter$(this, function (i, wrt) {
- ret.push(wrt.v[i]);
- });
- return new Sk.builtin.tuple(ret);
- }
- throw new Sk.builtin.TypeError("tuple indices must be integers, not " + Sk.abstr.typeName(index));
- };
- // todo; the numbers and order are taken from python, but the answer's
- // obviously not the same because there's no int wrapping. shouldn't matter,
- // but would be nice to make the hash() values the same if it's not too
- // expensive to simplify tests.
- Sk.builtin.tuple.prototype.tp$hash = function () {
- var y;
- var i;
- var mult = 1000003;
- var x = 0x345678;
- var len = this.v.length;
- for (i = 0; i < len; ++i) {
- y = Sk.builtin.hash(this.v[i]).v;
- if (y === -1) {
- return new Sk.builtin.int_(-1);
- }
- x = (x ^ y) * mult;
- mult += 82520 + len + len;
- }
- x += 97531;
- if (x === -1) {
- x = -2;
- }
- return new Sk.builtin.int_(x | 0);
- };
- Sk.builtin.tuple.prototype.sq$repeat = function (n) {
- var j;
- var i;
- var ret;
- n = Sk.misceval.asIndex(n);
- ret = [];
- for (i = 0; i < n; ++i) {
- for (j = 0; j < this.v.length; ++j) {
- ret.push(this.v[j]);
- }
- }
- return new Sk.builtin.tuple(ret);
- };
- Sk.builtin.tuple.prototype.nb$multiply = Sk.builtin.tuple.prototype.sq$repeat;
- Sk.builtin.tuple.prototype.nb$inplace_multiply = Sk.builtin.tuple.prototype.sq$repeat;
- Sk.builtin.tuple.prototype.__iter__ = new Sk.builtin.func(function (self) {
- Sk.builtin.pyCheckArgs("__iter__", arguments, 1, 1);
- return new Sk.builtin.tuple_iter_(self);
- });
- Sk.builtin.tuple.prototype.tp$iter = function () {
- return new Sk.builtin.tuple_iter_(this);
- };
- Sk.builtin.tuple.prototype.tp$richcompare = function (w, op) {
- //print(" tup rc", JSON.stringify(this.v), JSON.stringify(w), op);
- // w not a tuple
- var k;
- var i;
- var wl;
- var vl;
- var v;
- if (!w.__class__ ||
- !Sk.misceval.isTrue(Sk.builtin.isinstance(w, Sk.builtin.tuple))) {
- // shortcuts for eq/not
- if (op === "Eq") {
- return false;
- }
- if (op === "NotEq") {
- return true;
- }
- // todo; other types should have an arbitrary order
- return false;
- }
- v = this.v;
- w = w.v;
- vl = v.length;
- wl = w.length;
- for (i = 0; i < vl && i < wl; ++i) {
- k = Sk.misceval.richCompareBool(v[i], w[i], "Eq");
- if (!k) {
- break;
- }
- }
- if (i >= vl || i >= wl) {
- // no more items to compare, compare sizes
- switch (op) {
- case "Lt":
- return vl < wl;
- case "LtE":
- return vl <= wl;
- case "Eq":
- return vl === wl;
- case "NotEq":
- return vl !== wl;
- case "Gt":
- return vl > wl;
- case "GtE":
- return vl >= wl;
- default:
- goog.asserts.fail();
- }
- }
- // we have an item that's different
- // shortcuts for eq/not
- if (op === "Eq") {
- return false;
- }
- if (op === "NotEq") {
- return true;
- }
- // or, compare the differing element using the proper operator
- //print(" tup rcb end", i, v[i] instanceof Sk.builtin.str, JSON.stringify(v[i]), w[i] instanceof Sk.builtin.str, JSON.stringify(w[i]), op);
- return Sk.misceval.richCompareBool(v[i], w[i], op);
- };
- Sk.builtin.tuple.prototype.sq$concat = function (other) {
- var msg;
- if (other.__class__ != Sk.builtin.tuple) {
- msg = "can only concatenate tuple (not \"";
- msg += Sk.abstr.typeName(other) + "\") to tuple";
- throw new Sk.builtin.TypeError(msg);
- }
- return new Sk.builtin.tuple(this.v.concat(other.v));
- };
- Sk.builtin.tuple.prototype.sq$contains = function (ob) {
- var it, i;
- for (it = this.tp$iter(), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
- if (Sk.misceval.richCompareBool(i, ob, "Eq")) {
- return true;
- }
- }
- return false;
- };
- Sk.builtin.tuple.prototype.nb$add = Sk.builtin.tuple.prototype.sq$concat;
- Sk.builtin.tuple.prototype.nb$inplace_add = Sk.builtin.tuple.prototype.sq$concat;
- Sk.builtin.tuple.prototype.sq$length = function () {
- return this.v.length;
- };
- Sk.builtin.tuple.prototype["index"] = new Sk.builtin.func(function (self, item) {
- var i;
- var len = self.v.length;
- var obj = self.v;
- for (i = 0; i < len; ++i) {
- if (Sk.misceval.richCompareBool(obj[i], item, "Eq")) {
- return new Sk.builtin.int_(i);
- }
- }
- throw new Sk.builtin.ValueError("tuple.index(x): x not in tuple");
- });
- Sk.builtin.tuple.prototype["count"] = new Sk.builtin.func(function (self, item) {
- var i;
- var len = self.v.length;
- var obj = self.v;
- var count = 0;
- for (i = 0; i < len; ++i) {
- if (Sk.misceval.richCompareBool(obj[i], item, "Eq")) {
- count += 1;
- }
- }
- return new Sk.builtin.int_(count);
- });
- goog.exportSymbol("Sk.builtin.tuple", Sk.builtin.tuple);
- /**
- * @constructor
- * @param {Object} obj
- */
- Sk.builtin.tuple_iter_ = function (obj) {
- if (!(this instanceof Sk.builtin.tuple_iter_)) {
- return new Sk.builtin.tuple_iter_(obj);
- }
- this.$index = 0;
- this.$obj = obj.v.slice();
- this.sq$length = this.$obj.length;
- this.tp$iter = this;
- this.tp$iternext = function () {
- if (this.$index >= this.sq$length) {
- return undefined;
- }
- return this.$obj[this.$index++];
- };
- this.$r = function () {
- return new Sk.builtin.str("tupleiterator");
- };
- return this;
- };
- Sk.abstr.setUpInheritance("tupleiterator", Sk.builtin.tuple_iter_, Sk.builtin.object);
- Sk.builtin.tuple_iter_.prototype.__class__ = Sk.builtin.tuple_iter_;
- Sk.builtin.tuple_iter_.prototype.__iter__ = new Sk.builtin.func(function (self) {
- return self;
- });
- Sk.builtin.tuple_iter_.prototype["next"] = new Sk.builtin.func(function (self) {
- var ret = self.tp$iternext();
- if (ret === undefined) {
- throw new Sk.builtin.StopIteration();
- }
- return ret;
- });
|