mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
make instantiate_rigids_help use a loop/stack
This commit is contained in:
parent
991420731d
commit
497bc2db02
2 changed files with 69 additions and 91 deletions
|
@ -1259,104 +1259,35 @@ pub fn instantiate_rigids(subs: &mut Subs, var: Variable) {
|
||||||
subs.restore(var);
|
subs.restore(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate_rigids_help(subs: &mut Subs, max_rank: Rank, var: Variable) {
|
fn instantiate_rigids_help(subs: &mut Subs, max_rank: Rank, initial: Variable) {
|
||||||
use roc_types::subs::Content::*;
|
let mut stack = vec![initial];
|
||||||
use roc_types::subs::FlatType::*;
|
|
||||||
|
|
||||||
let desc = subs.get_without_compacting(var);
|
macro_rules! var_slice {
|
||||||
|
($variable_subs_slice:expr) => {{
|
||||||
if desc.copy.is_some() {
|
&subs.variables[$variable_subs_slice.slice.start as usize..]
|
||||||
return;
|
[..$variable_subs_slice.slice.length as usize]
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link the original variable to the new variable. This lets us
|
while let Some(var) = stack.pop() {
|
||||||
// avoid making multiple copies of the variable we are instantiating.
|
if subs.get_ref(var).copy.is_some() {
|
||||||
//
|
continue;
|
||||||
// Need to do this before recursively copying to avoid looping.
|
|
||||||
subs.set(
|
|
||||||
var,
|
|
||||||
Descriptor {
|
|
||||||
content: desc.content.clone(),
|
|
||||||
rank: desc.rank,
|
|
||||||
mark: Mark::NONE,
|
|
||||||
copy: var.into(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Now we recursively copy the content of the variable.
|
|
||||||
// We have already marked the variable as copied, so we
|
|
||||||
// will not repeat this work or crawl this variable again.
|
|
||||||
match desc.content {
|
|
||||||
Structure(flat_type) => {
|
|
||||||
match flat_type {
|
|
||||||
Apply(_, args) => {
|
|
||||||
for var_index in args.into_iter() {
|
|
||||||
let var = subs[var_index];
|
|
||||||
instantiate_rigids_help(subs, max_rank, var);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
subs.modify(var, |desc| {
|
||||||
instantiate_rigids_help(subs, max_rank, ret_var);
|
desc.rank = Rank::NONE;
|
||||||
instantiate_rigids_help(subs, max_rank, closure_var);
|
desc.mark = Mark::NONE;
|
||||||
|
desc.copy = OptVariable::from(var);
|
||||||
|
});
|
||||||
|
|
||||||
for index in arg_vars.into_iter() {
|
use Content::*;
|
||||||
let var = subs[index];
|
use FlatType::*;
|
||||||
instantiate_rigids_help(subs, max_rank, var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EmptyRecord | EmptyTagUnion | Erroneous(_) => {}
|
|
||||||
|
|
||||||
Record(fields, ext_var) => {
|
|
||||||
for index in fields.iter_variables() {
|
|
||||||
let var = subs[index];
|
|
||||||
instantiate_rigids_help(subs, max_rank, var);
|
|
||||||
}
|
|
||||||
|
|
||||||
instantiate_rigids_help(subs, max_rank, ext_var);
|
|
||||||
}
|
|
||||||
|
|
||||||
TagUnion(tags, ext_var) => {
|
|
||||||
for (_, index) in tags.iter_all() {
|
|
||||||
let slice = subs[index];
|
|
||||||
for var_index in slice {
|
|
||||||
let var = subs[var_index];
|
|
||||||
instantiate_rigids_help(subs, max_rank, var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instantiate_rigids_help(subs, max_rank, ext_var);
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionOrTagUnion(_tag_name, _symbol, ext_var) => {
|
|
||||||
instantiate_rigids_help(subs, max_rank, ext_var);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
|
||||||
instantiate_rigids_help(subs, max_rank, rec_var);
|
|
||||||
|
|
||||||
for (_, index) in tags.iter_all() {
|
|
||||||
let slice = subs[index];
|
|
||||||
for var_index in slice {
|
|
||||||
let var = subs[var_index];
|
|
||||||
instantiate_rigids_help(subs, max_rank, var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instantiate_rigids_help(subs, max_rank, ext_var);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
FlexVar(_) | Error => {}
|
|
||||||
|
|
||||||
RecursionVar { structure, .. } => {
|
|
||||||
instantiate_rigids_help(subs, max_rank, structure);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let desc = subs.get_ref(var);
|
||||||
|
match &desc.content {
|
||||||
RigidVar(name) => {
|
RigidVar(name) => {
|
||||||
// what it's all about: convert the rigid var into a flex var
|
// what it's all about: convert the rigid var into a flex var
|
||||||
|
let name = name.clone();
|
||||||
subs.set(
|
subs.set(
|
||||||
var,
|
var,
|
||||||
Descriptor {
|
Descriptor {
|
||||||
|
@ -1367,14 +1298,61 @@ fn instantiate_rigids_help(subs: &mut Subs, max_rank: Rank, var: Variable) {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
FlexVar(_) | Error => (),
|
||||||
|
|
||||||
Alias(_symbol, args, real_type_var) => {
|
RecursionVar { structure, .. } => {
|
||||||
for var_index in args.variables().into_iter() {
|
stack.push(*structure);
|
||||||
let var = subs[var_index];
|
|
||||||
instantiate_rigids_help(subs, max_rank, var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instantiate_rigids_help(subs, max_rank, real_type_var);
|
Structure(flat_type) => match flat_type {
|
||||||
|
Apply(_, args) => {
|
||||||
|
stack.extend(var_slice!(*args));
|
||||||
|
}
|
||||||
|
|
||||||
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
|
stack.extend(var_slice!(*arg_vars));
|
||||||
|
|
||||||
|
stack.push(*ret_var);
|
||||||
|
stack.push(*closure_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmptyRecord => (),
|
||||||
|
EmptyTagUnion => (),
|
||||||
|
|
||||||
|
Record(fields, ext_var) => {
|
||||||
|
stack.extend(var_slice!(fields.variables()));
|
||||||
|
|
||||||
|
stack.push(*ext_var);
|
||||||
|
}
|
||||||
|
TagUnion(tags, ext_var) => {
|
||||||
|
for slice_index in tags.variables() {
|
||||||
|
let slice = subs.variable_slices[slice_index.start as usize];
|
||||||
|
stack.extend(var_slice!(slice));
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push(*ext_var);
|
||||||
|
}
|
||||||
|
FunctionOrTagUnion(_, _, ext_var) => {
|
||||||
|
stack.push(*ext_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
|
for slice_index in tags.variables() {
|
||||||
|
let slice = subs.variable_slices[slice_index.start as usize];
|
||||||
|
stack.extend(var_slice!(slice));
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push(*ext_var);
|
||||||
|
stack.push(*rec_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
Erroneous(_) => (),
|
||||||
|
},
|
||||||
|
Alias(_, args, var) => {
|
||||||
|
stack.extend(var_slice!(args.variables()));
|
||||||
|
|
||||||
|
stack.push(*var);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub struct SubsSlice<T> {
|
||||||
|
|
||||||
/// An index into the Vec<T> of subs
|
/// An index into the Vec<T> of subs
|
||||||
pub struct SubsIndex<T> {
|
pub struct SubsIndex<T> {
|
||||||
start: u32,
|
pub start: u32,
|
||||||
_marker: std::marker::PhantomData<T>,
|
_marker: std::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1525,7 +1525,7 @@ pub enum Builtin {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct VariableSubsSlice {
|
pub struct VariableSubsSlice {
|
||||||
slice: SubsSlice<Variable>,
|
pub slice: SubsSlice<Variable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VariableSubsSlice {
|
impl VariableSubsSlice {
|
||||||
|
@ -1849,7 +1849,7 @@ impl RecordFields {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variables(&self) -> VariableSubsSlice {
|
pub const fn variables(&self) -> VariableSubsSlice {
|
||||||
let slice = SubsSlice::new(self.variables_start, self.length);
|
let slice = SubsSlice::new(self.variables_start, self.length);
|
||||||
|
|
||||||
VariableSubsSlice { slice }
|
VariableSubsSlice { slice }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue