librustc: Change the ID visitor to use traits instead of garbage-collected functions.

This commit is contained in:
Patrick Walton 2013-08-29 19:01:19 -07:00
parent 37c32e2495
commit 6ecbd75843
4 changed files with 94 additions and 54 deletions

View File

@ -24,6 +24,7 @@ use middle;
use util::ppaux::ty_to_str;
use std::at_vec;
use std::libc;
use extra::ebml::reader;
use extra::ebml;
use extra::serialize;
@ -849,6 +850,26 @@ impl write_tag_and_id for writer::Encoder {
}
}
struct SideTableEncodingIdVisitor {
ecx_ptr: *libc::c_void,
new_ebml_w: writer::Encoder,
maps: Maps,
}
impl ast_util::IdVisitingOperation for SideTableEncodingIdVisitor {
fn visit_id(&self, id: ast::NodeId) {
// Note: this will cause a copy of ebml_w, which is bad as
// it is mutable. But I believe it's harmless since we generate
// balanced EBML.
let mut new_ebml_w = self.new_ebml_w.clone();
// See above
let ecx: &e::EncodeContext = unsafe {
cast::transmute(self.ecx_ptr)
};
encode_side_tables_for_id(ecx, self.maps, &mut new_ebml_w, id)
}
}
fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
maps: Maps,
ebml_w: &mut writer::Encoder,
@ -856,22 +877,16 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
ebml_w.start_tag(c::tag_table as uint);
let new_ebml_w = (*ebml_w).clone();
// Because the ast visitor uses @fn, I can't pass in
// ecx directly, but /I/ know that it'll be fine since
// the lifetime is tied to the CrateContext that
// lives this entire section.
let ecx_ptr : *() = unsafe { cast::transmute(ecx) };
ast_util::visit_ids_for_inlined_item(
ii,
|id: ast::NodeId| {
// Note: this will cause a copy of ebml_w, which is bad as
// it is mutable. But I believe it's harmless since we generate
// balanced EBML.
let mut new_ebml_w = new_ebml_w.clone();
// See above
let ecx : &e::EncodeContext = unsafe { cast::transmute(ecx_ptr) };
encode_side_tables_for_id(ecx, maps, &mut new_ebml_w, id)
});
// Because the ast visitor uses @IdVisitingOperation, I can't pass in
// ecx directly, but /I/ know that it'll be fine since the lifetime is
// tied to the CrateContext that lives throughout this entire section.
ast_util::visit_ids_for_inlined_item(ii, @SideTableEncodingIdVisitor {
ecx_ptr: unsafe {
cast::transmute(ecx)
},
new_ebml_w: new_ebml_w,
maps: maps,
} as @ast_util::IdVisitingOperation);
ebml_w.end_tag();
}

View File

@ -1228,17 +1228,27 @@ fn lint_unused_mut() -> @mut OuterLint {
@mut UnusedMutLintVisitor{ stopping_on_items: false } as @mut OuterLint
}
fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
ast_util::id_visitor(|id| {
match cx.tcx.sess.lints.pop(&id) {
None => {},
struct LintReportingIdVisitor {
cx: @mut Context,
}
impl ast_util::IdVisitingOperation for LintReportingIdVisitor {
fn visit_id(&self, id: ast::NodeId) {
match self.cx.tcx.sess.lints.pop(&id) {
None => {}
Some(l) => {
for (lint, span, msg) in l.move_iter() {
cx.span_lint(lint, span, msg)
self.cx.span_lint(lint, span, msg)
}
}
}
}, false)
}
}
fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
ast_util::id_visitor(@LintReportingIdVisitor {
cx: cx,
} as @ast_util::IdVisitingOperation, false)
}
struct UnnecessaryAllocationLintVisitor { stopping_on_items: bool }

View File

@ -299,7 +299,7 @@ struct RustcEmitter {
impl diagnostic::Emitter for RustcEmitter {
fn emit(&self,
cmsp: Option<(@codemap::CodeMap, codemap::span)>,
cmsp: Option<(@codemap::CodeMap, codemap::Span)>,
msg: &str,
lvl: diagnostic::level) {
if lvl == diagnostic::fatal {

View File

@ -397,18 +397,22 @@ impl id_range {
}
}
pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool)
pub fn id_visitor(operation: @IdVisitingOperation, pass_through_items: bool)
-> @mut Visitor<()> {
let visitor = @mut IdVisitor {
visit_callback: vfn,
operation: operation,
pass_through_items: pass_through_items,
visited_outermost: false,
};
visitor as @mut Visitor<()>
}
pub trait IdVisitingOperation {
fn visit_id(&self, node_id: NodeId);
}
pub struct IdVisitor {
visit_callback: @fn(NodeId),
operation: @IdVisitingOperation,
pass_through_items: bool,
visited_outermost: bool,
}
@ -416,10 +420,10 @@ pub struct IdVisitor {
impl IdVisitor {
fn visit_generics_helper(&self, generics: &Generics) {
for type_parameter in generics.ty_params.iter() {
(self.visit_callback)(type_parameter.id)
self.operation.visit_id(type_parameter.id)
}
for lifetime in generics.lifetimes.iter() {
(self.visit_callback)(lifetime.id)
self.operation.visit_id(lifetime.id)
}
}
}
@ -430,26 +434,26 @@ impl Visitor<()> for IdVisitor {
_: Span,
node_id: NodeId,
env: ()) {
(self.visit_callback)(node_id);
self.operation.visit_id(node_id);
visit::walk_mod(self, module, env)
}
fn visit_view_item(&mut self, view_item: &view_item, env: ()) {
match view_item.node {
view_item_extern_mod(_, _, _, node_id) => {
(self.visit_callback)(node_id)
self.operation.visit_id(node_id)
}
view_item_use(ref view_paths) => {
for view_path in view_paths.iter() {
match view_path.node {
view_path_simple(_, _, node_id) |
view_path_glob(_, node_id) => {
(self.visit_callback)(node_id)
self.operation.visit_id(node_id)
}
view_path_list(_, ref paths, node_id) => {
(self.visit_callback)(node_id);
self.operation.visit_id(node_id);
for path in paths.iter() {
(self.visit_callback)(path.node.id)
self.operation.visit_id(path.node.id)
}
}
}
@ -460,7 +464,7 @@ impl Visitor<()> for IdVisitor {
}
fn visit_foreign_item(&mut self, foreign_item: @foreign_item, env: ()) {
(self.visit_callback)(foreign_item.id);
self.operation.visit_id(foreign_item.id);
visit::walk_foreign_item(self, foreign_item, env)
}
@ -473,11 +477,11 @@ impl Visitor<()> for IdVisitor {
}
}
(self.visit_callback)(item.id);
self.operation.visit_id(item.id);
match item.node {
item_enum(ref enum_definition, _) => {
for variant in enum_definition.variants.iter() {
(self.visit_callback)(variant.node.id)
self.operation.visit_id(variant.node.id)
}
}
_ => {}
@ -489,22 +493,22 @@ impl Visitor<()> for IdVisitor {
}
fn visit_local(&mut self, local: @Local, env: ()) {
(self.visit_callback)(local.id);
self.operation.visit_id(local.id);
visit::walk_local(self, local, env)
}
fn visit_block(&mut self, block: &Block, env: ()) {
(self.visit_callback)(block.id);
self.operation.visit_id(block.id);
visit::walk_block(self, block, env)
}
fn visit_stmt(&mut self, statement: @Stmt, env: ()) {
(self.visit_callback)(ast_util::stmt_id(statement));
self.operation.visit_id(ast_util::stmt_id(statement));
visit::walk_stmt(self, statement, env)
}
fn visit_pat(&mut self, pattern: @Pat, env: ()) {
(self.visit_callback)(pattern.id);
self.operation.visit_id(pattern.id);
visit::walk_pat(self, pattern, env)
}
@ -513,17 +517,17 @@ impl Visitor<()> for IdVisitor {
{
let optional_callee_id = expression.get_callee_id();
for callee_id in optional_callee_id.iter() {
(self.visit_callback)(*callee_id)
self.operation.visit_id(*callee_id)
}
}
(self.visit_callback)(expression.id);
self.operation.visit_id(expression.id);
visit::walk_expr(self, expression, env)
}
fn visit_ty(&mut self, typ: &Ty, env: ()) {
(self.visit_callback)(typ.id);
self.operation.visit_id(typ.id);
match typ.node {
ty_path(_, _, id) => (self.visit_callback)(id),
ty_path(_, _, id) => self.operation.visit_id(id),
_ => {}
}
visit::walk_ty(self, typ, env)
@ -549,21 +553,21 @@ impl Visitor<()> for IdVisitor {
}
}
(self.visit_callback)(node_id);
self.operation.visit_id(node_id);
match *function_kind {
visit::fk_item_fn(_, generics, _, _) => {
self.visit_generics_helper(generics)
}
visit::fk_method(_, generics, method) => {
(self.visit_callback)(method.self_id);
self.operation.visit_id(method.self_id);
self.visit_generics_helper(generics)
}
visit::fk_anon(_) | visit::fk_fn_block => {}
}
for argument in function_declaration.inputs.iter() {
(self.visit_callback)(argument.id)
self.operation.visit_id(argument.id)
}
visit::walk_fn(self,
@ -583,25 +587,36 @@ impl Visitor<()> for IdVisitor {
}
fn visit_struct_field(&mut self, struct_field: @struct_field, env: ()) {
(self.visit_callback)(struct_field.node.id);
self.operation.visit_id(struct_field.node.id);
visit::walk_struct_field(self, struct_field, env)
}
}
pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) {
pub fn visit_ids_for_inlined_item(item: &inlined_item,
operation: @IdVisitingOperation) {
let mut id_visitor = IdVisitor {
visit_callback: vfn,
operation: operation,
pass_through_items: true,
visited_outermost: false,
};
item.accept((), &mut id_visitor);
}
pub fn compute_id_range(visit_ids_fn: &fn(@fn(NodeId))) -> id_range {
let result = @mut id_range::max();
do visit_ids_fn |id| {
result.add(id);
struct IdRangeComputingVisitor {
result: @mut id_range,
}
impl IdVisitingOperation for IdRangeComputingVisitor {
fn visit_id(&self, id: NodeId) {
self.result.add(id)
}
}
pub fn compute_id_range(visit_ids_fn: &fn(@IdVisitingOperation)) -> id_range {
let result = @mut id_range::max();
visit_ids_fn(@IdRangeComputingVisitor {
result: result,
} as @IdVisitingOperation);
*result
}