mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Add JSON builtin, pass along solved specializations per module
This commit is contained in:
parent
312cdd0b70
commit
0f4be93e44
8 changed files with 93 additions and 13 deletions
|
@ -12,6 +12,7 @@ pub fn module_source(module_id: ModuleId) -> &'static str {
|
||||||
ModuleId::BOX => BOX,
|
ModuleId::BOX => BOX,
|
||||||
ModuleId::BOOL => BOOL,
|
ModuleId::BOOL => BOOL,
|
||||||
ModuleId::ENCODE => ENCODE,
|
ModuleId::ENCODE => ENCODE,
|
||||||
|
ModuleId::JSON => JSON,
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"ModuleId {:?} is not part of the standard library",
|
"ModuleId {:?} is not part of the standard library",
|
||||||
module_id
|
module_id
|
||||||
|
@ -28,3 +29,4 @@ const SET: &str = include_str!("../roc/Set.roc");
|
||||||
const BOX: &str = include_str!("../roc/Box.roc");
|
const BOX: &str = include_str!("../roc/Box.roc");
|
||||||
const BOOL: &str = include_str!("../roc/Bool.roc");
|
const BOOL: &str = include_str!("../roc/Bool.roc");
|
||||||
const ENCODE: &str = include_str!("../roc/Encode.roc");
|
const ENCODE: &str = include_str!("../roc/Encode.roc");
|
||||||
|
const JSON: &str = include_str!("../roc/Json.roc");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use roc_collections::{all::MutMap, VecSet};
|
use roc_collections::{all::MutMap, VecMap, VecSet};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
|
@ -46,6 +46,8 @@ impl AbilityMemberData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type SolvedSpecializations = VecMap<(Symbol, Symbol), MemberSpecialization>;
|
||||||
|
|
||||||
/// A particular specialization of an ability member.
|
/// A particular specialization of an ability member.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct MemberSpecialization {
|
pub struct MemberSpecialization {
|
||||||
|
@ -88,7 +90,7 @@ pub struct AbilitiesStore {
|
||||||
|
|
||||||
/// Maps a tuple (member, type) specifying that `type` declares an implementation of an ability
|
/// Maps a tuple (member, type) specifying that `type` declares an implementation of an ability
|
||||||
/// member `member`, to the exact symbol that implements the ability.
|
/// member `member`, to the exact symbol that implements the ability.
|
||||||
declared_specializations: MutMap<(Symbol, Symbol), MemberSpecialization>,
|
declared_specializations: SolvedSpecializations,
|
||||||
|
|
||||||
next_specialization_id: u32,
|
next_specialization_id: u32,
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
|
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
|
||||||
use roc_builtins::std::StdLib;
|
use roc_builtins::std::StdLib;
|
||||||
use roc_can::abilities::{AbilitiesStore, MemberTypeInfo};
|
use roc_can::abilities::{AbilitiesStore, MemberTypeInfo, SolvedSpecializations};
|
||||||
use roc_can::constraint::{Constraint, Constraints};
|
use roc_can::constraint::{Constraint, Constraints};
|
||||||
use roc_can::def::Declaration;
|
use roc_can::def::Declaration;
|
||||||
use roc_can::expected::Expected;
|
use roc_can::expected::Expected;
|
||||||
|
@ -89,6 +89,7 @@ impl ExposedForModule {
|
||||||
pub struct ExposedModuleTypes {
|
pub struct ExposedModuleTypes {
|
||||||
pub stored_vars_by_symbol: Vec<(Symbol, Variable)>,
|
pub stored_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||||
pub storage_subs: roc_types::subs::StorageSubs,
|
pub storage_subs: roc_types::subs::StorageSubs,
|
||||||
|
pub solved_specializations: SolvedSpecializations,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constrain_module(
|
pub fn constrain_module(
|
||||||
|
|
|
@ -14,6 +14,7 @@ const MODULES: &[(ModuleId, &str)] = &[
|
||||||
(ModuleId::SET, "Set.roc"),
|
(ModuleId::SET, "Set.roc"),
|
||||||
(ModuleId::BOX, "Box.roc"),
|
(ModuleId::BOX, "Box.roc"),
|
||||||
(ModuleId::ENCODE, "Encode.roc"),
|
(ModuleId::ENCODE, "Encode.roc"),
|
||||||
|
(ModuleId::JSON, "Json.roc"),
|
||||||
];
|
];
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -6,11 +6,11 @@ use crossbeam::thread;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use roc_builtins::roc::module_source;
|
use roc_builtins::roc::module_source;
|
||||||
use roc_builtins::std::borrow_stdlib;
|
use roc_builtins::std::borrow_stdlib;
|
||||||
use roc_can::abilities::AbilitiesStore;
|
use roc_can::abilities::{AbilitiesStore, SolvedSpecializations};
|
||||||
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
||||||
use roc_can::def::Declaration;
|
use roc_can::def::Declaration;
|
||||||
use roc_can::module::{canonicalize_module_defs, Module};
|
use roc_can::module::{canonicalize_module_defs, Module};
|
||||||
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecSet};
|
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
|
||||||
use roc_constrain::module::{
|
use roc_constrain::module::{
|
||||||
constrain_builtin_imports, constrain_module, ExposedByModule, ExposedForModule,
|
constrain_builtin_imports, constrain_module, ExposedByModule, ExposedForModule,
|
||||||
ExposedModuleTypes,
|
ExposedModuleTypes,
|
||||||
|
@ -166,6 +166,7 @@ impl Default for ModuleCache<'_> {
|
||||||
NUM,
|
NUM,
|
||||||
BOX,
|
BOX,
|
||||||
ENCODE,
|
ENCODE,
|
||||||
|
JSON,
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -376,7 +377,7 @@ fn start_phase<'a>(
|
||||||
constraint,
|
constraint,
|
||||||
var_store,
|
var_store,
|
||||||
imported_modules,
|
imported_modules,
|
||||||
&mut state.exposed_types,
|
&state.exposed_types,
|
||||||
dep_idents,
|
dep_idents,
|
||||||
declarations,
|
declarations,
|
||||||
state.cached_subs.clone(),
|
state.cached_subs.clone(),
|
||||||
|
@ -2132,6 +2133,7 @@ fn update<'a>(
|
||||||
ExposedModuleTypes {
|
ExposedModuleTypes {
|
||||||
stored_vars_by_symbol: solved_module.stored_vars_by_symbol,
|
stored_vars_by_symbol: solved_module.stored_vars_by_symbol,
|
||||||
storage_subs: solved_module.storage_subs,
|
storage_subs: solved_module.storage_subs,
|
||||||
|
solved_specializations: solved_module.solved_specializations,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2687,6 +2689,7 @@ fn load_module<'a>(
|
||||||
"Bool", ModuleId::BOOL
|
"Bool", ModuleId::BOOL
|
||||||
"Box", ModuleId::BOX
|
"Box", ModuleId::BOX
|
||||||
"Encode", ModuleId::ENCODE
|
"Encode", ModuleId::ENCODE
|
||||||
|
"Json", ModuleId::JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
let (filename, opt_shorthand) = module_name_to_path(src_dir, module_name, arc_shorthands);
|
let (filename, opt_shorthand) = module_name_to_path(src_dir, module_name, arc_shorthands);
|
||||||
|
@ -3486,19 +3489,41 @@ impl<'a> BuildTask<'a> {
|
||||||
// TODO trim down these arguments - possibly by moving Constraint into Module
|
// TODO trim down these arguments - possibly by moving Constraint into Module
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn solve_module(
|
fn solve_module(
|
||||||
module: Module,
|
mut module: Module,
|
||||||
ident_ids: IdentIds,
|
ident_ids: IdentIds,
|
||||||
module_timing: ModuleTiming,
|
module_timing: ModuleTiming,
|
||||||
constraints: Constraints,
|
constraints: Constraints,
|
||||||
constraint: ConstraintSoa,
|
constraint: ConstraintSoa,
|
||||||
var_store: VarStore,
|
var_store: VarStore,
|
||||||
imported_modules: MutMap<ModuleId, Region>,
|
imported_modules: MutMap<ModuleId, Region>,
|
||||||
exposed_types: &mut ExposedByModule,
|
exposed_types: &ExposedByModule,
|
||||||
dep_idents: IdentIdsByModule,
|
dep_idents: IdentIdsByModule,
|
||||||
declarations: Vec<Declaration>,
|
declarations: Vec<Declaration>,
|
||||||
cached_subs: CachedSubs,
|
cached_subs: CachedSubs,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
|
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
|
||||||
|
|
||||||
|
let abilities_store = &mut module.abilities_store;
|
||||||
|
|
||||||
|
for module in imported_modules.keys() {
|
||||||
|
let exposed = exposed_by_module
|
||||||
|
.get(module)
|
||||||
|
.unwrap_or_else(|| internal_error!("No exposed types for {:?}", module));
|
||||||
|
if let ExposedModuleTypes::Valid {
|
||||||
|
solved_specializations,
|
||||||
|
..
|
||||||
|
} = exposed
|
||||||
|
{
|
||||||
|
for ((member, typ), specialization) in solved_specializations.iter() {
|
||||||
|
abilities_store.register_specialization_for_type(
|
||||||
|
*member,
|
||||||
|
*typ,
|
||||||
|
*specialization,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let exposed_for_module =
|
let exposed_for_module =
|
||||||
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
|
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
|
||||||
|
|
||||||
|
@ -3594,6 +3619,7 @@ fn run_solve_solve(
|
||||||
module: Module,
|
module: Module,
|
||||||
) -> (
|
) -> (
|
||||||
Solved<Subs>,
|
Solved<Subs>,
|
||||||
|
SolvedSpecializations,
|
||||||
Vec<(Symbol, Variable)>,
|
Vec<(Symbol, Variable)>,
|
||||||
Vec<solve::TypeError>,
|
Vec<solve::TypeError>,
|
||||||
AbilitiesStore,
|
AbilitiesStore,
|
||||||
|
@ -3611,6 +3637,19 @@ fn run_solve_solve(
|
||||||
|
|
||||||
let mut subs = Subs::new_from_varstore(var_store);
|
let mut subs = Subs::new_from_varstore(var_store);
|
||||||
|
|
||||||
|
// We don't know what types we're about to solve for in our module, so we need to include the
|
||||||
|
// solved abilities across all dependencies.
|
||||||
|
// TODO: there's got to be a better way to do this. Maybe keep a cache of module -> solved
|
||||||
|
// abilities?
|
||||||
|
// let mut exposed_for_module = exposed_for_module;
|
||||||
|
// let mut imported_modules = VecSet::with_capacity(2);
|
||||||
|
// for imported in exposed_for_module.imported_values.iter() {
|
||||||
|
// imported_modules.insert(imported.module_id());
|
||||||
|
// }
|
||||||
|
// for module in imported_modules.into_iter() {
|
||||||
|
// let typechecked =
|
||||||
|
// }
|
||||||
|
|
||||||
let import_variables = add_imports(
|
let import_variables = add_imports(
|
||||||
&mut subs,
|
&mut subs,
|
||||||
&mut abilities_store,
|
&mut abilities_store,
|
||||||
|
@ -3628,7 +3667,7 @@ fn run_solve_solve(
|
||||||
solve_aliases.insert(*name, alias.clone());
|
solve_aliases.insert(*name, alias.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (solved_subs, exposed_vars_by_symbol, problems, abilities_store) = {
|
let (solved_subs, solved_specializations, exposed_vars_by_symbol, problems, abilities_store) = {
|
||||||
let (solved_subs, solved_env, problems, abilities_store) = roc_solve::module::run_solve(
|
let (solved_subs, solved_env, problems, abilities_store) = roc_solve::module::run_solve(
|
||||||
&constraints,
|
&constraints,
|
||||||
actual_constraint,
|
actual_constraint,
|
||||||
|
@ -3638,13 +3677,36 @@ fn run_solve_solve(
|
||||||
abilities_store,
|
abilities_store,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// STORE ABILITIES
|
||||||
|
let module_id = module.module_id;
|
||||||
|
let known_specializations =
|
||||||
|
abilities_store
|
||||||
|
.get_known_specializations()
|
||||||
|
.filter(|(member, typ)| {
|
||||||
|
// This module solved this specialization if either the member or the type comes from the
|
||||||
|
// module.
|
||||||
|
member.module_id() == module_id || typ.module_id() == module_id
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut solved_specializations: SolvedSpecializations = VecMap::default();
|
||||||
|
let mut specialization_symbols = VecSet::default();
|
||||||
|
for (member, typ) in known_specializations {
|
||||||
|
let specialization = abilities_store.get_specialization(member, typ).unwrap();
|
||||||
|
specialization_symbols.insert(specialization.symbol);
|
||||||
|
solved_specializations.insert((member, typ), specialization);
|
||||||
|
}
|
||||||
|
// END STORE ABILITIES
|
||||||
|
|
||||||
|
// Expose anything that is explicitly exposed by the header, or is a specialization of an
|
||||||
|
// ability.
|
||||||
let exposed_vars_by_symbol: Vec<_> = solved_env
|
let exposed_vars_by_symbol: Vec<_> = solved_env
|
||||||
.vars_by_symbol()
|
.vars_by_symbol()
|
||||||
.filter(|(k, _)| exposed_symbols.contains(k))
|
.filter(|(k, _)| exposed_symbols.contains(k) || specialization_symbols.contains(k))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
(
|
(
|
||||||
solved_subs,
|
solved_subs,
|
||||||
|
solved_specializations,
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
problems,
|
problems,
|
||||||
abilities_store,
|
abilities_store,
|
||||||
|
@ -3653,6 +3715,7 @@ fn run_solve_solve(
|
||||||
|
|
||||||
(
|
(
|
||||||
solved_subs,
|
solved_subs,
|
||||||
|
solved_specializations,
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
problems,
|
problems,
|
||||||
abilities_store,
|
abilities_store,
|
||||||
|
@ -3680,7 +3743,7 @@ fn run_solve<'a>(
|
||||||
// TODO remove when we write builtins in roc
|
// TODO remove when we write builtins in roc
|
||||||
let aliases = module.aliases.clone();
|
let aliases = module.aliases.clone();
|
||||||
|
|
||||||
let (solved_subs, exposed_vars_by_symbol, problems, abilities_store) = {
|
let (solved_subs, solved_specializations, exposed_vars_by_symbol, problems, abilities_store) = {
|
||||||
if module_id.is_builtin() {
|
if module_id.is_builtin() {
|
||||||
match cached_subs.lock().remove(&module_id) {
|
match cached_subs.lock().remove(&module_id) {
|
||||||
None => run_solve_solve(
|
None => run_solve_solve(
|
||||||
|
@ -3694,6 +3757,8 @@ fn run_solve<'a>(
|
||||||
Some((subs, exposed_vars_by_symbol)) => {
|
Some((subs, exposed_vars_by_symbol)) => {
|
||||||
(
|
(
|
||||||
Solved(subs),
|
Solved(subs),
|
||||||
|
// TODO(abilities) replace when we have abilities for builtins
|
||||||
|
VecMap::default(),
|
||||||
exposed_vars_by_symbol.to_vec(),
|
exposed_vars_by_symbol.to_vec(),
|
||||||
vec![],
|
vec![],
|
||||||
// TODO(abilities) replace when we have abilities for builtins
|
// TODO(abilities) replace when we have abilities for builtins
|
||||||
|
@ -3722,6 +3787,7 @@ fn run_solve<'a>(
|
||||||
problems,
|
problems,
|
||||||
aliases,
|
aliases,
|
||||||
stored_vars_by_symbol,
|
stored_vars_by_symbol,
|
||||||
|
solved_specializations,
|
||||||
storage_subs,
|
storage_subs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ impl ModuleName {
|
||||||
pub const RESULT: &'static str = "Result";
|
pub const RESULT: &'static str = "Result";
|
||||||
pub const BOX: &'static str = "Box";
|
pub const BOX: &'static str = "Box";
|
||||||
pub const ENCODE: &'static str = "Encode";
|
pub const ENCODE: &'static str = "Encode";
|
||||||
|
pub const JSON: &'static str = "Json";
|
||||||
|
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
self.0.as_str()
|
self.0.as_str()
|
||||||
|
|
|
@ -1313,6 +1313,9 @@ define_builtins! {
|
||||||
9 ENCODE: "Encode" => {
|
9 ENCODE: "Encode" => {
|
||||||
0 ENCODE_ENCODE: "Encode"
|
0 ENCODE_ENCODE: "Encode"
|
||||||
}
|
}
|
||||||
|
10 JSON: "Json" => {
|
||||||
|
0 JSON_JSON: "Json"
|
||||||
|
}
|
||||||
|
|
||||||
num_modules: 10 // Keep this count up to date by hand! (TODO: see the mut_map! macro for how we could determine this count correctly in the macro)
|
num_modules: 11 // Keep this count up to date by hand! (TODO: see the mut_map! macro for how we could determine this count correctly in the macro)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::solve::{self, Aliases};
|
use crate::solve::{self, Aliases};
|
||||||
use roc_can::abilities::AbilitiesStore;
|
use roc_can::abilities::{AbilitiesStore, SolvedSpecializations};
|
||||||
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
||||||
use roc_can::module::RigidVariables;
|
use roc_can::module::RigidVariables;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
|
@ -20,11 +20,15 @@ pub struct SolvedModule {
|
||||||
/// to create the types for HostExposed. This
|
/// to create the types for HostExposed. This
|
||||||
/// has some overlap with the StorageSubs fields,
|
/// has some overlap with the StorageSubs fields,
|
||||||
/// so maybe we can get rid of this at some point
|
/// so maybe we can get rid of this at some point
|
||||||
|
///
|
||||||
|
/// Contains both variables of symbols that are explicitly exposed by the header,
|
||||||
|
/// and the variables of any solved ability specializations we have.
|
||||||
pub exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
pub exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||||
|
|
||||||
/// Used when importing this module into another module
|
/// Used when importing this module into another module
|
||||||
pub stored_vars_by_symbol: Vec<(Symbol, Variable)>,
|
pub stored_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||||
pub storage_subs: StorageSubs,
|
pub storage_subs: StorageSubs,
|
||||||
|
pub solved_specializations: SolvedSpecializations,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_solve(
|
pub fn run_solve(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue