diff options
Diffstat (limited to 'src/rustc/middle/ast_map.rs')
| -rw-r--r-- | src/rustc/middle/ast_map.rs | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs new file mode 100644 index 00000000000..673b3649191 --- /dev/null +++ b/src/rustc/middle/ast_map.rs @@ -0,0 +1,152 @@ +import std::map; +import syntax::ast::*; +import syntax::ast_util; +import syntax::ast_util::inlined_item_methods; +import syntax::{visit, codemap}; + +enum path_elt { path_mod(str), path_name(str) } +type path = [path_elt]; + +fn path_to_str_with_sep(p: path, sep: str) -> str { + let strs = vec::map(p) {|e| + alt e { + path_mod(s) { s } + path_name(s) { s } + } + }; + str::connect(strs, sep) +} + +fn path_to_str(p: path) -> str { + path_to_str_with_sep(p, "::") +} + +enum ast_node { + node_item(@item, @path), + node_native_item(@native_item, @path), + node_method(@method, def_id, @path), + node_variant(variant, def_id, @path), + node_expr(@expr), + // Locals are numbered, because the alias analysis needs to know in which + // order they are introduced. + node_arg(arg, uint), + node_local(uint), + node_res_ctor(@item), +} + +type map = std::map::map<node_id, ast_node>; +type ctx = {map: map, mutable path: path, mutable local_id: uint}; +type vt = visit::vt<ctx>; + +fn mk_ast_map_visitor() -> vt { + ret visit::mk_vt(@{ + visit_item: map_item, + visit_native_item: map_native_item, + visit_expr: map_expr, + visit_fn: map_fn, + visit_local: map_local, + visit_arm: map_arm + with *visit::default_visitor() + }); +} + +fn map_crate(c: crate) -> map { + let cx = {map: std::map::new_int_hash(), + mutable path: [], + mutable local_id: 0u}; + visit::visit_crate(c, cx, mk_ast_map_visitor()); + ret cx.map; +} + +// Used for items loaded from external crate that are being inlined into this +// crate: +fn map_decoded_item(map: map, path: path, ii: inlined_item) { + // I believe it is ok for the local IDs of inlined items from other crates + // to overlap with the local ids from this crate, so just generate the ids + // starting from 0. (In particular, I think these ids are only used in + // alias analysis, which we will not be running on the inlined items, and + // even if we did I think it only needs an ordering between local + // variables that are simultaneously in scope). + let cx = {map: map, + mutable path: path, + mutable local_id: 0u}; + let v = mk_ast_map_visitor(); + ii.accept(cx, v); +} + +fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, + sp: codemap::span, id: node_id, cx: ctx, v: vt) { + for a in decl.inputs { + cx.map.insert(a.id, node_arg(a, cx.local_id)); + cx.local_id += 1u; + } + visit::visit_fn(fk, decl, body, sp, id, cx, v); +} + +fn number_pat(cx: ctx, pat: @pat) { + pat_util::walk_pat(pat) {|p| + alt p.node { + pat_ident(_, _) { + cx.map.insert(p.id, node_local(cx.local_id)); + cx.local_id += 1u; + } + _ {} + } + }; +} + +fn map_local(loc: @local, cx: ctx, v: vt) { + number_pat(cx, loc.node.pat); + visit::visit_local(loc, cx, v); +} + +fn map_arm(arm: arm, cx: ctx, v: vt) { + number_pat(cx, arm.pats[0]); + visit::visit_arm(arm, cx, v); +} + +fn map_item(i: @item, cx: ctx, v: vt) { + cx.map.insert(i.id, node_item(i, @cx.path)); + alt i.node { + item_impl(_, _, _, ms) { + let implid = ast_util::local_def(i.id); + for m in ms { cx.map.insert(m.id, node_method(m, implid, @cx.path)); } + } + item_res(_, _, _, dtor_id, ctor_id) { + cx.map.insert(ctor_id, node_res_ctor(i)); + cx.map.insert(dtor_id, node_item(i, @cx.path)); + } + item_enum(vs, _) { + for v in vs { + cx.map.insert(v.node.id, node_variant( + v, ast_util::local_def(i.id), + @(cx.path + [path_name(i.ident)]))); + } + } + _ { } + } + alt i.node { + item_mod(_) | item_native_mod(_) { cx.path += [path_mod(i.ident)]; } + _ { cx.path += [path_name(i.ident)]; } + } + visit::visit_item(i, cx, v); + vec::pop(cx.path); +} + +fn map_native_item(i: @native_item, cx: ctx, v: vt) { + cx.map.insert(i.id, node_native_item(i, @cx.path)); + visit::visit_native_item(i, cx, v); +} + +fn map_expr(ex: @expr, cx: ctx, v: vt) { + cx.map.insert(ex.id, node_expr(ex)); + visit::visit_expr(ex, cx, v); +} + +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// End: |
