mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Merge pull request #2096 from rtfeldman/alias-analysis-pull-heap-cell-out
alias analysis: recursive tag union refactor
This commit is contained in:
commit
adb8ff881c
9 changed files with 182 additions and 112 deletions
|
@ -686,8 +686,8 @@ where
|
||||||
self.set_last_seen(*sym, stmt, &owning_symbol);
|
self.set_last_seen(*sym, stmt, &owning_symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Reset(sym) => {
|
Expr::Reset { symbol, .. } => {
|
||||||
self.set_last_seen(*sym, stmt, &owning_symbol);
|
self.set_last_seen(*symbol, stmt, &owning_symbol);
|
||||||
}
|
}
|
||||||
Expr::EmptyArray => {}
|
Expr::EmptyArray => {}
|
||||||
Expr::RuntimeErrorFunction(_) => {}
|
Expr::RuntimeErrorFunction(_) => {}
|
||||||
|
|
|
@ -1108,7 +1108,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
..
|
..
|
||||||
} => build_tag(env, scope, union_layout, *tag_id, arguments, None, parent),
|
} => build_tag(env, scope, union_layout, *tag_id, arguments, None, parent),
|
||||||
|
|
||||||
Reset(symbol) => {
|
Reset { symbol, .. } => {
|
||||||
let (tag_ptr, layout) = load_symbol_and_layout(scope, symbol);
|
let (tag_ptr, layout) = load_symbol_and_layout(scope, symbol);
|
||||||
let tag_ptr = tag_ptr.into_pointer_value();
|
let tag_ptr = tag_ptr.into_pointer_value();
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ use roc_module::symbol::{
|
||||||
};
|
};
|
||||||
use roc_mono::ir::{
|
use roc_mono::ir::{
|
||||||
CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, Proc, ProcLayout, Procs,
|
CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, Proc, ProcLayout, Procs,
|
||||||
|
UpdateModeIds,
|
||||||
};
|
};
|
||||||
use roc_mono::layout::{Layout, LayoutCache, LayoutProblem};
|
use roc_mono::layout::{Layout, LayoutCache, LayoutProblem};
|
||||||
use roc_parse::ast::{self, StrLiteral, TypeAnnotation};
|
use roc_parse::ast::{self, StrLiteral, TypeAnnotation};
|
||||||
|
@ -835,6 +836,7 @@ enum Msg<'a> {
|
||||||
external_specializations_requested: BumpMap<ModuleId, ExternalSpecializations>,
|
external_specializations_requested: BumpMap<ModuleId, ExternalSpecializations>,
|
||||||
procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
problems: Vec<roc_mono::ir::MonoProblem>,
|
problems: Vec<roc_mono::ir::MonoProblem>,
|
||||||
|
update_mode_ids: UpdateModeIds,
|
||||||
module_timing: ModuleTiming,
|
module_timing: ModuleTiming,
|
||||||
subs: Subs,
|
subs: Subs,
|
||||||
},
|
},
|
||||||
|
@ -2098,6 +2100,7 @@ fn update<'a>(
|
||||||
MadeSpecializations {
|
MadeSpecializations {
|
||||||
module_id,
|
module_id,
|
||||||
mut ident_ids,
|
mut ident_ids,
|
||||||
|
mut update_mode_ids,
|
||||||
subs,
|
subs,
|
||||||
procedures,
|
procedures,
|
||||||
external_specializations_requested,
|
external_specializations_requested,
|
||||||
|
@ -2124,6 +2127,7 @@ fn update<'a>(
|
||||||
arena,
|
arena,
|
||||||
module_id,
|
module_id,
|
||||||
&mut ident_ids,
|
&mut ident_ids,
|
||||||
|
&mut update_mode_ids,
|
||||||
&mut state.procedures,
|
&mut state.procedures,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3922,6 +3926,7 @@ fn make_specializations<'a>(
|
||||||
) -> Msg<'a> {
|
) -> Msg<'a> {
|
||||||
let make_specializations_start = SystemTime::now();
|
let make_specializations_start = SystemTime::now();
|
||||||
let mut mono_problems = Vec::new();
|
let mut mono_problems = Vec::new();
|
||||||
|
let mut update_mode_ids = UpdateModeIds::new();
|
||||||
// do the thing
|
// do the thing
|
||||||
let mut mono_env = roc_mono::ir::Env {
|
let mut mono_env = roc_mono::ir::Env {
|
||||||
arena,
|
arena,
|
||||||
|
@ -3930,7 +3935,7 @@ fn make_specializations<'a>(
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
ptr_bytes,
|
ptr_bytes,
|
||||||
update_mode_counter: 0,
|
update_mode_ids: &mut update_mode_ids,
|
||||||
// call_specialization_counter=0 is reserved
|
// call_specialization_counter=0 is reserved
|
||||||
call_specialization_counter: 1,
|
call_specialization_counter: 1,
|
||||||
};
|
};
|
||||||
|
@ -3973,6 +3978,7 @@ fn make_specializations<'a>(
|
||||||
layout_cache,
|
layout_cache,
|
||||||
procedures,
|
procedures,
|
||||||
problems: mono_problems,
|
problems: mono_problems,
|
||||||
|
update_mode_ids,
|
||||||
subs,
|
subs,
|
||||||
external_specializations_requested,
|
external_specializations_requested,
|
||||||
module_timing,
|
module_timing,
|
||||||
|
@ -4016,6 +4022,7 @@ fn build_pending_specializations<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mono_problems = std::vec::Vec::new();
|
let mut mono_problems = std::vec::Vec::new();
|
||||||
|
let mut update_mode_ids = UpdateModeIds::new();
|
||||||
let mut subs = solved_subs.into_inner();
|
let mut subs = solved_subs.into_inner();
|
||||||
let mut mono_env = roc_mono::ir::Env {
|
let mut mono_env = roc_mono::ir::Env {
|
||||||
arena,
|
arena,
|
||||||
|
@ -4024,7 +4031,7 @@ fn build_pending_specializations<'a>(
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
ptr_bytes,
|
ptr_bytes,
|
||||||
update_mode_counter: 0,
|
update_mode_ids: &mut update_mode_ids,
|
||||||
// call_specialization_counter=0 is reserved
|
// call_specialization_counter=0 is reserved
|
||||||
call_specialization_counter: 1,
|
call_specialization_counter: 1,
|
||||||
};
|
};
|
||||||
|
|
|
@ -210,12 +210,15 @@ where
|
||||||
|
|
||||||
let mut builder = TypeDefBuilder::new();
|
let mut builder = TypeDefBuilder::new();
|
||||||
|
|
||||||
let variant_types = build_variant_types(&mut builder, &union_layout)?;
|
let variant_types = recursive_variant_types(&mut builder, &union_layout)?;
|
||||||
let root_type = if let UnionLayout::NonNullableUnwrapped(_) = union_layout {
|
let root_type = if let UnionLayout::NonNullableUnwrapped(_) = union_layout {
|
||||||
debug_assert_eq!(variant_types.len(), 1);
|
debug_assert_eq!(variant_types.len(), 1);
|
||||||
variant_types[0]
|
variant_types[0]
|
||||||
} else {
|
} else {
|
||||||
builder.add_union_type(&variant_types)?
|
let data_type = builder.add_union_type(&variant_types)?;
|
||||||
|
let cell_type = builder.add_heap_cell_type();
|
||||||
|
|
||||||
|
builder.add_tuple_type(&[cell_type, data_type])?
|
||||||
};
|
};
|
||||||
|
|
||||||
let type_def = builder.build(root_type)?;
|
let type_def = builder.build(root_type)?;
|
||||||
|
@ -867,8 +870,7 @@ fn call_spec(
|
||||||
|
|
||||||
builder.add_update(block, update_mode_var, cell)?;
|
builder.add_update(block, update_mode_var, cell)?;
|
||||||
|
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, bag)
|
||||||
builder.add_make_tuple(block, &[new_cell, bag])
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0]));
|
let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0]));
|
||||||
|
@ -998,9 +1000,8 @@ fn call_spec(
|
||||||
builder.add_recursive_touch(block, removed_element)?;
|
builder.add_recursive_touch(block, removed_element)?;
|
||||||
|
|
||||||
let new_bag = builder.add_get_tuple_field(block, removed, 0)?;
|
let new_bag = builder.add_get_tuple_field(block, removed, 0)?;
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
|
||||||
|
|
||||||
builder.add_make_tuple(block, &[new_cell, new_bag])
|
with_new_heap_cell(builder, block, new_bag)
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0]));
|
let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0]));
|
||||||
|
@ -1181,8 +1182,7 @@ fn list_append(
|
||||||
|
|
||||||
let new_bag = builder.add_bag_insert(block, bag, to_insert)?;
|
let new_bag = builder.add_bag_insert(block, bag, to_insert)?;
|
||||||
|
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, new_bag)
|
||||||
builder.add_make_tuple(block, &[new_cell, new_bag])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lowlevel_spec(
|
fn lowlevel_spec(
|
||||||
|
@ -1268,8 +1268,7 @@ fn lowlevel_spec(
|
||||||
|
|
||||||
builder.add_bag_insert(block, bag, to_insert)?;
|
builder.add_bag_insert(block, bag, to_insert)?;
|
||||||
|
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, bag)
|
||||||
builder.add_make_tuple(block, &[new_cell, bag])
|
|
||||||
}
|
}
|
||||||
ListSwap => {
|
ListSwap => {
|
||||||
let list = env.symbols[&arguments[0]];
|
let list = env.symbols[&arguments[0]];
|
||||||
|
@ -1279,8 +1278,7 @@ fn lowlevel_spec(
|
||||||
|
|
||||||
let _unit = builder.add_update(block, update_mode_var, cell)?;
|
let _unit = builder.add_update(block, update_mode_var, cell)?;
|
||||||
|
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, bag)
|
||||||
builder.add_make_tuple(block, &[new_cell, bag])
|
|
||||||
}
|
}
|
||||||
ListReverse => {
|
ListReverse => {
|
||||||
let list = env.symbols[&arguments[0]];
|
let list = env.symbols[&arguments[0]];
|
||||||
|
@ -1290,8 +1288,7 @@ fn lowlevel_spec(
|
||||||
|
|
||||||
let _unit = builder.add_update(block, update_mode_var, cell)?;
|
let _unit = builder.add_update(block, update_mode_var, cell)?;
|
||||||
|
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, bag)
|
||||||
builder.add_make_tuple(block, &[new_cell, bag])
|
|
||||||
}
|
}
|
||||||
ListAppend => {
|
ListAppend => {
|
||||||
let list = env.symbols[&arguments[0]];
|
let list = env.symbols[&arguments[0]];
|
||||||
|
@ -1359,8 +1356,7 @@ fn lowlevel_spec(
|
||||||
|
|
||||||
builder.add_bag_insert(block, bag, key_value)?;
|
builder.add_bag_insert(block, bag, key_value)?;
|
||||||
|
|
||||||
let new_cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, bag)
|
||||||
builder.add_make_tuple(block, &[new_cell, bag])
|
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {
|
||||||
// println!("missing {:?}", _other);
|
// println!("missing {:?}", _other);
|
||||||
|
@ -1381,13 +1377,10 @@ fn recursive_tag_variant(
|
||||||
) -> Result<TypeId> {
|
) -> Result<TypeId> {
|
||||||
let when_recursive = WhenRecursive::Loop(*union_layout);
|
let when_recursive = WhenRecursive::Loop(*union_layout);
|
||||||
|
|
||||||
let data_id = build_recursive_tuple_type(builder, fields, &when_recursive)?;
|
build_recursive_tuple_type(builder, fields, &when_recursive)
|
||||||
let cell_id = builder.add_heap_cell_type();
|
|
||||||
|
|
||||||
builder.add_tuple_type(&[cell_id, data_id])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_variant_types(
|
fn recursive_variant_types(
|
||||||
builder: &mut impl TypeContext,
|
builder: &mut impl TypeContext,
|
||||||
union_layout: &UnionLayout,
|
union_layout: &UnionLayout,
|
||||||
) -> Result<Vec<TypeId>> {
|
) -> Result<Vec<TypeId>> {
|
||||||
|
@ -1396,12 +1389,8 @@ fn build_variant_types(
|
||||||
let mut result;
|
let mut result;
|
||||||
|
|
||||||
match union_layout {
|
match union_layout {
|
||||||
NonRecursive(tags) => {
|
NonRecursive(_) => {
|
||||||
result = Vec::with_capacity(tags.len());
|
unreachable!()
|
||||||
|
|
||||||
for tag in tags.iter() {
|
|
||||||
result.push(build_tuple_type(builder, tag)?);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Recursive(tags) => {
|
Recursive(tags) => {
|
||||||
result = Vec::with_capacity(tags.len());
|
result = Vec::with_capacity(tags.len());
|
||||||
|
@ -1425,8 +1414,7 @@ fn build_variant_types(
|
||||||
result.push(recursive_tag_variant(builder, union_layout, tag)?);
|
result.push(recursive_tag_variant(builder, union_layout, tag)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let unit = builder.add_tuple_type(&[])?;
|
result.push(recursive_tag_variant(builder, union_layout, &[])?);
|
||||||
result.push(unit);
|
|
||||||
|
|
||||||
for tag in tags[cutoff..].iter() {
|
for tag in tags[cutoff..].iter() {
|
||||||
result.push(recursive_tag_variant(builder, union_layout, tag)?);
|
result.push(recursive_tag_variant(builder, union_layout, tag)?);
|
||||||
|
@ -1436,7 +1424,7 @@ fn build_variant_types(
|
||||||
nullable_id,
|
nullable_id,
|
||||||
other_fields: fields,
|
other_fields: fields,
|
||||||
} => {
|
} => {
|
||||||
let unit = builder.add_tuple_type(&[])?;
|
let unit = recursive_tag_variant(builder, union_layout, &[])?;
|
||||||
let other_type = recursive_tag_variant(builder, union_layout, fields)?;
|
let other_type = recursive_tag_variant(builder, union_layout, fields)?;
|
||||||
|
|
||||||
if *nullable_id {
|
if *nullable_id {
|
||||||
|
@ -1482,18 +1470,16 @@ fn expr_spec<'a>(
|
||||||
tag_id,
|
tag_id,
|
||||||
arguments,
|
arguments,
|
||||||
} => {
|
} => {
|
||||||
let variant_types = build_variant_types(builder, tag_layout)?;
|
|
||||||
|
|
||||||
let data_id = build_tuple_value(builder, env, block, arguments)?;
|
let data_id = build_tuple_value(builder, env, block, arguments)?;
|
||||||
let cell_id = builder.add_new_heap_cell(block)?;
|
|
||||||
|
|
||||||
let value_id = match tag_layout {
|
let value_id = match tag_layout {
|
||||||
UnionLayout::NonRecursive(_) => {
|
UnionLayout::NonRecursive(tags) => {
|
||||||
|
let variant_types = non_recursive_variant_types(builder, tags)?;
|
||||||
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
||||||
return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id);
|
return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id);
|
||||||
}
|
}
|
||||||
UnionLayout::NonNullableUnwrapped(_) => {
|
UnionLayout::NonNullableUnwrapped(_) => {
|
||||||
let value_id = builder.add_make_tuple(block, &[cell_id, data_id])?;
|
let value_id = data_id;
|
||||||
|
|
||||||
let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes();
|
let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes();
|
||||||
let type_name = TypeName(&type_name_bytes);
|
let type_name = TypeName(&type_name_bytes);
|
||||||
|
@ -1502,32 +1488,24 @@ fn expr_spec<'a>(
|
||||||
|
|
||||||
return builder.add_make_named(block, MOD_APP, type_name, value_id);
|
return builder.add_make_named(block, MOD_APP, type_name, value_id);
|
||||||
}
|
}
|
||||||
UnionLayout::Recursive(_) => builder.add_make_tuple(block, &[cell_id, data_id])?,
|
UnionLayout::Recursive(_) => data_id,
|
||||||
UnionLayout::NullableWrapped { nullable_id, .. } => {
|
UnionLayout::NullableWrapped { .. } => data_id,
|
||||||
if *tag_id == *nullable_id as _ {
|
UnionLayout::NullableUnwrapped { .. } => data_id,
|
||||||
data_id
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[cell_id, data_id])?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnionLayout::NullableUnwrapped { nullable_id, .. } => {
|
|
||||||
if *tag_id == *nullable_id as _ {
|
|
||||||
data_id
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[cell_id, data_id])?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let variant_types = recursive_variant_types(builder, tag_layout)?;
|
||||||
|
|
||||||
let union_id =
|
let union_id =
|
||||||
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)?;
|
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)?;
|
||||||
|
|
||||||
|
let tag_value_id = with_new_heap_cell(builder, block, union_id)?;
|
||||||
|
|
||||||
let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes();
|
let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes();
|
||||||
let type_name = TypeName(&type_name_bytes);
|
let type_name = TypeName(&type_name_bytes);
|
||||||
|
|
||||||
env.type_names.insert(*tag_layout);
|
env.type_names.insert(*tag_layout);
|
||||||
|
|
||||||
builder.add_make_named(block, MOD_APP, type_name, union_id)
|
builder.add_make_named(block, MOD_APP, type_name, tag_value_id)
|
||||||
}
|
}
|
||||||
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
||||||
UnionAtIndex {
|
UnionAtIndex {
|
||||||
|
@ -1553,16 +1531,20 @@ fn expr_spec<'a>(
|
||||||
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
|
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
|
||||||
let type_name = TypeName(&type_name_bytes);
|
let type_name = TypeName(&type_name_bytes);
|
||||||
|
|
||||||
|
// unwrap the named wrapper
|
||||||
let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?;
|
let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?;
|
||||||
let variant_id = builder.add_unwrap_union(block, union_id, *tag_id as u32)?;
|
|
||||||
|
// now we have a tuple (cell, union { ... }); decompose
|
||||||
|
let heap_cell = builder.add_get_tuple_field(block, union_id, TAG_CELL_INDEX)?;
|
||||||
|
let union_data = builder.add_get_tuple_field(block, union_id, TAG_DATA_INDEX)?;
|
||||||
|
|
||||||
// we're reading from this value, so touch the heap cell
|
// we're reading from this value, so touch the heap cell
|
||||||
let heap_cell = builder.add_get_tuple_field(block, variant_id, 0)?;
|
|
||||||
builder.add_touch(block, heap_cell)?;
|
builder.add_touch(block, heap_cell)?;
|
||||||
|
|
||||||
let tuple_value_id = builder.add_get_tuple_field(block, variant_id, 1)?;
|
// next, unwrap the union at the tag id that we've got
|
||||||
|
let variant_id = builder.add_unwrap_union(block, union_data, *tag_id as u32)?;
|
||||||
|
|
||||||
builder.add_get_tuple_field(block, tuple_value_id, index)
|
builder.add_get_tuple_field(block, variant_id, index)
|
||||||
}
|
}
|
||||||
UnionLayout::NonNullableUnwrapped { .. } => {
|
UnionLayout::NonNullableUnwrapped { .. } => {
|
||||||
let index = (*index) as u32;
|
let index = (*index) as u32;
|
||||||
|
@ -1573,16 +1555,20 @@ fn expr_spec<'a>(
|
||||||
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
|
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
|
||||||
let type_name = TypeName(&type_name_bytes);
|
let type_name = TypeName(&type_name_bytes);
|
||||||
|
|
||||||
let variant_id =
|
// a tuple ( cell, union { ... } )
|
||||||
builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?;
|
let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?;
|
||||||
|
|
||||||
|
// decompose
|
||||||
|
let heap_cell = builder.add_get_tuple_field(block, union_id, TAG_CELL_INDEX)?;
|
||||||
|
let union_data = builder.add_get_tuple_field(block, union_id, TAG_DATA_INDEX)?;
|
||||||
|
|
||||||
// we're reading from this value, so touch the heap cell
|
// we're reading from this value, so touch the heap cell
|
||||||
let heap_cell = builder.add_get_tuple_field(block, variant_id, 0)?;
|
|
||||||
builder.add_touch(block, heap_cell)?;
|
builder.add_touch(block, heap_cell)?;
|
||||||
|
|
||||||
let tuple_value_id = builder.add_get_tuple_field(block, variant_id, 1)?;
|
// next, unwrap the union at the tag id that we've got
|
||||||
|
let variant_id = builder.add_unwrap_union(block, union_data, *tag_id as u32)?;
|
||||||
|
|
||||||
builder.add_get_tuple_field(block, tuple_value_id, index)
|
builder.add_get_tuple_field(block, variant_id, index)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
StructAtIndex {
|
StructAtIndex {
|
||||||
|
@ -1613,9 +1599,7 @@ fn expr_spec<'a>(
|
||||||
if all_constants {
|
if all_constants {
|
||||||
new_static_list(builder, block)
|
new_static_list(builder, block)
|
||||||
} else {
|
} else {
|
||||||
let cell = builder.add_new_heap_cell(block)?;
|
with_new_heap_cell(builder, block, bag)
|
||||||
|
|
||||||
builder.add_make_tuple(block, &[cell, bag])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1626,7 +1610,7 @@ fn expr_spec<'a>(
|
||||||
}
|
}
|
||||||
_ => unreachable!("empty array does not have a list layout"),
|
_ => unreachable!("empty array does not have a list layout"),
|
||||||
},
|
},
|
||||||
Reset(symbol) => {
|
Reset { symbol, .. } => {
|
||||||
let type_id = layout_spec(builder, layout)?;
|
let type_id = layout_spec(builder, layout)?;
|
||||||
let value_id = env.symbols[symbol];
|
let value_id = env.symbols[symbol];
|
||||||
|
|
||||||
|
@ -1637,7 +1621,11 @@ fn expr_spec<'a>(
|
||||||
|
|
||||||
builder.add_terminate(block, type_id)
|
builder.add_terminate(block, type_id)
|
||||||
}
|
}
|
||||||
GetTagId { .. } => builder.add_make_tuple(block, &[]),
|
GetTagId { .. } => {
|
||||||
|
// TODO touch heap cell in recursive cases
|
||||||
|
|
||||||
|
builder.add_make_tuple(block, &[])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,6 +1646,19 @@ fn layout_spec(builder: &mut impl TypeContext, layout: &Layout) -> Result<TypeId
|
||||||
layout_spec_help(builder, layout, &WhenRecursive::Unreachable)
|
layout_spec_help(builder, layout, &WhenRecursive::Unreachable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn non_recursive_variant_types(
|
||||||
|
builder: &mut impl TypeContext,
|
||||||
|
tags: &[&[Layout]],
|
||||||
|
) -> Result<Vec<TypeId>> {
|
||||||
|
let mut result = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
|
for tag in tags.iter() {
|
||||||
|
result.push(build_tuple_type(builder, tag)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
fn layout_spec_help(
|
fn layout_spec_help(
|
||||||
builder: &mut impl TypeContext,
|
builder: &mut impl TypeContext,
|
||||||
layout: &Layout,
|
layout: &Layout,
|
||||||
|
@ -1674,8 +1675,6 @@ fn layout_spec_help(
|
||||||
when_recursive,
|
when_recursive,
|
||||||
),
|
),
|
||||||
Union(union_layout) => {
|
Union(union_layout) => {
|
||||||
let variant_types = build_variant_types(builder, union_layout)?;
|
|
||||||
|
|
||||||
match union_layout {
|
match union_layout {
|
||||||
UnionLayout::NonRecursive(&[]) => {
|
UnionLayout::NonRecursive(&[]) => {
|
||||||
// must model Void as Unit, otherwise we run into problems where
|
// must model Void as Unit, otherwise we run into problems where
|
||||||
|
@ -1683,7 +1682,10 @@ fn layout_spec_help(
|
||||||
// which is of course not possible
|
// which is of course not possible
|
||||||
builder.add_tuple_type(&[])
|
builder.add_tuple_type(&[])
|
||||||
}
|
}
|
||||||
UnionLayout::NonRecursive(_) => builder.add_union_type(&variant_types),
|
UnionLayout::NonRecursive(tags) => {
|
||||||
|
let variant_types = non_recursive_variant_types(builder, tags)?;
|
||||||
|
builder.add_union_type(&variant_types)
|
||||||
|
}
|
||||||
UnionLayout::Recursive(_)
|
UnionLayout::Recursive(_)
|
||||||
| UnionLayout::NullableUnwrapped { .. }
|
| UnionLayout::NullableUnwrapped { .. }
|
||||||
| UnionLayout::NullableWrapped { .. }
|
| UnionLayout::NullableWrapped { .. }
|
||||||
|
@ -1777,10 +1779,21 @@ const LIST_BAG_INDEX: u32 = 1;
|
||||||
const DICT_CELL_INDEX: u32 = LIST_CELL_INDEX;
|
const DICT_CELL_INDEX: u32 = LIST_CELL_INDEX;
|
||||||
const DICT_BAG_INDEX: u32 = LIST_BAG_INDEX;
|
const DICT_BAG_INDEX: u32 = LIST_BAG_INDEX;
|
||||||
|
|
||||||
fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) -> Result<ValueId> {
|
const TAG_CELL_INDEX: u32 = 0;
|
||||||
|
const TAG_DATA_INDEX: u32 = 1;
|
||||||
|
|
||||||
|
fn with_new_heap_cell(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
value: ValueId,
|
||||||
|
) -> Result<ValueId> {
|
||||||
let cell = builder.add_new_heap_cell(block)?;
|
let cell = builder.add_new_heap_cell(block)?;
|
||||||
|
builder.add_make_tuple(block, &[cell, value])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) -> Result<ValueId> {
|
||||||
let bag = builder.add_empty_bag(block, element_type)?;
|
let bag = builder.add_empty_bag(block, element_type)?;
|
||||||
builder.add_make_tuple(block, &[cell, bag])
|
with_new_heap_cell(builder, block, bag)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_dict(
|
fn new_dict(
|
||||||
|
@ -1789,10 +1802,9 @@ fn new_dict(
|
||||||
key_type: TypeId,
|
key_type: TypeId,
|
||||||
value_type: TypeId,
|
value_type: TypeId,
|
||||||
) -> Result<ValueId> {
|
) -> Result<ValueId> {
|
||||||
let cell = builder.add_new_heap_cell(block)?;
|
|
||||||
let element_type = builder.add_tuple_type(&[key_type, value_type])?;
|
let element_type = builder.add_tuple_type(&[key_type, value_type])?;
|
||||||
let bag = builder.add_empty_bag(block, element_type)?;
|
let bag = builder.add_empty_bag(block, element_type)?;
|
||||||
builder.add_make_tuple(block, &[cell, bag])
|
with_new_heap_cell(builder, block, bag)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
||||||
|
|
|
@ -726,7 +726,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
// the function must take it as an owned parameter
|
// the function must take it as an owned parameter
|
||||||
self.own_args_if_param(xs);
|
self.own_args_if_param(xs);
|
||||||
}
|
}
|
||||||
Reset(x) => {
|
Reset { symbol: x, .. } => {
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
self.own_var(*x);
|
self.own_var(*x);
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ pub fn occurring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
|
||||||
result.extend(arguments.iter().copied());
|
result.extend(arguments.iter().copied());
|
||||||
result.insert(*symbol);
|
result.insert(*symbol);
|
||||||
}
|
}
|
||||||
Reset(x) => {
|
Reset { symbol: x, .. } => {
|
||||||
result.insert(*x);
|
result.insert(*x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,7 +761,7 @@ impl<'a> Context<'a> {
|
||||||
self.arena.alloc(Stmt::Let(z, v, l, b))
|
self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
EmptyArray | Literal(_) | Reset(_) | RuntimeErrorFunction(_) => {
|
EmptyArray | Literal(_) | Reset { .. } | RuntimeErrorFunction(_) => {
|
||||||
// EmptyArray is always stack-allocated
|
// EmptyArray is always stack-allocated
|
||||||
// function pointers are persistent
|
// function pointers are persistent
|
||||||
self.arena.alloc(Stmt::Let(z, v, l, b))
|
self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
|
@ -779,7 +779,7 @@ impl<'a> Context<'a> {
|
||||||
// must this value be consumed?
|
// must this value be consumed?
|
||||||
let consume = consume_expr(&self.vars, expr);
|
let consume = consume_expr(&self.vars, expr);
|
||||||
|
|
||||||
let reset = matches!(expr, Expr::Reset(_));
|
let reset = matches!(expr, Expr::Reset { .. });
|
||||||
|
|
||||||
self.update_var_info_help(symbol, layout, persistent, consume, reset)
|
self.update_var_info_help(symbol, layout, persistent, consume, reset)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ static_assertions::assert_eq_size!([u8; 19 * 8], Stmt);
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
static_assertions::assert_eq_size!([u8; 20 * 8], Stmt);
|
static_assertions::assert_eq_size!([u8; 20 * 8], Stmt);
|
||||||
static_assertions::assert_eq_size!([u8; 6 * 8], ProcLayout);
|
static_assertions::assert_eq_size!([u8; 6 * 8], ProcLayout);
|
||||||
static_assertions::assert_eq_size!([u8; 8 * 8], Call);
|
static_assertions::assert_eq_size!([u8; 7 * 8], Call);
|
||||||
static_assertions::assert_eq_size!([u8; 6 * 8], CallType);
|
static_assertions::assert_eq_size!([u8; 5 * 8], CallType);
|
||||||
|
|
||||||
macro_rules! return_on_layout_error {
|
macro_rules! return_on_layout_error {
|
||||||
($env:expr, $layout_result:expr) => {
|
($env:expr, $layout_result:expr) => {
|
||||||
|
@ -318,11 +318,17 @@ impl<'a> Proc<'a> {
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
ident_ids: &'i mut IdentIds,
|
ident_ids: &'i mut IdentIds,
|
||||||
|
update_mode_ids: &'i mut UpdateModeIds,
|
||||||
procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
) {
|
) {
|
||||||
for (_, proc) in procs.iter_mut() {
|
for (_, proc) in procs.iter_mut() {
|
||||||
let new_proc =
|
let new_proc = crate::reset_reuse::insert_reset_reuse(
|
||||||
crate::reset_reuse::insert_reset_reuse(arena, home, ident_ids, proc.clone());
|
arena,
|
||||||
|
home,
|
||||||
|
ident_ids,
|
||||||
|
update_mode_ids,
|
||||||
|
proc.clone(),
|
||||||
|
);
|
||||||
*proc = new_proc;
|
*proc = new_proc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -988,8 +994,8 @@ pub struct Env<'a, 'i> {
|
||||||
pub home: ModuleId,
|
pub home: ModuleId,
|
||||||
pub ident_ids: &'i mut IdentIds,
|
pub ident_ids: &'i mut IdentIds,
|
||||||
pub ptr_bytes: u32,
|
pub ptr_bytes: u32,
|
||||||
pub update_mode_counter: u64,
|
pub update_mode_ids: &'i mut UpdateModeIds,
|
||||||
pub call_specialization_counter: u64,
|
pub call_specialization_counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'i> Env<'a, 'i> {
|
impl<'a, 'i> Env<'a, 'i> {
|
||||||
|
@ -1000,13 +1006,7 @@ impl<'a, 'i> Env<'a, 'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_update_mode_id(&mut self) -> UpdateModeId {
|
pub fn next_update_mode_id(&mut self) -> UpdateModeId {
|
||||||
let id = UpdateModeId {
|
self.update_mode_ids.next_id()
|
||||||
id: self.update_mode_counter,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.update_mode_counter += 1;
|
|
||||||
|
|
||||||
id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_call_specialization_id(&mut self) -> CallSpecId {
|
pub fn next_call_specialization_id(&mut self) -> CallSpecId {
|
||||||
|
@ -1282,26 +1282,43 @@ impl<'a> Call<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct CallSpecId {
|
pub struct CallSpecId {
|
||||||
id: u64,
|
id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallSpecId {
|
impl CallSpecId {
|
||||||
pub fn to_bytes(self) -> [u8; 8] {
|
pub fn to_bytes(self) -> [u8; 4] {
|
||||||
self.id.to_ne_bytes()
|
self.id.to_ne_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct UpdateModeId {
|
pub struct UpdateModeId {
|
||||||
id: u64,
|
id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateModeId {
|
impl UpdateModeId {
|
||||||
pub fn to_bytes(self) -> [u8; 8] {
|
pub fn to_bytes(self) -> [u8; 4] {
|
||||||
self.id.to_ne_bytes()
|
self.id.to_ne_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct UpdateModeIds {
|
||||||
|
next: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UpdateModeIds {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self { next: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_id(&mut self) -> UpdateModeId {
|
||||||
|
let id = UpdateModeId { id: self.next };
|
||||||
|
self.next += 1;
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum CallType<'a> {
|
pub enum CallType<'a> {
|
||||||
ByName {
|
ByName {
|
||||||
|
@ -1390,13 +1407,17 @@ pub enum Expr<'a> {
|
||||||
Reuse {
|
Reuse {
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
update_tag_id: bool,
|
update_tag_id: bool,
|
||||||
|
update_mode: UpdateModeId,
|
||||||
// normal Tag fields
|
// normal Tag fields
|
||||||
tag_layout: UnionLayout<'a>,
|
tag_layout: UnionLayout<'a>,
|
||||||
tag_name: TagName,
|
tag_name: TagName,
|
||||||
tag_id: TagIdIntType,
|
tag_id: TagIdIntType,
|
||||||
arguments: &'a [Symbol],
|
arguments: &'a [Symbol],
|
||||||
},
|
},
|
||||||
Reset(Symbol),
|
Reset {
|
||||||
|
symbol: Symbol,
|
||||||
|
update_mode: UpdateModeId,
|
||||||
|
},
|
||||||
|
|
||||||
RuntimeErrorFunction(&'a str),
|
RuntimeErrorFunction(&'a str),
|
||||||
}
|
}
|
||||||
|
@ -1491,6 +1512,7 @@ impl<'a> Expr<'a> {
|
||||||
symbol,
|
symbol,
|
||||||
tag_name,
|
tag_name,
|
||||||
arguments,
|
arguments,
|
||||||
|
update_mode,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let doc_tag = match tag_name {
|
let doc_tag = match tag_name {
|
||||||
|
@ -1508,11 +1530,19 @@ impl<'a> Expr<'a> {
|
||||||
.text("Reuse ")
|
.text("Reuse ")
|
||||||
.append(symbol_to_doc(alloc, *symbol))
|
.append(symbol_to_doc(alloc, *symbol))
|
||||||
.append(alloc.space())
|
.append(alloc.space())
|
||||||
|
.append(format!("{:?}", update_mode))
|
||||||
|
.append(alloc.space())
|
||||||
.append(doc_tag)
|
.append(doc_tag)
|
||||||
.append(alloc.space())
|
.append(alloc.space())
|
||||||
.append(alloc.intersperse(it, " "))
|
.append(alloc.intersperse(it, " "))
|
||||||
}
|
}
|
||||||
Reset(symbol) => alloc.text("Reset ").append(symbol_to_doc(alloc, *symbol)),
|
Reset {
|
||||||
|
symbol,
|
||||||
|
update_mode,
|
||||||
|
} => alloc.text(format!(
|
||||||
|
"Reset {{ symbol: {:?}, id: {} }}",
|
||||||
|
symbol, update_mode.id
|
||||||
|
)),
|
||||||
|
|
||||||
Struct(args) => {
|
Struct(args) => {
|
||||||
let it = args.iter().map(|s| symbol_to_doc(alloc, *s));
|
let it = args.iter().map(|s| symbol_to_doc(alloc, *s));
|
||||||
|
@ -5715,7 +5745,7 @@ fn substitute_in_expr<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reuse { .. } | Reset(_) => unreachable!("reset/reuse have not been introduced yet"),
|
Reuse { .. } | Reset { .. } => unreachable!("reset/reuse have not been introduced yet"),
|
||||||
|
|
||||||
Struct(args) => {
|
Struct(args) => {
|
||||||
let mut did_change = false;
|
let mut did_change = false;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::inc_dec::{collect_stmt, occurring_variables_expr, JPLiveVarMap, LiveVarSet};
|
use crate::inc_dec::{collect_stmt, occurring_variables_expr, JPLiveVarMap, LiveVarSet};
|
||||||
use crate::ir::{BranchInfo, Call, Expr, ListLiteralElement, Proc, Stmt};
|
use crate::ir::{
|
||||||
|
BranchInfo, Call, Expr, ListLiteralElement, Proc, Stmt, UpdateModeId, UpdateModeIds,
|
||||||
|
};
|
||||||
use crate::layout::{Layout, TagIdIntType, UnionLayout};
|
use crate::layout::{Layout, TagIdIntType, UnionLayout};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
@ -10,12 +12,14 @@ pub fn insert_reset_reuse<'a, 'i>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
ident_ids: &'i mut IdentIds,
|
ident_ids: &'i mut IdentIds,
|
||||||
|
update_mode_ids: &'i mut UpdateModeIds,
|
||||||
mut proc: Proc<'a>,
|
mut proc: Proc<'a>,
|
||||||
) -> Proc<'a> {
|
) -> Proc<'a> {
|
||||||
let mut env = Env {
|
let mut env = Env {
|
||||||
arena,
|
arena,
|
||||||
home,
|
home,
|
||||||
ident_ids,
|
ident_ids,
|
||||||
|
update_mode_ids,
|
||||||
jp_live_vars: Default::default(),
|
jp_live_vars: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,6 +54,7 @@ struct Env<'a, 'i> {
|
||||||
/// required for creating new `Symbol`s
|
/// required for creating new `Symbol`s
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
ident_ids: &'i mut IdentIds,
|
ident_ids: &'i mut IdentIds,
|
||||||
|
update_mode_ids: &'i mut UpdateModeIds,
|
||||||
|
|
||||||
jp_live_vars: JPLiveVarMap,
|
jp_live_vars: JPLiveVarMap,
|
||||||
}
|
}
|
||||||
|
@ -64,7 +69,7 @@ impl<'a, 'i> Env<'a, 'i> {
|
||||||
|
|
||||||
fn function_s<'a, 'i>(
|
fn function_s<'a, 'i>(
|
||||||
env: &mut Env<'a, 'i>,
|
env: &mut Env<'a, 'i>,
|
||||||
w: Symbol,
|
w: Opportunity,
|
||||||
c: &CtorInfo<'a>,
|
c: &CtorInfo<'a>,
|
||||||
stmt: &'a Stmt<'a>,
|
stmt: &'a Stmt<'a>,
|
||||||
) -> &'a Stmt<'a> {
|
) -> &'a Stmt<'a> {
|
||||||
|
@ -84,7 +89,8 @@ fn function_s<'a, 'i>(
|
||||||
let update_tag_id = true;
|
let update_tag_id = true;
|
||||||
|
|
||||||
let new_expr = Expr::Reuse {
|
let new_expr = Expr::Reuse {
|
||||||
symbol: w,
|
symbol: w.symbol,
|
||||||
|
update_mode: w.update_mode,
|
||||||
update_tag_id,
|
update_tag_id,
|
||||||
tag_layout: *tag_layout,
|
tag_layout: *tag_layout,
|
||||||
tag_id: *tag_id,
|
tag_id: *tag_id,
|
||||||
|
@ -175,13 +181,22 @@ fn function_s<'a, 'i>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Opportunity {
|
||||||
|
symbol: Symbol,
|
||||||
|
update_mode: UpdateModeId,
|
||||||
|
}
|
||||||
|
|
||||||
fn try_function_s<'a, 'i>(
|
fn try_function_s<'a, 'i>(
|
||||||
env: &mut Env<'a, 'i>,
|
env: &mut Env<'a, 'i>,
|
||||||
x: Symbol,
|
x: Symbol,
|
||||||
c: &CtorInfo<'a>,
|
c: &CtorInfo<'a>,
|
||||||
stmt: &'a Stmt<'a>,
|
stmt: &'a Stmt<'a>,
|
||||||
) -> &'a Stmt<'a> {
|
) -> &'a Stmt<'a> {
|
||||||
let w = env.unique_symbol();
|
let w = Opportunity {
|
||||||
|
symbol: env.unique_symbol(),
|
||||||
|
update_mode: env.update_mode_ids.next_id(),
|
||||||
|
};
|
||||||
|
|
||||||
let new_stmt = function_s(env, w, c, stmt);
|
let new_stmt = function_s(env, w, c, stmt);
|
||||||
|
|
||||||
|
@ -194,7 +209,7 @@ fn try_function_s<'a, 'i>(
|
||||||
|
|
||||||
fn insert_reset<'a>(
|
fn insert_reset<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
w: Symbol,
|
w: Opportunity,
|
||||||
x: Symbol,
|
x: Symbol,
|
||||||
union_layout: UnionLayout<'a>,
|
union_layout: UnionLayout<'a>,
|
||||||
mut stmt: &'a Stmt<'a>,
|
mut stmt: &'a Stmt<'a>,
|
||||||
|
@ -216,16 +231,21 @@ fn insert_reset<'a>(
|
||||||
| Array { .. }
|
| Array { .. }
|
||||||
| EmptyArray
|
| EmptyArray
|
||||||
| Reuse { .. }
|
| Reuse { .. }
|
||||||
| Reset(_)
|
| Reset { .. }
|
||||||
| RuntimeErrorFunction(_) => break,
|
| RuntimeErrorFunction(_) => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reset_expr = Expr::Reset(x);
|
let reset_expr = Expr::Reset {
|
||||||
|
symbol: x,
|
||||||
|
update_mode: w.update_mode,
|
||||||
|
};
|
||||||
|
|
||||||
let layout = Layout::Union(union_layout);
|
let layout = Layout::Union(union_layout);
|
||||||
|
|
||||||
stmt = env.arena.alloc(Stmt::Let(w, reset_expr, layout, stmt));
|
stmt = env
|
||||||
|
.arena
|
||||||
|
.alloc(Stmt::Let(w.symbol, reset_expr, layout, stmt));
|
||||||
|
|
||||||
for (symbol, expr, expr_layout) in stack.into_iter().rev() {
|
for (symbol, expr, expr_layout) in stack.into_iter().rev() {
|
||||||
stmt = env
|
stmt = env
|
||||||
|
@ -584,7 +604,7 @@ fn has_live_var_expr<'a>(expr: &'a Expr<'a>, needle: Symbol) -> bool {
|
||||||
Expr::Reuse {
|
Expr::Reuse {
|
||||||
symbol, arguments, ..
|
symbol, arguments, ..
|
||||||
} => needle == *symbol || arguments.iter().any(|s| *s == needle),
|
} => needle == *symbol || arguments.iter().any(|s| *s == needle),
|
||||||
Expr::Reset(symbol) => needle == *symbol,
|
Expr::Reset { symbol, .. } => needle == *symbol,
|
||||||
Expr::RuntimeErrorFunction(_) => false,
|
Expr::RuntimeErrorFunction(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ mod test_reporting {
|
||||||
use crate::helpers::{can_expr, infer_expr, CanExprOut, ParseErrOut};
|
use crate::helpers::{can_expr, infer_expr, CanExprOut, ParseErrOut};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
use roc_module::symbol::{Interns, ModuleId};
|
||||||
use roc_mono::ir::{Procs, Stmt};
|
use roc_mono::ir::{Procs, Stmt, UpdateModeIds};
|
||||||
use roc_mono::layout::LayoutCache;
|
use roc_mono::layout::LayoutCache;
|
||||||
use roc_reporting::report::{
|
use roc_reporting::report::{
|
||||||
can_problem, mono_problem, parse_problem, type_problem, Report, Severity, BLUE_CODE,
|
can_problem, mono_problem, parse_problem, type_problem, Report, Severity, BLUE_CODE,
|
||||||
|
@ -91,6 +91,7 @@ mod test_reporting {
|
||||||
// Compile and add all the Procs before adding main
|
// Compile and add all the Procs before adding main
|
||||||
let mut procs = Procs::new_in(&arena);
|
let mut procs = Procs::new_in(&arena);
|
||||||
let mut ident_ids = interns.all_ident_ids.remove(&home).unwrap();
|
let mut ident_ids = interns.all_ident_ids.remove(&home).unwrap();
|
||||||
|
let mut update_mode_ids = UpdateModeIds::new();
|
||||||
|
|
||||||
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||||
let ptr_bytes = 8;
|
let ptr_bytes = 8;
|
||||||
|
@ -101,8 +102,8 @@ mod test_reporting {
|
||||||
problems: &mut mono_problems,
|
problems: &mut mono_problems,
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
|
update_mode_ids: &mut update_mode_ids,
|
||||||
ptr_bytes,
|
ptr_bytes,
|
||||||
update_mode_counter: 0,
|
|
||||||
// call_specialization_counter=0 is reserved
|
// call_specialization_counter=0 is reserved
|
||||||
call_specialization_counter: 1,
|
call_specialization_counter: 1,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue