work on higher order lowlevels

This commit is contained in:
Folkert 2021-06-12 23:05:06 +02:00
parent 9476f63e07
commit 86f35c33cd
6 changed files with 81 additions and 14 deletions

View file

@ -826,6 +826,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
specialization_id,
..
} => {
let bytes = specialization_id.to_bytes();
let callee_var = CalleeSpecVar(&bytes);
@ -3815,18 +3816,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
($index:expr) => {{
let function_symbol = args[$index];
let fn_name = layout_ids
.get(function_symbol, &function_layout)
.to_symbol_string(function_symbol, &env.interns);
env.module
.get_function(fn_name.as_str())
.unwrap_or_else(|| {
panic!(
"Could not get pointer to unknown function {:?} {:?}",
fn_name, function_layout
)
})
function_value_by_func_spec(env, func_spec, function_symbol, function_layout)
}};
}

View file

@ -414,7 +414,64 @@ fn call_spec(
*update_mode,
call.arguments,
),
HigherOrderLowLevel { op, .. } => {
HigherOrderLowLevel {
specialization_id,
closure_layout: _,
op,
arg_layouts,
ret_layout,
..
} => {
let array = specialization_id.to_bytes();
let spec_var = CalleeSpecVar(&array);
let symbol = {
use roc_module::low_level::LowLevel::*;
match op {
ListMap | ListMapWithIndex => call.arguments[1],
ListMap2 => call.arguments[2],
ListMap3 => call.arguments[3],
ListWalk | ListWalkUntil | ListWalkBackwards | DictWalk => call.arguments[2],
ListKeepIf | ListKeepOks | ListKeepErrs => call.arguments[1],
ListSortWith => call.arguments[1],
_ => unreachable!(),
}
};
let it = arg_layouts.iter().copied();
let bytes = func_name_bytes_help(symbol, it, *ret_layout);
let name = FuncName(&bytes);
let module = MOD_APP;
{
use roc_module::low_level::LowLevel::*;
match op {
DictWalk => {
let dict = env.symbols[&call.arguments[0]];
let default = env.symbols[&call.arguments[1]];
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])?;
builder.add_call(block, spec_var, module, name, argument)?;
}
_ => {
// fake a call to the function argument
// to make sure the function is specialized
// very invalid
let arg_value_id = build_tuple_value(builder, env, block, &[])?;
builder.add_call(block, spec_var, module, name, arg_value_id)?;
}
}
}
// TODO overly pessimstic
// filter_map because one of the arguments is a function name, which
// is not defined in the env
@ -773,6 +830,9 @@ fn str_type<TC: TypeContext>(builder: &mut TC) -> Result<TypeId> {
const LIST_CELL_INDEX: u32 = 0;
const LIST_BAG_INDEX: u32 = 1;
const DICT_CELL_INDEX: u32 = LIST_CELL_INDEX;
const DICT_BAG_INDEX: u32 = LIST_BAG_INDEX;
fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) -> Result<ValueId> {
let cell = builder.add_new_heap_cell(block)?;
let bag = builder.add_empty_bag(block, element_type)?;

View file

@ -457,6 +457,8 @@ impl<'a> Context<'a> {
op,
closure_layout,
specialization_id,
arg_layouts,
ret_layout,
..
} => {
macro_rules! create_call {
@ -468,6 +470,8 @@ impl<'a> Context<'a> {
closure_layout: *closure_layout,
function_owns_closure_data: true,
specialization_id: *specialization_id,
arg_layouts,
ret_layout: *ret_layout,
}
} else {
call_type

View file

@ -1150,6 +1150,9 @@ pub enum CallType<'a> {
specialization_id: CallSpecId,
/// does the function need to own the closure data
function_owns_closure_data: bool,
/// function layout
arg_layouts: &'a [Layout<'a>],
ret_layout: Layout<'a>,
},
}
@ -2703,6 +2706,11 @@ 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;
match closure_data_layout {
Layout::Closure(_, lambda_set, _) => {
lowlevel_match_on_lambda_set(
@ -2715,10 +2723,12 @@ macro_rules! match_on_closure_argument {
closure_layout: function_layout,
specialization_id,
function_owns_closure_data: false,
arg_layouts,
ret_layout,
},
arguments: arena.alloc([$($x,)* top_level_function, closure_data]),
},
arena.alloc(top_level).full(),
function_layout,
$layout,
$assigned,
$hole,

View file

@ -43,6 +43,7 @@ pub enum Layout<'a> {
Struct(&'a [Layout<'a>]),
Union(UnionLayout<'a>),
RecursivePointer,
/// A function. The types of its arguments, then the type of its return value.
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),

View file

@ -6,5 +6,7 @@ platform examples/quicksort
provides [ mainForHost ]
effects fx.Effect {}
update : Model -> Model
mainForHost : List I64 -> List I64
mainForHost = \list -> quicksort list