Refactor helper routines to be less tied to match syntax

This commit is contained in:
Niko Matsakis 2013-05-29 16:32:07 -04:00
parent dcd84901c6
commit 2616581863

View file

@ -1124,10 +1124,10 @@ pub fn compare_values(cx: block,
}
}
pub fn store_non_ref_bindings(bcx: block,
data: &ArmData,
opt_temp_cleanups: Option<&mut ~[ValueRef]>)
-> block
fn store_non_ref_bindings(bcx: block,
bindings_map: &BindingsMap,
mut opt_temp_cleanups: Option<&mut ~[ValueRef]>)
-> block
{
/*!
*
@ -1139,8 +1139,7 @@ pub fn store_non_ref_bindings(bcx: block,
*/
let mut bcx = bcx;
let mut opt_temp_cleanups = opt_temp_cleanups;
for data.bindings_map.each_value |&binding_info| {
for bindings_map.each_value |&binding_info| {
match binding_info.trmode {
TrByValue(is_move, lldest) => {
let llval = Load(bcx, binding_info.llmatch); // get a T*
@ -1166,16 +1165,22 @@ pub fn store_non_ref_bindings(bcx: block,
return bcx;
}
pub fn insert_lllocals(bcx: block,
data: &ArmData,
add_cleans: bool) -> block {
fn insert_lllocals(bcx: block,
bindings_map: &BindingsMap,
binding_mode: IrrefutablePatternBindingMode,
add_cleans: bool) -> block {
/*!
*
* For each binding in `data.bindings_map`, adds an appropriate entry into
* the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for
* the bindings. */
* the bindings.
*/
for data.bindings_map.each_value |&binding_info| {
let llmap = match binding_mode {
BindLocal => bcx.fcx.lllocals,
BindArgument => bcx.fcx.llargs
};
for bindings_map.each_value |&binding_info| {
let llval = match binding_info.trmode {
// By value bindings: use the stack slot that we
// copied/moved the value into
@ -1193,8 +1198,10 @@ pub fn insert_lllocals(bcx: block,
}
};
bcx.fcx.lllocals.insert(binding_info.id,
local_mem(llval));
debug!("binding %? to %s",
binding_info.id,
val_str(bcx.ccx().tn, llval));
llmap.insert(binding_info.id, local_mem(llval));
}
return bcx;
}
@ -1215,8 +1222,8 @@ pub fn compile_guard(bcx: block,
let mut bcx = bcx;
let mut temp_cleanups = ~[];
bcx = store_non_ref_bindings(bcx, data, Some(&mut temp_cleanups));
bcx = insert_lllocals(bcx, data, false);
bcx = store_non_ref_bindings(bcx, &data.bindings_map, Some(&mut temp_cleanups));
bcx = insert_lllocals(bcx, &data.bindings_map, BindLocal, false);
let val = unpack_result!(bcx, {
do with_scope_result(bcx, guard_expr.info(),
@ -1613,6 +1620,42 @@ pub fn trans_match(bcx: block,
}
}
fn create_bindings_map(bcx: block, pat: @ast::pat) -> BindingsMap {
// Create the bindings map, which is a mapping from each binding name
// to an alloca() that will be the value for that local variable.
// Note that we use the names because each binding will have many ids
// from the various alternatives.
let ccx = bcx.ccx();
let tcx = bcx.tcx();
let mut bindings_map = HashMap::new();
do pat_bindings(tcx.def_map, pat) |bm, p_id, _s, path| {
let ident = path_to_ident(path);
let variable_ty = node_id_type(bcx, p_id);
let llvariable_ty = type_of::type_of(ccx, variable_ty);
let llmatch, trmode;
match bm {
ast::bind_by_copy | ast::bind_infer => {
// in this case, the final type of the variable will be T,
// but during matching we need to store a *T as explained
// above
let is_move = ccx.maps.moves_map.contains(&p_id);
llmatch = alloca(bcx, T_ptr(llvariable_ty));
trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
}
ast::bind_by_ref(_) => {
llmatch = alloca(bcx, llvariable_ty);
trmode = TrByRef;
}
};
bindings_map.insert(ident, BindingInfo {
llmatch: llmatch, trmode: trmode,
id: p_id, ty: variable_ty
});
}
return bindings_map;
}
pub fn trans_match_inner(scope_cx: block,
discr_expr: @ast::expr,
arms: &[ast::arm],
@ -1629,41 +1672,9 @@ pub fn trans_match_inner(scope_cx: block,
}
let mut arm_datas = ~[], matches = ~[];
for arms.each |arm| {
let body = scope_block(bcx, arm.body.info(), "case_body");
// Create the bindings map, which is a mapping from each binding name
// to an alloca() that will be the value for that local variable.
// Note that we use the names because each binding will have many ids
// from the various alternatives.
let mut bindings_map = HashMap::new();
do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, _s, path| {
let ident = path_to_ident(path);
let variable_ty = node_id_type(bcx, p_id);
let llvariable_ty = type_of::type_of(bcx.ccx(), variable_ty);
let llmatch, trmode;
match bm {
ast::bind_by_copy | ast::bind_infer => {
// in this case, the final type of the variable will be T,
// but during matching we need to store a *T as explained
// above
let is_move =
scope_cx.ccx().maps.moves_map.contains(&p_id);
llmatch = alloca(bcx, T_ptr(llvariable_ty));
trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
}
ast::bind_by_ref(_) => {
llmatch = alloca(bcx, llvariable_ty);
trmode = TrByRef;
}
};
bindings_map.insert(ident, BindingInfo {
llmatch: llmatch, trmode: trmode,
id: p_id, ty: variable_ty
});
}
for vec::each(arms) |arm| {
let body = scope_block(bcx, arm.body.info(), ~"case_body");
let bindings_map = create_bindings_map(bcx, arm.pats[0]);
let arm_data = @ArmData {bodycx: body,
arm: arm,
bindings_map: bindings_map};
@ -1697,11 +1708,11 @@ pub fn trans_match_inner(scope_cx: block,
// is just to reduce code space. See extensive comment at the start
// of the file for more details.
if arm_data.arm.guard.is_none() {
bcx = store_non_ref_bindings(bcx, *arm_data, None);
bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None);
}
// insert bindings into the lllocals map and add cleanups
bcx = insert_lllocals(bcx, *arm_data, true);
bcx = insert_lllocals(bcx, &arm_data.bindings_map, BindLocal, true);
bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest);
bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));