blob: c70b22893ae2e1a35429a3b2e5d8504f067a6eda [file] [log] [blame]
// Copyright 2015 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 build::{BlockAnd, BlockAndExtension, Builder};
use hair::*;
use rustc::mir::repr::*;
impl<'a,'tcx> Builder<'a,'tcx> {
pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<'tcx>>) -> BlockAnd<()> {
// This convoluted structure is to avoid using recursion as we walk down a list
// of statements. Basically, the structure we get back is something like:
//
// let x = <init> in {
// let y = <init> in {
// expr1;
// expr2;
// }
// }
//
// To process this, we keep a stack of (Option<CodeExtent>,
// vec::IntoIter<Stmt>) pairs. At each point we pull off the
// top most pair and extract one statement from the
// iterator. Once it's complete, we pop the scope from the
// first half the pair.
let this = self;
let mut stmt_lists = vec![(None, stmts.into_iter())];
while !stmt_lists.is_empty() {
let stmt = {
let &mut (_, ref mut stmts) = stmt_lists.last_mut().unwrap();
stmts.next()
};
let stmt = match stmt {
Some(stmt) => stmt,
None => {
let (extent, _) = stmt_lists.pop().unwrap();
if let Some(extent) = extent {
this.pop_scope(extent, block);
}
continue
}
};
let Stmt { span, kind } = this.hir.mirror(stmt);
match kind {
StmtKind::Let { remainder_scope, init_scope, pattern, initializer, stmts } => {
this.push_scope(remainder_scope, block);
stmt_lists.push((Some(remainder_scope), stmts.into_iter()));
unpack!(block = this.in_scope(init_scope, block, move |this| {
// FIXME #30046 ^~~~
match initializer {
Some(initializer) => {
this.expr_into_pattern(block, remainder_scope, pattern, initializer)
}
None => {
this.declare_bindings(remainder_scope, &pattern);
block.unit()
}
}
}));
}
StmtKind::Expr { scope, expr } => {
unpack!(block = this.in_scope(scope, block, |this| {
let expr = this.hir.mirror(expr);
let temp = this.temp(expr.ty.clone());
unpack!(block = this.into(&temp, block, expr));
this.cfg.push_drop(block, span, DropKind::Deep, &temp);
block.unit()
}));
}
}
}
block.unit()
}
}