mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41: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
|
.specialized
|
||||||
.contains_key(&(proc_name, full_layout.clone()))
|
.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 {
|
let call = Expr::FunctionCall {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName(proc_name),
|
||||||
ret_layout: ret_layout.clone(),
|
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 {
|
let call = Expr::FunctionCall {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName(proc_name),
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
|
@ -4762,30 +4773,106 @@ fn call_by_name<'a>(
|
||||||
let function_layout =
|
let function_layout =
|
||||||
FunctionLayouts::from_layout(env.arena, 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(
|
procs.specialized.insert(
|
||||||
(proc_name, function_layout.full.clone()),
|
(proc_name, function_layout.full.clone()),
|
||||||
Done(proc),
|
Done(proc),
|
||||||
);
|
);
|
||||||
|
|
||||||
let call = Expr::FunctionCall {
|
if field_symbols.is_empty() {
|
||||||
call_type: CallType::ByName(proc_name),
|
debug_assert!(loc_args.is_empty());
|
||||||
ret_layout: function_layout.result.clone(),
|
|
||||||
full_layout: function_layout.full,
|
|
||||||
arg_layouts: function_layout.arguments,
|
|
||||||
args: field_symbols,
|
|
||||||
};
|
|
||||||
|
|
||||||
let iter = loc_args
|
// This happens when we return a function, e.g.
|
||||||
.into_iter()
|
//
|
||||||
.rev()
|
// foo = Num.add
|
||||||
.zip(field_symbols.iter().rev());
|
//
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
|
||||||
let result =
|
// in the case of a closure specifically, we
|
||||||
Stmt::Let(assigned, call, function_layout.result, hole);
|
// 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(),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
assign_to_symbols(env, procs, layout_cache, iter, result)
|
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(),
|
||||||
|
full_layout: function_layout.full,
|
||||||
|
arg_layouts: function_layout.arguments,
|
||||||
|
args: field_symbols,
|
||||||
|
};
|
||||||
|
|
||||||
|
let iter = loc_args
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.zip(field_symbols.iter().rev());
|
||||||
|
|
||||||
|
let result = Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
call,
|
||||||
|
function_layout.result,
|
||||||
|
hole,
|
||||||
|
);
|
||||||
|
|
||||||
|
assign_to_symbols(
|
||||||
|
env,
|
||||||
|
procs,
|
||||||
|
layout_cache,
|
||||||
|
iter,
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let error_msg = env.arena.alloc(format!(
|
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() => {
|
None if assigned.module_id() != proc_name.module_id() => {
|
||||||
add_needed_external(procs, env, original_fn_var, proc_name);
|
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 {
|
let call = Expr::FunctionCall {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName(proc_name),
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
|
|
|
@ -5,4 +5,3 @@ main =
|
||||||
Effect.putLine "Write a thing!"
|
Effect.putLine "Write a thing!"
|
||||||
|> Effect.after (\{} -> Effect.getLine {})
|
|> Effect.after (\{} -> Effect.getLine {})
|
||||||
|> Effect.after (\line -> Effect.putLine line)
|
|> Effect.after (\line -> Effect.putLine line)
|
||||||
|
|
||||||
|
|
|
@ -8,3 +8,6 @@ platform folkertdev/foo
|
||||||
putLine : Str -> Effect {},
|
putLine : Str -> Effect {},
|
||||||
getLine : {} -> Effect Str
|
getLine : {} -> Effect Str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainForHost : Effect {} as Fx
|
||||||
|
mainForHost = main
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue