mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
enable tag unions as functions in code gen
This commit is contained in:
parent
174daeb3b5
commit
5f408c42b0
3 changed files with 44 additions and 7 deletions
|
@ -4212,6 +4212,7 @@ fn convert_tag_union<'a>(
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match variant {
|
match variant {
|
||||||
Never => unreachable!(
|
Never => unreachable!(
|
||||||
"The `[]` type has no constructors, source var {:?}",
|
"The `[]` type has no constructors, source var {:?}",
|
||||||
|
@ -4253,7 +4254,13 @@ fn convert_tag_union<'a>(
|
||||||
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
|
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
|
||||||
|
|
||||||
// even though this was originally a Tag, we treat it as a Struct from now on
|
// even though this was originally a Tag, we treat it as a Struct from now on
|
||||||
let stmt = Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole);
|
let stmt = if let [only_field] = field_symbols {
|
||||||
|
let mut hole = hole.clone();
|
||||||
|
substitute_in_exprs(env.arena, &mut hole, assigned, *only_field);
|
||||||
|
hole
|
||||||
|
} else {
|
||||||
|
Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole)
|
||||||
|
};
|
||||||
|
|
||||||
let iter = field_symbols_temp.into_iter().map(|(_, _, data)| data);
|
let iter = field_symbols_temp.into_iter().map(|(_, _, data)| data);
|
||||||
assign_to_symbols(env, procs, layout_cache, iter, stmt)
|
assign_to_symbols(env, procs, layout_cache, iter, stmt)
|
||||||
|
@ -4480,6 +4487,7 @@ fn tag_union_to_function<'a>(
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
let mut loc_pattern_args = vec![];
|
let mut loc_pattern_args = vec![];
|
||||||
let mut loc_expr_args = vec![];
|
let mut loc_expr_args = vec![];
|
||||||
|
|
||||||
for arg_var in argument_variables {
|
for arg_var in argument_variables {
|
||||||
let arg_symbol = env.unique_symbol();
|
let arg_symbol = env.unique_symbol();
|
||||||
|
|
||||||
|
@ -4490,12 +4498,14 @@ fn tag_union_to_function<'a>(
|
||||||
loc_pattern_args.push((arg_var, loc_pattern));
|
loc_pattern_args.push((arg_var, loc_pattern));
|
||||||
loc_expr_args.push((arg_var, loc_expr));
|
loc_expr_args.push((arg_var, loc_expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
let loc_body = Located::at_zero(roc_can::expr::Expr::Tag {
|
let loc_body = Located::at_zero(roc_can::expr::Expr::Tag {
|
||||||
variant_var: return_variable,
|
variant_var: return_variable,
|
||||||
name: tag_name,
|
name: tag_name,
|
||||||
arguments: loc_expr_args,
|
arguments: loc_expr_args,
|
||||||
ext_var,
|
ext_var,
|
||||||
});
|
});
|
||||||
|
|
||||||
let inserted = procs.insert_anonymous(
|
let inserted = procs.insert_anonymous(
|
||||||
env,
|
env,
|
||||||
proc_symbol,
|
proc_symbol,
|
||||||
|
@ -4506,8 +4516,9 @@ fn tag_union_to_function<'a>(
|
||||||
return_variable,
|
return_variable,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
);
|
);
|
||||||
|
|
||||||
match inserted {
|
match inserted {
|
||||||
Ok(layout) => {
|
Ok(_layout) => {
|
||||||
// only need to construct closure data
|
// only need to construct closure data
|
||||||
let full_layout =
|
let full_layout =
|
||||||
return_on_layout_error!(env, layout_cache.from_var(env.arena, whole_var, env.subs));
|
return_on_layout_error!(env, layout_cache.from_var(env.arena, whole_var, env.subs));
|
||||||
|
|
|
@ -996,7 +996,6 @@ fn applied_tag_function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn applied_tag_function_result() {
|
fn applied_tag_function_result() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1016,7 +1015,6 @@ fn applied_tag_function_result() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn applied_tag_function_linked_list() {
|
fn applied_tag_function_linked_list() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -1270,11 +1270,11 @@ fn unify_function_or_tag_union_and_func(
|
||||||
pool: &mut Pool,
|
pool: &mut Pool,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
tag_name: &TagName,
|
tag_name: &TagName,
|
||||||
_tag_symbol: Symbol,
|
tag_symbol: Symbol,
|
||||||
tag_ext: Variable,
|
tag_ext: Variable,
|
||||||
function_arguments: &[Variable],
|
function_arguments: &[Variable],
|
||||||
function_return: Variable,
|
function_return: Variable,
|
||||||
_function_lambda_set: Variable,
|
function_lambda_set: Variable,
|
||||||
left: bool,
|
left: bool,
|
||||||
) -> Outcome {
|
) -> Outcome {
|
||||||
use FlatType::*;
|
use FlatType::*;
|
||||||
|
@ -1287,12 +1287,40 @@ fn unify_function_or_tag_union_and_func(
|
||||||
|
|
||||||
let new_tag_union_var = fresh(subs, pool, ctx, content);
|
let new_tag_union_var = fresh(subs, pool, ctx, content);
|
||||||
|
|
||||||
let problems = if left {
|
let mut problems = if left {
|
||||||
unify_pool(subs, pool, new_tag_union_var, function_return)
|
unify_pool(subs, pool, new_tag_union_var, function_return)
|
||||||
} else {
|
} else {
|
||||||
unify_pool(subs, pool, function_return, new_tag_union_var)
|
unify_pool(subs, pool, function_return, new_tag_union_var)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let lambda_set_ext = subs.fresh_unnamed_flex_var();
|
||||||
|
|
||||||
|
let mut closure_tags = MutMap::with_capacity_and_hasher(1, default_hasher());
|
||||||
|
closure_tags.insert(TagName::Closure(tag_symbol), vec![]);
|
||||||
|
|
||||||
|
let lambda_set_content = Structure(TagUnion(closure_tags, lambda_set_ext));
|
||||||
|
|
||||||
|
let tag_lambda_set = register(
|
||||||
|
subs,
|
||||||
|
Descriptor {
|
||||||
|
content: lambda_set_content,
|
||||||
|
rank: ctx.first_desc.rank.min(ctx.second_desc.rank),
|
||||||
|
mark: Mark::NONE,
|
||||||
|
copy: OptVariable::NONE,
|
||||||
|
},
|
||||||
|
pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
let closure_problems = if left {
|
||||||
|
unify_pool(subs, pool, tag_lambda_set, function_lambda_set)
|
||||||
|
} else {
|
||||||
|
unify_pool(subs, pool, function_lambda_set, tag_lambda_set)
|
||||||
|
};
|
||||||
|
|
||||||
|
problems.extend(closure_problems);
|
||||||
|
}
|
||||||
|
|
||||||
if problems.is_empty() {
|
if problems.is_empty() {
|
||||||
let desc = if left {
|
let desc = if left {
|
||||||
subs.get(ctx.second)
|
subs.get(ctx.second)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue