From 32b8dcb97c29b723579fdeb0d93c16917762ae08 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 16 May 2011 13:58:13 -0700 Subject: [PATCH] rustc: Factor out the code that interns types into an "interner" data structure --- src/comp/middle/ty.rs | 54 +++++++++++++-------------------------- src/comp/rustc.rc | 1 + src/comp/util/interner.rs | 42 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 36 deletions(-) create mode 100644 src/comp/util/interner.rs diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 8c6d13925335..1c947e693efd 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 476822358434..78c228c5bb2b 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 000000000000..a9bf9bc4e333 --- /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); +} +