mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
make the simple case tail-recursive
This commit is contained in:
parent
4ca9ea0b89
commit
41df04184e
1 changed files with 44 additions and 45 deletions
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue