mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
work on higher order lowlevels
This commit is contained in:
parent
9476f63e07
commit
86f35c33cd
6 changed files with 81 additions and 14 deletions
|
@ -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)
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>),
|
||||
|
|
|
@ -6,5 +6,7 @@ platform examples/quicksort
|
|||
provides [ mainForHost ]
|
||||
effects fx.Effect {}
|
||||
|
||||
update : Model -> Model
|
||||
|
||||
mainForHost : List I64 -> List I64
|
||||
mainForHost = \list -> quicksort list
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue