Move placement in desugaring to lowering
This commit is contained in:
parent
bc364b4a0d
commit
7f469ba6c5
2 changed files with 106 additions and 157 deletions
|
|
@ -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),
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue