// Structure types (function(baselib) { var exports = {}; baselib.structs = exports; var StructType = function(name, // string type, // StructType numberOfArgs, // number numberOfFields, // number firstField, applyGuard, constructor, predicate, accessor, mutator) { this.name = name; this.type = type; this.numberOfArgs = numberOfArgs; this.numberOfFields = numberOfFields; this.firstField = firstField; this.applyGuard = applyGuard; this.constructor = constructor; this.predicate = predicate; this.accessor = accessor; this.mutator = mutator; }; StructType.prototype.toString = function(cache) { return '#'; }; StructType.prototype.equals = function(other, aUnionFind) { return this === other; }; // guard-function: array string (array -> value) // makeStructureType: string StructType number number boolean // guard-function -> StructType // // Creates a new structure type. var makeStructureType = function(theName, parentType, initFieldCnt, autoFieldCnt, autoV, guard) { // Defaults autoFieldCnt = autoFieldCnt || 0; parentType = parentType || DEFAULT_PARENT_TYPE; guard = guard || DEFAULT_GUARD; // rawConstructor creates a new struct type inheriting from // the parent, with no guard checks. var rawConstructor = function(name, args) { parentType.type.call(this, name, args); for (var i = 0; i < initFieldCnt; i++) { this._fields.push(args[i+parentType.numberOfArgs]); } for (var i = 0; i < autoFieldCnt; i++) { this._fields.push(autoV); } }; rawConstructor.prototype = baselib.heir(parentType.type.prototype); // Set type, necessary for equality checking rawConstructor.prototype.type = rawConstructor; // The structure type consists of the name, its constructor, a // record of how many argument it and its parent type contains, // the list of autofields, the guard, and functions corresponding // to the constructor, the predicate, the accessor, and mutators. var newType = new StructType( theName, rawConstructor, initFieldCnt + parentType.numberOfArgs, initFieldCnt + autoFieldCnt, parentType.firstField + parentType.numberOfFields, function(args, name, k) { return guard(args, name, function(result) { var parentArgs = result.slice(0, parentType.numberOfArgs); var restArgs = result.slice(parentType.numberOfArgs); return parentType.applyGuard( parentArgs, name, function(parentRes) { return k( parentRes.concat(restArgs) ); }); }); }, // constructor function() { var args = [].slice.call(arguments); return newType.applyGuard( args, baselib.symbols.Symbol.makeInstance(theName), function(res) { return new rawConstructor(theName, res); }); }, // predicate function(x) { return x instanceof rawConstructor; }, // accessor function(x, i) { return x._fields[i + this.firstField]; }, // mutator function(x, i, v) { x._fields[i + this.firstField] = v; }); return newType; }; ////////////////////////////////////////////////////////////////////// var Struct = function(constructorName, fields) { this._constructorName = constructorName; this._fields = []; }; Struct.prototype.toWrittenString = function(cache) { cache.put(this, true); var buffer = []; buffer.push("("); buffer.push(this._constructorName); for(var i = 0; i < this._fields.length; i++) { buffer.push(" "); buffer.push(plt.baselib.format.toWrittenString(this._fields[i], cache)); } buffer.push(")"); return buffer.join(""); }; Struct.prototype.toDisplayedString = function(cache) { return plt.baselib.format.toWrittenString(this, cache); }; Struct.prototype.toDomNode = function(params) { params.put(this, true); var node = document.createElement("span"); $(node).append(document.createTextNode("(")); $(node).append(document.createTextNode(this._constructorName)); for(var i = 0; i < this._fields.length; i++) { $(node).append(document.createTextNode(" ")); $(node).append(plt.baselib.format.toDomNode(this._fields[i], params)); } $(node).append(document.createTextNode(")")); return node; }; Struct.prototype.equals = function(other, aUnionFind) { if ( other.type == undefined || this.type !== other.type || !(other instanceof this.type) ) { return false; } for (var i = 0; i < this._fields.length; i++) { if (! equals(this._fields[i], other._fields[i], aUnionFind)) { return false; } } return true; } Struct.prototype.type = Struct; // // Struct Procedure types // var StructProc = function(type, name, numParams, isRest, usesState, impl) { // PrimProc.call(this, name, numParams, isRest, usesState, impl); // this.type = type; // }; // StructProc.prototype = baselib.heir(PrimProc.prototype); // var StructConstructorProc = function() { // StructProc.apply(this, arguments); // }; // StructConstructorProc.prototype = baselib.heir(StructProc.prototype); // var StructPredicateProc = function() { // StructProc.apply(this, arguments); // }; // StructPredicateProc.prototype = baselib.heir(StructProc.prototype); // var StructAccessorProc = function() { // StructProc.apply(this, arguments); // }; // StructAccessorProc.prototype = baselib.heir(StructProc.prototype); // var StructMutatorProc = function() { // StructProc.apply(this, arguments); // }; // StructMutatorProc.prototype = baselib.heir(StructProc.prototype); // Default structure guard just calls the continuation argument. var DEFAULT_GUARD = function(args, name, k) { return k(args); }; // The default parent type refers to the toplevel Struct. var DEFAULT_PARENT_TYPE = { type: Struct, numberOfArgs: 0, numberOfFields: 0, firstField: 0, applyGuard: DEFAULT_GUARD }; var isStruct = function(x) { return x instanceof Struct; }; var isStructType = function(x) { return x instanceof StructType; }; ////////////////////////////////////////////////////////////////////// exports.StructType = StructType; exports.Struct = Struct; exports.makeStructureType = makeStructureType; exports.isStruct = isStruct; exports.isStructType = isStructType; // exports.StructProc = StructProc; // exports.StructConstructorProc = StructConstructorProc; // exports.StructPredicateProc = StructPredicateProc; // exports.StructAccessorProc = StructAccessorProc; // exports.StructMutatorProc = StructMutatorProc; })(this['plt'].baselib);