introducing getEqualHashCode
This commit is contained in:
parent
fd28c199e9
commit
07b44b2239
|
@ -93,7 +93,8 @@
|
||||||
'make-hash
|
'make-hash
|
||||||
'make-hasheqv
|
'make-hasheqv
|
||||||
'make-hasheq
|
'make-hasheq
|
||||||
|
'hash-ref
|
||||||
|
'hash-set!
|
||||||
))
|
))
|
||||||
(define-predicate KernelPrimitiveName? KernelPrimitiveName)
|
(define-predicate KernelPrimitiveName? KernelPrimitiveName)
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,15 @@
|
||||||
return ((other instanceof Box) &&
|
return ((other instanceof Box) &&
|
||||||
baselib.equality.equals(this.val, other.val, aUnionFind));
|
baselib.equality.equals(this.val, other.val, aUnionFind));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Box.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("Box");
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.val, depth);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var makeBox = function(x) {
|
var makeBox = function(x) {
|
||||||
return new Box(x, true);
|
return new Box(x, true);
|
||||||
|
|
|
@ -60,6 +60,16 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Bytes.prototype.hashCode = function(depth) {
|
||||||
|
var i;
|
||||||
|
var k = baselib.hashes.getEqualHashCode('Bytes');
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
k += this.bytes[i];
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Bytes.prototype.toString = function(cache) {
|
Bytes.prototype.toString = function(cache) {
|
||||||
var ret = [], i;
|
var ret = [], i;
|
||||||
|
|
|
@ -67,7 +67,12 @@
|
||||||
return other instanceof Char && this.val == other.val;
|
return other instanceof Char && this.val == other.val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Char.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode('Char');
|
||||||
|
k += this.val.charCodeAt(0);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
exports.Char = Char;
|
exports.Char = Char;
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
return new WhalesongHashtable(
|
return new WhalesongHashtable(
|
||||||
"hash",
|
"hash",
|
||||||
function (x) {
|
function (x) {
|
||||||
return baselib.format.toWrittenString(x);
|
return getEqualHashCode(x);
|
||||||
},
|
},
|
||||||
function (x, y) {
|
function (x, y) {
|
||||||
return baselib.equality.equals(x, y, new baselib.UnionFind());
|
return baselib.equality.equals(x, y, new baselib.UnionFind());
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
return new WhalesongHashtable(
|
return new WhalesongHashtable(
|
||||||
"hasheqv",
|
"hasheqv",
|
||||||
function (x) {
|
function (x) {
|
||||||
return baselib.format.toWrittenString(x);
|
return getEqHashCode(x);
|
||||||
},
|
},
|
||||||
baselib.equality.eqv);
|
baselib.equality.eqv);
|
||||||
};
|
};
|
||||||
|
@ -134,7 +134,14 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WhalesongHashtable.prototype.hashCode = function(depth) {
|
||||||
|
var k = getEqualHashCode(this.type);
|
||||||
|
var keys = this.hash.keys(), i;
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
k += hashMix(getEqualHashCode(this.hash.get(keys[i]), depth));
|
||||||
|
}
|
||||||
|
return hashMix(k);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,9 +166,63 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Arbitrary magic number. We have to cut off the hashing at some point.
|
||||||
|
var MAX_HASH_DEPTH = 128;
|
||||||
|
|
||||||
|
// Returns a JavaScript number.
|
||||||
|
var getEqualHashCode = function (x, depth) {
|
||||||
|
var i, t, k = 0;
|
||||||
|
if (depth === undefined) { depth = 0; }
|
||||||
|
|
||||||
|
if (depth > MAX_HASH_DEPTH) { return 0; }
|
||||||
|
|
||||||
|
if (baselib.numbers.isNumber(x)) {
|
||||||
|
return hashMix(baselib.numbers.toFixnum(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baselib.strings.isString(x)) {
|
||||||
|
t = x.toString();
|
||||||
|
for (i = 0; i < t.length; i++) {
|
||||||
|
k += t.charCodeAt(i);
|
||||||
|
k = hashMix(k);
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x === undefined || x === null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof (x) === 'object' && typeof (y) === 'object' &&
|
||||||
|
typeof(x.hashCode) === 'function') {
|
||||||
|
return x.hashCode(depth + 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Does some weird math on k. Grabbed from Racket's implementation of hashes.
|
||||||
|
// References to: http://www.burtleburtle.net/bob/hash/doobs.html
|
||||||
|
var hashMix = function(k) {
|
||||||
|
k += (k << 10);
|
||||||
|
k ^= (k >> 6);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
exports.getEqHashCode = getEqHashCode;
|
exports.getEqHashCode = getEqHashCode;
|
||||||
|
exports.getEqualHashCode = getEqualHashCode;
|
||||||
|
exports.hashMix = hashMix;
|
||||||
|
|
||||||
exports.makeEqHashCode = makeEqHashCode;
|
exports.makeEqHashCode = makeEqHashCode;
|
||||||
exports.makeLowLevelEqHash = makeLowLevelEqHash;
|
exports.makeLowLevelEqHash = makeLowLevelEqHash;
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,13 @@
|
||||||
return other instanceof Keyword &&
|
return other instanceof Keyword &&
|
||||||
this.val === other.val;
|
this.val === other.val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Keyword.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("Keyword");
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.val, depth);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Keyword.prototype.toString = function (cache) {
|
Keyword.prototype.toString = function (cache) {
|
||||||
|
|
|
@ -20,6 +20,11 @@
|
||||||
return other instanceof Empty;
|
return other instanceof Empty;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Empty.prototype.hashCode = function(depth) {
|
||||||
|
return baselib.hashes.getEqualHashCode("empty");
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Empty.prototype.reverse = function () {
|
Empty.prototype.reverse = function () {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
@ -85,6 +90,16 @@
|
||||||
baselib.equality.equals(this.rest, other.rest, aUnionFind));
|
baselib.equality.equals(this.rest, other.rest, aUnionFind));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Cons.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("Cons");
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.first);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.rest);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Cons.append: (listof X) -> (listof X)
|
// Cons.append: (listof X) -> (listof X)
|
||||||
Cons.prototype.append = function (b) {
|
Cons.prototype.append = function (b) {
|
||||||
|
|
|
@ -16,6 +16,20 @@
|
||||||
return "#<path:" + String(this.path) + ">";
|
return "#<path:" + String(this.path) + ">";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Path.prototype.equals = function(other, aUnionFind) {
|
||||||
|
return (other instanceof Path &&
|
||||||
|
this.path === other.path);
|
||||||
|
};
|
||||||
|
|
||||||
|
Path.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("path");
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.path, depth);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var makePath = function (p) {
|
var makePath = function (p) {
|
||||||
|
|
|
@ -43,6 +43,12 @@
|
||||||
baselib.equality.equals(this.val, other.val, aUnionFind));
|
baselib.equality.equals(this.val, other.val, aUnionFind));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Placeholder.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.hashCode("Placeholder");
|
||||||
|
k += baselib.hashes.hashCode(this.val, depth);
|
||||||
|
return baselib.hashes.hashMix(k);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var makePlaceholder = function(v) {
|
var makePlaceholder = function(v) {
|
||||||
return new Placeholder(v);
|
return new Placeholder(v);
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
|
|
||||||
// Exceptions and error handling.
|
// Exceptions and error handling.
|
||||||
var raise = baselib.exceptions.raise;
|
var raise = baselib.exceptions.raise;
|
||||||
|
var raiseContractError = baselib.exceptions.raiseContractError;
|
||||||
var raiseArgumentTypeError = baselib.exceptions.raiseArgumentTypeError;
|
var raiseArgumentTypeError = baselib.exceptions.raiseArgumentTypeError;
|
||||||
var raiseArityMismatchError = baselib.exceptions.raiseArityMismatchError;
|
var raiseArityMismatchError = baselib.exceptions.raiseArityMismatchError;
|
||||||
|
|
||||||
|
@ -2558,13 +2559,14 @@
|
||||||
} else {
|
} else {
|
||||||
if (M.a === 2) {
|
if (M.a === 2) {
|
||||||
raiseContractError(
|
raiseContractError(
|
||||||
plt.baselib.format("hash-ref: no value found for key: ~e",
|
M,
|
||||||
|
baselib.format.format("hash-ref: no value found for key: ~e",
|
||||||
[key]));
|
[key]));
|
||||||
} else {
|
} else {
|
||||||
M.p = thunk;
|
M.p = thunk;
|
||||||
M.e.length -= M.a;
|
M.e.length -= M.a;
|
||||||
M.a = 0;
|
M.a = 0;
|
||||||
baselib.functions.rawApply();
|
baselib.functions.rawApply(M);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -107,6 +107,10 @@
|
||||||
return this.toString() === other.toString();
|
return this.toString() === other.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Str.prototype.hashCode = function(depth) {
|
||||||
|
return baselib.hashes.getEqualHashCode(this.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Str.prototype.set = function (i, c) {
|
Str.prototype.set = function (i, c) {
|
||||||
this.chars[i] = c;
|
this.chars[i] = c;
|
||||||
|
|
|
@ -60,6 +60,18 @@
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode(this.name);
|
||||||
|
var i;
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
for (i = 0; i < this._fields.length; i++) {
|
||||||
|
k += baselib.hashes.getEqualHashCode(this._fields[i]);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Struct.prototype.type = Struct;
|
Struct.prototype.type = Struct;
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +113,13 @@
|
||||||
return this === other;
|
return this === other;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StructType.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("StructType");
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.name);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,14 @@
|
||||||
return other instanceof Symbol &&
|
return other instanceof Symbol &&
|
||||||
this.val === other.val;
|
this.val === other.val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Symbol.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("Symbol");
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.val);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Symbol.prototype.toString = function (cache) {
|
Symbol.prototype.toString = function (cache) {
|
||||||
|
|
|
@ -56,6 +56,17 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Vector.prototype.hashCode = function(depth) {
|
||||||
|
var k = baselib.hashes.getEqualHashCode("Vector");
|
||||||
|
var i;
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
for (i = 0; i < this.elts.length; i++) {
|
||||||
|
k += baselib.hashes.getEqualHashCode(this.elts[i], depth);
|
||||||
|
k = baselib.hashes.hashMix(k);
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
};
|
||||||
|
|
||||||
Vector.prototype.toList = function () {
|
Vector.prototype.toList = function () {
|
||||||
var ret = baselib.lists.EMPTY, i;
|
var ret = baselib.lists.EMPTY, i;
|
||||||
for (i = this.length() - 1; i >= 0; i--) {
|
for (i = this.length() - 1; i >= 0; i--) {
|
||||||
|
|
|
@ -153,7 +153,8 @@
|
||||||
make-hash
|
make-hash
|
||||||
make-hasheqv
|
make-hasheqv
|
||||||
make-hasheq
|
make-hasheq
|
||||||
|
hash-ref
|
||||||
|
hash-set!
|
||||||
|
|
||||||
|
|
||||||
;; Kernel inlinable
|
;; Kernel inlinable
|
||||||
|
|
14
tests/more-tests/hash-code.rkt
Normal file
14
tests/more-tests/hash-code.rkt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#lang planet dyoo/whalesong/base
|
||||||
|
|
||||||
|
;; boxes
|
||||||
|
;; bytes
|
||||||
|
;; chars
|
||||||
|
;; hashes
|
||||||
|
;; keywords
|
||||||
|
;; lists
|
||||||
|
;; paths
|
||||||
|
;; placeholders
|
||||||
|
;; strings
|
||||||
|
;; structs
|
||||||
|
;; symbols
|
||||||
|
;; vectors
|
|
@ -33,4 +33,32 @@
|
||||||
(make-hasheq '((1 . one)
|
(make-hasheq '((1 . one)
|
||||||
(2 . two)
|
(2 . two)
|
||||||
(3 . three)
|
(3 . three)
|
||||||
(4 . four)))
|
(4 . four)))
|
||||||
|
|
||||||
|
(hash-ref (make-hash '((1 . one)
|
||||||
|
(2 . two)
|
||||||
|
(3 . three)))
|
||||||
|
1)
|
||||||
|
|
||||||
|
(hash-ref (make-hash '((1 . one)
|
||||||
|
(2 . two)
|
||||||
|
(3 . three)))
|
||||||
|
4
|
||||||
|
(lambda () 'not-found))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(define words '("this" "is" "a" "test" "that" "is" "only" "a" "test!"))
|
||||||
|
(define ht (make-hash))
|
||||||
|
(for-each (lambda (w)
|
||||||
|
(hash-set! ht
|
||||||
|
w
|
||||||
|
(add1 (hash-ref ht w (lambda () 0)))))
|
||||||
|
words)
|
||||||
|
(hash-ref ht "this")
|
||||||
|
(hash-ref ht "is")
|
||||||
|
(hash-ref ht "a")
|
||||||
|
(hash-ref ht "test")
|
||||||
|
(hash-ref ht "that")
|
||||||
|
(hash-ref ht "only")
|
||||||
|
(hash-ref ht "test!")
|
Loading…
Reference in New Issue
Block a user