Merge pull request #2109 from rtfeldman/refactor-passed-function

refactor passed (to higher order lowlevel) funcion
This commit is contained in:
Richard Feldman 2021-12-01 08:17:39 -05:00 committed by GitHub
commit e6bec46898
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 95 additions and 88 deletions

View file

@ -955,7 +955,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
}
CallType::HigherOrder(higher_order) => {
let bytes = higher_order.specialization_id.to_bytes();
let bytes = higher_order.passed_function.specialization_id.to_bytes();
let callee_var = CalleeSpecVar(&bytes);
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
@ -4686,20 +4686,23 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
func_spec: FuncSpec,
higher_order: &HigherOrderLowLevel<'a>,
) -> BasicValueEnum<'ctx> {
use roc_mono::ir::PassedFunction;
use roc_mono::low_level::HigherOrder::*;
let HigherOrderLowLevel {
op,
arg_layouts: argument_layouts,
ret_layout: result_layout,
function_owns_closure_data,
function_name,
function_env,
passed_function,
..
} = higher_order;
let function_owns_closure_data = *function_owns_closure_data;
let function_name = *function_name;
let PassedFunction {
argument_layouts,
return_layout: result_layout,
owns_captured_environment: function_owns_closure_data,
name: function_name,
captured_environment,
..
} = *passed_function;
// macros because functions cause lifetime issues related to the `env` or `layout_ids`
macro_rules! function_details {
@ -4712,7 +4715,8 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
return_layout,
);
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, function_env);
let (closure, closure_layout) =
load_symbol_and_lambda_set(scope, &captured_environment);
(function, closure, closure_layout)
}};
@ -4737,14 +4741,14 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
crate::llvm::build_list::list_walk_generic(
env,
layout_ids,
roc_function_call,
result_layout,
&result_layout,
list,
element_layout,
default,
@ -4974,7 +4978,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_keep_if(env, layout_ids, roc_function_call, list, element_layout)
@ -5003,14 +5007,14 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_keep_oks(
env,
layout_ids,
roc_function_call,
result_layout,
&result_layout,
list,
before_layout,
after_layout,
@ -5042,14 +5046,14 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_keep_errs(
env,
layout_ids,
roc_function_call,
result_layout,
&result_layout,
list,
before_layout,
after_layout,
@ -5094,7 +5098,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_sort_with(
@ -5197,7 +5201,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
dict_walk(

View file

@ -702,30 +702,30 @@ fn call_spec(
call.arguments,
),
HigherOrder(HigherOrderLowLevel {
specialization_id,
closure_env_layout,
update_mode,
op,
arg_layouts,
ret_layout,
function_name,
function_env,
passed_function,
..
}) => {
use crate::low_level::HigherOrder::*;
let array = specialization_id.to_bytes();
let array = passed_function.specialization_id.to_bytes();
let spec_var = CalleeSpecVar(&array);
let mode = update_mode.to_bytes();
let update_mode_var = UpdateModeVar(&mode);
let it = arg_layouts.iter().copied();
let bytes = func_name_bytes_help(*function_name, it, ret_layout);
let it = passed_function.argument_layouts.iter().copied();
let bytes =
func_name_bytes_help(passed_function.name, it, &passed_function.return_layout);
let name = FuncName(&bytes);
let module = MOD_APP;
let closure_env = env.symbols[function_env];
let closure_env = env.symbols[&passed_function.captured_environment];
let return_layout = &passed_function.return_layout;
let argument_layouts = passed_function.argument_layouts;
macro_rules! call_function {
($builder: expr, $block:expr, [$($arg:expr),+ $(,)?]) => {{
@ -757,7 +757,7 @@ fn call_spec(
Ok(new_state)
};
let state_layout = arg_layouts[0];
let state_layout = argument_layouts[0];
let state_type = layout_spec(builder, &state_layout)?;
let init_state = state;
@ -778,7 +778,7 @@ fn call_spec(
Ok(new_state)
};
let state_layout = arg_layouts[0];
let state_layout = argument_layouts[0];
let state_type = layout_spec(builder, &state_layout)?;
let init_state = state;
@ -802,7 +802,7 @@ fn call_spec(
Ok(new_state)
};
let state_layout = arg_layouts[0];
let state_layout = argument_layouts[0];
let state_type = layout_spec(builder, &state_layout)?;
let init_state = state;
@ -823,9 +823,9 @@ fn call_spec(
list_append(builder, block, update_mode_var, state, new_element)
};
let output_element_type = layout_spec(builder, ret_layout)?;
let output_element_type = layout_spec(builder, return_layout)?;
let state_layout = Layout::Builtin(Builtin::List(ret_layout));
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -846,9 +846,9 @@ fn call_spec(
list_append(builder, block, update_mode_var, state, new_element)
};
let output_element_type = layout_spec(builder, ret_layout)?;
let output_element_type = layout_spec(builder, return_layout)?;
let state_layout = Layout::Builtin(Builtin::List(ret_layout));
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -873,7 +873,7 @@ fn call_spec(
with_new_heap_cell(builder, block, bag)
};
let state_layout = Layout::Builtin(Builtin::List(&arg_layouts[0]));
let state_layout = Layout::Builtin(Builtin::List(&argument_layouts[0]));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = list;
@ -898,9 +898,9 @@ fn call_spec(
list_append(builder, block, update_mode_var, state, new_element)
};
let output_element_type = layout_spec(builder, ret_layout)?;
let output_element_type = layout_spec(builder, return_layout)?;
let state_layout = Layout::Builtin(Builtin::List(ret_layout));
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -931,9 +931,9 @@ fn call_spec(
list_append(builder, block, update_mode_var, state, new_element)
};
let output_element_type = layout_spec(builder, ret_layout)?;
let output_element_type = layout_spec(builder, return_layout)?;
let state_layout = Layout::Builtin(Builtin::List(ret_layout));
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -970,9 +970,9 @@ fn call_spec(
list_append(builder, block, update_mode_var, state, new_element)
};
let output_element_type = layout_spec(builder, ret_layout)?;
let output_element_type = layout_spec(builder, return_layout)?;
let state_layout = Layout::Builtin(Builtin::List(ret_layout));
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -1004,7 +1004,7 @@ fn call_spec(
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(&argument_layouts[0]));
let state_type = layout_spec(builder, &state_layout)?;
let init_state = list;
@ -1019,7 +1019,7 @@ fn call_spec(
_ => unreachable!(),
};
let result_repr = ResultRepr::from_layout(ret_layout);
let result_repr = ResultRepr::from_layout(return_layout);
let output_element_layout = match (keep_result, result_repr) {
(KeepResult::Errs, ResultRepr::ResultConcrete { err, .. }) => err,
@ -1132,7 +1132,7 @@ fn call_spec(
let list = env.symbols[xs];
// ListFindUnsafe returns { value: v, found: Bool=Int1 }
let output_layouts = vec![arg_layouts[0], Layout::Builtin(Builtin::Bool)];
let output_layouts = vec![argument_layouts[0], Layout::Builtin(Builtin::Bool)];
let output_layout = Layout::Struct(&output_layouts);
let output_type = layout_spec(builder, &output_layout)?;

View file

@ -595,20 +595,17 @@ impl<'a> BorrowInfState<'a> {
HigherOrder(HigherOrderLowLevel {
op,
arg_layouts,
ret_layout,
function_name,
function_env,
passed_function,
..
}) => {
use crate::low_level::HigherOrder::*;
let closure_layout = ProcLayout {
arguments: arg_layouts,
result: *ret_layout,
arguments: passed_function.argument_layouts,
result: passed_function.return_layout,
};
let function_ps = match param_map.get_symbol(*function_name, closure_layout) {
let function_ps = match param_map.get_symbol(passed_function.name, closure_layout) {
Some(function_ps) => function_ps,
None => unreachable!(),
};
@ -692,7 +689,7 @@ impl<'a> BorrowInfState<'a> {
// own the closure environment if the function needs to own it
let function_env_position = op.function_arity();
if let Some(false) = function_ps.get(function_env_position).map(|p| p.borrow) {
self.own_var(*function_env);
self.own_var(passed_function.captured_environment);
}
}

View file

@ -468,12 +468,8 @@ impl<'a> Context<'a> {
HigherOrder(HigherOrderLowLevel {
op,
closure_env_layout,
specialization_id,
update_mode,
arg_layouts,
ret_layout,
function_name,
function_env,
passed_function,
..
}) => {
// setup
@ -483,16 +479,14 @@ impl<'a> Context<'a> {
($borrows:expr) => {
Expr::Call(crate::ir::Call {
call_type: if let Some(OWNED) = $borrows.map(|p| p.borrow) {
let mut passed_function = *passed_function;
passed_function.owns_captured_environment = true;
let higher_order = HigherOrderLowLevel {
op: *op,
closure_env_layout: *closure_env_layout,
function_owns_closure_data: true,
specialization_id: *specialization_id,
update_mode: *update_mode,
function_name: *function_name,
function_env: *function_env,
arg_layouts,
ret_layout: *ret_layout,
passed_function,
};
CallType::HigherOrder(self.arena.alloc(higher_order))
@ -521,11 +515,14 @@ impl<'a> Context<'a> {
const CLOSURE_DATA: bool = BORROWED;
let function_layout = ProcLayout {
arguments: arg_layouts,
result: *ret_layout,
arguments: passed_function.argument_layouts,
result: passed_function.return_layout,
};
let function_ps = match self.param_map.get_symbol(*function_name, function_layout) {
let function_ps = match self
.param_map
.get_symbol(passed_function.name, function_layout)
{
Some(function_ps) => function_ps,
None => unreachable!(),
};

View file

@ -1346,31 +1346,35 @@ pub enum CallType<'a> {
HigherOrder(&'a HigherOrderLowLevel<'a>),
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PassedFunction<'a> {
/// name of the top-level function that is passed as an argument
/// e.g. in `List.map xs Num.abs` this would be `Num.abs`
pub name: Symbol,
pub argument_layouts: &'a [Layout<'a>],
pub return_layout: Layout<'a>,
pub specialization_id: CallSpecId,
/// Symbol of the environment captured by the function argument
pub captured_environment: Symbol,
pub owns_captured_environment: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct HigherOrderLowLevel<'a> {
pub op: crate::low_level::HigherOrder,
/// TODO I _think_ we can get rid of this, perhaps only keeping track of
/// the layout of the closure argument, if any
pub closure_env_layout: Option<Layout<'a>>,
/// name of the top-level function that is passed as an argument
/// e.g. in `List.map xs Num.abs` this would be `Num.abs`
pub function_name: Symbol,
/// Symbol of the environment captured by the function argument
pub function_env: Symbol,
/// does the function argument need to own the closure data
pub function_owns_closure_data: bool,
/// specialization id of the function argument, used for name generation
pub specialization_id: CallSpecId,
/// update mode of the higher order lowlevel itself
pub update_mode: UpdateModeId,
/// function layout, used for name generation
pub arg_layouts: &'a [Layout<'a>],
pub ret_layout: Layout<'a>,
pub passed_function: PassedFunction<'a>,
}
#[derive(Clone, Debug, PartialEq)]
@ -4193,16 +4197,21 @@ pub fn with_hole<'a>(
op,
closure_data_symbol,
|(top_level_function, closure_data, closure_env_layout, specialization_id, update_mode)| {
let passed_function = PassedFunction {
name: top_level_function,
captured_environment: closure_data_symbol,
owns_captured_environment: false,
specialization_id,
argument_layouts: arg_layouts,
return_layout: ret_layout,
};
let higher_order = HigherOrderLowLevel {
op: crate::low_level::HigherOrder::$ho { $($x,)* },
closure_env_layout,
specialization_id,
update_mode,
function_owns_closure_data: false,
function_env: closure_data_symbol,
function_name: top_level_function,
arg_layouts,
ret_layout,
passed_function,
};
self::Call {