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:
parent
32901104cb
commit
be8dc615c5
4 changed files with 122 additions and 79 deletions
|
@ -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));
|
||||
|
||||
|
|
119
src/librustc/middle/entry.rs
Normal file
119
src/librustc/middle/entry.rs
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -96,6 +96,7 @@ pub mod middle {
|
|||
pub mod lang_items;
|
||||
pub mod privacy;
|
||||
pub mod moves;
|
||||
pub mod entry;
|
||||
}
|
||||
|
||||
pub mod front {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue