Merge pull request #7533 from smores56/simple-can-solo

Move desugaring to new `roc_can_solo` crate
This commit is contained in:
Sam Mohr 2025-01-19 19:06:10 -08:00 committed by GitHub
commit 809fe23afd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
72 changed files with 3282 additions and 2630 deletions

View file

@ -8,6 +8,7 @@ license.workspace = true
version.workspace = true
[dependencies]
roc_can_solo.workspace = true
roc_collections.workspace = true
roc_error_macros.workspace = true
roc_exhaustive.workspace = true

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@ use roc_region::all::{LineInfo, Loc, Region};
use roc_types::subs::Variable;
/// The canonicalization environment for a particular module.
#[derive(Debug)]
pub struct Env<'a> {
/// The module's path. Opaques and unqualified references to identifiers
/// are assumed to be relative to this path.
@ -51,6 +52,36 @@ pub struct Env<'a> {
}
impl<'a> Env<'a> {
#[allow(clippy::too_many_arguments)]
pub fn from_solo_can(
arena: &'a Bump,
module_path: &'a Path,
home: ModuleId,
dep_idents: &'a IdentIdsByModule,
qualified_module_ids: &'a PackageModuleIds<'a>,
problems: Vec<Problem>,
opt_shorthand: Option<&'a str>,
src: &'a str,
line_info: &'a mut Option<LineInfo>,
) -> Self {
Env {
arena,
src,
home,
module_path,
dep_idents,
qualified_module_ids,
problems,
closures: MutMap::default(),
qualified_value_lookups: Default::default(),
tailcallable_symbol: None,
top_level_symbols: Default::default(),
home_params_record: None,
opt_shorthand,
line_info,
}
}
#[allow(clippy::too_many_arguments)]
pub fn new(
arena: &'a Bump,

View file

@ -1,9 +1,6 @@
use std::path::Path;
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
use crate::annotation::{canonicalize_annotation, AnnotationFor};
use crate::def::{canonicalize_defs, report_unused_imports, Def, DefKind};
use crate::desugar::desugar_record_destructures;
use crate::env::Env;
use crate::expr::{ClosureData, Declarations, ExpectLookup, Expr, Output, PendingDerives};
use crate::pattern::{
@ -16,8 +13,8 @@ use roc_collections::{MutMap, SendMap, VecMap, VecSet};
use roc_error_macros::internal_error;
use roc_module::ident::Ident;
use roc_module::ident::Lowercase;
use roc_module::symbol::{IdentId, IdentIds, IdentIdsByModule, ModuleId, PackageModuleIds, Symbol};
use roc_parse::ast::{Defs, TypeAnnotation};
use roc_module::symbol::{IdentId, ModuleId, Symbol};
use roc_parse::ast::{Collection, Defs, Pattern as ParsePattern, TypeAnnotation};
use roc_parse::header::HeaderType;
use roc_parse::pattern::PatternType;
use roc_problem::can::{Problem, RuntimeError};
@ -209,55 +206,19 @@ fn has_no_implementation(expr: &Expr) -> bool {
#[allow(clippy::too_many_arguments)]
pub fn canonicalize_module_defs<'a>(
arena: &'a Bump,
loc_defs: &'a mut Defs<'a>,
header_type: &'a roc_parse::header::HeaderType,
home: ModuleId,
module_path: &'a str,
src: &'a str,
qualified_module_ids: &'a PackageModuleIds<'a>,
exposed_ident_ids: IdentIds,
dep_idents: &'a IdentIdsByModule,
aliases: MutMap<Symbol, Alias>,
imported_abilities_state: PendingAbilitiesStore,
initial_scope: MutMap<Ident, (Symbol, Region)>,
exposed_symbols: VecSet<Symbol>,
symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)],
var_store: &mut VarStore,
opt_shorthand: Option<&'a str>,
mut scope: Scope,
mut env: Env<'a>,
loc_defs: Defs<'a>,
module_params: Option<(Region, Collection<'a, Loc<ParsePattern<'a>>>)>,
) -> ModuleOutput {
let mut can_exposed_imports = MutMap::default();
let mut scope = Scope::new(
home,
qualified_module_ids
.get_name(home)
.expect("home module not found")
.as_inner()
.to_owned(),
exposed_ident_ids,
imported_abilities_state,
);
let mut env = Env::new(
arena,
src,
home,
arena.alloc(Path::new(module_path)),
dep_idents,
qualified_module_ids,
opt_shorthand,
);
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,
);
}
// Desugar operators (convert them to Apply calls, taking into account
// operator precedence and associativity rules), before doing other canonicalization.
//
@ -266,8 +227,6 @@ pub fn canonicalize_module_defs<'a>(
// operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily.
crate::desugar::desugar_defs_node_values(&mut env, &mut scope, loc_defs);
let mut rigid_variables = RigidVariables::default();
// Initial scope values are treated like defs that appear before any others.
@ -319,51 +278,42 @@ pub fn canonicalize_module_defs<'a>(
let mut output = Output::default();
let module_params = header_type.get_params().as_ref().map(
|roc_parse::header::ModuleParams {
pattern,
before_arrow: _,
after_arrow: _,
}| {
let desugared_patterns =
desugar_record_destructures(&mut env, &mut scope, pattern.value);
let module_params = module_params.map(|(params_region, desugared_patterns)| {
let (destructs, _) = canonicalize_record_destructs(
&mut env,
var_store,
&mut scope,
&mut output,
PatternType::ModuleParams,
&desugared_patterns,
params_region,
PermitShadows(false),
);
let (destructs, _) = canonicalize_record_destructs(
&mut env,
var_store,
&mut scope,
&mut output,
PatternType::ModuleParams,
&desugared_patterns,
pattern.region,
PermitShadows(false),
);
let whole_symbol = scope.gen_unique_symbol();
env.top_level_symbols.insert(whole_symbol);
let whole_symbol = scope.gen_unique_symbol();
env.top_level_symbols.insert(whole_symbol);
let whole_var = var_store.fresh();
let whole_var = var_store.fresh();
env.home_params_record = Some((whole_symbol, whole_var));
env.home_params_record = Some((whole_symbol, whole_var));
ModuleParams {
region: pattern.region,
whole_var,
whole_symbol,
record_var: var_store.fresh(),
record_ext_var: var_store.fresh(),
destructs,
arity_by_name: Default::default(),
}
},
);
ModuleParams {
region: params_region,
whole_var,
whole_symbol,
record_var: var_store.fresh(),
record_ext_var: var_store.fresh(),
destructs,
arity_by_name: Default::default(),
}
});
let (defs, output, symbols_introduced, imports_introduced) = canonicalize_defs(
&mut env,
output,
var_store,
&mut scope,
loc_defs,
arena.alloc(loc_defs),
PatternType::TopLevelDef,
);

View file

@ -1,10 +1,11 @@
extern crate bumpalo;
use self::bumpalo::Bump;
use roc_can::desugar;
use roc_can::env::Env;
use roc_can::expr::{canonicalize_expr, Expr};
use roc_can::scope::Scope;
use roc_can_solo::env::SoloEnv;
use roc_can_solo::scope::SoloScope;
use roc_collections::all::MutMap;
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol};
use roc_problem::can::Problem;
@ -65,7 +66,9 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
// visited a BinOp node we'd recursively try to apply this to each of its nested
// operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily.
let loc_expr = desugar::desugar_expr(&mut env, &mut scope, &loc_expr);
let mut solo_env = SoloEnv::new(arena, expr_str, Path::new("Test.roc"));
let mut solo_scope = SoloScope::new();
let loc_expr = roc_can_solo::desugar::desugar_expr(&mut solo_env, &mut solo_scope, &loc_expr);
scope.add_alias(
Symbol::NUM_INT,