diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-09-29 13:17:46 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-10-09 11:53:41 +1300 |
| commit | 7f469ba6c5b0167949540d6c2afe51a0454767f5 (patch) | |
| tree | 78d9173f74811c35171f87550b43482da389b0e4 | |
| parent | bc364b4a0d678b29cba92ce948d948aee9d76b25 (diff) | |
| download | rust-7f469ba6c5b0167949540d6c2afe51a0454767f5.tar.gz rust-7f469ba6c5b0167949540d6c2afe51a0454767f5.zip | |
Move placement in desugaring to lowering
| -rw-r--r-- | src/librustc_front/lowering.rs | 106 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 157 |
2 files changed, 106 insertions, 157 deletions
diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index d9b834fe9fc..8a8620cbcca 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -752,6 +752,83 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> { ExprBox(ref e) => { hir::ExprBox(lower_expr(lctx, e)) } + + // Desugar ExprBox: `in (PLACE) EXPR` + ExprInPlace(Some(ref placer), ref value_expr) => { + // to: + // + // let p = PLACE; + // let mut place = Placer::make_place(p); + // let raw_place = Place::pointer(&mut place); + // push_unsafe!({ + // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); + // InPlace::finalize(place) + // }) + + // TODO + println!("{}", lctx.foo); + + let placer_expr = lower_expr(lctx, placer); + let value_expr = lower_expr(lctx, value_expr); + + let placer_ident = token::gensym_ident("placer"); + let agent_ident = token::gensym_ident("place"); + let p_ptr_ident = token::gensym_ident("p_ptr"); + + let make_place = ["ops", "Placer", "make_place"]; + let place_pointer = ["ops", "Place", "pointer"]; + let move_val_init = ["intrinsics", "move_val_init"]; + let inplace_finalize = ["ops", "InPlace", "finalize"]; + + let make_call = |lctx, p, args| { + let path = core_path(lctx, e.span, p); + let path = expr_path(lctx, path); + expr_call(lctx, e.span, path, args) + }; + + let mk_stmt_let = |lctx, bind, expr| { + stmt_let(lctx, e.span, false, bind, expr) + }; + let mk_stmt_let_mut = |lctx, bind, expr| { + stmt_let(lctx, e.span, true, bind, expr) + }; + + // let placer = <placer_expr> ; + let s1 = mk_stmt_let(lctx, placer_ident, placer_expr); + + // let mut place = Placer::make_place(placer); + let s2 = { + let call = make_call(lctx, &make_place, vec![expr_ident(lctx, e.span, placer_ident)]); + mk_stmt_let_mut(lctx, agent_ident, call) + }; + + // let p_ptr = Place::pointer(&mut place); + let s3 = { + let args = vec![expr_mut_addr_of(lctx, e.span, expr_ident(lctx, e.span, agent_ident))]; + let call = make_call(lctx, &place_pointer, args); + mk_stmt_let(lctx, p_ptr_ident, call) + }; + + // pop_unsafe!(EXPR)); + let pop_unsafe_expr = pop_unsafe_expr(lctx, value_expr, e.span); + + // push_unsafe!({ + // ptr::write(p_ptr, pop_unsafe!(<value_expr>)); + // InPlace::finalize(place) + // }) + let expr = { + let call_move_val_init = hir::StmtSemi(make_call( + lctx, &move_val_init, vec![expr_ident(lctx, e.span, p_ptr_ident), pop_unsafe_expr]), lctx.next_id()); + let call_move_val_init = respan(e.span, call_move_val_init); + + let call = make_call(lctx, &inplace_finalize, vec![expr_ident(lctx, e.span, agent_ident)]); + Some(push_unsafe_expr(lctx, vec![P(call_move_val_init)], call, e.span)) + }; + + let block = block_all(lctx, e.span, vec![s1, s2, s3], expr); + return expr_block(lctx, block); + } + ExprVec(ref exprs) => { hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect()) } @@ -895,9 +972,6 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> { ExprParen(ref ex) => { return lower_expr(lctx, ex); } - ExprInPlace(..) => { - panic!("todo"); - } // Desugar ExprIfLet // From: `if let <pat> = <sub_expr> <body> [<else_opt>]` @@ -1393,3 +1467,29 @@ fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec<Ident> { v.extend(components.iter().map(|s| str_to_ident(s))); return v } + +// Given suffix ["b","c","d"], returns path `::std::b::c::d` when +// `fld.cx.use_std`, and `::core::b::c::d` otherwise. +fn core_path(lctx: &LoweringContext, span: Span, components: &[&str]) -> hir::Path { + let idents = std_path(lctx, components); + path_global(span, idents) +} + +fn push_unsafe_expr(lctx: &LoweringContext, stmts: Vec<P<hir::Stmt>>, + expr: P<hir::Expr>, span: Span) + -> P<hir::Expr> { + let rules = hir::PushUnsafeBlock(hir::CompilerGenerated); + expr_block(lctx, P(hir::Block { + rules: rules, span: span, id: lctx.next_id(), + stmts: stmts, expr: Some(expr), + })) +} + +fn pop_unsafe_expr(lctx: &LoweringContext, expr: P<hir::Expr>, span: Span) + -> P<hir::Expr> { + let rules = hir::PopUnsafeBlock(hir::CompilerGenerated); + expr_block(lctx, P(hir::Block { + rules: rules, span: span, id: lctx.next_id(), + stmts: vec![], expr: Some(expr), + })) +} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f6767bc4e47..abda406dcc8 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -20,53 +20,20 @@ use attr; use attr::AttrMetaMethods; use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; -use codemap::{CompilerExpansion, CompilerExpansionFormat}; use ext::base::*; use feature_gate::{self, Features, GatedCfg}; use fold; use fold::*; use parse; use parse::token::{fresh_mark, fresh_name, intern}; -use parse::token; use ptr::P; use util::small_vector::SmallVector; use visit; use visit::Visitor; use std_inject; -// Given suffix ["b","c","d"], returns path `::std::b::c::d` when -// `fld.cx.use_std`, and `::core::b::c::d` otherwise. -fn mk_core_path(fld: &mut MacroExpander, - span: Span, - suffix: &[&'static str]) -> ast::Path { - let idents = fld.cx.std_path(suffix); - fld.cx.path_global(span, idents) -} pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { - fn push_compiler_expansion(fld: &mut MacroExpander, span: Span, - expansion_type: CompilerExpansionFormat) { - fld.cx.bt_push(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: CompilerExpansion(expansion_type), - - // This does *not* mean code generated after - // `push_compiler_expansion` is automatically exempt - // from stability lints; must also tag such code with - // an appropriate span from `fld.cx.backtrace()`. - allow_internal_unstable: true, - - span: None, - }, - }); - } - - // Sets the expn_id so that we can use unstable methods. - fn allow_unstable(fld: &mut MacroExpander, span: Span) -> Span { - Span { expn_id: fld.cx.backtrace(), ..span } - } - let expr_span = e.span; return e.and_then(|ast::Expr {id, node, span}| match node { @@ -94,118 +61,18 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { }) } - // Desugar ExprInPlace: `in PLACE { EXPR }` ast::ExprInPlace(placer, value_expr) => { - // to: - // - // let p = PLACE; - // let mut place = Placer::make_place(p); - // let raw_place = Place::pointer(&mut place); - // push_unsafe!({ - // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); - // InPlace::finalize(place) - // }) - // Ensure feature-gate is enabled feature_gate::check_for_placement_in( fld.cx.ecfg.features, &fld.cx.parse_sess.span_diagnostic, expr_span); - push_compiler_expansion(fld, expr_span, CompilerExpansionFormat::PlacementIn); - - let value_span = value_expr.span; - let placer_span = placer.span; - - let placer_expr = fld.fold_expr(placer); + let placer = fld.fold_expr(placer); let value_expr = fld.fold_expr(value_expr); - - let placer_ident = token::gensym_ident("placer"); - let agent_ident = token::gensym_ident("place"); - let p_ptr_ident = token::gensym_ident("p_ptr"); - - let placer = fld.cx.expr_ident(span, placer_ident); - let agent = fld.cx.expr_ident(span, agent_ident); - let p_ptr = fld.cx.expr_ident(span, p_ptr_ident); - - let make_place = ["ops", "Placer", "make_place"]; - let place_pointer = ["ops", "Place", "pointer"]; - let move_val_init = ["intrinsics", "move_val_init"]; - let inplace_finalize = ["ops", "InPlace", "finalize"]; - - let make_call = |fld: &mut MacroExpander, p, args| { - // We feed in the `expr_span` because codemap's span_allows_unstable - // allows the call_site span to inherit the `allow_internal_unstable` - // setting. - let span_unstable = allow_unstable(fld, expr_span); - let path = mk_core_path(fld, span_unstable, p); - let path = fld.cx.expr_path(path); - let expr_span_unstable = allow_unstable(fld, span); - fld.cx.expr_call(expr_span_unstable, path, args) - }; - - let stmt_let = |fld: &mut MacroExpander, bind, expr| { - fld.cx.stmt_let(placer_span, false, bind, expr) - }; - let stmt_let_mut = |fld: &mut MacroExpander, bind, expr| { - fld.cx.stmt_let(placer_span, true, bind, expr) - }; - - // let placer = <placer_expr> ; - let s1 = stmt_let(fld, placer_ident, placer_expr); - - // let mut place = Placer::make_place(placer); - let s2 = { - let call = make_call(fld, &make_place, vec![placer]); - stmt_let_mut(fld, agent_ident, call) - }; - - // let p_ptr = Place::pointer(&mut place); - let s3 = { - let args = vec![fld.cx.expr_mut_addr_of(placer_span, agent.clone())]; - let call = make_call(fld, &place_pointer, args); - stmt_let(fld, p_ptr_ident, call) - }; - - // pop_unsafe!(EXPR)); - let pop_unsafe_expr = pop_unsafe_expr(fld.cx, value_expr, value_span); - - // push_unsafe!({ - // ptr::write(p_ptr, pop_unsafe!(<value_expr>)); - // InPlace::finalize(place) - // }) - let expr = { - let call_move_val_init = StmtSemi(make_call( - fld, &move_val_init, vec![p_ptr, pop_unsafe_expr]), ast::DUMMY_NODE_ID); - let call_move_val_init = codemap::respan(value_span, call_move_val_init); - - let call = make_call(fld, &inplace_finalize, vec![agent]); - Some(push_unsafe_expr(fld.cx, vec![P(call_move_val_init)], call, span)) - }; - - let block = fld.cx.block_all(span, vec![s1, s2, s3], expr); - let result = fld.cx.expr_block(block); - fld.cx.bt_pop(); - result + fld.cx.expr(span, ast::ExprBox(Some(placer), value_expr)) } - // Issue #22181: - // Eventually a desugaring for `box EXPR` - // (similar to the desugaring above for `in PLACE BLOCK`) - // should go here, desugaring - // - // to: - // - // let mut place = BoxPlace::make_place(); - // let raw_place = Place::pointer(&mut place); - // let value = $value; - // unsafe { - // ::std::ptr::write(raw_place, value); - // Boxed::finalize(place) - // } - // - // But for now there are type-inference issues doing that. - ast::ExprWhile(cond, body, opt_ident) => { let cond = fld.fold_expr(cond); let (body, opt_ident) = expand_loop_block(body, opt_ident, fld); @@ -225,6 +92,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { } ast::ExprForLoop(pat, head, body, opt_ident) => { + let pat = fld.fold_pat(pat); let head = fld.fold_expr(head); let (body, opt_ident) = expand_loop_block(body, opt_ident, fld); fld.cx.expr(span, ast::ExprForLoop(pat, head, body, opt_ident)) @@ -247,25 +115,6 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { }, fld)) } }); - - fn push_unsafe_expr(cx: &mut ExtCtxt, stmts: Vec<P<ast::Stmt>>, - expr: P<ast::Expr>, span: Span) - -> P<ast::Expr> { - let rules = ast::PushUnsafeBlock(ast::CompilerGenerated); - cx.expr_block(P(ast::Block { - rules: rules, span: span, id: ast::DUMMY_NODE_ID, - stmts: stmts, expr: Some(expr), - })) - } - - fn pop_unsafe_expr(cx: &mut ExtCtxt, expr: P<ast::Expr>, span: Span) - -> P<ast::Expr> { - let rules = ast::PopUnsafeBlock(ast::CompilerGenerated); - cx.expr_block(P(ast::Block { - rules: rules, span: span, id: ast::DUMMY_NODE_ID, - stmts: vec![], expr: Some(expr), - })) - } } /// Expand a (not-ident-style) macro invocation. Returns the result |
