whalesong/js-assembler/runtime-src/baselib-lists.js
2011-07-06 17:00:42 -04:00

191 lines
4.7 KiB
JavaScript

// list structures (pairs, empty)
(function(baselib) {
var exports = {};
baselib.lists = exports;
Empty = function() {
};
Empty.EMPTY = new Empty();
Empty.prototype.equals = function(other, aUnionFind) {
return other instanceof Empty;
};
Empty.prototype.reverse = function() {
return this;
};
Empty.prototype.toWrittenString = function(cache) { return "empty"; };
Empty.prototype.toDisplayedString = function(cache) { return "empty"; };
Empty.prototype.toString = function(cache) { return "()"; };
// Empty.append: (listof X) -> (listof X)
Empty.prototype.append = function(b){
return b;
};
//////////////////////////////////////////////////////////////////////
// Cons Pairs
var Cons = function(first, rest) {
this.first = first;
this.rest = rest;
};
Cons.prototype.reverse = function() {
var lst = this;
var ret = Empty.EMPTY;
while (!isEmpty(lst)){
ret = Cons.makeInstance(lst.first, ret);
lst = lst.rest;
}
return ret;
};
Cons.makeInstance = function(first, rest) {
return new Cons(first, rest);
};
// FIXME: can we reduce the recursion on this?
Cons.prototype.equals = function(other, aUnionFind) {
if (! (other instanceof Cons)) {
return false;
}
return (plt.baselib.equality.equals(this.first, other.first, aUnionFind) &&
plt.baselib.equality.equals(this.rest, other.rest, aUnionFind));
};
// Cons.append: (listof X) -> (listof X)
Cons.prototype.append = function(b){
if (b === Empty.EMPTY)
return this;
var ret = b;
var lst = this.reverse();
while ( !isEmpty(lst) ) {
ret = Cons.makeInstance(lst.first, ret);
lst = lst.rest;
}
return ret;
};
Cons.prototype.toWrittenString = function(cache) {
cache.put(this, true);
var texts = [];
var p = this;
while ( p instanceof Cons ) {
texts.push(plt.baselib.format.toWrittenString(p.first, cache));
p = p.rest;
if (typeof(p) === 'object' && cache.containsKey(p)) {
break;
}
}
if ( p !== Empty.EMPTY ) {
texts.push('.');
texts.push(plt.baselib.format.toWrittenString(p, cache));
}
return "(" + texts.join(" ") + ")";
};
Cons.prototype.toString = Cons.prototype.toWrittenString;
Cons.prototype.toDisplayedString = function(cache) {
cache.put(this, true);
var texts = [];
var p = this;
while ( p instanceof Cons ) {
texts.push(plt.baselib.format.toDisplayedString(p.first, cache));
p = p.rest;
if (typeof(p) === 'object' && cache.containsKey(p)) {
break;
}
}
if ( p !== Empty.EMPTY ) {
texts.push('.');
texts.push(plt.baselib.format.toDisplayedString(p, cache));
}
return "(" + texts.join(" ") + ")";
};
Cons.prototype.toDomNode = function(cache) {
cache.put(this, true);
var node = document.createElement("span");
node.appendChild(document.createTextNode("("));
var p = this;
while ( p instanceof Cons ) {
appendChild(node, plt.baselib.format.toDomNode(p.first, cache));
p = p.rest;
if ( p !== Empty.EMPTY ) {
appendChild(node, document.createTextNode(" "));
}
if (typeof(p) === 'object' && cache.containsKey(p)) {
break;
}
}
if ( p !== Empty.EMPTY ) {
appendChild(node, document.createTextNode("."));
appendChild(node, document.createTextNode(" "));
appendChild(node, plt.baselib.format.toDomNode(p, cache));
}
node.appendChild(document.createTextNode(")"));
return node;
};
var isPair = function(x) { return x instanceof Cons; };
var makePair = Cons.makeInstance;
var makeList = function() {
var result = Empty.EMPTY;
for(var i = arguments.length-1; i >= 0; i--) {
result = Cons.makeInstance(arguments[i], result);
}
return result;
};
// isList: Any -> Boolean
// Returns true if x is a list (a chain of pairs terminated by EMPTY).
var isList = function(x) {
while (x !== Empty.EMPTY) {
if (x instanceof Cons){
x = x.rest;
} else {
return false;
}
}
return true;
};
//////////////////////////////////////////////////////////////////////
exports.EMPTY = Empty.EMPTY;
exports.Empty = Empty;
exports.Cons = Cons;
exports.isPair = isPair;
exports.isList = isList;
exports.makePair = makePair;
exports.makeList = makeList;
})(this['plt'].baselib);