mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
allow returning of funtions
e.g. foo = Num.add
This commit is contained in:
parent
b0c169bc5a
commit
1bce119b0a
3 changed files with 111 additions and 16 deletions
|
@ -4678,6 +4678,12 @@ fn call_by_name<'a>(
|
|||
.specialized
|
||||
.contains_key(&(proc_name, full_layout.clone()))
|
||||
{
|
||||
debug_assert_eq!(
|
||||
arg_layouts.len(),
|
||||
field_symbols.len(),
|
||||
"see call_by_name for background (scroll down a bit)"
|
||||
);
|
||||
|
||||
let call = Expr::FunctionCall {
|
||||
call_type: CallType::ByName(proc_name),
|
||||
ret_layout: ret_layout.clone(),
|
||||
|
@ -4721,6 +4727,11 @@ fn call_by_name<'a>(
|
|||
);
|
||||
}
|
||||
|
||||
debug_assert_eq!(
|
||||
arg_layouts.len(),
|
||||
field_symbols.len(),
|
||||
"see call_by_name for background (scroll down a bit)"
|
||||
);
|
||||
let call = Expr::FunctionCall {
|
||||
call_type: CallType::ByName(proc_name),
|
||||
ret_layout: ret_layout.clone(),
|
||||
|
@ -4762,13 +4773,78 @@ fn call_by_name<'a>(
|
|||
let function_layout =
|
||||
FunctionLayouts::from_layout(env.arena, layout);
|
||||
|
||||
procs.specialized.remove(&(proc_name, full_layout));
|
||||
procs.specialized.remove(&(proc_name, full_layout.clone()));
|
||||
|
||||
procs.specialized.insert(
|
||||
(proc_name, function_layout.full.clone()),
|
||||
Done(proc),
|
||||
);
|
||||
|
||||
if field_symbols.is_empty() {
|
||||
debug_assert!(loc_args.is_empty());
|
||||
|
||||
// This happens when we return a function, e.g.
|
||||
//
|
||||
// foo = Num.add
|
||||
//
|
||||
// Even though the layout (and type) are functions,
|
||||
// there are no arguments. This confuses our IR,
|
||||
// and we have to fix it here.
|
||||
match full_layout {
|
||||
Layout::Closure(_, closure_layout, _) => {
|
||||
let call = Expr::FunctionCall {
|
||||
call_type: CallType::ByName(proc_name),
|
||||
ret_layout: function_layout.result.clone(),
|
||||
full_layout: function_layout.full.clone(),
|
||||
arg_layouts: function_layout.arguments,
|
||||
args: field_symbols,
|
||||
};
|
||||
|
||||
// in the case of a closure specifically, we
|
||||
// have to create a custom layout, to make sure
|
||||
// the closure data is part of the layout
|
||||
let closure_struct_layout = Layout::Struct(
|
||||
env.arena.alloc([
|
||||
function_layout.full,
|
||||
closure_layout
|
||||
.as_block_of_memory_layout(),
|
||||
]),
|
||||
);
|
||||
|
||||
let result = Stmt::Let(
|
||||
assigned,
|
||||
call,
|
||||
closure_struct_layout,
|
||||
hole,
|
||||
);
|
||||
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
let call = Expr::FunctionCall {
|
||||
call_type: CallType::ByName(proc_name),
|
||||
ret_layout: function_layout.result.clone(),
|
||||
full_layout: function_layout.full.clone(),
|
||||
arg_layouts: function_layout.arguments,
|
||||
args: field_symbols,
|
||||
};
|
||||
|
||||
let result = Stmt::Let(
|
||||
assigned,
|
||||
call,
|
||||
function_layout.full,
|
||||
hole,
|
||||
);
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug_assert_eq!(
|
||||
function_layout.arguments.len(),
|
||||
field_symbols.len(),
|
||||
"scroll up a bit for background"
|
||||
);
|
||||
let call = Expr::FunctionCall {
|
||||
call_type: CallType::ByName(proc_name),
|
||||
ret_layout: function_layout.result.clone(),
|
||||
|
@ -4782,10 +4858,21 @@ fn call_by_name<'a>(
|
|||
.rev()
|
||||
.zip(field_symbols.iter().rev());
|
||||
|
||||
let result =
|
||||
Stmt::Let(assigned, call, function_layout.result, hole);
|
||||
let result = Stmt::Let(
|
||||
assigned,
|
||||
call,
|
||||
function_layout.result,
|
||||
hole,
|
||||
);
|
||||
|
||||
assign_to_symbols(env, procs, layout_cache, iter, result)
|
||||
assign_to_symbols(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
iter,
|
||||
result,
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
let error_msg = env.arena.alloc(format!(
|
||||
|
@ -4804,6 +4891,12 @@ fn call_by_name<'a>(
|
|||
None if assigned.module_id() != proc_name.module_id() => {
|
||||
add_needed_external(procs, env, original_fn_var, proc_name);
|
||||
|
||||
debug_assert_eq!(
|
||||
arg_layouts.len(),
|
||||
field_symbols.len(),
|
||||
"scroll up a bit for background"
|
||||
);
|
||||
|
||||
let call = Expr::FunctionCall {
|
||||
call_type: CallType::ByName(proc_name),
|
||||
ret_layout: ret_layout.clone(),
|
||||
|
|
|
@ -5,4 +5,3 @@ main =
|
|||
Effect.putLine "Write a thing!"
|
||||
|> Effect.after (\{} -> Effect.getLine {})
|
||||
|> Effect.after (\line -> Effect.putLine line)
|
||||
|
||||
|
|
|
@ -8,3 +8,6 @@ platform folkertdev/foo
|
|||
putLine : Str -> Effect {},
|
||||
getLine : {} -> Effect Str
|
||||
}
|
||||
|
||||
mainForHost : Effect {} as Fx
|
||||
mainForHost = main
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue