1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
// An "interner" is a data structure that associates values with uint tags and
// allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa.
import std::vec;
import std::map;
import std::map::hashmap;
import std::map::hashfn;
import std::map::eqfn;
import std::option;
import std::option::none;
import std::option::some;
mod interner {
type interner[T] = rec(
hashmap[T,uint] map,
mutable vec[T] vect,
hashfn[T] hasher,
eqfn[T] eqer
);
fn mk[T](hashfn[T] hasher, eqfn[T] eqer) -> interner[T] {
auto m = map::mk_hashmap[T,uint](hasher, eqer);
let vec[T] vect = [];
ret rec(map=m, mutable vect=vect, hasher=hasher, eqer=eqer);
}
fn intern[T](&interner[T] itr, &T val) -> uint {
alt (itr.map.find(val)) {
case (some[uint](?idx)) { ret idx; }
case (none[uint]) {
auto new_idx = vec::len[T](itr.vect);
itr.map.insert(val, new_idx);
itr.vect += [val];
ret new_idx;
}
}
}
fn get[T](&interner[T] itr, uint idx) -> T {
ret itr.vect.(idx);
}
}
|