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

@ -14,6 +14,13 @@ pub struct Annotation {
pub introduced_variables: IntroducedVariables,
pub references: MutSet<Symbol>,
pub aliases: SendMap<Symbol, Alias>,
pub variably_sized_types: VariablySizedTypes,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct VariablySizedTypes {
rigids: MutMap<Lowercase, ()>,
aliases: MutMap<Symbol, ()>,
}
#[derive(Clone, Debug, PartialEq, Default)]
@ -58,12 +65,6 @@ impl IntroducedVariables {
}
}
#[derive(Debug, Default)]
pub struct VariablySizedTypes {
rigids: MutMap<Lowercase, ()>,
aliases: MutMap<Symbol, ()>,
}
pub fn canonicalize_annotation(
env: &mut Env,
scope: &mut Scope,
@ -74,6 +75,7 @@ pub fn canonicalize_annotation(
let mut introduced_variables = IntroducedVariables::default();
let mut references = MutSet::default();
let mut aliases = SendMap::default();
let variably_sized_types = VariablySizedTypes::default();
let typ = can_annotation_help(
env,
annotation,
@ -90,6 +92,7 @@ pub fn canonicalize_annotation(
introduced_variables,
references,
aliases,
variably_sized_types,
}
}

View file

@ -2105,6 +2105,48 @@ fn annotation_to_attr_type(
let alias = Type::Alias(*symbol, new_fields, Box::new(actual_type));
(
actual_vars,
crate::builtins::builtin_type(Symbol::ATTR_ATTR, vec![uniq_type, alias]),
)
} else {
panic!("lifted type is not Attr")
}
}
HostExposedAlias {
name: symbol,
def_name,
arguments: fields,
actual_var,
actual,
} => {
let (mut actual_vars, lifted_actual) =
annotation_to_attr_type(var_store, actual, rigids, change_var_kind);
if let Type::Apply(attr_symbol, args) = lifted_actual {
debug_assert!(attr_symbol == Symbol::ATTR_ATTR);
let uniq_type = args[0].clone();
let actual_type = args[1].clone();
let mut new_fields = Vec::with_capacity(fields.len());
for (name, tipe) in fields {
let (lifted_vars, lifted) =
annotation_to_attr_type(var_store, tipe, rigids, change_var_kind);
actual_vars.extend(lifted_vars);
new_fields.push((name.clone(), lifted));
}
let alias = Type::HostExposedAlias {
name: *symbol,
def_name: *def_name,
arguments: new_fields,
actual_var: *actual_var,
actual: Box::new(actual_type),
};
(
actual_vars,
crate::builtins::builtin_type(Symbol::ATTR_ATTR, vec![uniq_type, alias]),

View file

@ -5,7 +5,6 @@ use crossbeam::deque::{Injector, Stealer, Worker};
use crossbeam::thread;
use parking_lot::Mutex;
use roc_builtins::std::{Mode, StdLib};
use roc_can::annotation::VariablySizedTypes;
use roc_can::constraint::Constraint;
use roc_can::def::Declaration;
use roc_can::module::{canonicalize_module_defs, Module};
@ -14,7 +13,7 @@ use roc_constrain::module::{
constrain_imports, pre_constrain_imports, ConstrainableImports, Import,
};
use roc_constrain::module::{constrain_module, ExposedModuleTypes, SubsByModule};
use roc_module::ident::{Ident, ModuleName};
use roc_module::ident::{Ident, Lowercase, ModuleName};
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, Symbol};
use roc_mono::ir::{
CapturedSymbols, ExternalSpecializations, MonoProblem, PartialProc, PendingSpecialization,
@ -211,7 +210,7 @@ struct ModuleCache<'a> {
found_specializations: MutMap<ModuleId, FoundSpecializationsModule<'a>>,
external_specializations_requested: MutMap<ModuleId, ExternalSpecializations>,
documentation: MutMap<ModuleId, ModuleDocumentation>,
host_exposed_variably_sized_types: MutMap<Symbol, VariablySizedTypes>,
variably_sized_layouts: MutMap<Symbol, VariablySizedLayouts<'a>>,
}
fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> BuildTask<'a> {
@ -471,10 +470,17 @@ pub struct MonomorphizedModule<'a> {
pub mono_problems: Vec<roc_mono::ir::MonoProblem>,
pub procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>,
pub exposed_to_host: MutMap<Symbol, Variable>,
pub variably_sized_layouts: MutMap<Symbol, VariablySizedLayouts<'a>>,
pub src: Box<str>,
pub timings: MutMap<ModuleId, ModuleTiming>,
}
#[derive(Debug, Default)]
pub struct VariablySizedLayouts<'a> {
rigids: MutMap<Lowercase, Layout<'a>>,
aliases: MutMap<Symbol, Layout<'a>>,
}
#[derive(Debug)]
struct ParsedModule<'a> {
module_id: ModuleId,
@ -533,6 +539,7 @@ enum Msg<'a> {
ident_ids: IdentIds,
layout_cache: LayoutCache<'a>,
external_specializations_requested: MutMap<ModuleId, ExternalSpecializations>,
variably_sized_layouts: MutMap<Symbol, VariablySizedLayouts<'a>>,
procedures: MutMap<(Symbol, Layout<'a>), Proc<'a>>,
problems: Vec<roc_mono::ir::MonoProblem>,
subs: Subs,
@ -1473,6 +1480,7 @@ fn update<'a>(
finished_info,
procedures,
external_specializations_requested,
variably_sized_layouts,
problems,
..
} => {
@ -1480,6 +1488,11 @@ fn update<'a>(
state.mono_problems.extend(problems);
state
.module_cache
.variably_sized_layouts
.extend(variably_sized_layouts);
for (module_id, requested) in external_specializations_requested {
let existing = match state
.module_cache
@ -1560,6 +1573,7 @@ fn finish_specialization<'a>(
type_problems,
can_problems,
procedures,
module_cache,
..
} = state;
@ -1573,6 +1587,7 @@ fn finish_specialization<'a>(
interns,
procedures,
src: src.into(),
variably_sized_layouts: module_cache.variably_sized_layouts,
timings: state.timings,
}
}
@ -2233,6 +2248,9 @@ fn make_specializations<'a>(
let external_specializations_requested = procs.externals_we_need.clone();
let procedures = procs.get_specialized_procs_without_rc(mono_env.arena);
// TODO
let variably_sized_layouts = MutMap::default();
Msg::MadeSpecializations {
module_id: home,
ident_ids,
@ -2242,6 +2260,7 @@ fn make_specializations<'a>(
subs,
finished_info,
external_specializations_requested,
variably_sized_layouts,
}
}

View file

@ -813,6 +813,36 @@ fn type_to_variable(
result
}
HostExposedAlias {
name: symbol,
arguments: args,
actual: alias_type,
actual_var,
..
} => {
let mut arg_vars = Vec::with_capacity(args.len());
let mut new_aliases = ImMap::default();
for (arg, arg_type) in args {
let arg_var = type_to_variable(subs, rank, pools, cached, arg_type);
arg_vars.push((arg.clone(), arg_var));
new_aliases.insert(arg.clone(), arg_var);
}
let alias_var = type_to_variable(subs, rank, pools, cached, alias_type);
let content = Content::Alias(*symbol, arg_vars, alias_var);
let result = register(subs, rank, pools, content);
// unify the actual_var with the result var
// this can be used to access the type of the actual_var
// to determine its layout later
let descriptor = subs.get(result);
subs.union(*actual_var, result, descriptor);
result
}
Erroneous(problem) => {
let content = Content::Structure(FlatType::Erroneous(problem.clone()));

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);