// 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::map; import std::map::{hashmap, hashfn, eqfn}; import dvec::{dvec, extensions}; type hash_interner = {map: hashmap, vect: dvec, hasher: hashfn, eqer: eqfn}; fn mk(hasher: hashfn, eqer: eqfn) -> interner { let m = map::hashmap::(hasher, eqer); let hi: hash_interner = {map: m, vect: dvec(), hasher: hasher, eqer: eqer}; ret hi as interner::; } /* when traits can extend traits, we should extend index to get [] */ iface interner { fn intern(T) -> uint; pure fn get(uint) -> T; fn len() -> uint; } impl of interner for hash_interner { fn intern(val: T) -> uint { alt self.map.find(val) { some(idx) { ret idx; } none { let new_idx = self.vect.len(); self.map.insert(val, new_idx); self.vect.push(val); ret new_idx; } } } // this isn't "pure" in the traditional sense, because it can go from // failing to returning a value as items are interned. But for typestate, // where we first check a pred and then rely on it, ceasing to fail is ok. pure fn get(idx: uint) -> T { self.vect.get_elt(idx) } fn len() -> uint { ret self.vect.len(); } }