mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
WIP
This commit is contained in:
parent
1c6fab7043
commit
db081cd84b
2 changed files with 273 additions and 4 deletions
|
@ -1381,6 +1381,265 @@ fn instantiate_rigids_help(
|
||||||
var
|
var
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deep_copy_var_to_help(
|
||||||
|
source: &Subs,
|
||||||
|
target: &mut Subs,
|
||||||
|
max_rank: Rank,
|
||||||
|
pools: &mut Pools,
|
||||||
|
var: Variable,
|
||||||
|
) -> Variable {
|
||||||
|
use roc_types::subs::Content::*;
|
||||||
|
use roc_types::subs::FlatType::*;
|
||||||
|
|
||||||
|
let desc = source.get_without_compacting(var);
|
||||||
|
|
||||||
|
if let Some(copy) = desc.copy.into_variable() {
|
||||||
|
return copy;
|
||||||
|
} else if desc.rank != Rank::NONE {
|
||||||
|
panic!(
|
||||||
|
"about to return a variable in source, but should only return variables from target"
|
||||||
|
);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
let make_descriptor = |content| Descriptor {
|
||||||
|
content,
|
||||||
|
rank: max_rank,
|
||||||
|
mark: Mark::NONE,
|
||||||
|
copy: OptVariable::NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let content = desc.content;
|
||||||
|
let copy = target.fresh(make_descriptor(content.clone()));
|
||||||
|
|
||||||
|
pools.get_mut(max_rank).push(copy);
|
||||||
|
|
||||||
|
// Link the original variable to the new variable. This lets us
|
||||||
|
// avoid making multiple copies of the variable we are instantiating.
|
||||||
|
//
|
||||||
|
// Need to do this before recursively copying to avoid looping.
|
||||||
|
source.set(
|
||||||
|
var,
|
||||||
|
Descriptor {
|
||||||
|
content: content.clone(),
|
||||||
|
rank: desc.rank,
|
||||||
|
mark: Mark::NONE,
|
||||||
|
copy: copy.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 content {
|
||||||
|
Structure(flat_type) => {
|
||||||
|
let new_flat_type = match flat_type {
|
||||||
|
Apply(symbol, args) => {
|
||||||
|
let mut new_arg_vars = Vec::with_capacity(args.len());
|
||||||
|
|
||||||
|
for index in args.into_iter() {
|
||||||
|
let var = source[index];
|
||||||
|
let copy_var = deep_copy_var_to_help(source, target, max_rank, pools, var);
|
||||||
|
new_arg_vars.push(copy_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let arg_vars = VariableSubsSlice::insert_into_subs(target, new_arg_vars);
|
||||||
|
|
||||||
|
Apply(symbol, arg_vars)
|
||||||
|
}
|
||||||
|
|
||||||
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
|
let new_ret_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, ret_var);
|
||||||
|
let new_closure_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, closure_var);
|
||||||
|
|
||||||
|
let mut new_arg_vars = Vec::with_capacity(arg_vars.len());
|
||||||
|
|
||||||
|
for index in arg_vars.into_iter() {
|
||||||
|
let var = source[index];
|
||||||
|
let copy_var = deep_copy_var_to_help(source, target, max_rank, pools, var);
|
||||||
|
new_arg_vars.push(copy_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let arg_vars = VariableSubsSlice::insert_into_subs(target, new_arg_vars);
|
||||||
|
|
||||||
|
Func(arg_vars, new_closure_var, new_ret_var)
|
||||||
|
}
|
||||||
|
|
||||||
|
same @ EmptyRecord | same @ EmptyTagUnion | same @ Erroneous(_) => same,
|
||||||
|
|
||||||
|
Record(fields, ext_var) => {
|
||||||
|
let record_fields = {
|
||||||
|
let mut new_vars = Vec::with_capacity(fields.len());
|
||||||
|
|
||||||
|
for index in fields.iter_variables() {
|
||||||
|
let var = source[index];
|
||||||
|
let copy_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, var);
|
||||||
|
|
||||||
|
new_vars.push(copy_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let field_names_start = target.field_names.len() as u32;
|
||||||
|
let variables_start = target.variables.len() as u32;
|
||||||
|
let field_types_start = target.record_fields.len() as u32;
|
||||||
|
|
||||||
|
let mut length = 0;
|
||||||
|
|
||||||
|
for ((i1, _, i3), var) in fields.iter_all().zip(new_vars) {
|
||||||
|
let record_field = source[i3].map(|_| var);
|
||||||
|
|
||||||
|
target.field_names.push(source[i1].clone());
|
||||||
|
target.record_fields.push(record_field.map(|_| ()));
|
||||||
|
target.variables.push(*record_field.as_inner());
|
||||||
|
|
||||||
|
length += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordFields {
|
||||||
|
length,
|
||||||
|
field_names_start,
|
||||||
|
variables_start,
|
||||||
|
field_types_start,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Record(
|
||||||
|
record_fields,
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, ext_var),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
TagUnion(tags, ext_var) => {
|
||||||
|
let mut new_variable_slices = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
|
let mut new_variables = Vec::new();
|
||||||
|
for index in tags.variables() {
|
||||||
|
let slice = source[index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = source[var_index];
|
||||||
|
let new_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, var);
|
||||||
|
new_variables.push(new_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_slice =
|
||||||
|
VariableSubsSlice::insert_into_subs(target, new_variables.drain(..));
|
||||||
|
|
||||||
|
new_variable_slices.push(new_slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_variables = {
|
||||||
|
let start = target.variable_slices.len() as u32;
|
||||||
|
let length = new_variable_slices.len() as u16;
|
||||||
|
target.variable_slices.extend(new_variable_slices);
|
||||||
|
|
||||||
|
SubsSlice::new(start, length)
|
||||||
|
};
|
||||||
|
|
||||||
|
let union_tags = UnionTags::from_slices(tags.tag_names(), new_variables);
|
||||||
|
|
||||||
|
let new_ext = deep_copy_var_to_help(source, target, max_rank, pools, ext_var);
|
||||||
|
TagUnion(union_tags, new_ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionOrTagUnion(tag_name, symbol, ext_var) => FunctionOrTagUnion(
|
||||||
|
tag_name,
|
||||||
|
symbol,
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, ext_var),
|
||||||
|
),
|
||||||
|
|
||||||
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
|
let mut new_variable_slices = Vec::with_capacity(tags.len());
|
||||||
|
|
||||||
|
let mut new_variables = Vec::new();
|
||||||
|
for index in tags.variables() {
|
||||||
|
let slice = source[index];
|
||||||
|
for var_index in slice {
|
||||||
|
let var = source[var_index];
|
||||||
|
let new_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, var);
|
||||||
|
new_variables.push(new_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_slice =
|
||||||
|
VariableSubsSlice::insert_into_subs(target, new_variables.drain(..));
|
||||||
|
|
||||||
|
new_variable_slices.push(new_slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_variables = {
|
||||||
|
let start = target.variable_slices.len() as u32;
|
||||||
|
let length = new_variable_slices.len() as u16;
|
||||||
|
target.variable_slices.extend(new_variable_slices);
|
||||||
|
|
||||||
|
SubsSlice::new(start, length)
|
||||||
|
};
|
||||||
|
|
||||||
|
let union_tags = UnionTags::from_slices(tags.tag_names(), new_variables);
|
||||||
|
|
||||||
|
let new_ext = deep_copy_var_to_help(source, target, max_rank, pools, ext_var);
|
||||||
|
let new_rec_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, rec_var);
|
||||||
|
|
||||||
|
RecursiveTagUnion(new_rec_var, union_tags, new_ext)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
target.set(copy, make_descriptor(Structure(new_flat_type)));
|
||||||
|
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
FlexVar(_) | Error => copy,
|
||||||
|
|
||||||
|
RecursionVar {
|
||||||
|
opt_name,
|
||||||
|
structure,
|
||||||
|
} => {
|
||||||
|
let new_structure = deep_copy_var_to_help(source, target, max_rank, pools, structure);
|
||||||
|
|
||||||
|
target.set(
|
||||||
|
copy,
|
||||||
|
make_descriptor(RecursionVar {
|
||||||
|
opt_name,
|
||||||
|
structure: new_structure,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
RigidVar(name) => {
|
||||||
|
target.set(copy, make_descriptor(FlexVar(Some(name))));
|
||||||
|
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
Alias(symbol, mut args, real_type_var) => {
|
||||||
|
let mut new_vars = Vec::with_capacity(args.variables().len());
|
||||||
|
|
||||||
|
for var_index in args.variables() {
|
||||||
|
let var = source[var_index];
|
||||||
|
let new_var = deep_copy_var_to_help(source, target, max_rank, pools, var);
|
||||||
|
|
||||||
|
new_vars.push(new_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.replace_variables(target, new_vars);
|
||||||
|
|
||||||
|
let new_real_type_var =
|
||||||
|
deep_copy_var_to_help(source, target, max_rank, pools, real_type_var);
|
||||||
|
let new_content = Alias(symbol, args, new_real_type_var);
|
||||||
|
|
||||||
|
target.set(copy, make_descriptor(new_content));
|
||||||
|
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deep_copy_var(subs: &mut Subs, rank: Rank, pools: &mut Pools, var: Variable) -> Variable {
|
fn deep_copy_var(subs: &mut Subs, rank: Rank, pools: &mut Pools, var: Variable) -> Variable {
|
||||||
let copy = deep_copy_var_help(subs, rank, pools, var);
|
let copy = deep_copy_var_help(subs, rank, pools, var);
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,12 @@ use ven_ena::unify::{InPlace, Snapshot, UnificationTable, UnifyKey};
|
||||||
// if your changes cause this number to go down, great!
|
// if your changes cause this number to go down, great!
|
||||||
// please change it to the lower number.
|
// please change it to the lower number.
|
||||||
// if it went up, maybe check that the change is really required
|
// if it went up, maybe check that the change is really required
|
||||||
static_assertions::assert_eq_size!([u8; 48], Descriptor);
|
static_assertions::assert_eq_size!([u8; 6 * 8], Descriptor);
|
||||||
static_assertions::assert_eq_size!([u8; 32], Content);
|
static_assertions::assert_eq_size!([u8; 4 * 8], Content);
|
||||||
static_assertions::assert_eq_size!([u8; 24], FlatType);
|
static_assertions::assert_eq_size!([u8; 3 * 8], FlatType);
|
||||||
static_assertions::assert_eq_size!([u8; 48], Problem);
|
static_assertions::assert_eq_size!([u8; 6 * 8], Problem);
|
||||||
|
static_assertions::assert_eq_size!([u8; 12], UnionTags);
|
||||||
|
static_assertions::assert_eq_size!([u8; 2 * 8], RecordFields);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub struct Mark(i32);
|
pub struct Mark(i32);
|
||||||
|
@ -1326,6 +1328,12 @@ impl From<Content> for Descriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assertions::assert_eq_size!([u8; 4 * 8], Content);
|
||||||
|
static_assertions::assert_eq_size!([u8; 4 * 8], (Variable, Option<Lowercase>));
|
||||||
|
static_assertions::assert_eq_size!([u8; 3 * 8], (Symbol, AliasVariables, Variable));
|
||||||
|
static_assertions::assert_eq_size!([u8; 12], AliasVariables);
|
||||||
|
static_assertions::assert_eq_size!([u8; 3 * 8], FlatType);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Content {
|
pub enum Content {
|
||||||
/// A type variable which the user did not name in an annotation,
|
/// A type variable which the user did not name in an annotation,
|
||||||
|
@ -1466,6 +1474,8 @@ impl Content {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assertions::assert_eq_size!([u8; 3 * 8], FlatType);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum FlatType {
|
pub enum FlatType {
|
||||||
Apply(Symbol, VariableSubsSlice),
|
Apply(Symbol, VariableSubsSlice),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue