Typecheck and compile opaque wrapping functions

This enables you to write something like

```
A := U8
List.map [1, 2, 3] @A
```

which will be compiled as if it was `List.map [1, 2, 3] \x -> @A x`.

Closes #3499
This commit is contained in:
Ayaz Hafiz 2022-07-12 18:38:03 -04:00
parent d889f1fda9
commit f1a6ea6a40
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
9 changed files with 360 additions and 15 deletions

View file

@ -1,6 +1,6 @@
use roc_can::{
def::Def,
expr::{AccessorData, ClosureData, Expr, Field, WhenBranch},
expr::{AccessorData, ClosureData, Expr, Field, OpaqueWrapFunctionData, WhenBranch},
};
use roc_module::ident::{Lowercase, TagName};
use roc_types::{
@ -543,6 +543,29 @@ fn deep_copy_type_vars_into_expr_help<C: CopyEnv>(
lambda_set_variables: lambda_set_variables.clone(),
},
OpaqueWrapFunction(OpaqueWrapFunctionData {
opaque_name,
opaque_var,
specialized_def_type,
type_arguments,
lambda_set_variables,
function_name,
function_var,
argument_var,
closure_var,
}) => OpaqueWrapFunction(OpaqueWrapFunctionData {
opaque_name: *opaque_name,
opaque_var: sub!(*opaque_var),
function_name: *function_name,
function_var: sub!(*function_var),
argument_var: sub!(*argument_var),
closure_var: sub!(*closure_var),
// The following three are only used for constraining
specialized_def_type: specialized_def_type.clone(),
type_arguments: type_arguments.clone(),
lambda_set_variables: lambda_set_variables.clone(),
}),
Expect {
loc_condition,
loc_continuation,

View file

@ -4387,6 +4387,60 @@ pub fn with_hole<'a>(
}
}
OpaqueWrapFunction(wrap_fn_data) => {
let opaque_var = wrap_fn_data.opaque_var;
let arg_symbol = env.unique_symbol();
let ClosureData {
name,
function_type,
arguments,
loc_body,
..
} = wrap_fn_data.to_closure_data(arg_symbol);
match procs.insert_anonymous(
env,
LambdaName::no_niche(name),
function_type,
arguments,
*loc_body,
CapturedSymbols::None,
opaque_var,
layout_cache,
) {
Ok(_) => {
let raw_layout = return_on_layout_error!(
env,
layout_cache.raw_from_var(env.arena, function_type, env.subs),
"Expr::OpaqueWrapFunction"
);
match raw_layout {
RawFunctionLayout::Function(_, lambda_set, _) => {
let lambda_name =
find_lambda_name(env, layout_cache, lambda_set, name, &[]);
construct_closure_data(
env,
lambda_set,
lambda_name,
&[],
assigned,
hole,
)
}
RawFunctionLayout::ZeroArgumentThunk(_) => {
internal_error!("should not be a thunk!")
}
}
}
Err(_error) => Stmt::RuntimeError(
"TODO convert anonymous function error to a RuntimeError string",
),
}
}
Update {
record_var,
symbol: structure,