Move `for` loop desugaring to lowering

This commit is contained in:
Nick Cameron 2015-09-28 15:00:15 +13:00
parent 56713a1684
commit 20083c1e1f
12 changed files with 420 additions and 214 deletions

View File

@ -80,13 +80,13 @@ DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
DEPS_rustc_resolve := rustc rustc_front log syntax
DEPS_rustc_privacy := rustc rustc_front log syntax
DEPS_rustc_front := std syntax log serialize
DEPS_rustc_lint := rustc log syntax
DEPS_rustc := syntax flate arena serialize getopts rbml \
DEPS_rustc := syntax flate arena serialize getopts rbml rustc_front\
log graphviz rustc_llvm rustc_back rustc_data_structures
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
DEPS_rustc_front := std syntax log serialize
DEPS_rustc_data_structures := std log serialize
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
test rustc_lint rustc_front

View File

@ -36,6 +36,7 @@ use middle::subst;
use middle::ty::{self, Ty};
use syntax::{ast, ast_util, codemap};
use syntax::ast::NodeIdAssigner;
use syntax::codemap::Span;
use syntax::ptr::P;

View File

@ -219,7 +219,7 @@ pub struct ctxt<'tcx> {
/// Common types, pre-interned for your convenience.
pub types: CommonTypes<'tcx>,
pub sess: Session,
pub sess: &'tcx Session,
pub def_map: DefMap,
pub named_region_map: resolve_lifetime::NamedRegionMap,
@ -443,7 +443,7 @@ impl<'tcx> ctxt<'tcx> {
/// to the context. The closure enforces that the type context and any interned
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
/// reference to the context, to allow formatting values that need it.
pub fn create_and_enter<F, R>(s: Session,
pub fn create_and_enter<F, R>(s: &'tcx Session,
arenas: &'tcx CtxtArenas<'tcx>,
def_map: DefMap,
named_region_map: resolve_lifetime::NamedRegionMap,
@ -452,7 +452,7 @@ impl<'tcx> ctxt<'tcx> {
region_maps: RegionMaps,
lang_items: middle::lang_items::LanguageItems,
stability: stability::Index<'tcx>,
f: F) -> (Session, R)
f: F) -> R
where F: FnOnce(&ctxt<'tcx>) -> R
{
let interner = RefCell::new(FnvHashMap());
@ -556,7 +556,6 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
pub mod tls {
use middle::ty;
use session::Session;
use std::fmt;
use syntax::codemap;
@ -574,17 +573,15 @@ pub mod tls {
})
}
pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
-> (Session, R) {
let result = codemap::SPAN_DEBUG.with(|span_dbg| {
pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F) -> R {
codemap::SPAN_DEBUG.with(|span_dbg| {
let original_span_debug = span_dbg.get();
span_dbg.set(span_debug);
let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
span_dbg.set(original_span_debug);
result
});
(tcx.sess, result)
})
}
pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {

View File

@ -15,7 +15,7 @@ use middle::dependency_format;
use session::search_paths::PathKind;
use util::nodemap::{NodeMap, FnvHashMap};
use syntax::ast::NodeId;
use syntax::ast::{NodeId, NodeIdAssigner};
use syntax::codemap::Span;
use syntax::diagnostic::{self, Emitter};
use syntax::diagnostics;
@ -236,9 +236,6 @@ impl Session {
}
lints.insert(id, vec!((lint_id, sp, msg)));
}
pub fn next_node_id(&self) -> ast::NodeId {
self.reserve_node_ids(1)
}
pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
let id = self.next_node_id.get();
@ -317,6 +314,12 @@ impl Session {
}
}
impl NodeIdAssigner for Session {
fn next_node_id(&self) -> NodeId {
self.reserve_node_ids(1)
}
}
fn split_msg_into_multilines(msg: &str) -> Option<String> {
// Conditions for enabling multi-line errors:
if !msg.contains("mismatched types") &&

View File

@ -42,7 +42,7 @@ use std::ffi::{OsString, OsStr};
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use syntax::ast;
use syntax::ast::{self, NodeIdAssigner};
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::diagnostics;
@ -71,7 +71,7 @@ pub fn compile_input(sess: Session,
// We need nested scopes here, because the intermediate results can keep
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
let (sess, result) = {
let result = {
let (outputs, expanded_crate, id) = {
let krate = phase_1_parse_input(&sess, cfg, input);
@ -113,7 +113,7 @@ pub fn compile_input(sess: Session,
let expanded_crate = assign_node_ids(&sess, expanded_crate);
// Lower ast -> hir.
let foo = &42;
let lcx = LoweringContext::new(foo);
let lcx = LoweringContext::new(foo, &sess, &expanded_crate);
let mut hir_forest = time(sess.time_passes(),
"lowering ast -> hir",
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
@ -141,7 +141,7 @@ pub fn compile_input(sess: Session,
lint::check_ast_crate(&sess, &expanded_crate)
});
phase_3_run_analysis_passes(sess,
phase_3_run_analysis_passes(&sess,
ast_map,
&arenas,
id,
@ -282,7 +282,7 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
pub ast_map: Option<&'a hir_map::Map<'ast>>,
pub analysis: Option<&'a ty::CrateAnalysis>,
pub tcx: Option<&'a ty::ctxt<'tcx>>,
pub lcx: Option<&'a LoweringContext<'tcx>>,
pub lcx: Option<&'a LoweringContext<'a, 'tcx>>,
pub trans: Option<&'a trans::CrateTranslation>,
}
@ -340,7 +340,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
krate: &'a ast::Crate,
hir_crate: &'a hir::Crate,
crate_name: &'a str,
lcx: &'a LoweringContext<'tcx>)
lcx: &'a LoweringContext<'a, 'tcx>)
-> CompileState<'a, 'ast, 'tcx> {
CompileState {
crate_name: Some(crate_name),
@ -359,7 +359,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
hir_crate: &'a hir::Crate,
analysis: &'a ty::CrateAnalysis,
tcx: &'a ty::ctxt<'tcx>,
lcx: &'a LoweringContext<'tcx>)
lcx: &'a LoweringContext<'a, 'tcx>)
-> CompileState<'a, 'ast, 'tcx> {
CompileState {
analysis: Some(analysis),
@ -659,13 +659,13 @@ pub fn make_map<'ast>(sess: &Session,
/// Run the resolution, typechecking, region checking and other
/// miscellaneous analysis passes on the crate. Return various
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
ast_map: front::map::Map<'tcx>,
arenas: &'tcx ty::CtxtArenas<'tcx>,
name: String,
make_glob_map: resolve::MakeGlobMap,
f: F)
-> (Session, R)
-> R
where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>,
ty::CrateAnalysis) -> R
{
@ -673,7 +673,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
let krate = ast_map.krate();
time(time_passes, "external crate/lib resolution", ||
LocalCrateReader::new(&sess, &ast_map).read_crates(krate));
LocalCrateReader::new(sess, &ast_map).read_crates(krate));
let lang_items = time(time_passes, "language item collection", ||
middle::lang_items::collect_language_items(&sess, &ast_map));
@ -687,7 +687,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
glob_map,
} =
time(time_passes, "resolution",
|| resolve::resolve_crate(&sess, &ast_map, make_glob_map));
|| resolve::resolve_crate(sess, &ast_map, make_glob_map));
// Discard MTWT tables that aren't required past resolution.
if !sess.opts.debugging_opts.keep_mtwt_tables {
@ -695,10 +695,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
}
let named_region_map = time(time_passes, "lifetime resolution",
|| middle::resolve_lifetime::krate(&sess, krate, &def_map));
|| middle::resolve_lifetime::krate(sess, krate, &def_map));
time(time_passes, "looking for entry point",
|| middle::entry::find_entry_point(&sess, &ast_map));
|| middle::entry::find_entry_point(sess, &ast_map));
sess.plugin_registrar_fn.set(
time(time_passes, "looking for plugin registrar", ||
@ -706,13 +706,13 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
sess.diagnostic(), krate)));
let region_map = time(time_passes, "region resolution", ||
middle::region::resolve_crate(&sess, krate));
middle::region::resolve_crate(sess, krate));
time(time_passes, "loop checking", ||
middle::check_loop::check_crate(&sess, krate));
middle::check_loop::check_crate(sess, krate));
time(time_passes, "static item recursion checking", ||
middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
middle::check_static_recursion::check_crate(sess, krate, &def_map, &ast_map));
ty::ctxt::create_and_enter(sess,
arenas,

View File

@ -131,7 +131,7 @@ pub fn parse_pretty(sess: &Session,
impl PpSourceMode {
/// Constructs a `PrinterSupport` object and passes it to `f`.
fn call_with_pp_support<'tcx, A, B, F>(&self,
sess: Session,
sess: &'tcx Session,
ast_map: Option<hir_map::Map<'tcx>>,
payload: B,
f: F) -> A where
@ -155,7 +155,7 @@ impl PpSourceMode {
}
}
fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
sess: Session,
sess: &'tcx Session,
ast_map: &hir_map::Map<'tcx>,
arenas: &'tcx ty::CtxtArenas<'tcx>,
id: String,
@ -185,7 +185,7 @@ impl PpSourceMode {
|tcx, _| {
let annotation = TypedAnnotation { tcx: tcx };
f(&annotation, payload, &ast_map.forest.krate)
}).1
})
}
_ => panic!("Should use call_with_pp_support"),
}
@ -224,13 +224,13 @@ trait HirPrinterSupport<'ast>: pprust_hir::PpAnn {
fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn;
}
struct NoAnn<'ast> {
sess: Session,
struct NoAnn<'ast, 'tcx> {
sess: &'tcx Session,
ast_map: Option<hir_map::Map<'ast>>
}
impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
fn sess<'a>(&'a self) -> &'a Session { &self.sess }
impl<'ast, 'tcx> PrinterSupport<'ast> for NoAnn<'ast, 'tcx> {
fn sess<'a>(&'a self) -> &'a Session { self.sess }
fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
self.ast_map.as_ref()
@ -239,8 +239,8 @@ impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
}
impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> {
fn sess<'a>(&'a self) -> &'a Session { &self.sess }
impl<'ast, 'tcx> HirPrinterSupport<'ast> for NoAnn<'ast, 'tcx> {
fn sess<'a>(&'a self) -> &'a Session { self.sess }
fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
self.ast_map.as_ref()
@ -249,16 +249,16 @@ impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> {
fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self }
}
impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {}
impl<'ast, 'tcx> pprust::PpAnn for NoAnn<'ast, 'tcx> {}
impl<'ast, 'tcx> pprust_hir::PpAnn for NoAnn<'ast, 'tcx> {}
struct IdentifiedAnnotation<'ast> {
sess: Session,
struct IdentifiedAnnotation<'ast, 'tcx> {
sess: &'tcx Session,
ast_map: Option<hir_map::Map<'ast>>,
}
impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
fn sess<'a>(&'a self) -> &'a Session { &self.sess }
impl<'ast, 'tcx> PrinterSupport<'ast> for IdentifiedAnnotation<'ast, 'tcx> {
fn sess<'a>(&'a self) -> &'a Session { self.sess }
fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
self.ast_map.as_ref()
@ -267,7 +267,7 @@ impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
}
impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> {
impl<'ast, 'tcx> pprust::PpAnn for IdentifiedAnnotation<'ast, 'tcx> {
fn pre(&self,
s: &mut pprust::State,
node: pprust::AnnNode) -> io::Result<()> {
@ -307,8 +307,8 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> {
}
}
impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
fn sess<'a>(&'a self) -> &'a Session { &self.sess }
impl<'ast, 'tcx> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast, 'tcx> {
fn sess<'a>(&'a self) -> &'a Session { self.sess }
fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
self.ast_map.as_ref()
@ -317,7 +317,7 @@ impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
fn pp_ann<'a>(&'a self) -> &'a pprust_hir::PpAnn { self }
}
impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
impl<'ast, 'tcx> pprust_hir::PpAnn for IdentifiedAnnotation<'ast, 'tcx> {
fn pre(&self,
s: &mut pprust_hir::State,
node: pprust_hir::AnnNode) -> io::Result<()> {
@ -356,13 +356,13 @@ impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
}
}
struct HygieneAnnotation<'ast> {
sess: Session,
struct HygieneAnnotation<'ast, 'tcx> {
sess: &'tcx Session,
ast_map: Option<hir_map::Map<'ast>>,
}
impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> {
fn sess<'a>(&'a self) -> &'a Session { &self.sess }
impl<'ast, 'tcx> PrinterSupport<'ast> for HygieneAnnotation<'ast, 'tcx> {
fn sess<'a>(&'a self) -> &'a Session { self.sess }
fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
self.ast_map.as_ref()
@ -371,7 +371,7 @@ impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> {
fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self }
}
impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> {
impl<'ast, 'tcx> pprust::PpAnn for HygieneAnnotation<'ast, 'tcx> {
fn post(&self,
s: &mut pprust::State,
node: pprust::AnnNode) -> io::Result<()> {
@ -671,7 +671,7 @@ pub fn pretty_print_input(sess: Session,
// the ordering of stuff super-finicky.
let mut hir_forest;
let foo = &42;
let lcx = LoweringContext::new(foo);
let lcx = LoweringContext::new(foo, &sess, &krate);
let arenas = ty::CtxtArenas::new();
let ast_map = if compute_ast_map {
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
@ -697,7 +697,7 @@ pub fn pretty_print_input(sess: Session,
// Silently ignores an identified node.
let out: &mut Write = &mut out;
s.call_with_pp_support(
sess, ast_map, box out, |annotation, out| {
&sess, ast_map, box out, |annotation, out| {
debug!("pretty printing source code {:?}", s);
let sess = annotation.sess();
pprust::print_crate(sess.codemap(),
@ -714,7 +714,7 @@ pub fn pretty_print_input(sess: Session,
(PpmHir(s), None) => {
let out: &mut Write = &mut out;
s.call_with_pp_support_hir(
sess, &ast_map.unwrap(), &arenas, id, box out, |annotation, out, krate| {
&sess, &ast_map.unwrap(), &arenas, id, box out, |annotation, out, krate| {
debug!("pretty printing source code {:?}", s);
let sess = annotation.sess();
pprust_hir::print_crate(sess.codemap(),
@ -730,7 +730,7 @@ pub fn pretty_print_input(sess: Session,
(PpmHir(s), Some(uii)) => {
let out: &mut Write = &mut out;
s.call_with_pp_support_hir(sess,
s.call_with_pp_support_hir(&sess,
&ast_map.unwrap(),
&arenas,
id,
@ -778,14 +778,14 @@ pub fn pretty_print_input(sess: Session,
match code {
Some(code) => {
let variants = gather_flowgraph_variants(&sess);
driver::phase_3_run_analysis_passes(sess,
driver::phase_3_run_analysis_passes(&sess,
ast_map,
&arenas,
id,
resolve::MakeGlobMap::No,
|tcx, _| {
print_flowgraph(variants, tcx, code, mode, out)
}).1
})
}
None => {
let message = format!("--pretty=flowgraph needs \

View File

@ -14,20 +14,38 @@ use hir;
use syntax::ast::*;
use syntax::ptr::P;
use syntax::codemap::{respan, Spanned};
use syntax::codemap::{respan, Spanned, Span};
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::{self, str_to_ident};
use syntax::std_inject;
pub struct LoweringContext<'hir> {
pub struct LoweringContext<'a, 'hir> {
// TODO
foo: &'hir i32,
id_assigner: &'a NodeIdAssigner,
crate_root: Option<&'static str>,
}
impl<'hir> LoweringContext<'hir> {
pub fn new(foo: &'hir i32) -> LoweringContext<'hir> {
impl<'a, 'hir> LoweringContext<'a, 'hir> {
pub fn new(foo: &'hir i32, id_assigner: &'a NodeIdAssigner, c: &Crate) -> LoweringContext<'a, 'hir> {
let crate_root = if std_inject::no_core(c) {
None
} else if std_inject::no_std(c) {
Some("core")
} else {
Some("std")
};
LoweringContext {
foo: foo,
id_assigner: id_assigner,
crate_root: crate_root,
}
}
fn next_id(&self) -> NodeId {
self.id_assigner.next_node_id()
}
}
pub fn lower_view_path(_lctx: &LoweringContext, view_path: &ViewPath) -> P<hir::ViewPath> {
@ -727,105 +745,105 @@ pub fn lower_pat(_lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
})
}
pub fn lower_expr(_lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
P(hir::Expr {
id: e.id,
node: match e.node {
ExprBox(ref e) => {
hir::ExprBox(lower_expr(_lctx, e))
hir::ExprBox(lower_expr(lctx, e))
}
ExprVec(ref exprs) => {
hir::ExprVec(exprs.iter().map(|x| lower_expr(_lctx, x)).collect())
hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect())
}
ExprRepeat(ref expr, ref count) => {
hir::ExprRepeat(lower_expr(_lctx, expr), lower_expr(_lctx, count))
hir::ExprRepeat(lower_expr(lctx, expr), lower_expr(lctx, count))
}
ExprTup(ref elts) => {
hir::ExprTup(elts.iter().map(|x| lower_expr(_lctx, x)).collect())
hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect())
}
ExprCall(ref f, ref args) => {
hir::ExprCall(lower_expr(_lctx, f),
args.iter().map(|x| lower_expr(_lctx, x)).collect())
hir::ExprCall(lower_expr(lctx, f),
args.iter().map(|x| lower_expr(lctx, x)).collect())
}
ExprMethodCall(i, ref tps, ref args) => {
hir::ExprMethodCall(
respan(i.span, i.node.name),
tps.iter().map(|x| lower_ty(_lctx, x)).collect(),
args.iter().map(|x| lower_expr(_lctx, x)).collect())
tps.iter().map(|x| lower_ty(lctx, x)).collect(),
args.iter().map(|x| lower_expr(lctx, x)).collect())
}
ExprBinary(binop, ref lhs, ref rhs) => {
hir::ExprBinary(lower_binop(_lctx, binop),
lower_expr(_lctx, lhs),
lower_expr(_lctx, rhs))
hir::ExprBinary(lower_binop(lctx, binop),
lower_expr(lctx, lhs),
lower_expr(lctx, rhs))
}
ExprUnary(op, ref ohs) => {
hir::ExprUnary(lower_unop(_lctx, op), lower_expr(_lctx, ohs))
hir::ExprUnary(lower_unop(lctx, op), lower_expr(lctx, ohs))
}
ExprLit(ref l) => hir::ExprLit(P((**l).clone())),
ExprCast(ref expr, ref ty) => {
hir::ExprCast(lower_expr(_lctx, expr), lower_ty(_lctx, ty))
hir::ExprCast(lower_expr(lctx, expr), lower_ty(lctx, ty))
}
ExprAddrOf(m, ref ohs) => {
hir::ExprAddrOf(lower_mutability(_lctx, m), lower_expr(_lctx, ohs))
hir::ExprAddrOf(lower_mutability(lctx, m), lower_expr(lctx, ohs))
}
ExprIf(ref cond, ref tr, ref fl) => {
hir::ExprIf(lower_expr(_lctx, cond),
lower_block(_lctx, tr),
fl.as_ref().map(|x| lower_expr(_lctx, x)))
hir::ExprIf(lower_expr(lctx, cond),
lower_block(lctx, tr),
fl.as_ref().map(|x| lower_expr(lctx, x)))
}
ExprWhile(ref cond, ref body, opt_ident) => {
hir::ExprWhile(lower_expr(_lctx, cond),
lower_block(_lctx, body),
hir::ExprWhile(lower_expr(lctx, cond),
lower_block(lctx, body),
opt_ident)
}
ExprLoop(ref body, opt_ident) => {
hir::ExprLoop(lower_block(_lctx, body),
hir::ExprLoop(lower_block(lctx, body),
opt_ident)
}
ExprMatch(ref expr, ref arms, ref source) => {
hir::ExprMatch(lower_expr(_lctx, expr),
arms.iter().map(|x| lower_arm(_lctx, x)).collect(),
lower_match_source(_lctx, source))
hir::ExprMatch(lower_expr(lctx, expr),
arms.iter().map(|x| lower_arm(lctx, x)).collect(),
lower_match_source(lctx, source))
}
ExprClosure(capture_clause, ref decl, ref body) => {
hir::ExprClosure(lower_capture_clause(_lctx, capture_clause),
lower_fn_decl(_lctx, decl),
lower_block(_lctx, body))
hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
lower_fn_decl(lctx, decl),
lower_block(lctx, body))
}
ExprBlock(ref blk) => hir::ExprBlock(lower_block(_lctx, blk)),
ExprBlock(ref blk) => hir::ExprBlock(lower_block(lctx, blk)),
ExprAssign(ref el, ref er) => {
hir::ExprAssign(lower_expr(_lctx, el), lower_expr(_lctx, er))
hir::ExprAssign(lower_expr(lctx, el), lower_expr(lctx, er))
}
ExprAssignOp(op, ref el, ref er) => {
hir::ExprAssignOp(lower_binop(_lctx, op),
lower_expr(_lctx, el),
lower_expr(_lctx, er))
hir::ExprAssignOp(lower_binop(lctx, op),
lower_expr(lctx, el),
lower_expr(lctx, er))
}
ExprField(ref el, ident) => {
hir::ExprField(lower_expr(_lctx, el), respan(ident.span, ident.node.name))
hir::ExprField(lower_expr(lctx, el), respan(ident.span, ident.node.name))
}
ExprTupField(ref el, ident) => {
hir::ExprTupField(lower_expr(_lctx, el), ident)
hir::ExprTupField(lower_expr(lctx, el), ident)
}
ExprIndex(ref el, ref er) => {
hir::ExprIndex(lower_expr(_lctx, el), lower_expr(_lctx, er))
hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er))
}
ExprRange(ref e1, ref e2) => {
hir::ExprRange(e1.as_ref().map(|x| lower_expr(_lctx, x)),
e2.as_ref().map(|x| lower_expr(_lctx, x)))
hir::ExprRange(e1.as_ref().map(|x| lower_expr(lctx, x)),
e2.as_ref().map(|x| lower_expr(lctx, x)))
}
ExprPath(ref qself, ref path) => {
let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
hir::QSelf {
ty: lower_ty(_lctx, ty),
ty: lower_ty(lctx, ty),
position: position
}
});
hir::ExprPath(qself, lower_path(_lctx, path))
hir::ExprPath(qself, lower_path(lctx, path))
}
ExprBreak(opt_ident) => hir::ExprBreak(opt_ident),
ExprAgain(opt_ident) => hir::ExprAgain(opt_ident),
ExprRet(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(_lctx, x))),
ExprRet(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(lctx, x))),
ExprInlineAsm(InlineAsm {
ref inputs,
ref outputs,
@ -838,10 +856,10 @@ pub fn lower_expr(_lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
expn_id,
}) => hir::ExprInlineAsm(hir::InlineAsm {
inputs: inputs.iter().map(|&(ref c, ref input)| {
(c.clone(), lower_expr(_lctx, input))
(c.clone(), lower_expr(lctx, input))
}).collect(),
outputs: outputs.iter().map(|&(ref c, ref out, ref is_rw)| {
(c.clone(), lower_expr(_lctx, out), *is_rw)
(c.clone(), lower_expr(lctx, out), *is_rw)
}).collect(),
asm: asm.clone(),
asm_str_style: asm_str_style,
@ -852,17 +870,124 @@ pub fn lower_expr(_lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
expn_id: expn_id,
}),
ExprStruct(ref path, ref fields, ref maybe_expr) => {
hir::ExprStruct(lower_path(_lctx, path),
fields.iter().map(|x| lower_field(_lctx, x)).collect(),
maybe_expr.as_ref().map(|x| lower_expr(_lctx, x)))
hir::ExprStruct(lower_path(lctx, path),
fields.iter().map(|x| lower_field(lctx, x)).collect(),
maybe_expr.as_ref().map(|x| lower_expr(lctx, x)))
},
ExprParen(ref ex) => {
return lower_expr(_lctx, ex);
return lower_expr(lctx, ex);
}
ExprInPlace(..) |
ExprIfLet(..) |
ExprWhileLet(..) |
ExprForLoop(..) |
ExprInPlace(..) => {
panic!("todo");
}
ExprIfLet(..) => {
panic!("todo");
}
ExprWhileLet(..) => {
panic!("todo");
}
// Desugar ExprForLoop
// From: `[opt_ident]: for <pat> in <head> <body>`
ExprForLoop(ref pat, ref head, ref body, ref opt_ident) => {
// to:
//
// {
// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
// mut iter => {
// [opt_ident]: loop {
// match ::std::iter::Iterator::next(&mut iter) {
// ::std::option::Option::Some(<pat>) => <body>,
// ::std::option::Option::None => break
// }
// }
// }
// };
// result
// }
// expand <head>
let head = lower_expr(lctx, head);
let iter = token::gensym_ident("iter");
// `::std::option::Option::Some(<pat>) => <body>`
let pat_arm = {
let body_block = lower_block(lctx, body);
let body_span = body_block.span;
let body_expr = P(hir::Expr {
id: lctx.next_id(),
node: hir::ExprBlock(body_block),
span: body_span,
});
let pat = lower_pat(lctx, pat);
let some_pat = pat_some(lctx, e.span, pat);
arm(vec![some_pat], body_expr)
};
// `::std::option::Option::None => break`
let break_arm = {
let break_expr = expr_break(lctx, e.span);
arm(vec![pat_none(lctx, e.span)], break_expr)
};
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
let next_path = {
let strs = std_path(lctx, &["iter", "Iterator", "next"]);
path_global(e.span, strs)
};
let ref_mut_iter = expr_mut_addr_of(lctx, e.span, expr_ident(lctx, e.span, iter));
let next_expr =
expr_call(lctx, e.span, expr_path(lctx, next_path), vec![ref_mut_iter]);
let arms = vec![pat_arm, break_arm];
expr(lctx,
e.span,
hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar))
};
// `[opt_ident]: loop { ... }`
let loop_block = block_expr(lctx, match_expr);
let loop_expr = expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident.clone()));
// `mut iter => { ... }`
let iter_arm = {
let iter_pat =
pat_ident_binding_mode(lctx, e.span, iter, hir::BindByValue(hir::MutMutable));
arm(vec![iter_pat], loop_expr)
};
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
let into_iter_path = {
let strs = std_path(lctx, &["iter", "IntoIterator", "into_iter"]);
path_global(e.span, strs)
};
expr_call(lctx, e.span, expr_path(lctx, into_iter_path), vec![head])
};
let match_expr = expr_match(lctx, e.span, into_iter_expr, vec![iter_arm]);
// `{ let result = ...; result }`
let result_ident = token::gensym_ident("result");
let result = expr_block(lctx,
block_all(lctx,
e.span,
vec![stmt_let(lctx,
e.span,
false,
result_ident,
match_expr)],
Some(expr_ident(lctx, e.span, result_ident))));
return result;
}
ExprMac(_) => panic!("Shouldn't exist here"),
},
span: e.span,
@ -972,3 +1097,168 @@ pub fn lower_trait_bound_modifier(_lctx: &LoweringContext,
TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
}
}
// Helper methods for building HIR.
fn arm(pats: Vec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
hir::Arm {
attrs: vec!(),
pats: pats,
guard: None,
body: expr
}
}
fn expr_break(lctx: &LoweringContext, span: Span) -> P<hir::Expr> {
expr(lctx, span, hir::ExprBreak(None))
}
fn expr_call(lctx: &LoweringContext, span: Span, e: P<hir::Expr>, args: Vec<P<hir::Expr>>) -> P<hir::Expr> {
expr(lctx, span, hir::ExprCall(e, args))
}
fn expr_ident(lctx: &LoweringContext, span: Span, id: Ident) -> P<hir::Expr> {
expr_path(lctx, path_ident(span, id))
}
fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>) -> P<hir::Expr> {
expr(lctx, span, hir::ExprAddrOf(hir::MutMutable, e))
}
fn expr_path(lctx: &LoweringContext, path: hir::Path) -> P<hir::Expr> {
expr(lctx, path.span, hir::ExprPath(None, path))
}
fn expr_match(lctx: &LoweringContext, span: Span, arg: P<hir::Expr>, arms: Vec<hir::Arm>) -> P<hir::Expr> {
expr(lctx, span, hir::ExprMatch(arg, arms, hir::MatchSource::Normal))
}
fn expr_block(lctx: &LoweringContext, b: P<hir::Block>) -> P<hir::Expr> {
expr(lctx, b.span, hir::ExprBlock(b))
}
fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_) -> P<hir::Expr> {
P(hir::Expr {
id: lctx.next_id(),
node: node,
span: span,
})
}
fn stmt_let(lctx: &LoweringContext, sp: Span, mutbl: bool, ident: Ident, ex: P<hir::Expr>) -> P<hir::Stmt> {
let pat = if mutbl {
pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable))
} else {
pat_ident(lctx, sp, ident)
};
let local = P(hir::Local {
pat: pat,
ty: None,
init: Some(ex),
id: lctx.next_id(),
span: sp,
});
let decl = respan(sp, hir::DeclLocal(local));
P(respan(sp, hir::StmtDecl(P(decl), lctx.next_id())))
}
fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> {
block_all(lctx, expr.span, Vec::new(), Some(expr))
}
fn block_all(lctx: &LoweringContext,
span: Span,
stmts: Vec<P<hir::Stmt>>,
expr: Option<P<hir::Expr>>) -> P<hir::Block> {
P(hir::Block {
stmts: stmts,
expr: expr,
id: lctx.next_id(),
rules: hir::DefaultBlock,
span: span,
})
}
fn pat_some(lctx: &LoweringContext, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
let some = std_path(lctx, &["option", "Option", "Some"]);
let path = path_global(span, some);
pat_enum(lctx, span, path, vec!(pat))
}
fn pat_none(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
let none = std_path(lctx, &["option", "Option", "None"]);
let path = path_global(span, none);
pat_enum(lctx, span, path, vec![])
}
fn pat_enum(lctx: &LoweringContext, span: Span, path: hir::Path, subpats: Vec<P<hir::Pat>>) -> P<hir::Pat> {
let pt = hir::PatEnum(path, Some(subpats));
pat(lctx, span, pt)
}
fn pat_ident(lctx: &LoweringContext, span: Span, ident: Ident) -> P<hir::Pat> {
pat_ident_binding_mode(lctx, span, ident, hir::BindByValue(hir::MutImmutable))
}
fn pat_ident_binding_mode(lctx: &LoweringContext,
span: Span,
ident: Ident,
bm: hir::BindingMode) -> P<hir::Pat> {
let pat_ident = hir::PatIdent(bm, Spanned{span: span, node: ident}, None);
pat(lctx, span, pat_ident)
}
fn pat(lctx: &LoweringContext, span: Span, pat: hir::Pat_) -> P<hir::Pat> {
P(hir::Pat { id: lctx.next_id(), node: pat, span: span })
}
fn path_ident(span: Span, id: Ident) -> hir::Path {
path(span, vec!(id))
}
fn path(span: Span, strs: Vec<Ident> ) -> hir::Path {
path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
}
fn path_global(span: Span, strs: Vec<Ident> ) -> hir::Path {
path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
}
fn path_all(sp: Span,
global: bool,
mut idents: Vec<Ident> ,
lifetimes: Vec<hir::Lifetime>,
types: Vec<P<hir::Ty>>,
bindings: Vec<P<hir::TypeBinding>> )
-> hir::Path {
let last_identifier = idents.pop().unwrap();
let mut segments: Vec<hir::PathSegment> = idents.into_iter()
.map(|ident| {
hir::PathSegment {
identifier: ident,
parameters: hir::PathParameters::none(),
}
}).collect();
segments.push(hir::PathSegment {
identifier: last_identifier,
parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: lifetimes,
types: OwnedSlice::from_vec(types),
bindings: OwnedSlice::from_vec(bindings),
})
});
hir::Path {
span: sp,
global: global,
segments: segments,
}
}
fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec<Ident> {
let mut v = Vec::new();
if let Some(s) = lctx.crate_root {
v.push(str_to_ident(s));
}
v.extend(components.iter().map(|s| str_to_ident(s)));
return v
}

View File

@ -76,7 +76,7 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
pub fn new(tcx: &'l ty::ctxt<'tcx>,
lcx: &'l LoweringContext<'tcx>,
lcx: &'l LoweringContext<'l, 'tcx>,
analysis: &'l ty::CrateAnalysis,
output_file: Box<File>)
-> DumpCsvVisitor<'l, 'tcx> {

View File

@ -38,7 +38,7 @@ mod dump_csv;
pub struct SaveContext<'l, 'tcx: 'l> {
tcx: &'l ty::ctxt<'tcx>,
lcx: &'l lowering::LoweringContext<'tcx>,
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
span_utils: SpanUtils<'l>,
}
@ -177,13 +177,15 @@ pub struct MethodCallData {
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
pub fn new(tcx: &'l ty::ctxt<'tcx>, lcx: &'l lowering::LoweringContext<'tcx>) -> SaveContext<'l, 'tcx> {
pub fn new(tcx: &'l ty::ctxt<'tcx>,
lcx: &'l lowering::LoweringContext<'l, 'tcx>)
-> SaveContext<'l, 'tcx> {
let span_utils = SpanUtils::new(&tcx.sess);
SaveContext::from_span_utils(tcx, lcx, span_utils)
}
pub fn from_span_utils(tcx: &'l ty::ctxt<'tcx>,
lcx: &'l lowering::LoweringContext<'tcx>,
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
span_utils: SpanUtils<'l>)
-> SaveContext<'l, 'tcx> {
SaveContext {
@ -709,7 +711,7 @@ impl<'v> Visitor<'v> for PathCollector {
}
pub fn process_crate<'l, 'tcx>(tcx: &'l ty::ctxt<'tcx>,
lcx: &'l lowering::LoweringContext<'tcx>,
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
krate: &ast::Crate,
analysis: &ty::CrateAnalysis,
odir: Option<&Path>) {

View File

@ -38,6 +38,7 @@ use std::cell::RefCell;
use std::rc::Rc;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ast::NodeIdAssigner;
use util::nodemap::{DefIdMap, FnvHashMap};
use rustc::front::map as hir_map;
use rustc::front::map::NodeItem;

View File

@ -375,6 +375,10 @@ pub const CRATE_NODE_ID: NodeId = 0;
/// small, positive ids.
pub const DUMMY_NODE_ID: NodeId = !0;
pub trait NodeIdAssigner {
fn next_node_id(&self) -> NodeId;
}
/// The AST represents all type param bounds as types.
/// typeck::collect::compute_bounds matches these against
/// the "special" built-in traits (see middle::lang_items) and

View File

@ -360,102 +360,10 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident))
}
// Desugar ExprForLoop
// From: `[opt_ident]: for <pat> in <head> <body>`
ast::ExprForLoop(pat, head, body, opt_ident) => {
// to:
//
// {
// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
// mut iter => {
// [opt_ident]: loop {
// match ::std::iter::Iterator::next(&mut iter) {
// ::std::option::Option::Some(<pat>) => <body>,
// ::std::option::Option::None => break
// }
// }
// }
// };
// result
// }
push_compiler_expansion(fld, span, CompilerExpansionFormat::ForLoop);
let span = fld.new_span(span);
// expand <head>
let head = fld.fold_expr(head);
let iter = token::gensym_ident("iter");
let pat_span = fld.new_span(pat.span);
// `::std::option::Option::Some(<pat>) => <body>`
let pat_arm = {
let body_expr = fld.cx.expr_block(body);
let pat = fld.fold_pat(pat);
let some_pat = fld.cx.pat_some(pat_span, pat);
fld.cx.arm(pat_span, vec![some_pat], body_expr)
};
// `::std::option::Option::None => break`
let break_arm = {
let break_expr = fld.cx.expr_break(span);
fld.cx.arm(span, vec![fld.cx.pat_none(span)], break_expr)
};
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
let next_path = {
let strs = fld.cx.std_path(&["iter", "Iterator", "next"]);
fld.cx.path_global(span, strs)
};
let ref_mut_iter = fld.cx.expr_mut_addr_of(span, fld.cx.expr_ident(span, iter));
let next_expr =
fld.cx.expr_call(span, fld.cx.expr_path(next_path), vec![ref_mut_iter]);
let arms = vec![pat_arm, break_arm];
fld.cx.expr(pat_span,
ast::ExprMatch(next_expr, arms, ast::MatchSource::ForLoopDesugar))
};
// `[opt_ident]: loop { ... }`
let loop_block = fld.cx.block_expr(match_expr);
let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
let loop_expr = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident));
// `mut iter => { ... }`
let iter_arm = {
let iter_pat =
fld.cx.pat_ident_binding_mode(span, iter, ast::BindByValue(ast::MutMutable));
fld.cx.arm(span, vec![iter_pat], loop_expr)
};
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
let into_iter_path = {
let strs = fld.cx.std_path(&["iter", "IntoIterator",
"into_iter"]);
fld.cx.path_global(span, strs)
};
fld.cx.expr_call(span, fld.cx.expr_path(into_iter_path), vec![head])
};
let match_expr = fld.cx.expr_match(span, into_iter_expr, vec![iter_arm]);
// `{ let result = ...; result }`
let result_ident = token::gensym_ident("result");
let result = fld.cx.expr_block(
fld.cx.block_all(
span,
vec![fld.cx.stmt_let(span, false, result_ident, match_expr)],
Some(fld.cx.expr_ident(span, result_ident))));
fld.cx.bt_pop();
result
let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
fld.cx.expr(span, ast::ExprForLoop(pat, head, body, opt_ident))
}
ast::ExprClosure(capture_clause, fn_decl, block) => {