From d6e0e79c79439c2704adb3afd6f05a946ca61f5d Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sun, 3 Jul 2011 15:50:12 -0400 Subject: [PATCH] still trying to understand the struct implementation --- js-assembler/get-runtime.rkt | 9 +- js-assembler/runtime-src/baselib.js | 23 +- js-assembler/runtime-src/baselib_hash.js | 12 +- js-assembler/runtime-src/baselib_structs.js | 277 ++++++++++++++++++ js-assembler/runtime-src/baselib_unionfind.js | 6 +- js-assembler/runtime-src/runtime.js | 4 +- js-assembler/runtime-src/types.js | 170 ----------- 7 files changed, 319 insertions(+), 182 deletions(-) create mode 100644 js-assembler/runtime-src/baselib_structs.js diff --git a/js-assembler/get-runtime.rkt b/js-assembler/get-runtime.rkt index 8345ed1..591388c 100644 --- a/js-assembler/get-runtime.rkt +++ b/js-assembler/get-runtime.rkt @@ -37,6 +37,7 @@ (define-runtime-path baselib.js "runtime-src/baselib.js") (define-runtime-path baselib_unionfind.js "runtime-src/baselib_unionfind.js") (define-runtime-path baselib_hash.js "runtime-src/baselib_hash.js") +(define-runtime-path baselib_structs.js "runtime-src/baselib_structs.js") (define-runtime-path jshashtable.js "runtime-src/jshashtable-2.1_src.js") @@ -62,12 +63,16 @@ jquery-protect-footer.js + jshashtable.js + jsnums.js + + baselib.js baselib_unionfind.js baselib_hash.js + baselib_structs.js - jshashtable.js - jsnums.js + link.js helpers.js types.js diff --git a/js-assembler/runtime-src/baselib.js b/js-assembler/runtime-src/baselib.js index b568ee8..938a8b0 100644 --- a/js-assembler/runtime-src/baselib.js +++ b/js-assembler/runtime-src/baselib.js @@ -1,5 +1,24 @@ // Skeleton for basic library functions if (! this['plt']) { this['plt'] = {}; } -(function (scope) { - scope['baselib'] = {}; +(function (plt) { + var baselib = {}; + plt['baselib'] = baselib; + + + + + + // Inheritance. + var heir = function(parentPrototype) { + var f = function() {} + f.prototype = parentPrototype; + return new f(); + }; + + + + + baselib.heir = heir; + + })(this['plt']); diff --git a/js-assembler/runtime-src/baselib_hash.js b/js-assembler/runtime-src/baselib_hash.js index 1706f68..3bc39e2 100644 --- a/js-assembler/runtime-src/baselib_hash.js +++ b/js-assembler/runtime-src/baselib_hash.js @@ -1,7 +1,8 @@ -(function(scope) { + +(function(baselib) { var hash = {}; - scope.hash = hash; + baselib.hash = hash; @@ -13,7 +14,7 @@ // getHashCode: any -> (or fixnum string) - // Produces a hashcode appropriate for eq. + // Given a value, produces a hashcode appropriate for eq. var getEqHashCode = function(x) { if (typeof(x) === 'string') { return x; @@ -30,6 +31,11 @@ return 0; }; + + // Creates a low-level hashtable, following the interface of + // http://www.timdown.co.uk/jshashtable/ + // + // Defined to use the getEqHashCode defined in baselib_hash.js. var makeLowLevelEqHash = function() { return new Hashtable(function(x) { return getEqHashCode(x); }, function(x, y) { return x === y; }); diff --git a/js-assembler/runtime-src/baselib_structs.js b/js-assembler/runtime-src/baselib_structs.js new file mode 100644 index 0000000..6087877 --- /dev/null +++ b/js-assembler/runtime-src/baselib_structs.js @@ -0,0 +1,277 @@ +// Structure types + +(function(baselib) { + var structs = {}; + baselib.structs = structs; + + + + + + + var StructType = function(name, type, numberOfArgs, numberOfFields, 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; + }; + + + + + + + + + // Creates a new structure type. + var makeStructureType = function(theName, + parentType, + initFieldCnt, + autoFieldCnt, + autoV, + guard) { + + // If no parent type given, then the parent type is Struct + 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, + 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(toWrittenString(this._fields[i], cache)); + } + buffer.push(")"); + return buffer.join(""); + }; + + Struct.prototype.toDisplayedString = function(cache) { + return toWrittenString(this, cache); + }; + + Struct.prototype.toDomNode = function(cache) { + cache.put(this, true); + var node = document.createElement("div"); + node.appendChild(document.createTextNode("(")); + node.appendChild(document.createTextNode(this._constructorName)); + for(var i = 0; i < this._fields.length; i++) { + node.appendChild(document.createTextNode(" ")); + appendChild(node, toDomNode(this._fields[i], cache)); + } + node.appendChild(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 }; + + + + + + + + + + + + + + + + + + + structs.StructType = StructType; + structs.Struct = Struct; + + +// structs.StructProc = StructProc; +// structs.StructConstructorProc = StructConstructorProc; +// structs.StructPredicateProc = StructPredicateProc; +// structs.StructAccessorProc = StructAccessorProc; +// structs.StructMutatorProc = StructMutatorProc; + + + structs.makeStructureType = makeStructureType; + + + + +})(this['plt'].baselib); \ No newline at end of file diff --git a/js-assembler/runtime-src/baselib_unionfind.js b/js-assembler/runtime-src/baselib_unionfind.js index 66f721b..a64852a 100644 --- a/js-assembler/runtime-src/baselib_unionfind.js +++ b/js-assembler/runtime-src/baselib_unionfind.js @@ -1,4 +1,4 @@ -(function(scope) { +(function(baselib) { @@ -10,7 +10,7 @@ var UnionFind = function() { // this.parenMap holds the arrows from an arbitrary pointer // to its parent. - this.parentMap = scope.hash.makeLowLevelEqHash(); + this.parentMap = baselib.hash.makeLowLevelEqHash(); } // find: ptr -> UnionFindNode @@ -36,6 +36,6 @@ - scope.UnionFind = UnionFind; + baselib.UnionFind = UnionFind; })(this['plt'].baselib); \ No newline at end of file diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 9dac9c6..952e08d 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -338,14 +338,14 @@ if(this['plt'] === undefined) { this['plt'] = {}; } // its argument stack space. // // + + // A Closure is a function that takes on more responsibilities: it is // responsible for popping off stack space before it finishes, and it // is also explicitly responsible for continuing the computation by // popping off the control stack and doing the jump. Because of this, // closures can do pretty much anything to the machine. - - // A closure consists of its free variables as well as a label // into its text segment. var Closure = function(label, arity, closedVals, displayName) { diff --git a/js-assembler/runtime-src/types.js b/js-assembler/runtime-src/types.js index 48eae69..133e354 100644 --- a/js-assembler/runtime-src/types.js +++ b/js-assembler/runtime-src/types.js @@ -453,11 +453,6 @@ if (! this['plt']) { this['plt'] = {}; } - var isBoolean = function(x) { - return (x === true || x === false); - } - - // Chars // Char: string -> Char @@ -1481,166 +1476,8 @@ String.prototype.toDisplayedString = function(cache) { - ////////////////////////////////////////////////////////////////////// - - var PrefixValue = function() { - this.slots = []; - this.definedMask = []; - }; - - PrefixValue.prototype.addSlot = function(v) { - if (v === undefined) { - this.slots.push(types.UNDEFINED); - this.definedMask.push(false); - } else { - this.slots.push(v); - if (v instanceof GlobalBucket) { - if (v.value === types.UNDEFINED) { - this.definedMask.push(false); - } else { - this.definedMask.push(true); - } - } else if (v instanceof NamedSlot) { - if (v.value === types.UNDEFINED) { - this.definedMask.push(false); - } else { - this.definedMask.push(true); - } - } else { - this.definedMask.push(true); - } - } - }; - - PrefixValue.prototype.ref = function(n) { - if (this.slots[n] instanceof GlobalBucket) { - if (this.definedMask[n]) { - return this.slots[n].value; - } else { - helpers.raise(types.incompleteExn( - types.exnFailContractVariable, - "reference to an identifier before its definition: " + this.slots[n].name, - [this.slots[n].name])); - } - } else if (this.slots[n] instanceof NamedSlot) { - if (this.definedMask[n]) { - return this.slots[n].value; - } else { - helpers.raise(types.incompleteExn( - types.exnFailContractVariable, - "reference to an identifier before its definition: " + this.slots[n].name, - [this.slots[n].name])); - } - } else { - if (this.definedMask[n]) { - return this.slots[n]; - } else { - helpers.raise(types.incompleteExn( - types.exnFailContractVariable, - "variable has not been defined", - [false])); - } - } - }; - - PrefixValue.prototype.lookup = function(name) { - for (var i = 0; i < this.slots.length; i++) { - if (this.slots[i] instanceof NamedSlot) { - if (this.slots[i].name === name) { - return this.slots[i].value; - } - } else if (this.slots[i] instanceof GlobalBucket) { - if (this.slots[i].name === name) { - return this.slots[i].value; - } - } - }; - return types.UNDEFINED; - }; - - PrefixValue.prototype.set = function(n, v) { - if (this.slots[n] instanceof GlobalBucket) { - this.slots[n].value = v; - this.definedMask[n] = true; - } else if (this.slots[n] instanceof NamedSlot) { - this.slots[n].value = v; - this.definedMask[n] = true; - } else { - this.slots[n] = v; - this.definedMask[n] = true; - } - }; - - - PrefixValue.prototype.length = function() { - return this.slots.length; - }; - - - var GlobalBucket = function(name, value) { - this.name = name; - this.value = value; - }; - - var NamedSlot = function(name, value) { - this.name = name; - this.value = value; - }; - - var ModuleVariableRecord = function(resolvedModuleName, - variableName) { - this.resolvedModuleName = resolvedModuleName; - this.variableName = variableName; - }; - - - ////////////////////////////////////////////////////////////////////// - - - var Namespace = function() { - this.prefixes = []; - this.bindings = {}; - }; - - - Namespace.prototype.addPrefix = function(prefixValue) { - this.prefixes.push(prefixValue); - }; - - - Namespace.prototype.getVariableValue = function(name) { - // FIXME: fill me in. - // first, look in bindings. - // if not there, then look into each of the prefixes. - }; - - - Namespace.prototype.setVariableValue = function(name, value) { - // FIXME: fill me in. - this.bindings[name] = value; - }; - - - - - ////////////////////////////////////////////////////////////////////// - - - var VariableReference = function(prefix, pos) { - this.prefix = prefix; - this.pos = pos; - }; - - VariableReference.prototype.ref = function() { - return this.prefix.ref(this.pos); - }; - - VariableReference.prototype.set = function(v) { - this.prefix.set(this.pos, v); - } - ////////////////////////////////////////////////////////////////////// // Continuation Marks @@ -2064,7 +1901,6 @@ String.prototype.toDisplayedString = function(cache) { types.isNumber = isNumber; types.isReal = jsnums.isReal; - types.isBoolean = isBoolean; types.isRational = jsnums.isRational; types.isComplex = isNumber; types.isInteger = jsnums.isInteger; @@ -2126,12 +1962,6 @@ String.prototype.toDisplayedString = function(cache) { types.isContinuationPromptTag = function(x) { return x instanceof ContinuationPromptTag; }; - types.PrefixValue = PrefixValue; - types.GlobalBucket = GlobalBucket; - types.NamedSlot = NamedSlot; - types.ModuleVariableRecord = ModuleVariableRecord; - types.VariableReference = VariableReference; - types.Box = Box; types.Placeholder = Placeholder; types.ThreadCell = ThreadCell;