/**
* @constructor
* @param {Array.<Object>} S
*/
Sk.builtin.set = function (S) {
var it, i;
var S_list;
if (!(this instanceof Sk.builtin.set)) {
return new Sk.builtin.set(S);
}
if (typeof(S) === "undefined") {
S = [];
}
this.set_reset_();
S_list = new Sk.builtin.list(S);
// python sorts sets on init, but not thereafter.
// Skulpt seems to init a new set each time you add/remove something
//Sk.builtin.list.prototype['sort'].func_code(S);
for (it = S_list.tp$iter(), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
Sk.builtin.set.prototype["add"].func_code(this, i);
}
this.__class__ = Sk.builtin.set;
this["v"] = this.v;
return this;
};
Sk.builtin.set.prototype.ob$type = Sk.builtin.type.makeIntoTypeObj("set", Sk.builtin.set);
Sk.builtin.set.prototype.set_iter_ = function () {
return this["v"].tp$iter();
};
Sk.builtin.set.prototype.set_reset_ = function () {
this.v = new Sk.builtin.dict([]);
};
Sk.builtin.set.prototype.tp$name = "set";
Sk.builtin.set.prototype["$r"] = function () {
var it, i;
var ret = [];
for (it = this.tp$iter(), i = it.tp$iternext(); i !== undefined; i = it.tp$iternext()) {
ret.push(Sk.misceval.objectRepr(i).v);
}
if(Sk.python3) {
return new Sk.builtin.str("{" + ret.join(", ") + "}");
} else {
return new Sk.builtin.str("set([" + ret.join(", ") + "])");
}
};
Sk.builtin.set.prototype.tp$getattr = Sk.builtin.object.prototype.GenericGetAttr;
// todo; you can't hash a set() -- what should this be?
Sk.builtin.set.prototype.tp$hash = Sk.builtin.none.none$;
Sk.builtin.set.prototype.tp$richcompare = function (w, op) {
// todo; NotImplemented if either isn't a set
var isSuper;
var isSub;
var wl;
var vl;
if (this === w && Sk.misceval.opAllowsEquality(op)) {
return true;
}
// w not a set
if (!w.__class__ || w.__class__ != Sk.builtin.set) {
// shortcuts for eq/not
if (op === "Eq") {
return false;
}
if (op === "NotEq") {
return true;
}
// todo; other types should have an arbitrary order
return false;
}
vl = this.sq$length();
wl = w.sq$length();
// easy short-cut
if (wl !== vl) {
if (op === "Eq") {
return false;
}
if (op === "NotEq") {
return true;
}
}
// used quite a lot in comparisons.
isSub = false;
isSuper = false;
// gather common info
switch (op) {
case "Lt":
case "LtE":
case "Eq":
case "NotEq":
isSub = Sk.builtin.set.prototype["issubset"].func_code(this, w).v;
break;
case "Gt":
case "GtE":
isSuper = Sk.builtin.set.prototype["issuperset"].func_code(this, w).v;
break;
default:
goog.asserts.fail();
}
switch (op) {
case "Lt":
return vl < wl && isSub;
case "LtE":
case "Eq": // we already know that the lengths are equal
return isSub;
case "NotEq":
return !isSub;
case "Gt":
return vl > wl && isSuper;
case "GtE":
return isSuper;
}
};
Sk.builtin.set.prototype.tp$iter = Sk.builtin.set.prototype.set_iter_;
Sk.builtin.set.prototype.sq$length = function () {
return this["v"].mp$length();
};
Sk.builtin.set.prototype.sq$contains = function(ob) {
return this["v"].sq$contains(ob);
};
Sk.builtin.set.prototype["isdisjoint"] = new Sk.builtin.func(function (self, other) {
// requires all items in self to not be in other
var isIn;
var it, item;
for (it = self.tp$iter(), item = it.tp$iternext(); item !== undefined; item = it.tp$iternext()) {
isIn = Sk.abstr.sequenceContains(other, item);
if (isIn) {
return Sk.builtin.bool.false$;
}
}
return Sk.builtin.bool.true$;
});
Sk.builtin.set.prototype["issubset"] = new Sk.builtin.func(function (self, other) {
var isIn;
var it, item;
var selfLength = self.sq$length();
var otherLength = other.sq$length();
if (selfLength > otherLength) {
// every item in this set can't be in other if it's shorter!
return Sk.builtin.bool.false$;
}
for (it = self.tp$iter(), item = it.tp$iternext(); item !== undefined; item = it.tp$iternext()) {
isIn = Sk.abstr.sequenceContains(other, item);
if (!isIn) {
return Sk.builtin.bool.false$;
}
}
return Sk.builtin.bool.true$;
});
Sk.builtin.set.prototype["issuperset"] = new Sk.builtin.func(function (self, other) {
return Sk.builtin.set.prototype["issubset"].func_code(other, self);
});
Sk.builtin.set.prototype["union"] = new Sk.builtin.func(function (self) {
var i;
var S = new Sk.builtin.set(self);
for (i = 1; i < arguments.length; i++) {
Sk.builtin.set.prototype["update"].func_code(S, arguments[i]);
}
return S;
});
Sk.builtin.set.prototype["intersection"] = new Sk.builtin.func(function (self) {
var S = Sk.builtin.set.prototype["copy"].func_code(self),
new_args = Array.prototype.slice.call(arguments); //copy array
new_args[0] = S;
Sk.builtin.set.prototype["intersection_update"].func_code.apply(null, new_args);
return S;
});
Sk.builtin.set.prototype["difference"] = new Sk.builtin.func(function (self, other) {
var S = Sk.builtin.set.prototype["copy"].func_code(self),
new_args = Array.prototype.slice.call(arguments); //copy array
new_args[0] = S;
Sk.builtin.set.prototype["difference_update"].func_code.apply(null, new_args);
return S;
});
Sk.builtin.set.prototype["symmetric_difference"] = new Sk.builtin.func(function (self, other) {
var it, item;
var S = Sk.builtin.set.prototype["union"].func_code(self, other);
for (it = S.tp$iter(), item = it.tp$iternext(); item !== undefined; item = it.tp$iternext()) {
if (Sk.abstr.sequenceContains(self, item) && Sk.abstr.sequenceContains(other, item)) {
Sk.builtin.set.prototype["discard"].func_code(S, item);
}
}
return S;
});
Sk.builtin.set.prototype["copy"] = new Sk.builtin.func(function (self) {
return new Sk.builtin.set(self);
});
Sk.builtin.set.prototype["update"] = new Sk.builtin.func(function (self, other) {
var it, item;
for (it = other.tp$iter(), item = it.tp$iternext(); item !== undefined; item = it.tp$iternext()) {
Sk.builtin.set.prototype["add"].func_code(self, item);
}
return Sk.builtin.none.none$;
});
Sk.builtin.set.prototype["intersection_update"] = new Sk.builtin.func(function (self, other) {
var i;
var it, item;
for (it = self.tp$iter(), item = it.tp$iternext(); item !== undefined; item = it.tp$iternext()) {
for (i = 1; i < arguments.length; i++) {
if (!Sk.abstr.sequenceContains(arguments[i], item)) {
Sk.builtin.set.prototype["discard"].func_code(self, item);
break;
}
}
}
return Sk.builtin.none.none$;
});
Sk.builtin.set.prototype["difference_update"] = new Sk.builtin.func(function (self, other) {
var i;
var it, item;
for (it = self.tp$iter(), item = it.tp$iternext(); item !== undefined; item = it.tp$iternext()) {
for (i = 1; i < arguments.length; i++) {
if (Sk.abstr.sequenceContains(arguments[i], item)) {
Sk.builtin.set.prototype["discard"].func_code(self, item);
break;
}
}
}
return Sk.builtin.none.none$;
});
Sk.builtin.set.prototype["symmetric_difference_update"] = new Sk.builtin.func(function (self, other) {
var sd = Sk.builtin.set.prototype["symmetric_difference"].func_code(self, other);
self.set_reset_();
Sk.builtin.set.prototype["update"].func_code(self, sd);
return Sk.builtin.none.none$;
});
Sk.builtin.set.prototype["add"] = new Sk.builtin.func(function (self, item) {
self.v.mp$ass_subscript(item, true);
return Sk.builtin.none.none$;
});
Sk.builtin.set.prototype["discard"] = new Sk.builtin.func(function (self, item) {
Sk.builtin.dict.prototype["pop"].func_code(self.v, item,
Sk.builtin.none.none$);
return Sk.builtin.none.none$;
});
Sk.builtin.set.prototype["pop"] = new Sk.builtin.func(function (self) {
var it, item;
if (self.sq$length() === 0) {
throw new Sk.builtin.KeyError("pop from an empty set");
}
it = self.tp$iter();
item = it.tp$iternext();
Sk.builtin.set.prototype["discard"].func_code(self, item);
return item;
});
Sk.builtin.set.prototype["remove"] = new Sk.builtin.func(function (self, item) {
self.v.mp$del_subscript(item);
return Sk.builtin.none.none$;
});
goog.exportSymbol("Sk.builtin.set", Sk.builtin.set);