mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
add HostExposedAlias
This commit is contained in:
parent
d19223dfb3
commit
c09b66a9cc
6 changed files with 215 additions and 10 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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()),
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue