40 lines
1.0 KiB
Rust
40 lines
1.0 KiB
Rust
// 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::ivec;
|
|
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;
|
|
|
|
type interner[T] =
|
|
{map: hashmap[T, uint],
|
|
mutable vect: T[],
|
|
hasher: hashfn[T],
|
|
eqer: eqfn[T]};
|
|
|
|
fn mk[@T](hasher: hashfn[T], eqer: eqfn[T]) -> interner[T] {
|
|
let m = map::mk_hashmap[T, uint](hasher, eqer);
|
|
ret {map: m, mutable vect: ~[], hasher: hasher, eqer: eqer};
|
|
}
|
|
|
|
fn intern[@T](itr: &interner[T], val: &T) -> uint {
|
|
alt itr.map.find(val) {
|
|
some(idx) { ret idx; }
|
|
none. {
|
|
let new_idx = ivec::len[T](itr.vect);
|
|
itr.map.insert(val, new_idx);
|
|
itr.vect += ~[val];
|
|
ret new_idx;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn get[T](itr: &interner[T], idx: uint) -> T { ret itr.vect.(idx); }
|
|
|
|
fn len[T](itr : &interner[T]) -> uint { ret ivec::len(itr.vect); }
|
|
|