shithub: mc

Download patch

ref: 83d26331a5419033927800760e8a59f1bd84d2b9
parent: 8a662861ad3ded8e965ab43e5bc254dd7ee85815
author: Lucas Gabriel Vuotto <[email protected]>
date: Wed Nov 1 12:53:26 EDT 2017

Use new traits to implement hash tables

Signed-off-by: Lucas Gabriel Vuotto <[email protected]>

--- a/bench/hashit.myr
+++ b/bench/hashit.myr
@@ -5,21 +5,21 @@
 	testr.bench([
 		[.name="hashstr", .fn={ctx;
 			for var i = 0; i < 1000; i++
-				std.strhash("foobar")
+				std.hash("foobar")
 			;;
 		}],
 		[.name="hashint", .fn={ctx
 			for var i = 0; i < 1000; i++
-				std.inthash(123)
+				std.hash(123)
 			;;
 		}],
 		[.name="hashlongstr", .fn={ctx
 			for var i = 0; i < 1000; i++
-				std.strhash(a)
+				std.hash(a)
 			;;
 		}],
 		[.name="htget", .fn={ctx
-			var h = std.mkht(std.strhash, std.streq)
+			var h = std.mkht()
 			std.htput(h, "foo", 123)
 			for var i = 0; i < 1000; i++
 				std.htget(h, "foo")
@@ -27,7 +27,7 @@
 			std.htfree(h)
 		}],
 		[.name="htput", .fn={ctx
-			var h = std.mkht(std.strhash, std.streq)
+			var h = std.mkht()
 			for var i = 0; i < 1000; i++
 				std.htput(h, "foo", 123)
 			;;
@@ -34,7 +34,7 @@
 			std.htfree(h)
 		}],
 		[.name="htputmany", .fn={ctx
-			var h = std.mkht(std.inthash, std.inteq)
+			var h = std.mkht()
 			for var i = 0; i < 1000; i++
 				std.htput(h, i, 123)
 			;;
--- a/lib/date/parse.myr
+++ b/lib/date/parse.myr
@@ -164,7 +164,7 @@
 
 const indexof = {dst, s, set, err
 	for var i = 0; i < set.len; i++
-		if s.len >= set[i].len && std.streq(s[:set[i].len], set[i])
+		if s.len >= set[i].len && std.cmp(s[:set[i].len], set[i])
 			dst# = i
 			-> s[set[i].len:]
 		;;
--- a/lib/fileutil/loopcheck+posixy.myr
+++ b/lib/fileutil/loopcheck+posixy.myr
@@ -14,7 +14,7 @@
 	var ht : std.htab((int64, int64), void)#
 	var l
 
-	ht = std.mkht(fidhash, fideq)
+	ht = std.mkht()
 	l = (ht : loopcheck)
 	looped(l, cwd)
 	-> l
@@ -48,18 +48,22 @@
 	;;
 }
 
-const fidhash = {fid
-	var dev, ino
+impl std.hashable (int64, int64) =
+	hash = {fid
+		var dev, ino
 
-	(dev, ino) = fid
-	-> std.inthash(dev) ^ std.inthash(ino)
-}
+		(dev, ino) = fid
+		-> std.hash(dev) ^ std.hash(ino)
+	}
+;;
 
-const fideq = {a, b
-	var adev, aino
-	var bdev, bino
+impl std.comparable (int64, int64) =
+	cmp = {a, b
+		var adev, aino
+		var bdev, bino
 
-	(adev, aino) = a
-	(bdev, bino) = b
-	-> adev == bdev && aino == bino
-}
+		(adev, aino) = a
+		(bdev, bino) = b
+		-> adev == bdev && aino == bino
+	}
+;;
--- a/lib/http/parse.myr
+++ b/lib/http/parse.myr
@@ -10,6 +10,19 @@
 	pkglocal const parsenumber	: (str : byte[:]#, base : int -> std.option(int))
 ;;
 
+const strcaseeq = {a : byte[:], b : byte[:] -> bool
+	var ca, cb
+
+	while a.len == 0 || b.len == 0
+		(ca, a) = std.strstep(a)
+		(cb, b) = std.strstep(b)
+		if std.tolower(ca) != std.tolower(cb)
+			-> false
+		;;
+	;;
+	-> a.len == b.len
+}
+
 const parsereq = {s
 	var r, err
 
@@ -221,7 +234,7 @@
 
 const findhdr = {r, name
 	for (k, v) : r.hdrs
-		if std.strcaseeq(k, name)
+		if strcaseeq(k, name)
 			-> `std.Some v
 		;;
 	;;
--- a/lib/inifile/parse.myr
+++ b/lib/inifile/parse.myr
@@ -44,7 +44,7 @@
 	var f
 
 	ini = std.mk([
-		.elts = std.mkht(keyhash, keyeq)
+		.elts = std.mkht()
 	])
 	p = std.mk([
 		.line = 1,
@@ -138,20 +138,3 @@
 		-> true
 	;;
 }
-
-const keyhash = {k
-	var sect, key
-
-	(sect, key) = k
-	-> std.strhash(sect) ^ std.strhash(key)
-}
-
-const keyeq = {a, b
-	var s1, k1
-	var s2, k2
-
-	(s1, k1) = a
-	(s2, k2) = a
-	-> std.streq(s1, s2) && std.streq(k1, k2)
-}
-
--- a/lib/inifile/types.myr
+++ b/lib/inifile/types.myr
@@ -11,4 +11,27 @@
 		sects	: byte[:][:]
 		elts	: std.htab((byte[:], byte[:]), byte[:])#
 	;;
+
+	impl std.hashable (byte[:], byte[:])
+	impl std.comparable (byte[:], byte[:])
+;;
+
+impl std.hashable (byte[:], byte[:]) =
+	hash = {k
+		var sect, key
+
+		(sect, key) = k
+		-> std.hash(sect) ^ std.hash(key)
+	}
+;;
+
+impl std.comparable (byte[:], byte[:]) =
+	cmp = {a, b
+		var s1, k1
+		var s2, k2
+
+		(s1, k1) = a
+		(s2, k2) = a
+		-> std.cmp(s1, s2) && std.cmp(k1, k2)
+	}
 ;;
--- a/lib/regex/compile.myr
+++ b/lib/regex/compile.myr
@@ -46,7 +46,7 @@
 		.nmatch = 1,
 		.debug = true,
 		.trace = trace,
-		.astloc = std.mkht(std.ptrhash, std.ptreq),
+		.astloc = std.mkht(),
 	])
 	res = regexcompile(re, 0)
 	-> res
--- a/lib/std/bitset.myr
+++ b/lib/std/bitset.myr
@@ -1,12 +1,13 @@
 use "alloc"
 use "die"
 use "extremum"
+use "hashfuncs"
 use "mk"
 use "slcp"
 use "sldup"
 use "slfill"
+use "traits"
 use "types"
-use "hashfuncs"
 
 pkg std =
 	type bitset = struct
@@ -28,10 +29,11 @@
 	const bsdiff	: (a : bitset#, b : bitset# -> void)
 	const bsintersect	: (a : bitset#, b : bitset# -> void)
 	const bsunion	: (a : bitset#, b : bitset# -> void)
-	const bseq	: (a : bitset#, b : bitset# -> bool)
 	const bsissubset	: (a : bitset#, b : bitset# -> bool)
-	const bshash	: (a : bitset# -> uint64)
 
+	impl comparable bitset#
+	impl hashable bitset#
+
 	type bsiter = struct
 		idx	: size
 		bs	: bitset#
@@ -145,25 +147,29 @@
 	-> true
 }
 
-const bseq = {a, b
-	eqsz(a, b)
-	for var i = 0; i < a.bits.len; i++
-		if a.bits[i] != b.bits[i]
-			-> false
+impl comparable bitset# =
+	cmp = {a, b
+		eqsz(a, b)
+		for var i = 0; i < a.bits.len; i++
+			if a.bits[i] != b.bits[i]
+				-> false
+			;;
 		;;
-	;;
-	-> true
-}
+		-> true
+	}
+;;
 
-const bshash = {a
-	var end : size
+impl hashable bitset# =
+	hash = {a
+		var end : size
 
-	end = a.bits.len
-	while end > 0 && a.bits[end - 1] == 0
-		end--
-	;;
-	-> std.slhash(a.bits[:end])
-}
+		end = a.bits.len
+		while end > 0 && a.bits[end - 1] == 0
+			end--
+		;;
+		-> std.hash(a.bits[:end])
+	}
+;;
 
 const ensurelen = {bs, len
 	if bs.bits.len <= len
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -21,6 +21,7 @@
 use "strsplit"
 use "syswrap"
 use "syswrap-ss"
+use "traits"
 use "types"
 use "utf"
 use "varargs"
@@ -55,7 +56,7 @@
 ;;
 
 const __init__ = {
-	fmtmap = mkht(strhash, streq)
+	fmtmap = mkht()
 }
 
 type fmtdesc = struct
--- a/lib/std/hashfuncs.myr
+++ b/lib/std/hashfuncs.myr
@@ -9,23 +9,8 @@
 use "utf"
 
 pkg std =
-	const strhash	: (s : byte[:]	-> uint64)
-	const streq	: (a : byte[:], b : byte[:]	-> bool)
-
-	const strcasehash	: (s : byte[:]	-> uint64)
-	const strcaseeq	: (a : byte[:], b : byte[:]	-> bool)
-
-	generic ptrhash	: (p : @a#	-> uint64)
-	generic ptreq	: (a : @a#, b : @a#	-> bool)
-
-	generic inthash	: (v : @a::(integral,numeric)	-> uint64)
-	generic inteq	: (a : @a::(integral,numeric), b : @a::(integral,numeric) -> bool)
-
-	const murmurhash2	: (data : byte[:], seed : uint32 -> uint32)
 	const siphash24	: (data : byte[:], seed : byte[16] -> uint64)
 
-	generic slhash	: (sl : @a[:] -> uint64)
-
 	impl comparable @a[:] =
 		cmp = {a, b
 			-> sleq(a, b)
@@ -64,119 +49,6 @@
 ;;
 
 const Seed : byte[16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
-
-generic slhash = {data : @a[:]
-	-> strhash(slbytes(data))
-}
-
-generic slbytes = {data : @a[:]
-	var n
-
-	n = data.len * sizeof(@a)
-	-> (data : byte#)[:n]
-}
-
-const strhash = {s
-	-> siphash24(s, Seed)
-}
-
-const strcaseeq = {a, b
-	var ca, cb
-
-	while true
-		if a.len == 0 || b.len == 0
-			break
-		;;
-		(ca, a) = std.charstep(a)
-		(cb, b) = std.charstep(b)
-		if std.tolower(ca) != std.tolower(cb)
-			-> false
-		;;
-	;;
-	-> a.len == b.len
-}
-
-const strcasehash = {s
-	var chars
-	var c, h
-
-	chars = [][:]
-	while s.len != 0
-		(c, s) = std.charstep(s)
-		std.slpush(&chars, std.tolower(c))
-	;;
-	h = siphash24(slbytes(chars), Seed)
-	slfree(chars)
-	-> h
-}
-
-const streq = {a, b
-	-> sleq(a, b)
-}
-
-generic ptrhash = {p : @a#
-	-> inthash((p : intptr))
-}
-
-generic ptreq = {a, b
-	-> a == b
-}
-
-generic inthash = {v : @a::(integral,numeric)
-	var p
-
-	p = (&v : byte#)
-	-> siphash24(p[0:sizeof(@a)], Seed)
-}
-
-generic inteq = {a, b
-	-> a == b
-}
-
-const murmurhash2 = {data, seed
-	const m = 0x5bd1e995;
-	const r = 24
-	var h, k
-	
-	h = seed ^ data.len
-	while data.len >= 4
-		k = (data[0] : uint32)
-		k |= (data[1] : uint32) << 8
-		k |= (data[2] : uint32) << 16
-		k |= (data[3] : uint32) << 24
-
-		k *= m
-		k ^= k >> r
-		k *= m
-
-		h *= m
-		h ^= k
-		data = data[4:]
-	;;
-
-	match data.len
-	| 3:
-		h ^= (data[2] : uint32) << 16
-		h ^= (data[1] : uint32) << 8
-		h ^= (data[0] : uint32)
-		h *= m
-	| 2:
-		h ^= (data[1] : uint32) << 8
-		h ^= (data[0] : uint32)
-		h *= m
-	| 1:
-		h ^= (data[0] : uint32)
-		h *= m
-	| 0:	/* nothing */
-	| _:	die("0 < len < 4 must be true")
-	;;
-
-	h ^= h >> 13
-	h *= m
-	h ^= h >> 15
-
-	-> h
-}
 
 const sipround = {v0, v1, v2, v3 -> (uint64, uint64, uint64, uint64)
 	v0 += v1
--- a/lib/std/htab.myr
+++ b/lib/std/htab.myr
@@ -2,6 +2,7 @@
 use "die"
 use "extremum"
 use "option"
+use "traits"
 use "types"
 
 pkg std =
@@ -17,8 +18,8 @@
 		dead	: bool[:]
 	;;
 
-	generic mkht	: (h : (k : @k -> uint64), eq : (a : @k, b : @k -> bool) -> htab(@k, @v)#)
-	generic htinit	: (ht : htab(@k, @v)#, h : (k : @k -> uint64), eq : (a : @k, b : @k -> bool) -> void)
+	generic mkht	: ( -> htab(@k, @v)#)
+	generic htinit	: (ht : htab(@k, @v)# -> void)
 	generic htfree	: (ht : htab(@k, @v)# -> void)
 	generic htput	: (ht : htab(@k, @v)#, k : @k, v : @v -> void)
 	generic htdel	: (ht : htab(@k, @v)#, k : @k -> void)
@@ -38,10 +39,10 @@
 
 const Initsz = 32
 
-generic hash = {ht, k
+generic xhash = {k
 	var h
 
-	h = ht.hash(k)
+	h = hash(k)
 	if h == 0
 		-> 1
 	else
@@ -82,7 +83,7 @@
 	var h
 
 	di = 0
-	h = hash(ht, k)
+	h = xhash(k)
 	i = h & (ht.keys.len - 1)
 	while true
 		while ht.hashes[i] != 0 && !ht.dead[i] && ht.hashes[i] != h
@@ -92,7 +93,7 @@
 		if ht.hashes[i] == 0
 			-> `None
 		;;
-		if ht.hashes[i] == h && !ht.dead[i] && ht.eq(ht.keys[i], k)
+		if ht.hashes[i] == h && !ht.dead[i] && cmp(ht.keys[i], k)
 			break
 		;;
 		di++
@@ -101,20 +102,16 @@
 	-> `Some i
 }
 
-generic mkht = {h, eq
+generic mkht = {
 	var ht
 
 	ht = alloc()
-	htinit(ht, h, eq)
+	htinit(ht)
 
 	-> ht
 }
 
-generic htinit = {ht, h, eq
-
-	ht.hash = h
-	ht.eq = eq
-
+generic htinit = {ht
 	ht.nelt = 0
 	ht.ndead = 0
 	ht.keys = slalloc(Initsz)
@@ -137,11 +134,11 @@
 	var neltincr
 
 	di = 0
-	h = hash(ht, k)
+	h = xhash(k)
 	i = h & (ht.keys.len - 1)
 	neltincr = 1
 	while ht.hashes[i] != 0 && !ht.dead[i]
-		if ht.hashes[i] == h &&	ht.eq(ht.keys[i], k)
+		if ht.hashes[i] == h &&	cmp(ht.keys[i], k)
 			neltincr = 0
 			break
 		;;
--- a/lib/std/resolve+posixy.myr
+++ b/lib/std/resolve+posixy.myr
@@ -72,8 +72,8 @@
 var nameservers	: netaddr[:]
 
 const __init__ = {
-	hostmap = mkht(strhash, streq)
-	dnscache = mkht(strhash, streq)
+	hostmap = mkht()
+	dnscache = mkht()
 	loadhosts()
 	loadresolv()
 }
--- a/lib/std/wait+plan9.myr
+++ b/lib/std/wait+plan9.myr
@@ -32,7 +32,7 @@
 var statusmap	: htab(pid, waitstatus)#
 
 const __init__ = {
-	statusmap = mkht(inthash, inteq)
+	statusmap = mkht()
 }
 
 const waitany = {
--- a/mbld/deps.myr
+++ b/mbld/deps.myr
@@ -362,8 +362,8 @@
 	;;
 
 	stk = [][:]
-	visited = std.mkht(std.ptrhash, std.ptreq)
-	looped = std.mkht(std.ptrhash, std.ptreq)
+	visited = std.mkht()
+	looped = std.mkht()
 	for n : g.nodes
 		checkloop(g, n, visited, looped, &stk)
 	;;
--- a/mbld/libs.myr
+++ b/mbld/libs.myr
@@ -119,9 +119,9 @@
 	var added, diradded, looped
 	var lo
 
-	added  = std.mkht(std.strhash, std.streq)
-	looped  = std.mkht(std.strhash, std.streq)
-	diradded  = std.mkht(std.strhash, std.streq)
+	added  = std.mkht()
+	looped  = std.mkht()
+	diradded  = std.mkht()
 
 	lo = sl#.len
 	for l : libs
--- a/mbld/main.myr
+++ b/mbld/main.myr
@@ -140,13 +140,13 @@
 	var b
 
 	b = std.zalloc()
-	b.libs = std.mkht(std.strhash, std.streq)
-	b.proc = std.mkht(std.inthash, std.inteq)
-	b.targs = std.mkht(std.strhash, std.streq)
-	b.tags = std.mkht(std.strhash, std.streq)
+	b.libs = std.mkht()
+	b.proc = std.mkht()
+	b.targs = std.mkht()
+	b.tags = std.mkht()
 	b.deps = std.mk([
-		.targs = std.mkht(std.strhash, std.streq),
-		.gen = std.mkht(std.strhash, std.streq),
+		.targs = std.mkht(),
+		.gen = std.mkht(),
 		.leaves = [][:],
 		.nodes = [][:],
 	])
--- a/mbld/parse.myr
+++ b/mbld/parse.myr
@@ -61,8 +61,8 @@
 	var all
 
 	all = [][:]
-	looped = std.mkht(std.strhash, std.streq)
-	marked = std.mkht(std.strhash, std.streq)
+	looped = std.mkht()
+	marked = std.mkht()
 	for dep : b.all
 		match gettarg(b.targs, dep)
 		| `Bin _:	all = visit(all, b, "all", dep, looped, marked)
--- a/mbld/syssel.myr
+++ b/mbld/syssel.myr
@@ -27,8 +27,8 @@
 		.file = file,
 		.line = line,
 		.targ = targ,
-		._match = std.mkht(std.strhash, std.streq),
-		._best = std.mkht(std.strhash, std.streq),
+		._match = std.mkht(),
+		._best = std.mkht(),
 		.sysattrs = b.tags
 	])
 	-> syssel
--- a/support/dumpleak.myr
+++ b/support/dumpleak.myr
@@ -38,7 +38,7 @@
 		;;
 	;;
 
-	stats.tab = std.mkht(std.inthash, std.inteq)
+	stats.tab = std.mkht()
 	for d : cmd.args
 		match bio.open(d, bio.Rd)
 		| `std.Ok f:	dump(d, f, &stats)
@@ -99,7 +99,7 @@
 const dumptrace = {tab
 	var aggr
 
-	aggr = std.mkht(hashintsl, std.sleq)
+	aggr = std.mkht()
 	for (k, (sz, stk)) : std.byhtkeyvals(tab)
 		match std.htget(aggr, stk[:stackaggr])
 		| `std.Some (count, total):	
@@ -119,14 +119,4 @@
 	| `std.Ok v:	-> v
 	| res:	std.fatal("failed to read {}: {}\n", path, res)
 	;;
-}
-
-const hashintsl = {sl
-	var h
-
-	h = 0
-	for i : sl
-		h ^= std.inthash(i)
-	;;
-	-> h
 }