mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Merge branch 'trunk' into dec-div
This commit is contained in:
commit
94dd8a7253
29 changed files with 2448 additions and 168 deletions
|
@ -519,7 +519,7 @@ where
|
|||
}
|
||||
Stmt::Join {
|
||||
parameters,
|
||||
continuation,
|
||||
body: continuation,
|
||||
remainder,
|
||||
..
|
||||
} => {
|
||||
|
|
|
@ -830,9 +830,10 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
|||
|
||||
CallType::HigherOrderLowLevel {
|
||||
op,
|
||||
closure_layout,
|
||||
function_owns_closure_data,
|
||||
specialization_id,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
..
|
||||
} => {
|
||||
let bytes = specialization_id.to_bytes();
|
||||
|
@ -846,8 +847,9 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
|||
scope,
|
||||
layout,
|
||||
*op,
|
||||
*closure_layout,
|
||||
func_spec,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
*function_owns_closure_data,
|
||||
arguments,
|
||||
)
|
||||
|
@ -1436,6 +1438,12 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
|||
structure,
|
||||
wrapped: Wrapped::RecordOrSingleTagUnion,
|
||||
..
|
||||
}
|
||||
| AccessAtIndex {
|
||||
index,
|
||||
structure,
|
||||
wrapped: Wrapped::LikeARoseTree,
|
||||
..
|
||||
} => {
|
||||
// extract field from a record
|
||||
match load_symbol_and_layout(scope, structure) {
|
||||
|
@ -2137,7 +2145,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
|||
id,
|
||||
parameters,
|
||||
remainder,
|
||||
continuation,
|
||||
body: continuation,
|
||||
} => {
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
|
@ -3161,7 +3169,7 @@ fn build_procedures_help<'a, 'ctx, 'env>(
|
|||
let it = procedures.iter().map(|x| x.1);
|
||||
|
||||
let solutions = match roc_mono::alias_analysis::spec_program(entry_point, it) {
|
||||
Err(e) => panic!("Error in alias analysis: {:?}", e),
|
||||
Err(e) => panic!("Error in alias analysis: {}", e),
|
||||
Ok(solutions) => solutions,
|
||||
};
|
||||
|
||||
|
@ -3815,8 +3823,9 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
scope: &Scope<'a, 'ctx>,
|
||||
return_layout: &Layout<'a>,
|
||||
op: LowLevel,
|
||||
function_layout: Layout<'a>,
|
||||
func_spec: FuncSpec,
|
||||
argument_layouts: &[Layout<'a>],
|
||||
result_layout: &Layout<'a>,
|
||||
function_owns_closure_data: bool,
|
||||
args: &[Symbol],
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
|
@ -3828,6 +3837,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
macro_rules! passed_function_at_index {
|
||||
($index:expr) => {{
|
||||
let function_symbol = args[$index];
|
||||
let function_layout = Layout::FunctionPointer(argument_layouts, return_layout);
|
||||
|
||||
function_value_by_func_spec(env, func_spec, function_symbol, function_layout)
|
||||
}};
|
||||
|
@ -4095,7 +4105,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
&function_layout,
|
||||
result_layout,
|
||||
list,
|
||||
before_layout,
|
||||
after_layout,
|
||||
|
@ -4139,7 +4149,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
&function_layout,
|
||||
result_layout,
|
||||
list,
|
||||
before_layout,
|
||||
after_layout,
|
||||
|
|
|
@ -601,18 +601,12 @@ pub fn list_keep_oks<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
function_layout: &Layout<'a>,
|
||||
// Layout of the `Result after *`
|
||||
result_layout: &Layout<'a>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
before_layout: &Layout<'a>,
|
||||
after_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
// Layout of the `Result after *`
|
||||
let result_layout = match function_layout {
|
||||
Layout::FunctionPointer(_, ret) => ret,
|
||||
Layout::Closure(_, _, ret) => ret,
|
||||
_ => unreachable!("not a callable layout"),
|
||||
};
|
||||
|
||||
let dec_result_fn = build_dec_wrapper(env, layout_ids, result_layout);
|
||||
|
||||
call_bitcode_fn(
|
||||
|
@ -638,18 +632,12 @@ pub fn list_keep_errs<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
function_layout: &Layout<'a>,
|
||||
// Layout of the `Result * err`
|
||||
result_layout: &Layout<'a>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
before_layout: &Layout<'a>,
|
||||
after_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
// Layout of the `Result after *`
|
||||
let result_layout = match function_layout {
|
||||
Layout::FunctionPointer(_, ret) => ret,
|
||||
Layout::Closure(_, _, ret) => ret,
|
||||
_ => unreachable!("not a callable layout"),
|
||||
};
|
||||
|
||||
let dec_result_fn = build_dec_wrapper(env, layout_ids, result_layout);
|
||||
|
||||
call_bitcode_fn(
|
||||
|
|
|
@ -19,19 +19,22 @@ pub const STATIC_STR_NAME: ConstName = ConstName(&Symbol::STR_ALIAS_ANALYSIS_STA
|
|||
|
||||
const ENTRY_POINT_NAME: &[u8] = b"mainForHost";
|
||||
|
||||
pub fn func_name_bytes(proc: &Proc) -> [u8; 16] {
|
||||
pub fn func_name_bytes(proc: &Proc) -> [u8; SIZE] {
|
||||
func_name_bytes_help(proc.name, proc.args.iter().map(|x| x.0), proc.ret_layout)
|
||||
}
|
||||
|
||||
const DEBUG: bool = false;
|
||||
const SIZE: usize = if DEBUG { 50 } else { 16 };
|
||||
|
||||
pub fn func_name_bytes_help<'a, I>(
|
||||
symbol: Symbol,
|
||||
argument_layouts: I,
|
||||
return_layout: Layout<'a>,
|
||||
) -> [u8; 16]
|
||||
) -> [u8; SIZE]
|
||||
where
|
||||
I: Iterator<Item = Layout<'a>>,
|
||||
{
|
||||
let mut name_bytes = [0u8; 16];
|
||||
let mut name_bytes = [0u8; SIZE];
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::Hash;
|
||||
|
@ -75,9 +78,27 @@ where
|
|||
*target = *source;
|
||||
}
|
||||
|
||||
if DEBUG {
|
||||
for (i, c) in (format!("{:?}", symbol)).chars().take(25).enumerate() {
|
||||
name_bytes[25 + i] = c as u8;
|
||||
}
|
||||
}
|
||||
|
||||
name_bytes
|
||||
}
|
||||
|
||||
fn bytes_as_ascii(bytes: &[u8]) -> String {
|
||||
use std::fmt::Write;
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
for byte in bytes {
|
||||
write!(buf, "{:02X}", byte).unwrap();
|
||||
}
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
pub fn spec_program<'a, I>(
|
||||
entry_point: crate::ir::EntryPoint<'a>,
|
||||
procs: I,
|
||||
|
@ -102,15 +123,34 @@ where
|
|||
m.add_const(STATIC_STR_NAME, static_str_def)?;
|
||||
|
||||
// the entry point wrapper
|
||||
let roc_main_bytes = func_name_bytes_help(
|
||||
entry_point.symbol,
|
||||
entry_point.layout.arguments.iter().copied(),
|
||||
entry_point.layout.result,
|
||||
);
|
||||
let roc_main = FuncName(&roc_main_bytes);
|
||||
|
||||
let entry_point_function = build_entry_point(entry_point.layout, roc_main)?;
|
||||
let entry_point_name = FuncName(ENTRY_POINT_NAME);
|
||||
let entry_point_function = build_entry_point(entry_point.layout, entry_point_name)?;
|
||||
m.add_func(entry_point_name, entry_point_function)?;
|
||||
|
||||
// all other functions
|
||||
for proc in procs {
|
||||
let bytes = func_name_bytes(proc);
|
||||
let func_name = FuncName(&bytes);
|
||||
|
||||
if DEBUG {
|
||||
eprintln!(
|
||||
"{:?}: {:?} with {:?} args",
|
||||
proc.name,
|
||||
bytes_as_ascii(&bytes),
|
||||
proc.args.len()
|
||||
);
|
||||
}
|
||||
|
||||
let spec = proc_spec(proc)?;
|
||||
|
||||
m.add_func(FuncName(&func_name_bytes(proc)), spec)?;
|
||||
m.add_func(func_name, spec)?;
|
||||
}
|
||||
|
||||
m.build()?
|
||||
|
@ -126,7 +166,9 @@ where
|
|||
p.build()?
|
||||
};
|
||||
|
||||
// eprintln!("{}", program.to_source_string());
|
||||
if DEBUG {
|
||||
eprintln!("{}", program.to_source_string());
|
||||
}
|
||||
|
||||
morphic_lib::solve(program)
|
||||
}
|
||||
|
@ -198,11 +240,25 @@ fn stmt_spec(
|
|||
use Stmt::*;
|
||||
|
||||
match stmt {
|
||||
Let(symbol, expr, layout, continuation) => {
|
||||
let value_id = expr_spec(builder, env, block, layout, expr)?;
|
||||
Let(symbol, expr, expr_layout, mut continuation) => {
|
||||
let value_id = expr_spec(builder, env, block, expr_layout, expr)?;
|
||||
env.symbols.insert(*symbol, value_id);
|
||||
|
||||
let mut queue = vec![symbol];
|
||||
|
||||
while let Let(symbol, expr, expr_layout, c) = continuation {
|
||||
let value_id = expr_spec(builder, env, block, expr_layout, expr)?;
|
||||
env.symbols.insert(*symbol, value_id);
|
||||
|
||||
queue.push(symbol);
|
||||
continuation = c;
|
||||
}
|
||||
|
||||
let result = stmt_spec(builder, env, block, layout, continuation)?;
|
||||
env.symbols.remove(symbol);
|
||||
|
||||
for symbol in queue {
|
||||
env.symbols.remove(symbol);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -235,7 +291,7 @@ fn stmt_spec(
|
|||
cond_layout: _,
|
||||
branches,
|
||||
default_branch,
|
||||
ret_layout,
|
||||
ret_layout: _lies,
|
||||
} => {
|
||||
let mut cases = Vec::with_capacity(branches.len() + 1);
|
||||
|
||||
|
@ -246,7 +302,7 @@ fn stmt_spec(
|
|||
|
||||
for branch in it {
|
||||
let block = builder.add_block();
|
||||
let value_id = stmt_spec(builder, env, block, ret_layout, branch)?;
|
||||
let value_id = stmt_spec(builder, env, block, layout, branch)?;
|
||||
cases.push(BlockExpr(block, value_id));
|
||||
}
|
||||
|
||||
|
@ -282,7 +338,7 @@ fn stmt_spec(
|
|||
Join {
|
||||
id,
|
||||
parameters,
|
||||
continuation,
|
||||
body,
|
||||
remainder,
|
||||
} => {
|
||||
let mut type_ids = Vec::new();
|
||||
|
@ -298,27 +354,33 @@ fn stmt_spec(
|
|||
let (jpid, jp_argument) =
|
||||
builder.declare_continuation(block, jp_arg_type_id, ret_type_id)?;
|
||||
|
||||
// NOTE join point arguments can shadow variables from the outer scope
|
||||
// the ordering of steps here is important
|
||||
|
||||
// add this ID so both body and remainder can reference it
|
||||
env.join_points.insert(*id, jpid);
|
||||
|
||||
// first, with the current variable bindings, process the remainder
|
||||
let cont_block = builder.add_block();
|
||||
let cont_value_id = stmt_spec(builder, env, cont_block, layout, remainder)?;
|
||||
|
||||
// only then introduce variables bound by the jump point, and process its body
|
||||
let join_body_sub_block = {
|
||||
env.join_points.insert(*id, jpid);
|
||||
let jp_body_block = builder.add_block();
|
||||
|
||||
// unpack the argument
|
||||
for (i, p) in parameters.iter().enumerate() {
|
||||
let value_id =
|
||||
builder.add_get_tuple_field(jp_body_block, jp_argument, i as u32)?;
|
||||
|
||||
env.symbols.insert(p.symbol, value_id);
|
||||
}
|
||||
|
||||
let jp_body_value_id = stmt_spec(builder, env, jp_body_block, layout, remainder)?;
|
||||
let jp_body_value_id = stmt_spec(builder, env, jp_body_block, layout, body)?;
|
||||
|
||||
BlockExpr(jp_body_block, jp_body_value_id)
|
||||
};
|
||||
|
||||
// NOTE the symbols bound by the join point can shadow the argument symbols of the
|
||||
// surrounding function, so we don't remove them from the env here
|
||||
|
||||
let cont_block = builder.add_block();
|
||||
let cont_value_id = stmt_spec(builder, env, cont_block, layout, continuation)?;
|
||||
|
||||
env.join_points.remove(id);
|
||||
builder.define_continuation(jpid, join_body_sub_block)?;
|
||||
|
||||
|
@ -423,7 +485,7 @@ fn call_spec(
|
|||
),
|
||||
HigherOrderLowLevel {
|
||||
specialization_id,
|
||||
closure_layout: _,
|
||||
closure_env_layout,
|
||||
op,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
|
@ -458,15 +520,160 @@ fn call_spec(
|
|||
DictWalk => {
|
||||
let dict = env.symbols[&call.arguments[0]];
|
||||
let default = env.symbols[&call.arguments[1]];
|
||||
let closure_env = env.symbols[&call.arguments[3]];
|
||||
|
||||
let bag = builder.add_get_tuple_field(block, dict, DICT_BAG_INDEX)?;
|
||||
let _cell = builder.add_get_tuple_field(block, dict, DICT_CELL_INDEX)?;
|
||||
|
||||
let first = builder.add_bag_get(block, bag)?;
|
||||
|
||||
let argument = builder.add_make_tuple(block, &[first, default])?;
|
||||
let key = builder.add_get_tuple_field(block, first, 0)?;
|
||||
let val = builder.add_get_tuple_field(block, first, 1)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[key, val, default])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[key, val, default, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListWalk | ListWalkBackwards | ListWalkUntil => {
|
||||
let list = env.symbols[&call.arguments[0]];
|
||||
let default = env.symbols[&call.arguments[1]];
|
||||
let closure_env = env.symbols[&call.arguments[3]];
|
||||
|
||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||
let _cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
||||
|
||||
let first = builder.add_bag_get(block, bag)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[first, default])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[first, default, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListMapWithIndex => {
|
||||
let list = env.symbols[&call.arguments[0]];
|
||||
let closure_env = env.symbols[&call.arguments[2]];
|
||||
|
||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||
let _cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
||||
|
||||
let first = builder.add_bag_get(block, bag)?;
|
||||
let index = builder.add_make_tuple(block, &[])?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[first, index])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[first, index, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListMap => {
|
||||
let list1 = env.symbols[&call.arguments[0]];
|
||||
let closure_env = env.symbols[&call.arguments[2]];
|
||||
|
||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
||||
|
||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[elem1])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[elem1, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListSortWith => {
|
||||
let list1 = env.symbols[&call.arguments[0]];
|
||||
let closure_env = env.symbols[&call.arguments[2]];
|
||||
|
||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
||||
|
||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[elem1, elem1])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[elem1, elem1, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListMap2 => {
|
||||
let list1 = env.symbols[&call.arguments[0]];
|
||||
let list2 = env.symbols[&call.arguments[1]];
|
||||
let closure_env = env.symbols[&call.arguments[3]];
|
||||
|
||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
||||
|
||||
let bag2 = builder.add_get_tuple_field(block, list2, LIST_BAG_INDEX)?;
|
||||
let _cell2 = builder.add_get_tuple_field(block, list2, LIST_CELL_INDEX)?;
|
||||
let elem2 = builder.add_bag_get(block, bag2)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[elem1, elem2])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[elem1, elem2, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListMap3 => {
|
||||
let list1 = env.symbols[&call.arguments[0]];
|
||||
let list2 = env.symbols[&call.arguments[1]];
|
||||
let list3 = env.symbols[&call.arguments[2]];
|
||||
let closure_env = env.symbols[&call.arguments[4]];
|
||||
|
||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
||||
|
||||
let bag2 = builder.add_get_tuple_field(block, list2, LIST_BAG_INDEX)?;
|
||||
let _cell2 = builder.add_get_tuple_field(block, list2, LIST_CELL_INDEX)?;
|
||||
let elem2 = builder.add_bag_get(block, bag2)?;
|
||||
|
||||
let bag3 = builder.add_get_tuple_field(block, list3, LIST_BAG_INDEX)?;
|
||||
let _cell3 = builder.add_get_tuple_field(block, list3, LIST_CELL_INDEX)?;
|
||||
let elem3 = builder.add_bag_get(block, bag3)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[elem1, elem2, elem3])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[elem1, elem2, elem3, closure_env])?
|
||||
};
|
||||
builder.add_call(block, spec_var, module, name, argument)?;
|
||||
}
|
||||
|
||||
ListKeepIf | ListKeepOks | ListKeepErrs => {
|
||||
let list = env.symbols[&call.arguments[0]];
|
||||
let closure_env = env.symbols[&call.arguments[2]];
|
||||
|
||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||
// let _cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
||||
|
||||
let first = builder.add_bag_get(block, bag)?;
|
||||
|
||||
let argument = if closure_env_layout.is_none() {
|
||||
builder.add_make_tuple(block, &[first])?
|
||||
} else {
|
||||
builder.add_make_tuple(block, &[first, closure_env])?
|
||||
};
|
||||
let result = builder.add_call(block, spec_var, module, name, argument)?;
|
||||
let unit = builder.add_tuple_type(&[])?;
|
||||
builder.add_unknown_with(block, &[result], unit)?;
|
||||
}
|
||||
|
||||
_ => {
|
||||
// fake a call to the function argument
|
||||
// to make sure the function is specialized
|
||||
|
@ -653,7 +860,7 @@ fn expr_spec(
|
|||
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
||||
AccessAtIndex {
|
||||
index,
|
||||
field_layouts,
|
||||
field_layouts: _,
|
||||
structure,
|
||||
wrapped,
|
||||
} => {
|
||||
|
@ -673,17 +880,20 @@ fn expr_spec(
|
|||
Wrapped::RecordOrSingleTagUnion => {
|
||||
builder.add_get_tuple_field(block, value_id, *index as u32)
|
||||
}
|
||||
Wrapped::LikeARoseTree => {
|
||||
let result_type = layout_spec(builder, layout)?;
|
||||
builder.add_unknown_with(block, &[value_id], result_type)
|
||||
}
|
||||
Wrapped::MultiTagUnion => {
|
||||
// Clearly this is not generally correct, but it should be for our examples
|
||||
let hacky_is_recursive =
|
||||
field_layouts.iter().any(|l| l == &Layout::RecursivePointer);
|
||||
// let hacky_is_recursive = field_layouts.iter().any(|l| l == &Layout::RecursivePointer);
|
||||
// if hacky_is_recursive {
|
||||
|
||||
if hacky_is_recursive {
|
||||
let result_type = layout_spec(builder, layout)?;
|
||||
builder.add_unknown_with(block, &[value_id], result_type)
|
||||
} else {
|
||||
builder.add_get_tuple_field(block, value_id, *index as u32)
|
||||
}
|
||||
// we don't know what constructor we are at this point, so how can we get a
|
||||
// field from an enum value?
|
||||
|
||||
let result_type = layout_spec(builder, layout)?;
|
||||
builder.add_unknown_with(block, &[value_id], result_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -700,7 +910,9 @@ fn expr_spec(
|
|||
bag = builder.add_bag_insert(block, bag, value_id)?;
|
||||
}
|
||||
|
||||
Ok(bag)
|
||||
let cell = builder.add_new_heap_cell(block)?;
|
||||
|
||||
builder.add_make_tuple(block, &[cell, bag])
|
||||
}
|
||||
|
||||
EmptyArray => {
|
||||
|
@ -827,8 +1039,7 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeI
|
|||
|
||||
fn str_type<TC: TypeContext>(builder: &mut TC) -> Result<TypeId> {
|
||||
let cell_id = builder.add_heap_cell_type();
|
||||
let len_id = builder.add_tuple_type(&[])?;
|
||||
builder.add_tuple_type(&[cell_id, len_id])
|
||||
builder.add_tuple_type(&[cell_id])
|
||||
}
|
||||
|
||||
// const OK_TAG_ID: u8 = 1u8;
|
||||
|
|
|
@ -193,7 +193,7 @@ impl<'a> ParamMap<'a> {
|
|||
id: j,
|
||||
parameters: xs,
|
||||
remainder: v,
|
||||
continuation: b,
|
||||
body: b,
|
||||
} => {
|
||||
let already_in_there = self
|
||||
.items
|
||||
|
@ -393,15 +393,20 @@ impl<'a> BorrowInfState<'a> {
|
|||
}
|
||||
|
||||
HigherOrderLowLevel {
|
||||
op, closure_layout, ..
|
||||
op,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
..
|
||||
} => {
|
||||
use roc_module::low_level::LowLevel::*;
|
||||
|
||||
debug_assert!(op.is_higher_order());
|
||||
|
||||
let closure_layout = Layout::FunctionPointer(arg_layouts, ret_layout);
|
||||
|
||||
match op {
|
||||
ListMap | ListKeepIf | ListKeepOks | ListKeepErrs => {
|
||||
match self.param_map.get_symbol(arguments[1], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[1], closure_layout) {
|
||||
Some(function_ps) => {
|
||||
// own the list if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
|
@ -417,7 +422,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
}
|
||||
}
|
||||
ListMapWithIndex => {
|
||||
match self.param_map.get_symbol(arguments[1], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[1], closure_layout) {
|
||||
Some(function_ps) => {
|
||||
// own the list if the function wants to own the element
|
||||
if !function_ps[1].borrow {
|
||||
|
@ -432,7 +437,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
ListMap2 => match self.param_map.get_symbol(arguments[2], *closure_layout) {
|
||||
ListMap2 => match self.param_map.get_symbol(arguments[2], closure_layout) {
|
||||
Some(function_ps) => {
|
||||
// own the lists if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
|
@ -450,7 +455,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
}
|
||||
None => unreachable!(),
|
||||
},
|
||||
ListMap3 => match self.param_map.get_symbol(arguments[3], *closure_layout) {
|
||||
ListMap3 => match self.param_map.get_symbol(arguments[3], closure_layout) {
|
||||
Some(function_ps) => {
|
||||
// own the lists if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
|
@ -471,7 +476,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
None => unreachable!(),
|
||||
},
|
||||
ListSortWith => {
|
||||
match self.param_map.get_symbol(arguments[1], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[1], closure_layout) {
|
||||
Some(function_ps) => {
|
||||
// always own the input list
|
||||
self.own_var(arguments[0]);
|
||||
|
@ -485,7 +490,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
}
|
||||
}
|
||||
ListWalk | ListWalkUntil | ListWalkBackwards | DictWalk => {
|
||||
match self.param_map.get_symbol(arguments[2], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[2], closure_layout) {
|
||||
Some(function_ps) => {
|
||||
// own the data structure if the function wants to own the element
|
||||
if !function_ps[0].borrow {
|
||||
|
@ -618,7 +623,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
id: j,
|
||||
parameters: ys,
|
||||
remainder: v,
|
||||
continuation: b,
|
||||
body: b,
|
||||
} => {
|
||||
let old = self.param_set.clone();
|
||||
self.update_param_set(ys);
|
||||
|
|
|
@ -597,7 +597,7 @@ fn to_relevant_branch_help<'a>(
|
|||
start.extend(end);
|
||||
}
|
||||
}
|
||||
Wrapped::RecordOrSingleTagUnion => {
|
||||
Wrapped::RecordOrSingleTagUnion | Wrapped::LikeARoseTree => {
|
||||
let sub_positions = arguments.into_iter().enumerate().map(
|
||||
|(index, (pattern, _))| {
|
||||
let mut new_path = path.to_vec();
|
||||
|
@ -956,7 +956,7 @@ pub fn optimize_when<'a>(
|
|||
stmt = Stmt::Join {
|
||||
id,
|
||||
parameters: &[],
|
||||
continuation: env.arena.alloc(body),
|
||||
body: env.arena.alloc(body),
|
||||
remainder: env.arena.alloc(stmt),
|
||||
};
|
||||
}
|
||||
|
@ -1329,7 +1329,7 @@ fn compile_guard<'a>(
|
|||
id,
|
||||
parameters: arena.alloc([param]),
|
||||
remainder: stmt,
|
||||
continuation: arena.alloc(cond),
|
||||
body: arena.alloc(cond),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1622,7 +1622,7 @@ fn decide_to_branching<'a>(
|
|||
Stmt::Join {
|
||||
id: fail_jp_id,
|
||||
parameters: &[],
|
||||
continuation: fail,
|
||||
body: fail,
|
||||
remainder: arena.alloc(test_stmt),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -622,7 +622,7 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
|||
Join {
|
||||
id,
|
||||
parameters,
|
||||
continuation,
|
||||
body: continuation,
|
||||
remainder,
|
||||
} => {
|
||||
let continuation = expand_and_cancel(env, continuation);
|
||||
|
@ -631,7 +631,7 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
|||
let stmt = Join {
|
||||
id: *id,
|
||||
parameters,
|
||||
continuation,
|
||||
body: continuation,
|
||||
remainder,
|
||||
};
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ pub fn occurring_variables(stmt: &Stmt<'_>) -> (MutSet<Symbol>, MutSet<Symbol>)
|
|||
|
||||
Join {
|
||||
parameters,
|
||||
continuation,
|
||||
body: continuation,
|
||||
remainder,
|
||||
..
|
||||
} => {
|
||||
|
@ -455,7 +455,7 @@ impl<'a> Context<'a> {
|
|||
|
||||
HigherOrderLowLevel {
|
||||
op,
|
||||
closure_layout,
|
||||
closure_env_layout,
|
||||
specialization_id,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
|
@ -467,7 +467,7 @@ impl<'a> Context<'a> {
|
|||
call_type: if let Some(OWNED) = $borrows.map(|p| p.borrow) {
|
||||
HigherOrderLowLevel {
|
||||
op: *op,
|
||||
closure_layout: *closure_layout,
|
||||
closure_env_layout: *closure_env_layout,
|
||||
function_owns_closure_data: true,
|
||||
specialization_id: *specialization_id,
|
||||
arg_layouts,
|
||||
|
@ -497,12 +497,14 @@ impl<'a> Context<'a> {
|
|||
const FUNCTION: bool = BORROWED;
|
||||
const CLOSURE_DATA: bool = BORROWED;
|
||||
|
||||
let function_layout = Layout::FunctionPointer(arg_layouts, ret_layout);
|
||||
|
||||
match op {
|
||||
roc_module::low_level::LowLevel::ListMap
|
||||
| roc_module::low_level::LowLevel::ListKeepIf
|
||||
| roc_module::low_level::LowLevel::ListKeepOks
|
||||
| roc_module::low_level::LowLevel::ListKeepErrs => {
|
||||
match self.param_map.get_symbol(arguments[1], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[1], function_layout) {
|
||||
Some(function_ps) => {
|
||||
let borrows = [function_ps[0].borrow, FUNCTION, CLOSURE_DATA];
|
||||
|
||||
|
@ -524,7 +526,7 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
}
|
||||
roc_module::low_level::LowLevel::ListMapWithIndex => {
|
||||
match self.param_map.get_symbol(arguments[1], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[1], function_layout) {
|
||||
Some(function_ps) => {
|
||||
let borrows = [function_ps[1].borrow, FUNCTION, CLOSURE_DATA];
|
||||
|
||||
|
@ -545,7 +547,7 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
}
|
||||
roc_module::low_level::LowLevel::ListMap2 => {
|
||||
match self.param_map.get_symbol(arguments[2], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[2], function_layout) {
|
||||
Some(function_ps) => {
|
||||
let borrows = [
|
||||
function_ps[0].borrow,
|
||||
|
@ -572,7 +574,7 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
}
|
||||
roc_module::low_level::LowLevel::ListMap3 => {
|
||||
match self.param_map.get_symbol(arguments[3], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[3], function_layout) {
|
||||
Some(function_ps) => {
|
||||
let borrows = [
|
||||
function_ps[0].borrow,
|
||||
|
@ -601,7 +603,7 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
}
|
||||
roc_module::low_level::LowLevel::ListSortWith => {
|
||||
match self.param_map.get_symbol(arguments[1], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[1], function_layout) {
|
||||
Some(function_ps) => {
|
||||
let borrows = [OWNED, FUNCTION, CLOSURE_DATA];
|
||||
|
||||
|
@ -623,7 +625,7 @@ impl<'a> Context<'a> {
|
|||
| roc_module::low_level::LowLevel::ListWalkUntil
|
||||
| roc_module::low_level::LowLevel::ListWalkBackwards
|
||||
| roc_module::low_level::LowLevel::DictWalk => {
|
||||
match self.param_map.get_symbol(arguments[2], *closure_layout) {
|
||||
match self.param_map.get_symbol(arguments[2], function_layout) {
|
||||
Some(function_ps) => {
|
||||
// borrow data structure based on first argument of the folded function
|
||||
// borrow the default based on second argument of the folded function
|
||||
|
@ -978,7 +980,7 @@ impl<'a> Context<'a> {
|
|||
id: j,
|
||||
parameters: _,
|
||||
remainder: b,
|
||||
continuation: v,
|
||||
body: v,
|
||||
} => {
|
||||
// get the parameters with borrow signature
|
||||
let xs = self.param_map.get_join_point(*j);
|
||||
|
@ -1000,7 +1002,7 @@ impl<'a> Context<'a> {
|
|||
id: *j,
|
||||
parameters: xs,
|
||||
remainder: b,
|
||||
continuation: v,
|
||||
body: v,
|
||||
}),
|
||||
b_live_vars,
|
||||
)
|
||||
|
@ -1143,7 +1145,7 @@ pub fn collect_stmt(
|
|||
id: j,
|
||||
parameters,
|
||||
remainder: b,
|
||||
continuation: v,
|
||||
body: v,
|
||||
} => {
|
||||
let mut j_live_vars = collect_stmt(v, jp_live_vars, MutSet::default());
|
||||
for param in parameters.iter() {
|
||||
|
|
|
@ -890,9 +890,10 @@ pub enum Stmt<'a> {
|
|||
Join {
|
||||
id: JoinPointId,
|
||||
parameters: &'a [Param<'a>],
|
||||
/// does not contain jumps to this id
|
||||
continuation: &'a Stmt<'a>,
|
||||
/// the "body" of the join point, contains the jumps to this id
|
||||
/// body of the join point
|
||||
/// what happens after _jumping to_ the join point
|
||||
body: &'a Stmt<'a>,
|
||||
/// what happens after _defining_ the join point
|
||||
remainder: &'a Stmt<'a>,
|
||||
},
|
||||
Jump(JoinPointId, &'a [Symbol]),
|
||||
|
@ -1013,6 +1014,8 @@ pub enum Wrapped {
|
|||
EmptyRecord,
|
||||
SingleElementRecord,
|
||||
RecordOrSingleTagUnion,
|
||||
/// Like a rose tree; recursive, but only one tag
|
||||
LikeARoseTree,
|
||||
MultiTagUnion,
|
||||
}
|
||||
|
||||
|
@ -1045,7 +1048,7 @@ impl Wrapped {
|
|||
},
|
||||
_ => Some(Wrapped::MultiTagUnion),
|
||||
},
|
||||
NonNullableUnwrapped(_) => Some(Wrapped::RecordOrSingleTagUnion),
|
||||
NonNullableUnwrapped(_) => Some(Wrapped::LikeARoseTree),
|
||||
|
||||
NullableWrapped { .. } | NullableUnwrapped { .. } => {
|
||||
Some(Wrapped::MultiTagUnion)
|
||||
|
@ -1151,7 +1154,7 @@ pub enum CallType<'a> {
|
|||
HigherOrderLowLevel {
|
||||
op: LowLevel,
|
||||
/// the layout of the closure argument, if any
|
||||
closure_layout: Layout<'a>,
|
||||
closure_env_layout: Option<Layout<'a>>,
|
||||
/// specialization id of the function argument
|
||||
specialization_id: CallSpecId,
|
||||
/// does the function need to own the closure data
|
||||
|
@ -1476,7 +1479,7 @@ impl<'a> Stmt<'a> {
|
|||
Join {
|
||||
id,
|
||||
parameters,
|
||||
continuation,
|
||||
body: continuation,
|
||||
remainder,
|
||||
} => {
|
||||
let it = parameters.iter().map(|p| symbol_to_doc(alloc, p.symbol));
|
||||
|
@ -2712,8 +2715,6 @@ macro_rules! match_on_closure_argument {
|
|||
|
||||
let arena = $env.arena;
|
||||
|
||||
let function_layout = arena.alloc(top_level).full();
|
||||
|
||||
let arg_layouts = top_level.arguments;
|
||||
let ret_layout = top_level.result;
|
||||
|
||||
|
@ -2723,10 +2724,10 @@ macro_rules! match_on_closure_argument {
|
|||
$env,
|
||||
lambda_set,
|
||||
$closure_data_symbol,
|
||||
|top_level_function, closure_data, function_layout, specialization_id| self::Call {
|
||||
|top_level_function, closure_data, closure_env_layout, specialization_id| self::Call {
|
||||
call_type: CallType::HigherOrderLowLevel {
|
||||
op: $op,
|
||||
closure_layout: function_layout,
|
||||
closure_env_layout,
|
||||
specialization_id,
|
||||
function_owns_closure_data: false,
|
||||
arg_layouts,
|
||||
|
@ -2734,7 +2735,6 @@ macro_rules! match_on_closure_argument {
|
|||
},
|
||||
arguments: arena.alloc([$($x,)* top_level_function, closure_data]),
|
||||
},
|
||||
function_layout,
|
||||
$layout,
|
||||
$assigned,
|
||||
$hole,
|
||||
|
@ -3328,7 +3328,7 @@ pub fn with_hole<'a>(
|
|||
id,
|
||||
parameters: env.arena.alloc([param]),
|
||||
remainder: env.arena.alloc(stmt),
|
||||
continuation: hole,
|
||||
body: hole,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3381,7 +3381,7 @@ pub fn with_hole<'a>(
|
|||
id,
|
||||
parameters: env.arena.alloc([param]),
|
||||
remainder: env.arena.alloc(stmt),
|
||||
continuation: env.arena.alloc(hole),
|
||||
body: env.arena.alloc(hole),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4275,7 +4275,10 @@ fn convert_tag_union<'a>(
|
|||
)
|
||||
}
|
||||
|
||||
Unwrapped(_, field_layouts) => {
|
||||
Unwrapped {
|
||||
arguments: field_layouts,
|
||||
..
|
||||
} => {
|
||||
let field_symbols_temp = sorted_field_symbols(env, procs, layout_cache, args);
|
||||
|
||||
let mut field_symbols = Vec::with_capacity_in(field_layouts.len(), env.arena);
|
||||
|
@ -5327,7 +5330,7 @@ fn substitute_in_stmt_help<'a>(
|
|||
id,
|
||||
parameters,
|
||||
remainder,
|
||||
continuation,
|
||||
body: continuation,
|
||||
} => {
|
||||
let opt_remainder = substitute_in_stmt_help(arena, remainder, subs);
|
||||
let opt_continuation = substitute_in_stmt_help(arena, continuation, subs);
|
||||
|
@ -5340,7 +5343,7 @@ fn substitute_in_stmt_help<'a>(
|
|||
id: *id,
|
||||
parameters,
|
||||
remainder,
|
||||
continuation,
|
||||
body: continuation,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
|
@ -7013,7 +7016,10 @@ fn from_can_pattern_help<'a>(
|
|||
union,
|
||||
}
|
||||
}
|
||||
Unwrapped(_, field_layouts) => {
|
||||
Unwrapped {
|
||||
arguments: field_layouts,
|
||||
..
|
||||
} => {
|
||||
let union = crate::exhaustive::Union {
|
||||
render_as: RenderAs::Tag,
|
||||
alternatives: vec![Ctor {
|
||||
|
@ -7708,13 +7714,12 @@ fn lowlevel_match_on_lambda_set<'a, ToLowLevelCall>(
|
|||
lambda_set: LambdaSet<'a>,
|
||||
closure_data_symbol: Symbol,
|
||||
to_lowlevel_call: ToLowLevelCall,
|
||||
function_layout: Layout<'a>,
|
||||
return_layout: Layout<'a>,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a>
|
||||
where
|
||||
ToLowLevelCall: Fn(Symbol, Symbol, Layout<'a>, CallSpecId) -> Call<'a> + Copy,
|
||||
ToLowLevelCall: Fn(Symbol, Symbol, Option<Layout<'a>>, CallSpecId) -> Call<'a> + Copy,
|
||||
{
|
||||
match lambda_set.runtime_representation() {
|
||||
Layout::Union(_) => {
|
||||
|
@ -7726,8 +7731,8 @@ where
|
|||
closure_tag_id_symbol,
|
||||
Layout::Builtin(crate::layout::TAG_SIZE),
|
||||
closure_data_symbol,
|
||||
lambda_set.is_represented(),
|
||||
to_lowlevel_call,
|
||||
function_layout,
|
||||
return_layout,
|
||||
assigned,
|
||||
hole,
|
||||
|
@ -7755,7 +7760,7 @@ where
|
|||
let call = to_lowlevel_call(
|
||||
function_symbol,
|
||||
closure_data_symbol,
|
||||
function_layout,
|
||||
lambda_set.is_represented(),
|
||||
call_spec_id,
|
||||
);
|
||||
|
||||
|
@ -7770,8 +7775,8 @@ where
|
|||
closure_tag_id_symbol,
|
||||
Layout::Builtin(Builtin::Int1),
|
||||
closure_data_symbol,
|
||||
lambda_set.is_represented(),
|
||||
to_lowlevel_call,
|
||||
function_layout,
|
||||
return_layout,
|
||||
assigned,
|
||||
hole,
|
||||
|
@ -7786,8 +7791,8 @@ where
|
|||
closure_tag_id_symbol,
|
||||
Layout::Builtin(Builtin::Int8),
|
||||
closure_data_symbol,
|
||||
lambda_set.is_represented(),
|
||||
to_lowlevel_call,
|
||||
function_layout,
|
||||
return_layout,
|
||||
assigned,
|
||||
hole,
|
||||
|
@ -7804,14 +7809,14 @@ fn lowlevel_union_lambda_set_to_switch<'a, ToLowLevelCall>(
|
|||
closure_tag_id_symbol: Symbol,
|
||||
closure_tag_id_layout: Layout<'a>,
|
||||
closure_data_symbol: Symbol,
|
||||
closure_env_layout: Option<Layout<'a>>,
|
||||
to_lowlevel_call: ToLowLevelCall,
|
||||
function_layout: Layout<'a>,
|
||||
return_layout: Layout<'a>,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a>
|
||||
where
|
||||
ToLowLevelCall: Fn(Symbol, Symbol, Layout<'a>, CallSpecId) -> Call<'a> + Copy,
|
||||
ToLowLevelCall: Fn(Symbol, Symbol, Option<Layout<'a>>, CallSpecId) -> Call<'a> + Copy,
|
||||
{
|
||||
debug_assert!(!lambda_set.is_empty());
|
||||
|
||||
|
@ -7828,7 +7833,7 @@ where
|
|||
let call = to_lowlevel_call(
|
||||
*function_symbol,
|
||||
closure_data_symbol,
|
||||
function_layout,
|
||||
closure_env_layout,
|
||||
call_spec_id,
|
||||
);
|
||||
let stmt = build_call(env, call, assigned, return_layout, env.arena.alloc(hole));
|
||||
|
@ -7859,7 +7864,7 @@ where
|
|||
Stmt::Join {
|
||||
id: join_point_id,
|
||||
parameters: &*env.arena.alloc([param]),
|
||||
continuation: hole,
|
||||
body: hole,
|
||||
remainder: env.arena.alloc(switch),
|
||||
}
|
||||
}
|
||||
|
@ -8017,7 +8022,7 @@ fn union_lambda_set_to_switch<'a>(
|
|||
Stmt::Join {
|
||||
id: join_point_id,
|
||||
parameters: &*env.arena.alloc([param]),
|
||||
continuation: hole,
|
||||
body: hole,
|
||||
remainder: env.arena.alloc(switch),
|
||||
}
|
||||
}
|
||||
|
@ -8161,7 +8166,7 @@ fn enum_lambda_set_to_switch<'a>(
|
|||
Stmt::Join {
|
||||
id: join_point_id,
|
||||
parameters: &*env.arena.alloc([param]),
|
||||
continuation: hole,
|
||||
body: hole,
|
||||
remainder: env.arena.alloc(switch),
|
||||
}
|
||||
}
|
||||
|
@ -8229,14 +8234,14 @@ fn lowlevel_enum_lambda_set_to_switch<'a, ToLowLevelCall>(
|
|||
closure_tag_id_symbol: Symbol,
|
||||
closure_tag_id_layout: Layout<'a>,
|
||||
closure_data_symbol: Symbol,
|
||||
closure_env_layout: Option<Layout<'a>>,
|
||||
to_lowlevel_call: ToLowLevelCall,
|
||||
function_layout: Layout<'a>,
|
||||
return_layout: Layout<'a>,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a>
|
||||
where
|
||||
ToLowLevelCall: Fn(Symbol, Symbol, Layout<'a>, CallSpecId) -> Call<'a> + Copy,
|
||||
ToLowLevelCall: Fn(Symbol, Symbol, Option<Layout<'a>>, CallSpecId) -> Call<'a> + Copy,
|
||||
{
|
||||
debug_assert!(!lambda_set.is_empty());
|
||||
|
||||
|
@ -8253,7 +8258,7 @@ where
|
|||
let call = to_lowlevel_call(
|
||||
*function_symbol,
|
||||
closure_data_symbol,
|
||||
function_layout,
|
||||
closure_env_layout,
|
||||
call_spec_id,
|
||||
);
|
||||
let stmt = build_call(
|
||||
|
@ -8290,7 +8295,7 @@ where
|
|||
Stmt::Join {
|
||||
id: join_point_id,
|
||||
parameters: &*env.arena.alloc([param]),
|
||||
continuation: hole,
|
||||
body: hole,
|
||||
remainder: env.arena.alloc(switch),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,6 +143,14 @@ impl<'a> LambdaSet<'a> {
|
|||
*self.representation
|
||||
}
|
||||
|
||||
pub fn is_represented(&self) -> Option<Layout<'a>> {
|
||||
if let Layout::Struct(&[]) = self.representation {
|
||||
None
|
||||
} else {
|
||||
Some(*self.representation)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn layout_for_member(&self, function_symbol: Symbol) -> ClosureRepresentation<'a> {
|
||||
debug_assert!(
|
||||
self.set.iter().any(|(s, _)| *s == function_symbol),
|
||||
|
@ -281,7 +289,9 @@ impl<'a> LambdaSet<'a> {
|
|||
Unit | UnitWithArguments => Layout::Struct(&[]),
|
||||
BoolUnion { .. } => Layout::Builtin(Builtin::Int1),
|
||||
ByteUnion(_) => Layout::Builtin(Builtin::Int8),
|
||||
Unwrapped(_tag_name, layouts) => Layout::Struct(layouts.into_bump_slice()),
|
||||
Unwrapped {
|
||||
arguments: layouts, ..
|
||||
} => Layout::Struct(layouts.into_bump_slice()),
|
||||
Wrapped(variant) => {
|
||||
use WrappedVariant::*;
|
||||
|
||||
|
@ -1266,9 +1276,15 @@ pub enum UnionVariant<'a> {
|
|||
Never,
|
||||
Unit,
|
||||
UnitWithArguments,
|
||||
BoolUnion { ttrue: TagName, ffalse: TagName },
|
||||
BoolUnion {
|
||||
ttrue: TagName,
|
||||
ffalse: TagName,
|
||||
},
|
||||
ByteUnion(Vec<'a, TagName>),
|
||||
Unwrapped(TagName, Vec<'a, Layout<'a>>),
|
||||
Unwrapped {
|
||||
tag_name: TagName,
|
||||
arguments: Vec<'a, Layout<'a>>,
|
||||
},
|
||||
Wrapped(WrappedVariant<'a>),
|
||||
}
|
||||
|
||||
|
@ -1486,7 +1502,10 @@ pub fn union_sorted_tags_help<'a>(
|
|||
fields: layouts.into_bump_slice(),
|
||||
})
|
||||
} else {
|
||||
UnionVariant::Unwrapped(tag_name, layouts)
|
||||
UnionVariant::Unwrapped {
|
||||
tag_name,
|
||||
arguments: layouts,
|
||||
}
|
||||
}
|
||||
}
|
||||
num_tags => {
|
||||
|
@ -1638,7 +1657,10 @@ pub fn layout_from_tag_union<'a>(
|
|||
Unit | UnitWithArguments => Layout::Struct(&[]),
|
||||
BoolUnion { .. } => Layout::Builtin(Builtin::Int1),
|
||||
ByteUnion(_) => Layout::Builtin(Builtin::Int8),
|
||||
Unwrapped(_, mut field_layouts) => {
|
||||
Unwrapped {
|
||||
arguments: mut field_layouts,
|
||||
..
|
||||
} => {
|
||||
if field_layouts.len() == 1 {
|
||||
field_layouts.pop().unwrap()
|
||||
} else {
|
||||
|
|
|
@ -60,7 +60,7 @@ pub fn make_tail_recursive<'a>(
|
|||
id,
|
||||
remainder: jump,
|
||||
parameters: params,
|
||||
continuation: new,
|
||||
body: new,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ fn insert_jumps<'a>(
|
|||
id,
|
||||
parameters,
|
||||
remainder,
|
||||
continuation,
|
||||
body: continuation,
|
||||
} => {
|
||||
let opt_remainder = insert_jumps(arena, remainder, goal_id, needle);
|
||||
let opt_continuation = insert_jumps(arena, continuation, goal_id, needle);
|
||||
|
@ -173,7 +173,7 @@ fn insert_jumps<'a>(
|
|||
id: *id,
|
||||
parameters,
|
||||
remainder,
|
||||
continuation,
|
||||
body: continuation,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue