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::BOOL => BOOL,
|
||||
ModuleId::ENCODE => ENCODE,
|
||||
ModuleId::JSON => JSON,
|
||||
_ => panic!(
|
||||
"ModuleId {:?} is not part of the standard library",
|
||||
module_id
|
||||
|
@ -28,3 +29,4 @@ const SET: &str = include_str!("../roc/Set.roc");
|
|||
const BOX: &str = include_str!("../roc/Box.roc");
|
||||
const BOOL: &str = include_str!("../roc/Bool.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_module::symbol::Symbol;
|
||||
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.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct MemberSpecialization {
|
||||
|
@ -88,7 +90,7 @@ pub struct AbilitiesStore {
|
|||
|
||||
/// Maps a tuple (member, type) specifying that `type` declares an implementation of an ability
|
||||
/// member `member`, to the exact symbol that implements the ability.
|
||||
declared_specializations: MutMap<(Symbol, Symbol), MemberSpecialization>,
|
||||
declared_specializations: SolvedSpecializations,
|
||||
|
||||
next_specialization_id: u32,
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::expr::{constrain_def_make_constraint, constrain_def_pattern, Env};
|
||||
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::def::Declaration;
|
||||
use roc_can::expected::Expected;
|
||||
|
@ -89,6 +89,7 @@ impl ExposedForModule {
|
|||
pub struct ExposedModuleTypes {
|
||||
pub stored_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||
pub storage_subs: roc_types::subs::StorageSubs,
|
||||
pub solved_specializations: SolvedSpecializations,
|
||||
}
|
||||
|
||||
pub fn constrain_module(
|
||||
|
|
|
@ -14,6 +14,7 @@ const MODULES: &[(ModuleId, &str)] = &[
|
|||
(ModuleId::SET, "Set.roc"),
|
||||
(ModuleId::BOX, "Box.roc"),
|
||||
(ModuleId::ENCODE, "Encode.roc"),
|
||||
(ModuleId::JSON, "Json.roc"),
|
||||
];
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -6,11 +6,11 @@ use crossbeam::thread;
|
|||
use parking_lot::Mutex;
|
||||
use roc_builtins::roc::module_source;
|
||||
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::def::Declaration;
|
||||
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::{
|
||||
constrain_builtin_imports, constrain_module, ExposedByModule, ExposedForModule,
|
||||
ExposedModuleTypes,
|
||||
|
@ -166,6 +166,7 @@ impl Default for ModuleCache<'_> {
|
|||
NUM,
|
||||
BOX,
|
||||
ENCODE,
|
||||
JSON,
|
||||
}
|
||||
|
||||
Self {
|
||||
|
@ -376,7 +377,7 @@ fn start_phase<'a>(
|
|||
constraint,
|
||||
var_store,
|
||||
imported_modules,
|
||||
&mut state.exposed_types,
|
||||
&state.exposed_types,
|
||||
dep_idents,
|
||||
declarations,
|
||||
state.cached_subs.clone(),
|
||||
|
@ -2132,6 +2133,7 @@ fn update<'a>(
|
|||
ExposedModuleTypes {
|
||||
stored_vars_by_symbol: solved_module.stored_vars_by_symbol,
|
||||
storage_subs: solved_module.storage_subs,
|
||||
solved_specializations: solved_module.solved_specializations,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -2687,6 +2689,7 @@ fn load_module<'a>(
|
|||
"Bool", ModuleId::BOOL
|
||||
"Box", ModuleId::BOX
|
||||
"Encode", ModuleId::ENCODE
|
||||
"Json", ModuleId::JSON
|
||||
}
|
||||
|
||||
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
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn solve_module(
|
||||
module: Module,
|
||||
mut module: Module,
|
||||
ident_ids: IdentIds,
|
||||
module_timing: ModuleTiming,
|
||||
constraints: Constraints,
|
||||
constraint: ConstraintSoa,
|
||||
var_store: VarStore,
|
||||
imported_modules: MutMap<ModuleId, Region>,
|
||||
exposed_types: &mut ExposedByModule,
|
||||
exposed_types: &ExposedByModule,
|
||||
dep_idents: IdentIdsByModule,
|
||||
declarations: Vec<Declaration>,
|
||||
cached_subs: CachedSubs,
|
||||
) -> Self {
|
||||
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 =
|
||||
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
|
||||
|
||||
|
@ -3594,6 +3619,7 @@ fn run_solve_solve(
|
|||
module: Module,
|
||||
) -> (
|
||||
Solved<Subs>,
|
||||
SolvedSpecializations,
|
||||
Vec<(Symbol, Variable)>,
|
||||
Vec<solve::TypeError>,
|
||||
AbilitiesStore,
|
||||
|
@ -3611,6 +3637,19 @@ fn run_solve_solve(
|
|||
|
||||
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(
|
||||
&mut subs,
|
||||
&mut abilities_store,
|
||||
|
@ -3628,7 +3667,7 @@ fn run_solve_solve(
|
|||
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(
|
||||
&constraints,
|
||||
actual_constraint,
|
||||
|
@ -3638,13 +3677,36 @@ fn run_solve_solve(
|
|||
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
|
||||
.vars_by_symbol()
|
||||
.filter(|(k, _)| exposed_symbols.contains(k))
|
||||
.filter(|(k, _)| exposed_symbols.contains(k) || specialization_symbols.contains(k))
|
||||
.collect();
|
||||
|
||||
(
|
||||
solved_subs,
|
||||
solved_specializations,
|
||||
exposed_vars_by_symbol,
|
||||
problems,
|
||||
abilities_store,
|
||||
|
@ -3653,6 +3715,7 @@ fn run_solve_solve(
|
|||
|
||||
(
|
||||
solved_subs,
|
||||
solved_specializations,
|
||||
exposed_vars_by_symbol,
|
||||
problems,
|
||||
abilities_store,
|
||||
|
@ -3680,7 +3743,7 @@ fn run_solve<'a>(
|
|||
// TODO remove when we write builtins in roc
|
||||
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() {
|
||||
match cached_subs.lock().remove(&module_id) {
|
||||
None => run_solve_solve(
|
||||
|
@ -3694,6 +3757,8 @@ fn run_solve<'a>(
|
|||
Some((subs, exposed_vars_by_symbol)) => {
|
||||
(
|
||||
Solved(subs),
|
||||
// TODO(abilities) replace when we have abilities for builtins
|
||||
VecMap::default(),
|
||||
exposed_vars_by_symbol.to_vec(),
|
||||
vec![],
|
||||
// TODO(abilities) replace when we have abilities for builtins
|
||||
|
@ -3722,6 +3787,7 @@ fn run_solve<'a>(
|
|||
problems,
|
||||
aliases,
|
||||
stored_vars_by_symbol,
|
||||
solved_specializations,
|
||||
storage_subs,
|
||||
};
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ impl ModuleName {
|
|||
pub const RESULT: &'static str = "Result";
|
||||
pub const BOX: &'static str = "Box";
|
||||
pub const ENCODE: &'static str = "Encode";
|
||||
pub const JSON: &'static str = "Json";
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.0.as_str()
|
||||
|
|
|
@ -1313,6 +1313,9 @@ define_builtins! {
|
|||
9 ENCODE: "Encode" => {
|
||||
0 ENCODE_ENCODE: "Encode"
|
||||
}
|
||||
|
||||
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)
|
||||
10 JSON: "Json" => {
|
||||
0 JSON_JSON: "Json"
|
||||
}
|
||||
|
||||
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 roc_can::abilities::AbilitiesStore;
|
||||
use roc_can::abilities::{AbilitiesStore, SolvedSpecializations};
|
||||
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
||||
use roc_can::module::RigidVariables;
|
||||
use roc_collections::all::MutMap;
|
||||
|
@ -20,11 +20,15 @@ pub struct SolvedModule {
|
|||
/// to create the types for HostExposed. This
|
||||
/// has some overlap with the StorageSubs fields,
|
||||
/// 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)>,
|
||||
|
||||
/// Used when importing this module into another module
|
||||
pub stored_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||
pub storage_subs: StorageSubs,
|
||||
pub solved_specializations: SolvedSpecializations,
|
||||
}
|
||||
|
||||
pub fn run_solve(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue