make the simple case tail-recursive

This commit is contained in:
Folkert 2022-03-05 00:26:03 +01:00
parent 4ca9ea0b89
commit 41df04184e
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C

View file

@ -1,6 +1,6 @@
use bumpalo::Bump; use bumpalo::Bump;
use roc_can::constraint::Constraint::{self, *}; use roc_can::constraint::Constraint::{self, *};
use roc_can::constraint::PresenceConstraint; use roc_can::constraint::{LetConstraint, PresenceConstraint};
use roc_can::expected::{Expected, PExpected}; use roc_can::expected::{Expected, PExpected};
use roc_collections::all::MutMap; use roc_collections::all::MutMap;
use roc_module::ident::TagName; use roc_module::ident::TagName;
@ -218,6 +218,11 @@ enum Work<'a> {
constraint: &'a Constraint, constraint: &'a Constraint,
}, },
CheckForInfiniteTypes(LocalDefVarsVec<(Symbol, Loc<Variable>)>), CheckForInfiniteTypes(LocalDefVarsVec<(Symbol, Loc<Variable>)>),
LetConSimple {
env: &'a Env,
rank: Rank,
let_con: &'a LetConstraint,
},
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -241,6 +246,11 @@ fn solve(
let mut stack = vec![initial]; let mut stack = vec![initial];
while let Some(work_item) = stack.pop() { while let Some(work_item) = stack.pop() {
let (env, rank, constraint) = match work_item { let (env, rank, constraint) = match work_item {
Work::Constraint {
env,
rank,
constraint,
} => (env, rank, constraint),
Work::CheckForInfiniteTypes(def_vars) => { Work::CheckForInfiniteTypes(def_vars) => {
for (symbol, loc_var) in def_vars.iter() { for (symbol, loc_var) in def_vars.iter() {
check_for_infinite_type(subs, problems, *symbol, *loc_var); check_for_infinite_type(subs, problems, *symbol, *loc_var);
@ -248,11 +258,35 @@ fn solve(
// No constraint to be solved // No constraint to be solved
continue; continue;
} }
Work::Constraint { Work::LetConSimple { env, rank, let_con } => {
env, // Add a variable for each def to new_vars_by_env.
rank, let mut local_def_vars = LocalDefVarsVec::with_length(let_con.def_types.len());
constraint,
} => (env, rank, constraint), for (symbol, loc_type) in let_con.def_types.iter() {
let var = type_to_var(subs, rank, pools, cached_aliases, &loc_type.value);
local_def_vars.push((
*symbol,
Loc {
value: var,
region: loc_type.region,
},
));
}
let mut new_env = env.clone();
for (symbol, loc_var) in local_def_vars.iter() {
new_env.insert_symbol_var_if_vacant(*symbol, loc_var.value);
}
stack.push(Work::CheckForInfiniteTypes(local_def_vars));
stack.push(Work::Constraint {
env: arena.alloc(new_env),
rank,
constraint: &let_con.ret_constraint,
});
continue;
}
}; };
state = match constraint { state = match constraint {
@ -471,47 +505,12 @@ fn solve(
}); });
state state
} }
ret_con if let_con.rigid_vars.is_empty() && let_con.flex_vars.is_empty() => { _ if let_con.rigid_vars.is_empty() && let_con.flex_vars.is_empty() => {
// TODO: make into `WorkItem` with `After` stack.push(Work::LetConSimple { env, rank, let_con });
let state = solve(
arena,
env,
state,
rank,
pools,
problems,
cached_aliases,
subs,
&let_con.defs_constraint,
);
// Add a variable for each def to new_vars_by_env.
let mut local_def_vars =
LocalDefVarsVec::with_length(let_con.def_types.len());
for (symbol, loc_type) in let_con.def_types.iter() {
let var =
type_to_var(subs, rank, pools, cached_aliases, &loc_type.value);
local_def_vars.push((
*symbol,
Loc {
value: var,
region: loc_type.region,
},
));
}
let mut new_env = env.clone();
for (symbol, loc_var) in local_def_vars.iter() {
new_env.insert_symbol_var_if_vacant(*symbol, loc_var.value);
}
stack.push(Work::CheckForInfiniteTypes(local_def_vars));
stack.push(Work::Constraint { stack.push(Work::Constraint {
env: arena.alloc(new_env), env,
rank, rank,
constraint: ret_con, constraint: &let_con.defs_constraint,
}); });
state state