still trying to understand the struct implementation
This commit is contained in:
parent
72a002801b
commit
d6e0e79c79
|
@ -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
|
||||
|
|
|
@ -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']);
|
||||
|
|
|
@ -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; });
|
||||
|
|
277
js-assembler/runtime-src/baselib_structs.js
Normal file
277
js-assembler/runtime-src/baselib_structs.js
Normal file
|
@ -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 '#<struct-type:' + this.name + '>';
|
||||
};
|
||||
|
||||
|
||||
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);
|
|
@ -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);
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user