mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
got some lowlevel stuff working
This commit is contained in:
parent
051712c90b
commit
f02f655e0b
3 changed files with 139 additions and 46 deletions
|
@ -3950,9 +3950,6 @@ pub fn with_hole<'a>(
|
|||
if let Layout::Closure(_, lambda_set, _) = full_layout {
|
||||
let closure_data_symbol = function_symbol;
|
||||
|
||||
// layout of the closure record
|
||||
let closure_data_layout = lambda_set.runtime_representation();
|
||||
|
||||
result = match_on_lambda_set(
|
||||
env,
|
||||
lambda_set,
|
||||
|
@ -3988,9 +3985,6 @@ pub fn with_hole<'a>(
|
|||
Layout::Closure(_, lambda_set, _) => {
|
||||
let closure_data_symbol = env.unique_symbol();
|
||||
|
||||
// layout of the closure record
|
||||
let closure_data_layout = lambda_set.runtime_representation();
|
||||
|
||||
result = match_on_lambda_set(
|
||||
env,
|
||||
lambda_set,
|
||||
|
@ -4110,7 +4104,28 @@ pub fn with_hole<'a>(
|
|||
let list_symbol = arg_symbols[0];
|
||||
let closure_data_symbol = arg_symbols[1];
|
||||
|
||||
panic!()
|
||||
let closure_data_layout = return_on_layout_error!(
|
||||
env,
|
||||
layout_cache.from_var(env.arena, args[1].0, env.subs)
|
||||
);
|
||||
|
||||
let arena = env.arena;
|
||||
|
||||
match closure_data_layout {
|
||||
Layout::Closure(_, lambda_set, _) => lowlevel_match_on_lambda_set(
|
||||
env,
|
||||
lambda_set,
|
||||
closure_data_symbol,
|
||||
|top_level_function, closure_data| self::Call {
|
||||
call_type: CallType::LowLevel { op },
|
||||
arguments: arena.alloc([list_symbol, top_level_function]),
|
||||
},
|
||||
layout,
|
||||
assigned,
|
||||
hole,
|
||||
),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let call = self::Call {
|
||||
|
@ -5923,7 +5938,6 @@ fn call_by_name_help<'a>(
|
|||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
dbg!(proc_name, &loc_args);
|
||||
let original_fn_var = fn_var;
|
||||
let arena = env.arena;
|
||||
|
||||
|
@ -7378,18 +7392,78 @@ pub fn num_argument_to_int_or_float(
|
|||
}
|
||||
}
|
||||
|
||||
fn lambda_set_lowlevel<'a, F>(
|
||||
/// Use the lambda set to figure out how to make a lowlevel call
|
||||
fn lowlevel_match_on_lambda_set<'a, F>(
|
||||
env: &mut Env<'a, '_>,
|
||||
lambda_set: &'a [(TagName, &'a [Layout<'a>])],
|
||||
to_lowlevel_call: F,
|
||||
closure_tag_id_symbol: Symbol,
|
||||
lambda_set: LambdaSet<'a>,
|
||||
closure_data_symbol: Symbol,
|
||||
to_lowlevel_call: F,
|
||||
return_layout: Layout<'a>,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a>
|
||||
where
|
||||
F: Fn(Symbol) -> Stmt<'a>,
|
||||
F: Fn(Symbol, Symbol) -> Call<'a> + Copy,
|
||||
{
|
||||
match lambda_set.runtime_representation() {
|
||||
Layout::Union(_) => {
|
||||
let closure_tag_id_symbol = env.unique_symbol();
|
||||
|
||||
let result = lowlevel_union_lambda_set_to_switch(
|
||||
env,
|
||||
lambda_set.set,
|
||||
closure_tag_id_symbol,
|
||||
Layout::Builtin(crate::layout::TAG_SIZE),
|
||||
closure_data_symbol,
|
||||
to_lowlevel_call,
|
||||
return_layout,
|
||||
assigned,
|
||||
hole,
|
||||
);
|
||||
|
||||
// extract & assign the closure_tag_id_symbol
|
||||
let expr = Expr::AccessAtIndex {
|
||||
index: 0,
|
||||
field_layouts: env.arena.alloc([Layout::Builtin(Builtin::Int64)]),
|
||||
structure: closure_data_symbol,
|
||||
wrapped: Wrapped::MultiTagUnion,
|
||||
};
|
||||
|
||||
Stmt::Let(
|
||||
closure_tag_id_symbol,
|
||||
expr,
|
||||
Layout::Builtin(Builtin::Int64),
|
||||
env.arena.alloc(result),
|
||||
)
|
||||
}
|
||||
Layout::Struct(_) => {
|
||||
let function_symbol = lambda_set.set[0].0;
|
||||
|
||||
// build the call
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::Call(to_lowlevel_call(function_symbol, closure_data_symbol)),
|
||||
return_layout,
|
||||
env.arena.alloc(hole),
|
||||
)
|
||||
}
|
||||
other => todo!("{:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
fn lowlevel_union_lambda_set_to_switch<'a, F>(
|
||||
env: &mut Env<'a, '_>,
|
||||
lambda_set: &'a [(Symbol, &'a [Layout<'a>])],
|
||||
closure_tag_id_symbol: Symbol,
|
||||
closure_tag_id_layout: Layout<'a>,
|
||||
closure_data_symbol: Symbol,
|
||||
to_lowlevel_call: F,
|
||||
return_layout: Layout<'a>,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a>
|
||||
where
|
||||
F: Fn(Symbol, Symbol) -> Call<'a> + Copy,
|
||||
{
|
||||
debug_assert!(!lambda_set.is_empty());
|
||||
|
||||
|
@ -7397,13 +7471,19 @@ where
|
|||
|
||||
let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena);
|
||||
|
||||
for (i, (tag_name, _)) in lambda_set.iter().enumerate() {
|
||||
if let TagName::Closure(function_symbol) = tag_name {
|
||||
let stmt = to_lowlevel_call(*function_symbol);
|
||||
branches.push((i as u64, BranchInfo::None, stmt));
|
||||
} else {
|
||||
unreachable!("non-closure tag in lambda set")
|
||||
}
|
||||
for (i, (function_symbol, _)) in lambda_set.iter().enumerate() {
|
||||
let assigned = env.unique_symbol();
|
||||
|
||||
let hole = Stmt::Jump(join_point_id, env.arena.alloc([assigned]));
|
||||
|
||||
// build the call
|
||||
let stmt = Stmt::Let(
|
||||
assigned,
|
||||
Expr::Call(to_lowlevel_call(*function_symbol, closure_data_symbol)),
|
||||
return_layout,
|
||||
env.arena.alloc(hole),
|
||||
);
|
||||
branches.push((i as u64, BranchInfo::None, stmt));
|
||||
}
|
||||
|
||||
let default_branch = {
|
||||
|
@ -7414,7 +7494,7 @@ where
|
|||
|
||||
let switch = Stmt::Switch {
|
||||
cond_symbol: closure_tag_id_symbol,
|
||||
cond_layout: Layout::Builtin(Builtin::Int64),
|
||||
cond_layout: closure_tag_id_layout,
|
||||
branches: branches.into_bump_slice(),
|
||||
default_branch,
|
||||
ret_layout: return_layout,
|
||||
|
@ -7434,6 +7514,31 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn lowlevel_union_lambda_set_branch<'a, F>(
|
||||
env: &mut Env<'a, '_>,
|
||||
join_point_id: JoinPointId,
|
||||
function_symbol: Symbol,
|
||||
closure_data_symbol: Symbol,
|
||||
closure_data_layout: Layout<'a>,
|
||||
to_lowlevel_call: F,
|
||||
return_layout: Layout<'a>,
|
||||
) -> Stmt<'a>
|
||||
where
|
||||
F: Fn(Symbol, Symbol) -> Call<'a> + Copy,
|
||||
{
|
||||
let assigned = env.unique_symbol();
|
||||
|
||||
let hole = Stmt::Jump(join_point_id, env.arena.alloc([assigned]));
|
||||
|
||||
// build the call
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::Call(to_lowlevel_call(function_symbol, closure_data_symbol)),
|
||||
return_layout,
|
||||
env.arena.alloc(hole),
|
||||
)
|
||||
}
|
||||
|
||||
/// Use the lambda set to figure out how to make a call-by-name
|
||||
fn match_on_lambda_set<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
|
@ -7452,6 +7557,7 @@ fn match_on_lambda_set<'a>(
|
|||
let result = union_lambda_set_to_switch(
|
||||
env,
|
||||
lambda_set.set,
|
||||
lambda_set.runtime_representation(),
|
||||
closure_tag_id_symbol,
|
||||
Layout::Builtin(crate::layout::TAG_SIZE),
|
||||
closure_data_symbol,
|
||||
|
@ -7480,7 +7586,7 @@ fn match_on_lambda_set<'a>(
|
|||
Layout::Struct(fields) => {
|
||||
let function_symbol = lambda_set.set[0].0;
|
||||
|
||||
lambda_set_to_switch_make_branch_help(
|
||||
union_lambda_set_branch_help(
|
||||
env,
|
||||
function_symbol,
|
||||
closure_data_symbol,
|
||||
|
@ -7531,6 +7637,7 @@ fn match_on_lambda_set<'a>(
|
|||
fn union_lambda_set_to_switch<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
lambda_set: &'a [(Symbol, &'a [Layout<'a>])],
|
||||
closure_layout: Layout<'a>,
|
||||
closure_tag_id_symbol: Symbol,
|
||||
closure_tag_id_layout: Layout<'a>,
|
||||
closure_data_symbol: Symbol,
|
||||
|
@ -7546,16 +7653,8 @@ fn union_lambda_set_to_switch<'a>(
|
|||
|
||||
let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena);
|
||||
|
||||
let closure_layout = {
|
||||
let mut temporary = Vec::with_capacity_in(lambda_set.len(), env.arena);
|
||||
|
||||
temporary.extend(lambda_set.iter().map(|x| x.1));
|
||||
|
||||
Layout::Union(UnionLayout::NonRecursive(temporary.into_bump_slice()))
|
||||
};
|
||||
|
||||
for (i, (function_symbol, _)) in lambda_set.iter().enumerate() {
|
||||
let stmt = lambda_set_to_switch_make_branch(
|
||||
let stmt = union_lambda_set_branch(
|
||||
env,
|
||||
join_point_id,
|
||||
*function_symbol,
|
||||
|
@ -7596,7 +7695,7 @@ fn union_lambda_set_to_switch<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn lambda_set_to_switch_make_branch<'a>(
|
||||
fn union_lambda_set_branch<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
join_point_id: JoinPointId,
|
||||
function_symbol: Symbol,
|
||||
|
@ -7610,7 +7709,7 @@ fn lambda_set_to_switch_make_branch<'a>(
|
|||
|
||||
let hole = Stmt::Jump(join_point_id, env.arena.alloc([result_symbol]));
|
||||
|
||||
lambda_set_to_switch_make_branch_help(
|
||||
union_lambda_set_branch_help(
|
||||
env,
|
||||
function_symbol,
|
||||
closure_data_symbol,
|
||||
|
@ -7623,7 +7722,7 @@ fn lambda_set_to_switch_make_branch<'a>(
|
|||
)
|
||||
}
|
||||
|
||||
fn lambda_set_to_switch_make_branch_help<'a>(
|
||||
fn union_lambda_set_branch_help<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
function_symbol: Symbol,
|
||||
closure_data_symbol: Symbol,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue