1
Fork 0

rustc: Move code for discovering the crate entry point into its own pass

It doesn't have anything to do with resolve and the logic will likely get
more involved in the future, after #4433
This commit is contained in:
Brian Anderson 2013-04-29 14:56:05 -07:00
parent 32901104cb
commit be8dc615c5
4 changed files with 122 additions and 79 deletions

View file

@ -225,6 +225,8 @@ pub fn compile_rest(sess: Session,
time(time_passes, ~"resolution", ||
middle::resolve::resolve_crate(sess, lang_items, crate));
time(time_passes, ~"looking for entry point", || middle::entry::find_entry_point(sess, crate));
let freevars = time(time_passes, ~"freevar finding", ||
freevars::annotate_freevars(def_map, crate));

View file

@ -0,0 +1,119 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use driver::session;
use driver::session::Session;
use syntax::parse::token::special_idents;
use syntax::ast::{crate, node_id, item, item_fn};
use syntax::codemap::span;
use syntax::visit::{default_visitor, mk_vt, vt, Visitor, visit_crate, visit_item};
use syntax::attr::{attrs_contains_name};
struct EntryContext {
session: Session,
// The function that has attribute named 'main'
attr_main_fn: Option<(node_id, span)>,
// The functions that could be main functions
main_fns: ~[Option<(node_id, span)>],
// The function that has the attribute 'start' on it
start_fn: Option<(node_id, span)>,
}
type EntryVisitor = vt<@mut EntryContext>;
pub fn find_entry_point(session: Session, crate: @crate) {
let ctxt = @mut EntryContext {
session: session,
attr_main_fn: None,
main_fns: ~[],
start_fn: None,
};
visit_crate(crate, ctxt, mk_vt(@Visitor {
visit_item: |item, ctxt, visitor| find_item(item, ctxt, visitor),
.. *default_visitor()
}));
check_duplicate_main(ctxt);
}
fn find_item(item: @item, ctxt: @mut EntryContext, visitor: EntryVisitor) {
match item.node {
item_fn(*) => {
// If this is the main function, we must record it in the
// session.
// FIXME #4404 android JNI hacks
if !*ctxt.session.building_library ||
ctxt.session.targ_cfg.os == session::os_android {
if ctxt.attr_main_fn.is_none() &&
item.ident == special_idents::main {
ctxt.main_fns.push(Some((item.id, item.span)));
}
if attrs_contains_name(item.attrs, ~"main") {
if ctxt.attr_main_fn.is_none() {
ctxt.attr_main_fn = Some((item.id, item.span));
} else {
ctxt.session.span_err(
item.span,
~"multiple 'main' functions");
}
}
if attrs_contains_name(item.attrs, ~"start") {
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((item.id, item.span));
} else {
ctxt.session.span_err(
item.span,
~"multiple 'start' functions");
}
}
}
}
_ => ()
}
visit_item(item, ctxt, visitor);
}
// main function checking
//
// be sure that there is only one main function
fn check_duplicate_main(ctxt: @mut EntryContext) {
let this = &mut *ctxt;
if this.attr_main_fn.is_none() && this.start_fn.is_none() {
if this.main_fns.len() >= 1u {
let mut i = 1u;
while i < this.main_fns.len() {
let (_, dup_main_span) = this.main_fns[i].unwrap();
this.session.span_err(
dup_main_span,
~"multiple 'main' functions");
i += 1;
}
*this.session.entry_fn = this.main_fns[0];
*this.session.entry_type = Some(session::EntryMain);
}
} else if !this.start_fn.is_none() {
*this.session.entry_fn = this.start_fn;
*this.session.entry_type = Some(session::EntryStart);
} else {
*this.session.entry_fn = this.attr_main_fn;
*this.session.entry_type = Some(session::EntryMain);
}
}

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use driver::session;
use driver::session::Session;
use metadata::csearch::{each_path, get_trait_method_def_ids};
use metadata::csearch::get_method_name_and_self_ty;
@ -794,11 +793,6 @@ pub fn Resolver(session: Session,
namespaces: ~[ TypeNS, ValueNS ],
attr_main_fn: None,
main_fns: ~[],
start_fn: None,
def_map: @mut HashMap::new(),
export_map2: @mut HashMap::new(),
trait_map: HashMap::new(),
@ -856,15 +850,6 @@ pub struct Resolver {
// The four namespaces.
namespaces: ~[Namespace],
// The function that has attribute named 'main'
attr_main_fn: Option<(node_id, span)>,
// The functions that could be main functions
main_fns: ~[Option<(node_id, span)>],
// The function that has the attribute 'start' on it
start_fn: Option<(node_id, span)>,
def_map: DefMap,
export_map2: ExportMap2,
trait_map: TraitMap,
@ -885,7 +870,6 @@ pub impl Resolver {
self.resolve_crate();
self.session.abort_if_errors();
self.check_duplicate_main();
self.check_for_unused_imports_if_necessary();
}
@ -3545,40 +3529,6 @@ pub impl Resolver {
}
item_fn(ref fn_decl, _, _, ref generics, ref block) => {
// If this is the main function, we must record it in the
// session.
// FIXME #4404 android JNI hacks
if !*self.session.building_library ||
self.session.targ_cfg.os == session::os_android {
if self.attr_main_fn.is_none() &&
item.ident == special_idents::main {
self.main_fns.push(Some((item.id, item.span)));
}
if attrs_contains_name(item.attrs, ~"main") {
if self.attr_main_fn.is_none() {
self.attr_main_fn = Some((item.id, item.span));
} else {
self.session.span_err(
item.span,
~"multiple 'main' functions");
}
}
if attrs_contains_name(item.attrs, ~"start") {
if self.start_fn.is_none() {
self.start_fn = Some((item.id, item.span));
} else {
self.session.span_err(
item.span,
~"multiple 'start' functions");
}
}
}
self.resolve_function(OpaqueFunctionRibKind,
Some(fn_decl),
HasTypeParameters
@ -5109,35 +5059,6 @@ pub impl Resolver {
}
}
//
// main function checking
//
// be sure that there is only one main function
//
fn check_duplicate_main(@mut self) {
let this = &mut *self;
if this.attr_main_fn.is_none() && this.start_fn.is_none() {
if this.main_fns.len() >= 1u {
let mut i = 1u;
while i < this.main_fns.len() {
let (_, dup_main_span) = this.main_fns[i].unwrap();
this.session.span_err(
dup_main_span,
~"multiple 'main' functions");
i += 1;
}
*this.session.entry_fn = this.main_fns[0];
*this.session.entry_type = Some(session::EntryMain);
}
} else if !this.start_fn.is_none() {
*this.session.entry_fn = this.start_fn;
*this.session.entry_type = Some(session::EntryStart);
} else {
*this.session.entry_fn = this.attr_main_fn;
*this.session.entry_type = Some(session::EntryMain);
}
}
//
// Unused import checking
//

View file

@ -96,6 +96,7 @@ pub mod middle {
pub mod lang_items;
pub mod privacy;
pub mod moves;
pub mod entry;
}
pub mod front {