mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 20:28:02 +00:00
Use a shared env for desugaring and the rest of canonicalization
This refactor simplifies the desugar pass by reducing the number of arguments threaded through each recursive function call. - Add the module src string to `Env`. - Add `line_info` to `Env` as a lazy-evaled function. - Refactor desugar functions to take the `can::Env` struct in place of a number of params. This is mostly a find-and-replace, but in a few places `Vec::from_iter_in` was changed to `Vec::with_capacity_in` followed by a `for` loop in order to avoid lifetime issues. - Remove unnecessary linter annotations for `clippy::too_many_arguments`
This commit is contained in:
parent
640bd15ca1
commit
b515bfa77e
6 changed files with 349 additions and 880 deletions
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ use roc_collections::{MutMap, VecSet};
|
|||
use roc_module::ident::{Ident, ModuleName};
|
||||
use roc_module::symbol::{IdentIdsByModule, ModuleId, PQModuleName, PackageModuleIds, Symbol};
|
||||
use roc_problem::can::{Problem, RuntimeError};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_region::all::{LineInfo, Loc, Region};
|
||||
use roc_types::subs::Variable;
|
||||
|
||||
/// The canonicalization environment for a particular module.
|
||||
|
@ -44,11 +44,16 @@ pub struct Env<'a> {
|
|||
pub arena: &'a Bump,
|
||||
|
||||
pub opt_shorthand: Option<&'a str>,
|
||||
|
||||
pub src: &'a str,
|
||||
|
||||
line_info: &'a mut Option<LineInfo>,
|
||||
}
|
||||
|
||||
impl<'a> Env<'a> {
|
||||
pub fn new(
|
||||
arena: &'a Bump,
|
||||
src: &'a str,
|
||||
home: ModuleId,
|
||||
module_path: &'a Path,
|
||||
dep_idents: &'a IdentIdsByModule,
|
||||
|
@ -57,6 +62,7 @@ impl<'a> Env<'a> {
|
|||
) -> Env<'a> {
|
||||
Env {
|
||||
arena,
|
||||
src,
|
||||
home,
|
||||
module_path,
|
||||
dep_idents,
|
||||
|
@ -69,6 +75,7 @@ impl<'a> Env<'a> {
|
|||
top_level_symbols: VecSet::default(),
|
||||
home_params_record: None,
|
||||
opt_shorthand,
|
||||
line_info: arena.alloc(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,4 +226,14 @@ impl<'a> Env<'a> {
|
|||
pub fn problem(&mut self, problem: Problem) {
|
||||
self.problems.push(problem)
|
||||
}
|
||||
|
||||
/// Lazily calculate line_info only if required. This way it there are no
|
||||
/// `dbg` statements, we never pay the cast of scanning the source an extra
|
||||
/// time.
|
||||
pub fn line_info(&mut self) -> &LineInfo {
|
||||
if self.line_info.is_none() {
|
||||
*self.line_info = Some(LineInfo::new(self.src));
|
||||
}
|
||||
self.line_info.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -240,6 +240,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
);
|
||||
let mut env = Env::new(
|
||||
arena,
|
||||
src,
|
||||
home,
|
||||
arena.alloc(Path::new(module_path)),
|
||||
dep_idents,
|
||||
|
@ -266,16 +267,7 @@ 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(
|
||||
arena,
|
||||
&mut scope,
|
||||
loc_defs,
|
||||
src,
|
||||
&mut None,
|
||||
module_path,
|
||||
true,
|
||||
&mut env.problems,
|
||||
);
|
||||
crate::desugar::desugar_defs_node_values(&mut env, &mut scope, loc_defs, true);
|
||||
|
||||
let mut rigid_variables = RigidVariables::default();
|
||||
|
||||
|
|
|
@ -53,6 +53,17 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
|||
Default::default(),
|
||||
);
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let mut env = Env::new(
|
||||
arena,
|
||||
expr_str,
|
||||
home,
|
||||
Path::new("Test.roc"),
|
||||
&dep_idents,
|
||||
&qualified_module_ids,
|
||||
None,
|
||||
);
|
||||
|
||||
// Desugar operators (convert them to Apply calls, taking into account
|
||||
// operator precedence and associativity rules), before doing other canonicalization.
|
||||
//
|
||||
|
@ -60,15 +71,7 @@ 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(
|
||||
arena,
|
||||
&mut scope,
|
||||
&loc_expr,
|
||||
expr_str,
|
||||
&mut None,
|
||||
arena.alloc("TestPath"),
|
||||
&mut Default::default(),
|
||||
);
|
||||
let loc_expr = desugar::desugar_expr(&mut env, &mut scope, &loc_expr);
|
||||
|
||||
scope.add_alias(
|
||||
Symbol::NUM_INT,
|
||||
|
@ -82,15 +85,6 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
|||
roc_types::types::AliasKind::Structural,
|
||||
);
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let mut env = Env::new(
|
||||
arena,
|
||||
home,
|
||||
Path::new("Test.roc"),
|
||||
&dep_idents,
|
||||
&qualified_module_ids,
|
||||
None,
|
||||
);
|
||||
let (loc_expr, output) = canonicalize_expr(
|
||||
&mut env,
|
||||
&mut var_store,
|
||||
|
|
|
@ -6,32 +6,39 @@ mod suffixed_tests {
|
|||
use bumpalo::Bump;
|
||||
use insta::assert_snapshot;
|
||||
use roc_can::desugar::desugar_defs_node_values;
|
||||
use roc_can::env::Env;
|
||||
use roc_can::scope::Scope;
|
||||
use roc_module::symbol::{IdentIds, ModuleIds};
|
||||
use roc_module::symbol::{IdentIds, ModuleIds, PackageModuleIds};
|
||||
use roc_parse::test_helpers::parse_defs_with;
|
||||
use std::path::Path;
|
||||
|
||||
macro_rules! run_test {
|
||||
($src:expr) => {{
|
||||
let arena = &Bump::new();
|
||||
let home = ModuleIds::default().get_or_insert(&"Test".into());
|
||||
|
||||
let mut scope = Scope::new(
|
||||
home,
|
||||
"TestPath".into(),
|
||||
IdentIds::default(),
|
||||
Default::default(),
|
||||
);
|
||||
let mut defs = parse_defs_with(arena, indoc!($src)).unwrap();
|
||||
desugar_defs_node_values(
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let qualified_module_ids = PackageModuleIds::default();
|
||||
let mut env = Env::new(
|
||||
arena,
|
||||
&mut scope,
|
||||
&mut defs,
|
||||
$src,
|
||||
&mut None,
|
||||
"test.roc",
|
||||
true,
|
||||
&mut Default::default(),
|
||||
home,
|
||||
Path::new("test.roc"),
|
||||
&dep_idents,
|
||||
&qualified_module_ids,
|
||||
None,
|
||||
);
|
||||
|
||||
let mut defs = parse_defs_with(arena, indoc!($src)).unwrap();
|
||||
desugar_defs_node_values(&mut env, &mut scope, &mut defs, true);
|
||||
|
||||
let snapshot = format!("{:#?}", &defs);
|
||||
println!("{}", snapshot);
|
||||
assert_snapshot!(snapshot);
|
||||
|
|
|
@ -168,6 +168,17 @@ pub fn can_expr_with<'a>(
|
|||
Default::default(),
|
||||
);
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let mut env = Env::new(
|
||||
arena,
|
||||
expr_str,
|
||||
home,
|
||||
Path::new("Test.roc"),
|
||||
&dep_idents,
|
||||
&module_ids,
|
||||
None,
|
||||
);
|
||||
|
||||
// Desugar operators (convert them to Apply calls, taking into account
|
||||
// operator precedence and associativity rules), before doing other canonicalization.
|
||||
//
|
||||
|
@ -175,25 +186,8 @@ pub fn can_expr_with<'a>(
|
|||
// 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(
|
||||
arena,
|
||||
&mut scope,
|
||||
&loc_expr,
|
||||
expr_str,
|
||||
&mut None,
|
||||
arena.alloc("TestPath"),
|
||||
&mut Default::default(),
|
||||
);
|
||||
let loc_expr = desugar::desugar_expr(&mut env, &mut scope, &loc_expr);
|
||||
|
||||
let dep_idents = IdentIds::exposed_builtins(0);
|
||||
let mut env = Env::new(
|
||||
arena,
|
||||
home,
|
||||
Path::new("Test.roc"),
|
||||
&dep_idents,
|
||||
&module_ids,
|
||||
None,
|
||||
);
|
||||
let (loc_expr, output) = canonicalize_expr(
|
||||
&mut env,
|
||||
&mut var_store,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue