Move desugaring to new roc_can_solo crate

This commit is contained in:
Sam Mohr 2025-01-19 07:16:43 -08:00
parent b183ba19ae
commit fce14d31b0
No known key found for this signature in database
GPG key ID: EA41D161A3C1BC99
72 changed files with 3294 additions and 2630 deletions

View file

@ -15,11 +15,14 @@ use parking_lot::Mutex;
use roc_builtins::roc::module_source;
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints, TypeOrVar};
use roc_can::env::Env;
use roc_can::expr::{Declarations, ExpectLookup, PendingDerives};
use roc_can::module::{
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
ModuleParams, ResolvedImplementations, TypeState,
};
use roc_can::scope::Scope;
use roc_can_solo::module::{solo_canonicalize_module_defs, SoloCanOutput};
use roc_collections::soa::slice_extend_new;
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
use roc_constrain::module::constrain_module;
@ -204,9 +207,20 @@ fn start_phase<'a>(
root_type: state.root_type.clone(),
}
}
Phase::SoloCanonicalize => {
// canonicalize the file
let parsed = state.module_cache.parsed.get(&module_id).unwrap().clone();
BuildTask::SoloCanonicalize { parsed }
}
Phase::CanonicalizeAndConstrain => {
// canonicalize the file
let parsed = state.module_cache.parsed.remove(&module_id).unwrap();
let solo_can_output = state
.module_cache
.solo_canonicalized
.remove(&module_id)
.unwrap();
let deps_by_name = &parsed.deps_by_name;
let num_deps = deps_by_name.len();
@ -318,6 +332,7 @@ fn start_phase<'a>(
exposed_module_ids: state.exposed_modules,
exec_mode: state.exec_mode,
imported_module_params,
solo_can_output,
}
}
@ -577,6 +592,7 @@ enum Msg<'a> {
Many(Vec<Msg<'a>>),
Header(ModuleHeader<'a>),
Parsed(ParsedModule<'a>),
SoloCanonicalized(ModuleId, CanSolo<'a>),
CanonicalizedAndConstrained(CanAndCon),
SolvedTypes {
module_id: ModuleId,
@ -651,6 +667,9 @@ enum Msg<'a> {
IncorrectModuleName(FileError<'a, IncorrectModuleName<'a>>),
}
#[derive(Debug)]
struct CanSolo<'a>(SoloCanOutput<'a>);
#[derive(Debug)]
struct CanAndCon {
constrained_module: ConstrainedModule,
@ -890,6 +909,9 @@ enum BuildTask<'a> {
ident_ids_by_module: SharedIdentIdsByModule,
root_type: RootType,
},
SoloCanonicalize {
parsed: ParsedModule<'a>,
},
CanonicalizeAndConstrain {
parsed: ParsedModule<'a>,
qualified_module_ids: PackageModuleIds<'a>,
@ -901,6 +923,7 @@ enum BuildTask<'a> {
skip_constraint_gen: bool,
exec_mode: ExecutionMode,
imported_module_params: VecMap<ModuleId, ModuleParams>,
solo_can_output: SoloCanOutput<'a>,
},
Solve {
module: Module,
@ -2411,6 +2434,23 @@ fn update<'a>(
Ok(state)
}
SoloCanonicalized(module_id, CanSolo(solo_can_output)) => {
log!("solo canonicalized module {:?}", module_id);
state
.module_cache
.solo_canonicalized
.insert(module_id, solo_can_output);
let work = state
.dependencies
.notify(module_id, Phase::SoloCanonicalize);
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
CanonicalizedAndConstrained(CanAndCon {
constrained_module,
canonicalization_problems,
@ -2462,6 +2502,7 @@ fn update<'a>(
Ok(state)
}
SolvedTypes {
module_id,
ident_ids,
@ -5082,6 +5123,31 @@ fn build_platform_header<'a>(
build_header(info, parse_state, module_ids, module_timing)
}
#[allow(clippy::unnecessary_wraps)]
fn canonicalize_solo<'a>(arena: &'a Bump, parsed: ParsedModule<'a>) -> CanSolo<'a> {
let canonicalize_solo_start = Instant::now();
let ParsedModule {
module_path,
header_type,
src,
parsed_defs,
mut module_timing,
..
} = parsed;
let parsed_defs = arena.alloc(parsed_defs);
let solo_can_output =
solo_canonicalize_module_defs(arena, header_type, parsed_defs, module_path, src);
let canonicalize_solo_end = Instant::now();
module_timing.canonicalize_solo = canonicalize_solo_end.duration_since(canonicalize_solo_start);
CanSolo(solo_can_output)
}
#[allow(clippy::unnecessary_wraps)]
fn canonicalize_and_constrain<'a>(
arena: &'a Bump,
@ -5095,21 +5161,21 @@ fn canonicalize_and_constrain<'a>(
exposed_module_ids: &[ModuleId],
exec_mode: ExecutionMode,
imported_module_params: VecMap<ModuleId, ModuleParams>,
solo_can_output: SoloCanOutput<'a>,
) -> CanAndCon {
let canonicalize_start = Instant::now();
let ParsedModule {
module_id,
module_path,
src,
header_type,
exposed_ident_ids,
parsed_defs,
initial_scope,
available_modules,
mut module_timing,
symbols_from_requires,
opt_shorthand,
exposed_ident_ids,
..
} = parsed;
@ -5117,27 +5183,55 @@ fn canonicalize_and_constrain<'a>(
let _before = roc_types::types::get_type_clone_count();
let parsed_defs_for_docs = parsed_defs.clone();
let parsed_defs = arena.alloc(parsed_defs);
let mut var_store = VarStore::default();
let env = Env::from_solo_can(
arena,
&module_path,
module_id,
&dep_idents,
qualified_module_ids,
solo_can_output.problems,
opt_shorthand,
solo_can_output.src,
solo_can_output.lazy_line_info,
);
let mut scope = Scope::new(
module_id,
qualified_module_ids
.get_name(module_id)
.expect("home module not found")
.as_inner()
.to_owned(),
exposed_ident_ids,
imported_abilities_state,
);
for (name, alias) in aliases.into_iter() {
scope.add_alias(
name,
alias.region,
alias.type_variables,
alias.infer_ext_in_output_variables,
alias.typ,
alias.kind,
);
}
let mut module_output = canonicalize_module_defs(
arena,
parsed_defs,
&header_type,
module_id,
&*arena.alloc(module_path.to_string_lossy()),
src,
qualified_module_ids,
exposed_ident_ids,
&dep_idents,
aliases,
imported_abilities_state,
initial_scope,
exposed_symbols,
&symbols_from_requires,
&mut var_store,
opt_shorthand,
scope,
env,
solo_can_output.loc_defs,
solo_can_output.module_params,
);
let mut types = Types::new();
@ -6237,6 +6331,12 @@ fn run_task<'a>(
ident_ids_by_module,
root_type,
),
SoloCanonicalize { parsed } => {
let module_id = parsed.module_id;
let solo_can = canonicalize_solo(arena, parsed);
Ok(Msg::SoloCanonicalized(module_id, solo_can))
}
CanonicalizeAndConstrain {
parsed,
qualified_module_ids,
@ -6248,6 +6348,7 @@ fn run_task<'a>(
exposed_module_ids,
exec_mode,
imported_module_params,
solo_can_output,
} => {
let can_and_con = canonicalize_and_constrain(
arena,
@ -6261,6 +6362,7 @@ fn run_task<'a>(
exposed_module_ids,
exec_mode,
imported_module_params,
solo_can_output,
);
Ok(Msg::CanonicalizedAndConstrained(can_and_con))

View file

@ -189,7 +189,7 @@ pub struct MonomorphizedModule<'a> {
pub glue_layouts: GlueLayouts<'a>,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ParsedModule<'a> {
pub module_id: ModuleId,
pub module_path: PathBuf,
@ -237,11 +237,12 @@ pub struct ExposedToHost {
pub getters: Vec<Symbol>,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ModuleTiming {
pub read_roc_file: Duration,
pub parse_header: Duration,
pub parse_body: Duration,
pub canonicalize_solo: Duration,
pub canonicalize: Duration,
pub constrain: Duration,
pub solve: Duration,
@ -261,6 +262,7 @@ impl ModuleTiming {
read_roc_file: Duration::default(),
parse_header: Duration::default(),
parse_body: Duration::default(),
canonicalize_solo: Duration::default(),
canonicalize: Duration::default(),
constrain: Duration::default(),
solve: Duration::default(),
@ -281,6 +283,7 @@ impl ModuleTiming {
read_roc_file,
parse_header,
parse_body,
canonicalize_solo,
canonicalize,
constrain,
solve,
@ -297,6 +300,7 @@ impl ModuleTiming {
.checked_sub(*find_specializations)?
.checked_sub(*solve)?
.checked_sub(*constrain)?
.checked_sub(*canonicalize_solo)?
.checked_sub(*canonicalize)?
.checked_sub(*parse_body)?
.checked_sub(*parse_header)?

View file

@ -5,6 +5,7 @@ use crate::module::{
};
use roc_can::abilities::PendingAbilitiesStore;
use roc_can::module::ModuleParams;
use roc_can_solo::module::SoloCanOutput;
use roc_collections::{MutMap, MutSet, VecMap};
use roc_module::ident::ModuleName;
use roc_module::symbol::{ModuleId, PQModuleName, Symbol};
@ -26,6 +27,7 @@ pub(crate) struct ModuleCache<'a> {
pub(crate) parsed: MutMap<ModuleId, ParsedModule<'a>>,
pub(crate) aliases: MutMap<ModuleId, MutMap<Symbol, (bool, Alias)>>,
pub(crate) pending_abilities: MutMap<ModuleId, PendingAbilitiesStore>,
pub(crate) solo_canonicalized: MutMap<ModuleId, SoloCanOutput<'a>>,
pub(crate) constrained: MutMap<ModuleId, ConstrainedModule>,
pub(crate) module_params: MutMap<ModuleId, ModuleParams>,
pub(crate) typechecked: MutMap<ModuleId, TypeCheckedModule<'a>>,
@ -45,6 +47,8 @@ pub(crate) struct ModuleCache<'a> {
pub(crate) type_problems: MutMap<ModuleId, Vec<TypeError>>,
pub(crate) sources: MutMap<ModuleId, (PathBuf, &'a str)>,
#[allow(dead_code)]
pub(crate) content_hashes: MutMap<ModuleId, String>,
}
impl<'a> ModuleCache<'a> {
@ -65,6 +69,19 @@ impl<'a> ModuleCache<'a> {
pub fn has_errors(&self) -> bool {
self.has_can_errors() || self.has_type_errors()
}
#[allow(dead_code)]
pub fn add_module_content_hash(&mut self, module_id: ModuleId, contents: &str) -> String {
let hash = Self::hash_contents(contents);
self.content_hashes.insert(module_id, hash.clone());
hash
}
#[allow(dead_code)]
pub fn hash_contents(contents: &str) -> String {
base64_url::encode(blake3::hash(contents.as_bytes()).as_bytes())
}
}
impl Default for ModuleCache<'_> {
@ -101,6 +118,7 @@ impl Default for ModuleCache<'_> {
parsed: Default::default(),
aliases: Default::default(),
pending_abilities: Default::default(),
solo_canonicalized: Default::default(),
constrained: Default::default(),
module_params: Default::default(),
typechecked: Default::default(),
@ -116,6 +134,7 @@ impl Default for ModuleCache<'_> {
can_problems: Default::default(),
type_problems: Default::default(),
sources: Default::default(),
content_hashes: Default::default(),
}
}
}