Merge branch 'trunk' of github.com:rtfeldman/roc into wasm-reduce-recursion

This commit is contained in:
Brian Carroll 2021-11-23 09:36:28 +00:00
commit 858e1b5ff5
10 changed files with 109 additions and 137 deletions

View File

@ -810,17 +810,13 @@ fn type_to_variable<'a>(
*/
let mut arg_vars = Vec::with_capacity(args.len());
let mut new_aliases = BumpMap::new_in(arena);
for (arg, arg_type_id) in args.iter(mempool) {
for (_, arg_type_id) in args.iter(mempool) {
let arg_type = mempool.get(*arg_type_id);
let arg_var = type_to_variable(arena, mempool, subs, rank, pools, cached, arg_type);
let arg_str = arg.as_str(mempool);
arg_vars.push((roc_module::ident::Lowercase::from(arg_str), arg_var));
new_aliases.insert(arg_str, arg_var);
arg_vars.push(arg_var);
}
let arg_vars = AliasVariables::insert_into_subs(subs, arg_vars, []);

View File

@ -29,7 +29,7 @@ impl std::ops::Deref for ModuleName {
}
/// An uncapitalized identifier, such as a field name or local variable
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Lowercase(IdentStr);
/// A capitalized identifier, such as a tag name or module name

View File

@ -100,15 +100,17 @@ impl Pools {
}
pub fn get_mut(&mut self, rank: Rank) -> &mut Vec<Variable> {
self.0
.get_mut(rank.into_usize())
.unwrap_or_else(|| panic!("Compiler bug: could not find pool at rank {}", rank))
match self.0.get_mut(rank.into_usize()) {
Some(reference) => reference,
None => panic!("Compiler bug: could not find pool at rank {}", rank),
}
}
pub fn get(&self, rank: Rank) -> &Vec<Variable> {
self.0
.get(rank.into_usize())
.unwrap_or_else(|| panic!("Compiler bug: could not find pool at rank {}", rank))
match self.0.get(rank.into_usize()) {
Some(reference) => reference,
None => panic!("Compiler bug: could not find pool at rank {}", rank),
}
}
pub fn iter(&self) -> std::slice::Iter<'_, Vec<Variable>> {
@ -628,18 +630,6 @@ fn type_to_var(
type_to_variable(subs, rank, pools, &arena, typ)
}
/// Abusing existing functions for our purposes
/// this is to put a solved type back into subs
pub fn insert_type_into_subs(subs: &mut Subs, typ: &Type) -> Variable {
let rank = Rank::NONE;
let mut pools = Pools::default();
// capacity based on the false hello world program
let arena = bumpalo::Bump::with_capacity(4 * 1024);
type_to_variable(subs, rank, &mut pools, &arena, typ)
}
fn type_to_variable<'a>(
subs: &mut Subs,
rank: Rank,
@ -652,14 +642,13 @@ fn type_to_variable<'a>(
match typ {
Variable(var) => *var,
Apply(symbol, args) => {
let mut new_arg_vars = Vec::with_capacity_in(args.len(), arena);
let arg_vars = VariableSubsSlice::reserve_into_subs(subs, args.len());
for arg in args {
for (i, arg) in (arg_vars.slice.start as usize..).zip(args) {
let var = type_to_variable(subs, rank, pools, arena, arg);
new_arg_vars.push(var);
subs.variables[i] = var;
}
let arg_vars = VariableSubsSlice::insert_into_subs(subs, new_arg_vars);
let flat_type = FlatType::Apply(*symbol, arg_vars);
let content = Content::Structure(flat_type);
@ -669,16 +658,14 @@ fn type_to_variable<'a>(
EmptyTagUnion => Variable::EMPTY_TAG_UNION,
// This case is important for the rank of boolean variables
Function(arg_vars, closure_type, ret_type) => {
let mut new_arg_vars = Vec::with_capacity_in(arg_vars.len(), arena);
Function(args, closure_type, ret_type) => {
let arg_vars = VariableSubsSlice::reserve_into_subs(subs, args.len());
for arg in arg_vars {
for (i, arg) in (arg_vars.slice.start as usize..).zip(args) {
let var = type_to_variable(subs, rank, pools, arena, arg);
new_arg_vars.push(var);
subs.variables[i] = var;
}
let arg_vars = VariableSubsSlice::insert_into_subs(subs, new_arg_vars);
let ret_var = type_to_variable(subs, rank, pools, arena, ret_type);
let closure_var = type_to_variable(subs, rank, pools, arena, closure_type);
let content = Content::Structure(FlatType::Func(arg_vars, closure_var, ret_var));
@ -801,10 +788,10 @@ fn type_to_variable<'a>(
let mut arg_vars = Vec::with_capacity_in(args.len(), arena);
for (arg, arg_type) in args {
for (_, arg_type) in args {
let arg_var = type_to_variable(subs, rank, pools, arena, arg_type);
arg_vars.push((arg.clone(), arg_var));
arg_vars.push(arg_var);
}
let lambda_set_variables_it = lambda_set_variables
@ -829,10 +816,10 @@ fn type_to_variable<'a>(
} => {
let mut arg_vars = Vec::with_capacity_in(args.len(), arena);
for (arg, arg_type) in args {
for (_, arg_type) in args {
let arg_var = type_to_variable(subs, rank, pools, arena, arg_type);
arg_vars.push((arg.clone(), arg_var));
arg_vars.push(arg_var);
}
let lambda_set_variables_it = lambda_set_variables
@ -884,14 +871,13 @@ fn type_to_union_tags<'a>(
let mut tag_vars = Vec::with_capacity_in(tags.len(), arena);
let mut tag_argument_vars = Vec::with_capacity_in(tags.len(), arena);
for (tag, tag_argument_types) in tags {
for arg_type in tag_argument_types {
let new_var = type_to_variable(subs, rank, pools, arena, arg_type);
tag_argument_vars.push(new_var);
}
let new_slice = VariableSubsSlice::reserve_into_subs(subs, tag_argument_types.len());
let new_slice = VariableSubsSlice::insert_into_subs(subs, tag_argument_vars.drain(..));
for (i, arg) in (new_slice.slice.start as usize..).zip(tag_argument_types) {
let var = type_to_variable(subs, rank, pools, arena, arg);
subs.variables[i] = var;
}
tag_vars.push((tag.clone(), new_slice));
}
@ -1654,12 +1640,14 @@ fn deep_copy_var_help(
}
fn register(subs: &mut Subs, rank: Rank, pools: &mut Pools, content: Content) -> Variable {
let var = subs.fresh(Descriptor {
let descriptor = Descriptor {
content,
rank,
mark: Mark::NONE,
copy: OptVariable::NONE,
});
};
let var = subs.fresh(descriptor);
pools.get_mut(rank).push(var);

View File

@ -199,7 +199,7 @@ fn find_names_needed(
}
Alias(_symbol, args, _actual) => {
// only find names for named parameters!
for var_index in args.variables().into_iter().take(args.len()) {
for var_index in args.into_iter().take(args.len()) {
let var = subs[var_index];
find_names_needed(var, subs, roots, root_appearances, names_taken);
}
@ -309,7 +309,6 @@ fn write_content(env: &Env, content: &Content, subs: &Subs, buf: &mut String, pa
debug_assert_eq!(args.len(), 1);
let arg_var_index = args
.variables()
.into_iter()
.next()
.expect("Num was not applied to a type argument!");
@ -337,7 +336,7 @@ fn write_content(env: &Env, content: &Content, subs: &Subs, buf: &mut String, pa
_ => write_parens!(write_parens, buf, {
write_symbol(env, *symbol, buf);
for var_index in args.variables() {
for var_index in args.into_iter() {
let var = subs[var_index];
buf.push(' ');
write_content(

View File

@ -229,7 +229,7 @@ impl SolvedType {
}
}
pub fn from_var(subs: &Subs, var: Variable) -> Self {
fn from_var(subs: &Subs, var: Variable) -> Self {
let mut seen = RecursionVars::default();
Self::from_var_help(subs, &mut seen, var)
}
@ -254,16 +254,17 @@ impl SolvedType {
Alias(symbol, args, actual_var) => {
let mut new_args = Vec::with_capacity(args.len());
for (name_index, var_index) in args.named_type_arguments() {
for var_index in args.named_type_arguments() {
let arg_var = subs[var_index];
new_args.push((
subs[name_index].clone(),
Self::from_var_help(subs, recursion_vars, arg_var),
));
let node = Self::from_var_help(subs, recursion_vars, arg_var);
// NOTE we fake the lowercase here: the user will never get to see it anyway
new_args.push((Lowercase::default(), node));
}
let mut solved_lambda_sets = Vec::with_capacity(0);
for var_index in args.unnamed_type_arguments() {
let var = subs[var_index];

View File

@ -797,7 +797,7 @@ fn integer_type(
Content::Structure(FlatType::TagUnion(tags, Variable::EMPTY_TAG_UNION))
});
let vars = AliasVariables::insert_into_subs(subs, [("range".into(), signed64)], []);
let vars = AliasVariables::insert_into_subs(subs, [signed64], []);
subs.set_content(num_integer_signed64, {
Content::Alias(Symbol::NUM_INTEGER, vars, at_signed64)
});
@ -812,7 +812,7 @@ fn integer_type(
Content::Structure(FlatType::TagUnion(tags, Variable::EMPTY_TAG_UNION))
});
let vars = AliasVariables::insert_into_subs(subs, [("range".into(), integer_signed64)], []);
let vars = AliasVariables::insert_into_subs(subs, [integer_signed64], []);
subs.set_content(num_integer_signed64, {
Content::Alias(Symbol::NUM_NUM, vars, at_num_integer_signed64)
});
@ -1358,7 +1358,7 @@ 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; 8], AliasVariables);
static_assertions::assert_eq_size!([u8; 3 * 8], FlatType);
#[derive(Clone, Debug)]
@ -1382,29 +1382,26 @@ pub enum Content {
#[derive(Clone, Copy, Debug, Default)]
pub struct AliasVariables {
pub lowercases_start: u32,
pub variables_start: u32,
pub lowercases_len: u16,
pub variables_len: u16,
pub all_variables_len: u16,
/// an alias has type variables and lambda set variables
pub type_variables_len: u16,
}
impl AliasVariables {
pub const fn names(&self) -> SubsSlice<Lowercase> {
SubsSlice::new(self.lowercases_start, self.lowercases_len)
}
pub const fn variables(&self) -> VariableSubsSlice {
VariableSubsSlice {
slice: SubsSlice::new(self.variables_start, self.variables_len),
slice: SubsSlice::new(self.variables_start, self.all_variables_len),
}
}
pub const fn len(&self) -> usize {
self.lowercases_len as usize
self.type_variables_len as usize
}
pub const fn is_empty(&self) -> bool {
self.lowercases_len == 0
self.type_variables_len == 0
}
pub fn replace_variables(
@ -1416,24 +1413,21 @@ impl AliasVariables {
subs.variables.extend(variables);
let variables_len = (subs.variables.len() - variables_start as usize) as u16;
debug_assert_eq!(variables_len, self.variables_len);
debug_assert_eq!(variables_len, self.all_variables_len);
self.variables_start = variables_start;
}
pub fn named_type_arguments(
&self,
) -> impl Iterator<Item = (SubsIndex<Lowercase>, SubsIndex<Variable>)> {
let names = self.names();
let vars = self.variables();
names.into_iter().zip(vars.into_iter())
pub fn named_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
self.variables()
.into_iter()
.take(self.type_variables_len as usize)
}
pub fn unnamed_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
self.variables()
.into_iter()
.skip(self.lowercases_len as usize)
.skip(self.type_variables_len as usize)
}
pub fn insert_into_subs<I1, I2>(
@ -1442,38 +1436,41 @@ impl AliasVariables {
unnamed_arguments: I2,
) -> Self
where
I1: IntoIterator<Item = (Lowercase, Variable)>,
I1: IntoIterator<Item = Variable>,
I2: IntoIterator<Item = Variable>,
{
let lowercases_start = subs.field_names.len() as u32;
let variables_start = subs.variables.len() as u32;
let it1 = type_arguments.into_iter();
let it2 = unnamed_arguments.into_iter();
subs.variables.extend(type_arguments);
subs.variables
.reserve(it1.size_hint().0 + it2.size_hint().0);
subs.field_names.reserve(it1.size_hint().0);
let type_variables_len = (subs.variables.len() as u32 - variables_start) as u16;
for (field_name, var) in it1 {
subs.field_names.push(field_name);
subs.variables.push(var);
subs.variables.extend(unnamed_arguments);
let all_variables_len = (subs.variables.len() as u32 - variables_start) as u16;
if type_variables_len == 3 {
panic!();
}
subs.variables.extend(it2);
let lowercases_len = (subs.field_names.len() as u32 - lowercases_start) as u16;
let variables_len = (subs.variables.len() as u32 - variables_start) as u16;
Self {
lowercases_start,
variables_start,
lowercases_len,
variables_len,
type_variables_len,
all_variables_len,
}
}
}
impl IntoIterator for AliasVariables {
type Item = <VariableSubsSlice as IntoIterator>::Item;
type IntoIter = <VariableSubsSlice as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.variables().into_iter()
}
}
impl Content {
#[inline(always)]
pub fn is_number(&self) -> bool {
@ -1548,6 +1545,15 @@ impl VariableSubsSlice {
}
}
pub fn reserve_into_subs(subs: &mut Subs, length: usize) -> Self {
let start = subs.variables.len() as u32;
subs.variables
.extend(std::iter::repeat(Variable::NULL).take(length));
Self::new(start, length as u16)
}
pub fn insert_into_subs<I>(subs: &mut Subs, input: I) -> Self
where
I: IntoIterator<Item = Variable>,
@ -2081,7 +2087,7 @@ fn occurs(
let mut new_seen = seen.clone();
new_seen.insert(root_var);
for var_index in args.variables().into_iter() {
for var_index in args.into_iter() {
let var = subs[var_index];
short_circuit_help(subs, root_var, &new_seen, var)?;
}
@ -2265,7 +2271,7 @@ fn explicit_substitute(
in_var
}
Alias(symbol, args, actual) => {
for index in args.variables().into_iter() {
for index in args.into_iter() {
let var = subs[index];
let new_var = explicit_substitute(subs, from, to, var, seen);
subs[index] = new_var;
@ -2322,12 +2328,9 @@ fn get_var_names(
RigidVar(name) => add_name(subs, 0, name, var, RigidVar, taken_names),
Alias(_, args, _) => args
.variables()
.into_iter()
.fold(taken_names, |answer, arg_var| {
get_var_names(subs, subs[arg_var], answer)
}),
Alias(_, args, _) => args.into_iter().fold(taken_names, |answer, arg_var| {
get_var_names(subs, subs[arg_var], answer)
}),
Structure(flat_type) => match flat_type {
FlatType::Apply(_, args) => {
@ -2528,15 +2531,14 @@ fn content_to_err_type(
Alias(symbol, args, aliased_to) => {
let err_type = var_to_err_type(subs, state, aliased_to);
let mut err_args = Vec::with_capacity(args.names().len());
let mut err_args = Vec::with_capacity(args.len());
for (name_index, var_index) in args.named_type_arguments() {
let name = subs[name_index].clone();
for var_index in args.into_iter() {
let var = subs[var_index];
let arg = var_to_err_type(subs, state, var);
err_args.push((name, arg));
err_args.push(arg);
}
ErrorType::Alias(symbol, err_args, Box::new(err_type))
@ -2989,7 +2991,6 @@ impl StorageSubs {
offsets: &StorageSubsOffsets,
mut alias_variables: AliasVariables,
) -> AliasVariables {
alias_variables.lowercases_start += offsets.field_names;
alias_variables.variables_start += offsets.variables;
alias_variables
@ -3357,9 +3358,9 @@ fn deep_copy_var_to_help<'a>(
}
Alias(symbol, mut args, real_type_var) => {
let mut new_vars = Vec::with_capacity_in(args.variables().len(), arena);
let mut new_vars = Vec::with_capacity_in(args.len(), arena);
for var_index in args.variables() {
for var_index in args.into_iter() {
let var = source[var_index];
let new_var = deep_copy_var_to_help(arena, visited, source, target, max_rank, var);
@ -3368,12 +3369,6 @@ fn deep_copy_var_to_help<'a>(
args.replace_variables(target, new_vars);
let lowercases = &source.field_names[args.lowercases_start as usize..]
[..args.lowercases_len as usize];
args.lowercases_start = target.field_names.len() as u32;
target.field_names.extend(lowercases.iter().cloned());
let new_real_type_var =
deep_copy_var_to_help(arena, visited, source, target, max_rank, real_type_var);
let new_content = Alias(symbol, args, new_real_type_var);

View File

@ -1241,7 +1241,7 @@ pub enum ErrorType {
TagUnion(SendMap<TagName, Vec<ErrorType>>, TypeExt),
RecursiveTagUnion(Box<ErrorType>, SendMap<TagName, Vec<ErrorType>>, TypeExt),
Function(Vec<ErrorType>, Box<ErrorType>, Box<ErrorType>),
Alias(Symbol, Vec<(Lowercase, ErrorType)>, Box<ErrorType>),
Alias(Symbol, Vec<ErrorType>, Box<ErrorType>),
Error,
}
@ -1303,7 +1303,7 @@ fn write_error_type_help(
Alias(Symbol::NUM_NUM, mut arguments, _actual) => {
debug_assert!(arguments.len() == 1);
let argument = arguments.remove(0).1;
let argument = arguments.remove(0);
match argument {
Type(Symbol::NUM_INTEGER, _) => {
@ -1421,7 +1421,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens:
Alias(Symbol::NUM_NUM, mut arguments, _actual) => {
debug_assert!(arguments.len() == 1);
let argument = arguments.remove(0).1;
let argument = arguments.remove(0);
match argument {
Type(Symbol::NUM_INTEGER, _) => {
@ -1456,7 +1456,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens:
for arg in arguments {
buf.push(' ');
write_debug_error_type_help(arg.1, buf, Parens::InTypeParam);
write_debug_error_type_help(arg, buf, Parens::InTypeParam);
}
// useful for debugging

View File

@ -209,7 +209,8 @@ fn unify_alias(
problems
} else {
mismatch!("{}", symbol)
dbg!(args.len(), other_args.len());
mismatch!("{:?}", symbol)
}
} else {
unify_pool(subs, pool, real_var, *other_real_var)

View File

@ -471,12 +471,7 @@ fn read_main_roc_file(project_dir_path_opt: Option<&Path>) -> (PathStr, String)
let project_dir_path_str = path_to_string(project_dir_path);
if let Some(&roc_file_name) = roc_file_names.first() {
let full_roc_file_path_str = vec![
project_dir_path_str.clone(),
"/".to_owned(),
roc_file_name.clone(),
]
.join("");
let full_roc_file_path_str = path_to_string(&project_dir_path.join(roc_file_name));
let file_as_str = std::fs::read_to_string(&Path::new(&full_roc_file_path_str))
.unwrap_or_else(|err| panic!("In the provided project {:?}, I found the roc file {}, but I failed to read it: {}", &project_dir_path_str, &full_roc_file_path_str, err));

View File

@ -1493,7 +1493,7 @@ pub fn to_doc<'b>(
parens,
alloc.symbol_foreign_qualified(symbol),
args.into_iter()
.map(|(_, arg)| to_doc(alloc, Parens::InTypeParam, arg))
.map(|arg| to_doc(alloc, Parens::InTypeParam, arg))
.collect(),
),
@ -1657,10 +1657,7 @@ fn to_diff<'b>(
}
(Alias(symbol1, args1, _), Alias(symbol2, args2, _)) if symbol1 == symbol2 => {
// TODO remove collects
let a1 = args1.into_iter().map(|(_, v)| v).collect::<Vec<_>>();
let a2 = args2.into_iter().map(|(_, v)| v).collect::<Vec<_>>();
let args_diff = traverse(alloc, Parens::InTypeParam, a1, a2);
let args_diff = traverse(alloc, Parens::InTypeParam, args1, args2);
let left = report_text::apply(
alloc,
parens,
@ -1729,8 +1726,8 @@ fn to_diff<'b>(
ErrorType::Alias(Symbol::NUM_NUM, args, _) => {
matches!(
&args.get(0),
Some((_, ErrorType::Type(Symbol::NUM_INTEGER, _)))
| Some((_, ErrorType::Alias(Symbol::NUM_INTEGER, _, _)))
Some(ErrorType::Type(Symbol::NUM_INTEGER, _))
| Some(ErrorType::Alias(Symbol::NUM_INTEGER, _, _))
)
}
_ => false,
@ -1750,8 +1747,8 @@ fn to_diff<'b>(
ErrorType::Alias(Symbol::NUM_NUM, args, _) => {
matches!(
&args.get(0),
Some((_, ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _)))
| Some((_, ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _)))
Some(ErrorType::Type(Symbol::NUM_FLOATINGPOINT, _))
| Some(ErrorType::Alias(Symbol::NUM_FLOATINGPOINT, _, _))
)
}
_ => false,