about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcore/cmp.rs10
-rw-r--r--src/libcore/core.rc2
-rw-r--r--src/libcore/int-template.rs14
-rw-r--r--src/libcore/uint-template.rs14
-rw-r--r--src/libstd/sort.rs13
-rw-r--r--src/rustc/driver/driver.rs4
-rw-r--r--src/rustc/driver/rustc.rs3
-rw-r--r--src/rustc/metadata/decoder.rs2
-rw-r--r--src/rustc/middle/astencode.rs9
-rw-r--r--src/rustc/middle/liveness.rs61
-rw-r--r--src/rustc/middle/trans/base.rs34
-rw-r--r--src/rustc/middle/tstate/auxiliary.rs5
-rw-r--r--src/rustc/middle/ty.rs6
-rw-r--r--src/rustc/middle/typeck/astconv.rs3
-rw-r--r--src/rustc/middle/typeck/check.rs3
-rw-r--r--src/rustc/util/ppaux.rs10
16 files changed, 79 insertions, 114 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
new file mode 100644
index 00000000000..aea97cf1649
--- /dev/null
+++ b/src/libcore/cmp.rs
@@ -0,0 +1,10 @@
+#[doc="Interfaces used for comparison."]
+
+iface ord {
+    fn lt(&&other: self) -> bool;
+}
+
+iface eq {
+    fn eq(&&other: self) -> bool;
+}
+
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index 84cebcceccd..668eb3c82b9 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -45,6 +45,7 @@ export tuple;
 export to_str;
 export swappable;
 export dvec, dvec_iter;
+export cmp;
 
 // NDM seems to be necessary for resolve to work
 export option_iter;
@@ -153,6 +154,7 @@ mod tuple;
 
 // Ubiquitous-utility-type modules
 
+mod cmp;
 mod either;
 mod iter;
 mod logging;
diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs
index 156724cb061..4011ac1a18a 100644
--- a/src/libcore/int-template.rs
+++ b/src/libcore/int-template.rs
@@ -1,4 +1,5 @@
 import T = inst::T;
+import cmp::{eq, ord};
 
 export min_value, max_value;
 export min, max;
@@ -10,6 +11,7 @@ export range;
 export compl;
 export abs;
 export parse_buf, from_str, to_str, to_str_bytes, str;
+export ord, eq;
 
 const min_value: T = -1 as T << (inst::bits - 1 as T);
 const max_value: T = min_value - 1 as T;
@@ -108,6 +110,18 @@ fn to_str_bytes<U>(n: T, radix: uint, f: fn([u8]/&) -> U) -> U {
 #[doc = "Convert to a string"]
 fn str(i: T) -> str { ret to_str(i, 10u); }
 
+impl ord of ord for T {
+    fn lt(&&other: T) -> bool {
+        ret self < other;
+    }
+}
+
+impl eq of eq for T {
+    fn eq(&&other: T) -> bool {
+        ret self == other;
+    }
+}
+
 
 // FIXME: Has alignment issues on windows and 32-bit linux
 #[test]
diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs
index a63d01e6e8e..7126fb3d007 100644
--- a/src/libcore/uint-template.rs
+++ b/src/libcore/uint-template.rs
@@ -1,4 +1,5 @@
 import T = inst::T;
+import cmp::{eq, ord};
 
 export min_value, max_value;
 export min, max;
@@ -10,6 +11,7 @@ export range;
 export compl;
 export to_str, to_str_bytes;
 export from_str, from_str_radix, str, parse_buf;
+export ord, eq;
 
 const min_value: T = 0 as T;
 const max_value: T = 0 as T - 1 as T;
@@ -49,6 +51,18 @@ pure fn compl(i: T) -> T {
     max_value ^ i
 }
 
+impl ord of ord for T {
+    fn lt(&&other: T) -> bool {
+        ret self < other;
+    }
+}
+
+impl eq of eq for T {
+    fn eq(&&other: T) -> bool {
+        ret self == other;
+    }
+}
+
 #[doc = "
 Parse a buffer of bytes
 
diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs
index 7e16578fd9c..76c71d7ed2a 100644
--- a/src/libstd/sort.rs
+++ b/src/libstd/sort.rs
@@ -1,5 +1,6 @@
 #[doc = "Sorting methods"];
 import vec::len;
+import int::{eq, ord};
 
 export le;
 export merge_sort;
@@ -141,7 +142,6 @@ fn qsort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
     qsort3::<T>(compare_func_lt, compare_func_eq, arr, i, right);
 }
 
-// FIXME: This should take lt and eq types (#2348)
 #[doc = "
 Fancy quicksort. Sorts a mut vector in place.
 
@@ -152,10 +152,9 @@ According to these slides this is the algorithm of choice for
 
 This is an unstable sort.
 "]
-fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
-                       arr: [mut T]) {
+fn quick_sort3<T: copy ord eq>(arr: [mut T]) {
     if len::<T>(arr) == 0u { ret; }
-    qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,
+    qsort3::<T>({ |x, y| x.lt(y) }, { |x, y| x.eq(y) }, arr, 0,
                 (len::<T>(arr) as int) - 1);
 }
 
@@ -163,11 +162,7 @@ fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
 mod test_qsort3 {
     fn check_sort(v1: [mut int], v2: [mut int]) {
         let len = vec::len::<int>(v1);
-        fn lt(&&a: int, &&b: int) -> bool { ret a < b; }
-        fn equal(&&a: int, &&b: int) -> bool { ret a == b; }
-        let f1 = lt;
-        let f2 = equal;
-        quick_sort3::<int>(f1, f2, v1);
+        quick_sort3::<int>(v1);
         let mut i = 0u;
         while i < len {
             log(debug, v2[i]);
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 6d4f48595d2..e769455376a 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -194,7 +194,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
          bind middle::check_loop::check_crate(ty_cx, crate));
     time(time_passes, "alt checking",
          bind middle::check_alt::check_crate(ty_cx, crate));
-    let (last_use_map, spill_map) =
+    let last_use_map =
         time(time_passes, "liveness checking",
              bind middle::liveness::check_crate(ty_cx, method_map, crate));
     time(time_passes, "typestate checking",
@@ -216,7 +216,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
     let maps = {mutbl_map: mutbl_map, root_map: root_map,
                 copy_map: copy_map, last_use_map: last_use_map,
                 impl_map: impl_map, method_map: method_map,
-                vtable_map: vtable_map, spill_map: spill_map};
+                vtable_map: vtable_map};
 
     let (llmod, link_meta) =
         time(time_passes, "translation",
diff --git a/src/rustc/driver/rustc.rs b/src/rustc/driver/rustc.rs
index db185215bea..5e88df1de5e 100644
--- a/src/rustc/driver/rustc.rs
+++ b/src/rustc/driver/rustc.rs
@@ -15,7 +15,8 @@ import std::map::hashmap;
 import getopts::{opt_present};
 import rustc::driver::driver::*;
 import syntax::codemap;
-import rustc::driver::{diagnostic, session};
+import syntax::diagnostic;
+import rustc::driver::session;
 import rustc::middle::lint;
 import io::reader_util;
 
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 644d519fc0f..4df45033a77 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -7,7 +7,6 @@ import syntax::{ast, ast_util};
 import syntax::attr;
 import middle::ty;
 import syntax::ast_map;
-import common::*;
 import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
         parse_ident};
 import syntax::print::pprust;
@@ -15,6 +14,7 @@ import cmd=cstore::crate_metadata;
 import util::ppaux::ty_to_str;
 import ebml::deserializer;
 import syntax::diagnostic::span_handler;
+import common::*;
 
 export class_dtor;
 export get_class_fields;
diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs
index 2fd59cb2166..6ebf0ed9ec6 100644
--- a/src/rustc/middle/astencode.rs
+++ b/src/rustc/middle/astencode.rs
@@ -57,7 +57,6 @@ type maps = {
     impl_map: middle::resolve::impl_map,
     method_map: middle::typeck::method_map,
     vtable_map: middle::typeck::vtable_map,
-    spill_map: middle::liveness::spill_map
 };
 
 type decode_ctxt = @{
@@ -839,12 +838,6 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt,
         }
     }
 
-    option::iter(maps.spill_map.find(id)) {|_m|
-        ebml_w.tag(c::tag_table_spill) {||
-            ebml_w.id(id);
-        }
-    }
-
     option::iter(maps.last_use_map.find(id)) {|m|
         ebml_w.tag(c::tag_table_last_use) {||
             ebml_w.id(id);
@@ -953,8 +946,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
             dcx.maps.mutbl_map.insert(id, ());
         } else if tag == (c::tag_table_copy as uint) {
             dcx.maps.copy_map.insert(id, ());
-        } else if tag == (c::tag_table_spill as uint) {
-            dcx.maps.spill_map.insert(id, ());
         } else {
             let val_doc = entry_doc[c::tag_table_val];
             let val_dsr = ebml::ebml_deserializer(val_doc);
diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs
index 3f82e647ab6..048823f4553 100644
--- a/src/rustc/middle/liveness.rs
+++ b/src/rustc/middle/liveness.rs
@@ -57,7 +57,6 @@ import capture::{cap_move, cap_drop, cap_copy, cap_ref};
 
 export check_crate;
 export last_use_map;
-export spill_map;
 
 // Maps from an expr id to a list of variable ids for which this expr
 // is the last use.  Typically, the expr is a path and the node id is
@@ -66,13 +65,6 @@ export spill_map;
 // list of closed over variables that can be moved into the closure.
 type last_use_map = hashmap<node_id, @dvec<node_id>>;
 
-// A set of variable ids which must be spilled (stored on the stack).
-// We add in any variables or arguments where:
-// (1) the variables are moved;
-// (2) the address of the variable/argument is taken;
-// or (3) we find a last use (as they may be moved).
-type spill_map = hashmap<node_id, ()>;
-
 enum variable = uint;
 enum live_node = uint;
 
@@ -85,7 +77,7 @@ enum live_node_kind {
 
 fn check_crate(tcx: ty::ctxt,
                method_map: typeck::method_map,
-               crate: @crate) -> (last_use_map, spill_map) {
+               crate: @crate) -> last_use_map {
     let visitor = visit::mk_vt(@{
         visit_fn: visit_fn,
         visit_local: visit_local,
@@ -94,12 +86,11 @@ fn check_crate(tcx: ty::ctxt,
     });
 
     let last_use_map = int_hash();
-    let spill_map = int_hash();
     let initial_maps = @ir_maps(tcx, method_map,
-                                last_use_map, spill_map);
+                                last_use_map);
     visit::visit_crate(*crate, initial_maps, visitor);
     tcx.sess.abort_if_errors();
-    ret (last_use_map, spill_map);
+    ret last_use_map;
 }
 
 impl of to_str::to_str for live_node {
@@ -162,7 +153,6 @@ class ir_maps {
     let tcx: ty::ctxt;
     let method_map: typeck::method_map;
     let last_use_map: last_use_map;
-    let spill_map: spill_map;
 
     let mut num_live_nodes: uint;
     let mut num_vars: uint;
@@ -174,11 +164,10 @@ class ir_maps {
     let mut lnks: [live_node_kind];
 
     new(tcx: ty::ctxt, method_map: typeck::method_map,
-        last_use_map: last_use_map, spill_map: spill_map) {
+        last_use_map: last_use_map) {
         self.tcx = tcx;
         self.method_map = method_map;
         self.last_use_map = last_use_map;
-        self.spill_map = spill_map;
 
         self.num_live_nodes = 0u;
         self.num_vars = 0u;
@@ -264,17 +253,6 @@ class ir_maps {
         self.lnks[*ln]
     }
 
-    fn add_spill(var: variable) {
-        let vk = self.var_kinds[*var];
-        alt vk {
-          vk_local(id, _) | vk_arg(id, _, by_val) {
-            #debug["adding spill for %?", vk];
-            self.spill_map.insert(id, ());
-          }
-          vk_arg(*) | vk_field(_) | vk_self | vk_implicit_ret {}
-        }
-    }
-
     fn add_last_use(expr_id: node_id, var: variable) {
         let vk = self.var_kinds[*var];
         #debug["Node %d is a last use of variable %?", expr_id, vk];
@@ -308,7 +286,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
 
     // swap in a new set of IR maps for this function body:
     let fn_maps = @ir_maps(self.tcx, self.method_map,
-                           self.last_use_map, self.spill_map);
+                           self.last_use_map);
 
     #debug["creating fn_maps: %x", ptr::addr_of(*fn_maps) as uint];
 
@@ -1407,11 +1385,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
         vt.visit_expr(f, self, vt);
         vec::iter2(args, targs) { |arg_expr, arg_ty|
             alt ty::resolved_mode(self.tcx, arg_ty.mode) {
-              by_val | by_copy {
-                vt.visit_expr(arg_expr, self, vt);
-              }
-              by_ref | by_mutbl_ref {
-                self.spill_expr(arg_expr);
+              by_val | by_copy | by_ref | by_mutbl_ref{
                 vt.visit_expr(arg_expr, self, vt);
               }
               by_move {
@@ -1421,10 +1395,6 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
         }
       }
 
-      expr_addr_of(_, arg_expr) {
-        self.spill_expr(arg_expr);
-      }
-
       // no correctness conditions related to liveness
       expr_if_check(*) | expr_if(*) | expr_alt(*) |
       expr_while(*) | expr_loop(*) |
@@ -1434,7 +1404,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
       expr_assert(*) | expr_check(*) | expr_copy(*) |
       expr_loop_body(*) | expr_cast(*) | expr_unary(*) | expr_fail(*) |
       expr_ret(*) | expr_break | expr_cont | expr_lit(_) |
-      expr_block(*) | expr_swap(*) | expr_mac(*) {
+      expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) {
         visit::visit_expr(expr, self, vt);
       }
     }
@@ -1501,10 +1471,7 @@ impl check_methods for @liveness {
                ln.to_str(), var.to_str()];
 
         alt (*self).live_on_exit(ln, var) {
-          none {
-            // update spill map to include this variable, as it is moved:
-            (*self.ir).add_spill(var);
-          }
+          none { }
           some(lnk) {
             self.report_illegal_move(span, lnk, var);
           }
@@ -1516,20 +1483,10 @@ impl check_methods for @liveness {
           some(_) {}
           none {
             (*self.ir).add_last_use(expr.id, var);
-
-            // update spill map to include this variable, as it may be moved:
-            (*self.ir).add_spill(var);
           }
        }
     }
 
-    fn spill_expr(expr: @expr) {
-        alt (*self).variable_from_path(expr) {
-          some(var) {(*self.ir).add_spill(var)}
-          none {}
-        }
-    }
-
     fn check_move_from_expr(expr: @expr, vt: vt<@liveness>) {
         #debug["check_move_from_expr(node %d: %s)",
                expr.id, expr_to_str(expr)];
@@ -1775,4 +1732,4 @@ impl check_methods for @liveness {
             }
         }
     }
- }
\ No newline at end of file
+ }
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 62c3134e9ab..e6708385b03 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -3749,6 +3749,8 @@ fn lval_to_dps(bcx: block, e: @ast::expr, dest: dest) -> block {
     let ty = expr_ty(bcx, e);
     let lv = trans_lval(bcx, e);
     let last_use = (lv.kind == owned && last_use_map.contains_key(e.id));
+    #debug["is last use (%s) = %b, %d", expr_to_str(e), last_use,
+           lv.kind as int];
     lval_result_to_dps(lv, ty, last_use, dest)
 }
 
@@ -4039,29 +4041,10 @@ fn init_local(bcx: block, local: @ast::local) -> block {
     let ty = node_id_type(bcx, local.node.id);
     let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
       some(local_mem(v)) { v }
-      some(_) { bcx.tcx().sess.span_bug(local.span,
+      _ { bcx.tcx().sess.span_bug(local.span,
                         "init_local: Someone forgot to document why it's\
                          safe to assume local.node.init must be local_mem!");
-      }
-      // This is a local that is kept immediate
-      none {
-        let initexpr = alt local.node.init {
-                some({expr, _}) { expr }
-                none { bcx.tcx().sess.span_bug(local.span,
-                        "init_local: late-initialized var appears to \
-                 be an immediate -- possibly init_local was called \
-                 without calling alloc_local"); }
-            };
-        let mut {bcx, val, kind} = trans_temp_lval(bcx, initexpr);
-        if kind != temporary {
-            if kind == owned { val = Load(bcx, val); }
-            let rs = take_ty_immediate(bcx, val, ty);
-            bcx = rs.bcx; val = rs.val;
-            add_clean_temp(bcx, val, ty);
         }
-        bcx.fcx.lllocals.insert(local.node.pat.id, local_imm(val));
-        ret bcx;
-      }
     };
 
     let mut bcx = bcx;
@@ -4341,17 +4324,6 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
       ast::pat_ident(pth, none) { some(path_to_ident(pth)) }
       _ { none }
     };
-    // Do not allocate space for locals that can be kept immediate.
-    let ccx = cx.ccx();
-    if option::is_some(simple_name) &&
-       !ccx.maps.mutbl_map.contains_key(local.node.pat.id) &&
-       !ccx.maps.spill_map.contains_key(local.node.pat.id) &&
-       ty::type_is_immediate(t) {
-        alt local.node.init {
-          some({op: ast::init_assign, _}) { ret cx; }
-          _ {}
-        }
-    }
     let val = alloc_ty(cx, t);
     if cx.sess().opts.debuginfo {
         option::iter(simple_name) {|name|
diff --git a/src/rustc/middle/tstate/auxiliary.rs b/src/rustc/middle/tstate/auxiliary.rs
index c34953ac33e..a41812f72a7 100644
--- a/src/rustc/middle/tstate/auxiliary.rs
+++ b/src/rustc/middle/tstate/auxiliary.rs
@@ -13,9 +13,8 @@ import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate,
                      set_postcondition, ts_ann,
                      clear_in_postcond,
                      clear_in_poststate_};
-import tritv::*;
-import bitvectors::promises_;
 import driver::session::session;
+import tritv::{dont_care, tfalse, tritv_get, ttrue};
 
 import syntax::print::pprust::{constr_args_to_str, lit_to_str};
 
@@ -811,7 +810,7 @@ fn copy_in_poststate_two(fcx: fn_ctxt, src_post: poststate,
         // dest def_id
         let insts = find_instances(fcx, subst, val);
         for insts.each {|p|
-            if promises_(p.from, src_post) {
+            if bitvectors::promises_(p.from, src_post) {
                 set_in_poststate_(p.to, target_post);
             }
         }
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 3b32bca1e5f..73f601cf4b0 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -4,19 +4,19 @@ import std::map::hashmap;
 import driver::session;
 import session::session;
 import syntax::{ast, ast_map};
-import syntax::ast::*;
 import syntax::ast_util;
 import syntax::ast_util::{is_local, local_def, split_class_items,
                           new_def_hash};
 import syntax::codemap::span;
 import metadata::csearch;
-import util::common::*;
 import util::ppaux::region_to_str;
 import util::ppaux::vstore_to_str;
 import util::ppaux::{ty_to_str, tys_to_str, ty_constr_to_str};
-import syntax::print::pprust::*;
 import middle::lint::{get_warning_level, vecs_not_implicitly_copyable,
                       ignore};
+import syntax::ast::*;
+import syntax::print::pprust::*;
+
 export ty_vid, region_vid, vid;
 export br_hashmap;
 export is_instantiable;
diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs
index d8ce3d83a60..476ef9d3ba5 100644
--- a/src/rustc/middle/typeck/astconv.rs
+++ b/src/rustc/middle/typeck/astconv.rs
@@ -45,7 +45,8 @@ an rptr (`&r.T`) use the region `r` that appears in the rptr.
 "];
 
 import check::fn_ctxt;
-import rscope::*;
+import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
+import rscope::{in_binding_rscope, region_scope, type_rscope};
 
 iface ast_conv {
     fn tcx() -> ty::ctxt;
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index 2649dc6c675..70167192afc 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -71,7 +71,8 @@ import collect::{methods}; // ccx.to_ty()
 import method::{methods};  // methods for method::lookup
 import middle::ty::tys_in_fn_ty;
 import regionmanip::{replace_bound_regions_in_fn_ty, region_of};
-import rscope::*;
+import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
+import rscope::{in_binding_rscope, region_scope, type_rscope};
 
 type fn_ctxt =
     // var_bindings, locals and next_var_id are shared
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index 60f4ea8dabf..c5c445702d5 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -1,6 +1,14 @@
 import std::map::hashmap;
 import middle::ty;
-import middle::ty::*;
+import middle::ty::{arg, bound_region, br_anon, br_named, canon_mode};
+import middle::ty::{ck_block, ck_box, ck_uniq, constr, ctxt, field, method};
+import middle::ty::{mt, re_bound, re_free, re_scope, re_var, region, t};
+import middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_constr, ty_enum};
+import middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_iface, ty_int};
+import middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
+import middle::ty::{ty_ptr, ty_rec, ty_res, ty_rptr, ty_self, ty_str, ty_tup};
+import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral};
+import middle::ty::{ty_vec, vid};
 import metadata::encoder;
 import syntax::codemap;
 import syntax::print::pprust;