
its just a regular Snap! object, but with a separate class
class source
/*
you can have properly supported custom js types in Snap!
*/
if (!window.ADT) {
function parseLisp(str) {
let proc = new Process(null, world.childThatIsA(IDE_Morph).stage);
proc.pushContext();
return proc.assemble(proc.parseCode(str));
}
class ADT extends List {
constructor() {
super([]);
this.add(new List(["...", this.constructor.proto]));
}
toString(){
return "<"+this.lookup("_type")+">"
}
static
__do(self, action, args) {
if (!(self instanceof ADT))
throw new Error("expecting a js defined adt but got a " + Process.prototype.reportTypeOf(self));
if (self[action] == List.prototype[action])
throw new Error("cannot call list methods directly");
return self[action](...args.itemsArray()) ?? '';
}
static
proto = new List([
new List(["_type", "adt"]),
new List(["__do", ADT.__do]),
new List(["_morph", parseLisp(`(call (get __do) (this [object]) "toString" (list))`)])
]);
static
init(cls) {
if (!cls.prototype instanceof this) {
throw new Error("expecting a js defined adt type but got " + cls.name);
}
if (Object.hasOwn(cls,"proto")) return;
if (cls.prototype.__proto__.constructor !== this)
this.init(cls.prototype.__proto__.constructor);
let proto = new List([new List(["...", cls.prototype.__proto__.constructor.proto])])
for (let k of Object.getOwnPropertyNames(cls.prototype)) {
proto.bind(k, parseLisp(`(call (get __do) (this [object]) ${k} (this [inputs]))`));
}
proto.bind("_type", cls.adtType || cls.name);
cls.proto = proto;
}
}
window.ADT = ADT;
}
how to use
-
extend
ADTclass CustomType extends ADT{ constructor(){ super(); } _morph(){ return new TextMorph("hello from custom type"); } static adtType="foobar" } -
initialize the class
ADT.init(CustomType);
sorry about deleting it, I was unsure if it should go on the forum