integrating the immutable hashes
This commit is contained in:
parent
93d7991960
commit
923d418840
|
@ -93,10 +93,13 @@
|
||||||
'make-hash
|
'make-hash
|
||||||
'make-hasheqv
|
'make-hasheqv
|
||||||
'make-hasheq
|
'make-hasheq
|
||||||
|
'make-immutable-hash
|
||||||
|
'make-immutable-hasheqv
|
||||||
|
'make-immutable-hasheq
|
||||||
'hash-ref
|
'hash-ref
|
||||||
'hash-set!
|
'hash-set!
|
||||||
|
'hash-set
|
||||||
'equal-hash-code
|
'equal-hash-code
|
||||||
|
|
||||||
))
|
))
|
||||||
(define-predicate KernelPrimitiveName? KernelPrimitiveName)
|
(define-predicate KernelPrimitiveName? KernelPrimitiveName)
|
||||||
|
|
||||||
|
|
|
@ -258,6 +258,23 @@
|
||||||
var checkHash = makeCheckArgumentType(
|
var checkHash = makeCheckArgumentType(
|
||||||
baselib.hashes.isHash,
|
baselib.hashes.isHash,
|
||||||
'hash');
|
'hash');
|
||||||
|
var checkHasheq = makeCheckArgumentType(
|
||||||
|
baselib.hashes.isHasheq,
|
||||||
|
'hash');
|
||||||
|
var checkHasheqv = makeCheckArgumentType(
|
||||||
|
baselib.hashes.isHasheqv,
|
||||||
|
'hash');
|
||||||
|
var checkMutableHash = makeCheckArgumentType(
|
||||||
|
function(x) { return baselib.hashes.isHash(x) && ! x.isImmutable()},
|
||||||
|
'mutable hash');
|
||||||
|
var checkImmutableHash = makeCheckArgumentType(
|
||||||
|
function(x) { return baselib.hashes.isHash(x) && x.isImmutable()},
|
||||||
|
'immutable hash');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -298,5 +315,7 @@
|
||||||
exports.checkContinuationPromptTag = checkContinuationPromptTag;
|
exports.checkContinuationPromptTag = checkContinuationPromptTag;
|
||||||
exports.checkExn = checkExn;
|
exports.checkExn = checkExn;
|
||||||
exports.checkHash = checkHash;
|
exports.checkHash = checkHash;
|
||||||
|
exports.checkImmutableHash = checkImmutableHash;
|
||||||
|
exports.checkMutableHash = checkMutableHash;
|
||||||
|
|
||||||
}(this.plt.baselib));
|
}(this.plt.baselib));
|
||||||
|
|
|
@ -66,7 +66,6 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var makeEqHashtable = function() {
|
var makeEqHashtable = function() {
|
||||||
return new WhalesongHashtable(
|
return new WhalesongHashtable(
|
||||||
"hasheq",
|
"hasheq",
|
||||||
|
@ -88,8 +87,21 @@
|
||||||
return new WhalesongHashtable(
|
return new WhalesongHashtable(
|
||||||
"hasheqv",
|
"hasheqv",
|
||||||
getEqvHashCode,
|
getEqvHashCode,
|
||||||
baselib.equality.eqv,
|
eqv,
|
||||||
new Hashtable(getEqvHashCode, baselib.equality.eqv));
|
new Hashtable(getEqvHashCode, eqv));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var makeImmutableEqHashtable = function() {
|
||||||
|
return makeEqHashtable().toImmutable();
|
||||||
|
};
|
||||||
|
|
||||||
|
var makeImmutableEqualHashtable = function() {
|
||||||
|
return makeEqualHashtable().toImmutable();
|
||||||
|
};
|
||||||
|
|
||||||
|
var makeImmutableEqvHashtable = function() {
|
||||||
|
return makeEqvHashtable().toImmutable();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,9 +123,6 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Whalesong's Hashtables are a thin wrapper around the mutable Hashtable
|
// Whalesong's Hashtables are a thin wrapper around the mutable Hashtable
|
||||||
// class to make it printable and equatable.
|
// class to make it printable and equatable.
|
||||||
|
@ -187,10 +196,18 @@
|
||||||
this.hash.put(key, value);
|
this.hash.put(key, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WhalesongHashtable.prototype.functionalPut = function(key, value) {
|
||||||
|
return this.toImmutable().functionalPut(key, value);
|
||||||
|
};
|
||||||
|
|
||||||
WhalesongHashtable.prototype.remove = function(key) {
|
WhalesongHashtable.prototype.remove = function(key) {
|
||||||
this.hash.remove(key);
|
this.hash.remove(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WhalesongHashtable.prototype.functionalRemove = function(key) {
|
||||||
|
return this.toImmutable().functionalRemove(key);
|
||||||
|
};
|
||||||
|
|
||||||
WhalesongHashtable.prototype.containsKey = function(key) {
|
WhalesongHashtable.prototype.containsKey = function(key) {
|
||||||
return this.hash.containsKey(key);
|
return this.hash.containsKey(key);
|
||||||
};
|
};
|
||||||
|
@ -199,6 +216,20 @@
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WhalesongHashtable.prototype.toImmutable = function() {
|
||||||
|
var keycmp = makeComparator(this.hash_function, this.equality_function)
|
||||||
|
var immutable = new WhalesongImmutableHashtable(
|
||||||
|
this.type,
|
||||||
|
this.hash_function,
|
||||||
|
this.equality_function,
|
||||||
|
LLRBTree.makeMap(keycmp));
|
||||||
|
var keys = this.hash.keys();
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
immutable = immutable.functionalPut(keys[i], this.hash.get(keys[i]));
|
||||||
|
}
|
||||||
|
return immutable;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -206,12 +237,14 @@
|
||||||
// Whalesong's immutable hashtables are a thin wrapper around the
|
// Whalesong's immutable hashtables are a thin wrapper around the
|
||||||
// llrbtree class to make it printable and equatable.
|
// llrbtree class to make it printable and equatable.
|
||||||
// llrbtree comes from: https://github.com/dyoo/js-llrbtree
|
// llrbtree comes from: https://github.com/dyoo/js-llrbtree
|
||||||
var WhalesongImmutableHashtable = function (type, hash_function, equality_function) {
|
var WhalesongImmutableHashtable = function (type,
|
||||||
|
hash_function,
|
||||||
|
equality_function,
|
||||||
|
map) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.hash_function = hash_function;
|
this.hash_function = hash_function;
|
||||||
this.equality_function = equality_function;
|
this.equality_function = equality_function;
|
||||||
this.keycmp = makeComparator(hash_function, equality_function);
|
this.map = map;
|
||||||
this.map = LLRBTree.makeMap(keycmp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
WhalesongImmutableHashtable.prototype.toWrittenString = function (cache) {
|
WhalesongImmutableHashtable.prototype.toWrittenString = function (cache) {
|
||||||
|
@ -249,7 +282,6 @@
|
||||||
if (litems.length !== ritems.length) {
|
if (litems.length !== ritems.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < litems.length; i++) {
|
for (i = 0; i < litems.length; i++) {
|
||||||
if (!(baselib.equality.equals(litems[i][0], ritems[i][0], aUnionFind))) {
|
if (!(baselib.equality.equals(litems[i][0], ritems[i][0], aUnionFind))) {
|
||||||
|
@ -284,6 +316,10 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
WhalesongImmutableHashtable.prototype.functionalPut = function(key, value) {
|
WhalesongImmutableHashtable.prototype.functionalPut = function(key, value) {
|
||||||
|
return new WhalesongImmutableHashtable(this.type,
|
||||||
|
this.hash_function,
|
||||||
|
this.equality_function,
|
||||||
|
this.map.put(key, value));
|
||||||
};
|
};
|
||||||
|
|
||||||
WhalesongImmutableHashtable.prototype.remove = function(key) {
|
WhalesongImmutableHashtable.prototype.remove = function(key) {
|
||||||
|
@ -291,7 +327,10 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
WhalesongImmutableHashtable.prototype.functionalRemove = function(key) {
|
WhalesongImmutableHashtable.prototype.functionalRemove = function(key) {
|
||||||
// this.hash.remove(key);
|
return new WhalesongImmutableHashtable(this.type,
|
||||||
|
this.hash_function,
|
||||||
|
this.equality_function,
|
||||||
|
this.map.remove(key));
|
||||||
};
|
};
|
||||||
|
|
||||||
WhalesongImmutableHashtable.prototype.containsKey = function(key) {
|
WhalesongImmutableHashtable.prototype.containsKey = function(key) {
|
||||||
|
@ -305,12 +344,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var isHash = function (x) {
|
var isHash = function (x) {
|
||||||
return (x instanceof WhalesongHashtable || x instanceof WhalesongImmutableHashtable);
|
return (x instanceof WhalesongHashtable || x instanceof WhalesongImmutableHashtable);
|
||||||
};
|
};
|
||||||
|
@ -325,8 +358,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Arbitrary magic number. We have to cut off the hashing at some point.
|
// Arbitrary magic number. We have to cut off the hashing at some point.
|
||||||
var MAX_HASH_DEPTH = 128;
|
var MAX_HASH_DEPTH = 128;
|
||||||
|
|
||||||
|
@ -377,6 +408,8 @@
|
||||||
|
|
||||||
exports.getEqHashCode = getEqHashCode;
|
exports.getEqHashCode = getEqHashCode;
|
||||||
exports.getEqualHashCode = getEqualHashCode;
|
exports.getEqualHashCode = getEqualHashCode;
|
||||||
|
exports.getEqvHashCode = getEqvHashCode;
|
||||||
|
|
||||||
exports.hashMix = hashMix;
|
exports.hashMix = hashMix;
|
||||||
|
|
||||||
exports.makeEqHashCode = makeEqHashCode;
|
exports.makeEqHashCode = makeEqHashCode;
|
||||||
|
@ -386,9 +419,11 @@
|
||||||
exports.makeEqvHashtable = makeEqvHashtable;
|
exports.makeEqvHashtable = makeEqvHashtable;
|
||||||
exports.makeEqualHashtable = makeEqualHashtable;
|
exports.makeEqualHashtable = makeEqualHashtable;
|
||||||
|
|
||||||
|
exports.makeImmutableEqHashtable = makeImmutableEqHashtable;
|
||||||
|
exports.makeImmutableEqvHashtable = makeImmutableEqvHashtable;
|
||||||
|
exports.makeImmutableEqualHashtable = makeImmutableEqualHashtable;
|
||||||
|
|
||||||
exports.isHash = isHash;
|
exports.isHash = isHash;
|
||||||
exports.isHashEqv = isHashEqv;
|
exports.isHashEqv = isHashEqv;
|
||||||
exports.isHashEq = isHashEq;
|
exports.isHashEq = isHashEq;
|
||||||
|
|
||||||
|
|
||||||
}(window.plt.baselib, Hashtable));
|
}(window.plt.baselib, Hashtable));
|
|
@ -15,6 +15,7 @@
|
||||||
// show up outside this section!
|
// show up outside this section!
|
||||||
var isNumber = baselib.numbers.isNumber;
|
var isNumber = baselib.numbers.isNumber;
|
||||||
|
|
||||||
|
var isProcedure = baselib.functions.isProcedure;
|
||||||
var isReal = baselib.numbers.isReal;
|
var isReal = baselib.numbers.isReal;
|
||||||
var isInexact = baselib.numbers.isInexact;
|
var isInexact = baselib.numbers.isInexact;
|
||||||
var isComplex = baselib.numbers.isComplex;
|
var isComplex = baselib.numbers.isComplex;
|
||||||
|
@ -118,6 +119,8 @@
|
||||||
var checkContinuationMarkSet = baselib.check.checkContinuationMarkSet;
|
var checkContinuationMarkSet = baselib.check.checkContinuationMarkSet;
|
||||||
var checkExn = baselib.check.checkExn;
|
var checkExn = baselib.check.checkExn;
|
||||||
var checkHash = baselib.check.checkHash;
|
var checkHash = baselib.check.checkHash;
|
||||||
|
var checkMutableHash = baselib.check.checkMutableHash;
|
||||||
|
var checkImmutableHash = baselib.check.checkImmutableHash;
|
||||||
var checkAny = baselib.check.makeCheckArgumentType(
|
var checkAny = baselib.check.makeCheckArgumentType(
|
||||||
function(x) { return true; },
|
function(x) { return true; },
|
||||||
'any');
|
'any');
|
||||||
|
@ -127,12 +130,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Primitives are the set of primitive values. Not all primitives
|
// Primitives are the set of primitive values. Not all primitives
|
||||||
// are coded here; several of them (including call/cc) are injected by
|
// are coded here; several of them (including call/cc) are injected by
|
||||||
// the bootstrapping code in compiler/boostrapped-primitives.rkt
|
// the bootstrapping code in compiler/boostrapped-primitives.rkt
|
||||||
|
@ -1385,7 +1382,7 @@
|
||||||
'procedure?',
|
'procedure?',
|
||||||
1,
|
1,
|
||||||
function (M) {
|
function (M) {
|
||||||
return baselib.functions.isProcedure(M.e[M.e.length - 1]);
|
return isProcedure(M.e[M.e.length - 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
installPrimitiveProcedure(
|
installPrimitiveProcedure(
|
||||||
|
@ -2504,6 +2501,15 @@
|
||||||
return hash;
|
return hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var initializeImmutableHash = function(lst, hash) {
|
||||||
|
while (lst !== NULL) {
|
||||||
|
hash = hash.functionalPut(lst.first.first, lst.first.rest);
|
||||||
|
lst = lst.rest;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
installPrimitiveProcedure(
|
installPrimitiveProcedure(
|
||||||
'hash?',
|
'hash?',
|
||||||
1,
|
1,
|
||||||
|
@ -2544,15 +2550,48 @@
|
||||||
return initializeHash(lst, plt.baselib.hashes.makeEqualHashtable());
|
return initializeHash(lst, plt.baselib.hashes.makeEqualHashtable());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
installPrimitiveProcedure(
|
||||||
|
'make-immutable-hasheq',
|
||||||
|
makeList(0, 1),
|
||||||
|
function(M) {
|
||||||
|
var lst = NULL;
|
||||||
|
if (M.a === 1) {
|
||||||
|
lst = checkListofPairs(M, 'make-hasheq', 0);
|
||||||
|
}
|
||||||
|
return initializeImmutableHash(lst, plt.baselib.hashes.makeImmutableEqHashtable());
|
||||||
|
});
|
||||||
|
|
||||||
|
installPrimitiveProcedure(
|
||||||
|
'make-immutable-hasheqv',
|
||||||
|
makeList(0, 1),
|
||||||
|
function(M) {
|
||||||
|
var lst = NULL;
|
||||||
|
if (M.a === 1) {
|
||||||
|
lst = checkListofPairs(M, 'make-hasheqv', 0);
|
||||||
|
}
|
||||||
|
return initializeImmutableHash(lst, plt.baselib.hashes.makeImmutableEqvHashtable());
|
||||||
|
});
|
||||||
|
|
||||||
|
installPrimitiveProcedure(
|
||||||
|
'make-immutable-hash',
|
||||||
|
makeList(0, 1),
|
||||||
|
function(M) {
|
||||||
|
var lst = NULL;
|
||||||
|
if (M.a === 1) {
|
||||||
|
lst = checkListofPairs(M, 'make-hash', 0);
|
||||||
|
}
|
||||||
|
return initializeImmutableHash(lst, plt.baselib.hashes.makeImmutableEqualHashtable());
|
||||||
|
});
|
||||||
|
|
||||||
installPrimitiveClosure(
|
installPrimitiveClosure(
|
||||||
'hash-ref',
|
'hash-ref',
|
||||||
makeList(2, 3),
|
makeList(2, 3),
|
||||||
function(M) {
|
function(M) {
|
||||||
var hash = checkHash(M, 'hash-ref', 0);
|
var hash = checkHash(M, 'hash-ref', 0);
|
||||||
var key = checkAny(M, 'hash-ref', 1);
|
var key = checkAny(M, 'hash-ref', 1);
|
||||||
var thunk;
|
var thunkOrFailVal;
|
||||||
if (M.a === 3) {
|
if (M.a === 3) {
|
||||||
thunk = checkProcedure(M, 'hash-ref', 2);
|
thunkOrFailVal = checkAny(M, 'hash-ref', 2);
|
||||||
}
|
}
|
||||||
if (hash.containsKey(key)) {
|
if (hash.containsKey(key)) {
|
||||||
finalizeClosureCall(M, hash.get(key));
|
finalizeClosureCall(M, hash.get(key));
|
||||||
|
@ -2562,11 +2601,15 @@
|
||||||
M,
|
M,
|
||||||
baselib.format.format("hash-ref: no value found for key: ~e",
|
baselib.format.format("hash-ref: no value found for key: ~e",
|
||||||
[key]));
|
[key]));
|
||||||
} else {
|
} else {
|
||||||
M.p = thunk;
|
if (isProcedure(thunkOrFailVal)) {
|
||||||
M.e.length -= M.a;
|
M.p = thunkOrFailVal;
|
||||||
M.a = 0;
|
M.e.length -= M.a;
|
||||||
baselib.functions.rawApply(M);
|
M.a = 0;
|
||||||
|
baselib.functions.rawApply(M);
|
||||||
|
} else {
|
||||||
|
finalizeClosureCall(M, thunkOrFailVal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2575,13 +2618,23 @@
|
||||||
'hash-set!',
|
'hash-set!',
|
||||||
3,
|
3,
|
||||||
function(M){
|
function(M){
|
||||||
var hash = checkHash(M, 'hash-set!', 0);
|
var hash = checkMutableHash(M, 'hash-set!', 0);
|
||||||
var key = checkAny(M, 'hash-set!', 1);
|
var key = checkAny(M, 'hash-set!', 1);
|
||||||
var value = checkAny(M, 'hash-set!', 2);
|
var value = checkAny(M, 'hash-set!', 2);
|
||||||
hash.put(key, value);
|
hash.put(key, value);
|
||||||
return VOID;
|
return VOID;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
installPrimitiveProcedure(
|
||||||
|
'hash-set',
|
||||||
|
3,
|
||||||
|
function(M){
|
||||||
|
var hash = checkImmutableHash(M, 'hash-set', 0);
|
||||||
|
var key = checkAny(M, 'hash-set', 1);
|
||||||
|
var value = checkAny(M, 'hash-set', 2);
|
||||||
|
return hash.functionalPut(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
installPrimitiveProcedure(
|
installPrimitiveProcedure(
|
||||||
'hash-has-key?',
|
'hash-has-key?',
|
||||||
2,
|
2,
|
||||||
|
|
|
@ -153,8 +153,12 @@
|
||||||
make-hash
|
make-hash
|
||||||
make-hasheqv
|
make-hasheqv
|
||||||
make-hasheq
|
make-hasheq
|
||||||
|
make-immutable-hash
|
||||||
|
make-immutable-hasheqv
|
||||||
|
make-immutable-hasheq
|
||||||
hash-ref
|
hash-ref
|
||||||
hash-set!
|
hash-set!
|
||||||
|
hash-set
|
||||||
equal-hash-code
|
equal-hash-code
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,3 +21,6 @@ not-found
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
danny
|
||||||
|
dyoo@hashcollision.org
|
||||||
|
unknown
|
||||||
|
|
|
@ -61,4 +61,12 @@
|
||||||
(hash-ref ht "test")
|
(hash-ref ht "test")
|
||||||
(hash-ref ht "that")
|
(hash-ref ht "that")
|
||||||
(hash-ref ht "only")
|
(hash-ref ht "only")
|
||||||
(hash-ref ht "test!")
|
(hash-ref ht "test!")
|
||||||
|
|
||||||
|
|
||||||
|
(let* ([ht (make-immutable-hash)]
|
||||||
|
[ht (hash-set ht 'name "danny")]
|
||||||
|
[ht (hash-set ht 'email "dyoo@hashcollision.org")])
|
||||||
|
(displayln (hash-ref ht 'name "unknown"))
|
||||||
|
(displayln (hash-ref ht 'email "unknown"))
|
||||||
|
(displayln (hash-ref ht 'phone "unknown")))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user