add HostExposedAlias

This commit is contained in:
Folkert 2020-11-04 13:19:57 +01:00
parent d19223dfb3
commit c09b66a9cc
6 changed files with 215 additions and 10 deletions

View file

@ -53,6 +53,14 @@ pub enum SolvedType {
/// A type alias
Alias(Symbol, Vec<(Lowercase, SolvedType)>, Box<SolvedType>),
HostExposedAlias {
name: Symbol,
def_name: Symbol,
arguments: Vec<(Lowercase, SolvedType)>,
actual_var: VarId,
actual: Box<SolvedType>,
},
/// a boolean algebra Bool
Boolean(SolvedBool),
@ -194,6 +202,28 @@ impl SolvedType {
SolvedType::Alias(*symbol, solved_args, Box::new(solved_type))
}
HostExposedAlias {
name,
def_name,
arguments,
actual_var,
actual,
} => {
let solved_type = Self::from_type(solved_subs, actual);
let mut solved_args = Vec::with_capacity(arguments.len());
for (name, var) in arguments {
solved_args.push((name.clone(), Self::from_type(solved_subs, var)));
}
SolvedType::HostExposedAlias {
name: *name,
def_name: *def_name,
arguments: solved_args,
actual_var: VarId::from_var(*actual_var, solved_subs.inner()),
actual: Box::new(solved_type),
}
}
Boolean(val) => SolvedType::Boolean(SolvedBool::from_bool(&val, solved_subs.inner())),
Variable(var) => Self::from_var(solved_subs.inner(), *var),
}
@ -486,6 +516,29 @@ pub fn to_type(
Type::Alias(*symbol, type_variables, Box::new(actual))
}
HostExposedAlias {
name,
def_name,
arguments: solved_type_variables,
actual_var,
actual: solved_actual,
} => {
let mut type_variables = Vec::with_capacity(solved_type_variables.len());
for (lowercase, solved_arg) in solved_type_variables {
type_variables.push((lowercase.clone(), to_type(solved_arg, free_vars, var_store)));
}
let actual = to_type(solved_actual, free_vars, var_store);
Type::HostExposedAlias {
name: *name,
def_name: *def_name,
arguments: type_variables,
actual_var: var_id_to_flex_var(*actual_var, free_vars, var_store),
actual: Box::new(actual),
}
}
Error => Type::Erroneous(Problem::SolvedTypeError),
Erroneous(problem) => Type::Erroneous(problem.clone()),
}

View file

@ -143,6 +143,13 @@ pub enum Type {
Record(SendMap<Lowercase, RecordField<Type>>, Box<Type>),
TagUnion(Vec<(TagName, Vec<Type>)>, Box<Type>),
Alias(Symbol, Vec<(Lowercase, Type)>, Box<Type>),
HostExposedAlias {
name: Symbol,
def_name: Symbol,
arguments: Vec<(Lowercase, Type)>,
actual_var: Variable,
actual: Box<Type>,
},
RecursiveTagUnion(Variable, Vec<(TagName, Vec<Type>)>, Box<Type>),
/// Applying a type to some arguments (e.g. Map.Map String Int)
Apply(Symbol, Vec<Type>),
@ -206,6 +213,20 @@ impl fmt::Debug for Type {
Ok(())
}
Type::HostExposedAlias {
name, arguments, ..
} => {
write!(f, "HostExposedAlias {:?}", name)?;
for (_, arg) in arguments {
write!(f, " {:?}", arg)?;
}
// Sometimes it's useful to see the expansion of the alias
// write!(f, "[ but actually {:?} ]", _actual)?;
Ok(())
}
Type::Record(fields, ext) => {
write!(f, "{{")?;
@ -405,6 +426,16 @@ impl Type {
}
actual_type.substitute(substitutions);
}
HostExposedAlias {
arguments,
actual: actual_type,
..
} => {
for (_, value) in arguments.iter_mut() {
value.substitute(substitutions);
}
actual_type.substitute(substitutions);
}
Apply(_, args) => {
for arg in args {
arg.substitute(substitutions);
@ -453,6 +484,12 @@ impl Type {
Alias(_, _, actual_type) => {
actual_type.substitute_alias(rep_symbol, actual);
}
HostExposedAlias {
actual: actual_type,
..
} => {
actual_type.substitute_alias(rep_symbol, actual);
}
Apply(symbol, _) if *symbol == rep_symbol => {
*self = actual.clone();
@ -496,6 +533,9 @@ impl Type {
Alias(alias_symbol, _, actual_type) => {
alias_symbol == &rep_symbol || actual_type.contains_symbol(rep_symbol)
}
HostExposedAlias { name, actual, .. } => {
name == &rep_symbol || actual.contains_symbol(rep_symbol)
}
Apply(symbol, _) if *symbol == rep_symbol => true,
Apply(_, args) => args.iter().any(|arg| arg.contains_symbol(rep_symbol)),
EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) | Boolean(_) => false,
@ -528,6 +568,7 @@ impl Type {
.any(|arg| arg.contains_variable(rep_variable))
}
Alias(_, _, actual_type) => actual_type.contains_variable(rep_variable),
HostExposedAlias { actual, .. } => actual.contains_variable(rep_variable),
Apply(_, args) => args.iter().any(|arg| arg.contains_variable(rep_variable)),
EmptyRec | EmptyTagUnion | Erroneous(_) | Boolean(_) => false,
}
@ -579,7 +620,12 @@ impl Type {
}
ext.instantiate_aliases(region, aliases, var_store, introduced);
}
Alias(_, type_args, actual_type) => {
HostExposedAlias {
arguments: type_args,
actual: actual_type,
..
}
| Alias(_, type_args, actual_type) => {
for arg in type_args {
arg.1
.instantiate_aliases(region, aliases, var_store, introduced);
@ -761,6 +807,10 @@ fn symbols_help(tipe: &Type, accum: &mut ImSet<Symbol>) {
accum.insert(*alias_symbol);
symbols_help(&actual_type, accum);
}
HostExposedAlias { name, actual, .. } => {
accum.insert(*name);
symbols_help(&actual, accum);
}
Apply(symbol, args) => {
accum.insert(*symbol);
args.iter().for_each(|arg| symbols_help(arg, accum));
@ -830,6 +880,14 @@ fn variables_help(tipe: &Type, accum: &mut ImSet<Variable>) {
}
variables_help(actual, accum);
}
HostExposedAlias {
arguments, actual, ..
} => {
for (_, arg) in arguments {
variables_help(arg, accum);
}
variables_help(actual, accum);
}
Apply(_, args) => {
for x in args {
variables_help(x, accum);