about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-05-16 13:58:13 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-05-16 13:58:13 -0700
commit32b8dcb97c29b723579fdeb0d93c16917762ae08 (patch)
tree08072f5337debd3fcb516cbda7d09cc13bff495f /src/comp
parent3760bfab87498d71f9341ffac1aa027f26028656 (diff)
downloadrust-32b8dcb97c29b723579fdeb0d93c16917762ae08.tar.gz
rust-32b8dcb97c29b723579fdeb0d93c16917762ae08.zip
rustc: Factor out the code that interns types into an "interner" data structure
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/ty.rs54
-rw-r--r--src/comp/rustc.rc1
-rw-r--r--src/comp/util/interner.rs42
3 files changed, 61 insertions, 36 deletions
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 8c6d1392533..1c947e693ef 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -33,6 +33,8 @@ import util::common::new_def_hash;
 import util::common::span;
 import util::typestate_ann::ts_ann;
 
+import util::interner;
+
 // Data types
 
 tag mode {
@@ -159,19 +161,14 @@ const uint idx_native   = 18u;
 const uint idx_type     = 19u;
 const uint idx_first_others = 20u;
 
-type type_store = rec(mutable vec[raw_t] others,
-                      hashmap[raw_t,uint] other_structural);
+type type_store = interner::interner[raw_t];
 
 type ty_param_substs_opt_and_ty = tup(option::t[vec[ty::t]], ty::t);
 type node_type_table =
     @mutable vec[mutable option::t[ty::ty_param_substs_opt_and_ty]];
 
 fn mk_type_store() -> @type_store {
-    let vec[raw_t] others = vec();
-    let hashmap[raw_t,uint] ost =
-        map::mk_hashmap[raw_t,uint](hash_raw_ty, eq_raw_ty);
-
-    auto ts = @rec(mutable others=others, other_structural=ost);
+    auto ts = @interner::mk_interner[raw_t](hash_raw_ty, eq_raw_ty);
 
     intern(ts, ty_nil, none[str]);
     intern(ts, ty_bool, none[str]);
@@ -194,7 +191,7 @@ fn mk_type_store() -> @type_store {
     intern(ts, ty_native, none[str]);
     intern(ts, ty_type, none[str]);
 
-    assert _vec::len(ts.others) == idx_first_others;
+    assert _vec::len(ts.vect) == idx_first_others;
 
     ret ts;
 }
@@ -240,7 +237,7 @@ fn mk_raw_ty(&@type_store ts, &sty st, &option::t[str] cname) -> raw_t {
                       &mutable bool has_vars,
                       &mutable bool has_locals,
                       &t tt) {
-        auto rt = ts.others.(tt);
+        auto rt = interner::get[raw_t](*ts, tt);
         has_params = has_params || rt.has_params;
         has_bound_params = has_bound_params || rt.has_bound_params;
         has_vars = has_vars || rt.has_vars;
@@ -355,32 +352,13 @@ fn mk_raw_ty(&@type_store ts, &sty st, &option::t[str] cname) -> raw_t {
             has_locals = has_locals);
 }
 
-fn intern_raw_ty(&@type_store ts, &raw_t rt) {
-    auto type_num = _vec::len[raw_t](ts.others);
-    ts.others += vec(rt);
-    ts.other_structural.insert(rt, type_num);
-}
-
 fn intern(&@type_store ts, &sty st, &option::t[str] cname) {
-    intern_raw_ty(ts, mk_raw_ty(ts, st, cname));
+    interner::intern[raw_t](*ts, mk_raw_ty(ts, st, cname));
 }
 
 fn gen_ty_full(&ctxt cx, &sty st, &option::t[str] cname) -> t {
     auto raw_type = mk_raw_ty(cx.ts, st, cname);
-
-    // Is it interned?
-    alt (cx.ts.other_structural.find(raw_type)) {
-        case (some[t](?typ)) {
-            ret typ;
-        }
-        case (none[t]) {
-            // Nope: Insert it and return.
-            auto type_num = _vec::len[raw_t](cx.ts.others);
-            intern_raw_ty(cx.ts, raw_type);
-            // log_err "added: " + ty_to_str(tystore, raw_type);
-            ret type_num;
-        }
-    }
+    ret interner::intern[raw_t](*cx.ts, raw_type);
 }
 
 // These are private constructors to this module. External users should always
@@ -484,10 +462,14 @@ fn mk_native(&ctxt cx) -> t  { ret idx_native; }
 
 
 // Returns the one-level-deep type structure of the given type.
-fn struct(&ctxt cx, &t typ) -> sty { ret cx.ts.others.(typ).struct; }
+fn struct(&ctxt cx, &t typ) -> sty {
+    ret interner::get[raw_t](*cx.ts, typ).struct;
+}
 
 // Returns the canonical name of the given type.
-fn cname(&ctxt cx, &t typ) -> option::t[str] { ret cx.ts.others.(typ).cname; }
+fn cname(&ctxt cx, &t typ) -> option::t[str] {
+    ret interner::get[raw_t](*cx.ts, typ).cname;
+}
 
 
 // Stringification
@@ -1525,19 +1507,19 @@ fn count_ty_params(ctxt cx, t ty) -> uint {
 }
 
 fn type_contains_vars(&ctxt cx, &t typ) -> bool {
-    ret cx.ts.others.(typ).has_vars;
+    ret interner::get[raw_t](*cx.ts, typ).has_vars;
 }
 
 fn type_contains_locals(&ctxt cx, &t typ) -> bool {
-    ret cx.ts.others.(typ).has_locals;
+    ret interner::get[raw_t](*cx.ts, typ).has_locals;
 }
 
 fn type_contains_params(&ctxt cx, &t typ) -> bool {
-    ret cx.ts.others.(typ).has_params;
+    ret interner::get[raw_t](*cx.ts, typ).has_params;
 }
 
 fn type_contains_bound_params(&ctxt cx, &t typ) -> bool {
-    ret cx.ts.others.(typ).has_bound_params;
+    ret interner::get[raw_t](*cx.ts, typ).has_bound_params;
 }
 
 // Type accessors for substructures of types
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index 47682235843..78c228c5bb2 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -52,6 +52,7 @@ mod driver {
 
 mod util {
     mod common;
+    mod interner;
     mod typestate_ann;
 }
 
diff --git a/src/comp/util/interner.rs b/src/comp/util/interner.rs
new file mode 100644
index 00000000000..a9bf9bc4e33
--- /dev/null
+++ b/src/comp/util/interner.rs
@@ -0,0 +1,42 @@
+// 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;
+
+type interner[T] = rec(
+    hashmap[T,uint] map,
+    mutable vec[T] vect,
+    hashfn[T] hasher,
+    eqfn[T] eqer
+);
+
+fn mk_interner[T](hashfn[T] hasher, eqfn[T] eqer) -> interner[T] {
+    auto m = map::mk_hashmap[T,uint](hasher, eqer);
+    let vec[T] vect = vec();
+    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 += vec(val);
+            ret new_idx;
+        }
+    }
+}
+
+fn get[T](&interner[T] itr, uint idx) -> T {
+    ret itr.vect.(idx);
+}
+