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