about summary refs log tree commit diff
path: root/src/comp/util/data.rs
blob: 78dae38a42605ac04c7806d3932474eef596e504 (plain)
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


// 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(?idx)) { ret idx; }
            case (none) {
                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); }
}