diff --git a/ast/src/canonicalization/module.rs b/ast/src/canonicalization/module.rs index 1e7fb78242..f0e71a4a4a 100644 --- a/ast/src/canonicalization/module.rs +++ b/ast/src/canonicalization/module.rs @@ -40,287 +40,3 @@ pub struct ModuleOutput { pub ident_ids: IdentIds, pub references: MutSet, } - -// TODO trim these down -#[allow(clippy::too_many_arguments)] -pub fn canonicalize_module_defs<'a>( - arena: &Bump, - loc_defs: &'a [Loc>], - home: ModuleId, - module_ids: &ModuleIds, - exposed_ident_ids: IdentIds, - dep_idents: IdentIdsByModule, - aliases: MutMap, - exposed_imports: MutMap, - mut exposed_symbols: MutSet, - var_store: &mut VarStore, -) -> Result { - let mut pool = Pool::with_capacity(1 << 10); - let mut can_exposed_imports = MutMap::default(); - let mut scope = Scope::new(home, &mut pool, var_store); - let num_deps = dep_idents.len(); - - for (name, alias) in aliases.into_iter() { - let vars = PoolVec::with_capacity(alias.targs.len() as u32, &mut pool); - - for (node_id, targ_id) in vars.iter_node_ids().zip(alias.targs.iter_node_ids()) { - let (poolstr, var) = &pool[targ_id]; - pool[node_id] = (poolstr.shallow_clone(), *var); - } - scope.add_alias(&mut pool, name, vars, alias.actual); - } - - // Desugar operators (convert them to Apply calls, taking into account - // operator precedence and associativity rules), before doing other canonicalization. - // - // If we did this *during* canonicalization, then each time we - // 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 mut desugared = - bumpalo::collections::Vec::with_capacity_in(loc_defs.len() + num_deps, arena); - - for loc_def in loc_defs.iter() { - desugared.push(&*arena.alloc(Loc { - value: desugar_def(arena, &loc_def.value), - region: loc_def.region, - })); - } - - let mut env = Env::new( - home, - arena, - &mut pool, - var_store, - dep_idents, - module_ids, - exposed_ident_ids, - ); - let mut lookups = Vec::with_capacity(num_deps); - let rigid_variables = MutMap::default(); - - // Exposed values are treated like defs that appear before any others, e.g. - // - // imports [Foo.{ bar, baz }] - // - // ...is basically the same as if we'd added these extra defs at the start of the module: - // - // bar = Foo.bar - // baz = Foo.baz - // - // Here we essentially add those "defs" to "the beginning of the module" - // by canonicalizing them right before we canonicalize the actual ast::Def nodes. - for (ident, (symbol, region)) in exposed_imports { - let first_char = ident.as_inline_str().chars().next().unwrap(); - - if first_char.is_lowercase() { - // this is a value definition - let expr_var = env.var_store.fresh(); - - match scope.import(ident, symbol, region) { - Ok(()) => { - // Add an entry to exposed_imports using the current module's name - // as the key; e.g. if this is the Foo module and we have - // exposes [Bar.{ baz }] then insert Foo.baz as the key, so when - // anything references `baz` in this Foo module, it will resolve to Bar.baz. - can_exposed_imports.insert(symbol, expr_var); - - // This will be used during constraint generation, - // to add the usual Lookup constraint as if this were a normal def. - lookups.push((symbol, expr_var, region)); - } - Err((_shadowed_symbol, _region)) => { - panic!("TODO gracefully handle shadowing in imports.") - } - } - } else { - // This is a type alias - - // the should already be added to the scope when this module is canonicalized - debug_assert!(scope.contains_alias(symbol)); - } - } - - let (defs, _scope, output, symbols_introduced) = canonicalize_defs( - &mut env, - Output::default(), - &scope, - &desugared, - PatternType::TopLevelDef, - ); - - // See if any of the new idents we defined went unused. - // If any were unused and also not exposed, report it. - for (symbol, region) in symbols_introduced { - if !output.references.has_lookup(symbol) && !exposed_symbols.contains(&symbol) { - env.problem(Problem::UnusedDef(symbol, region)); - } - } - - // TODO register rigids - // for (var, lowercase) in output.introduced_variables.name_by_var.clone() { - // rigid_variables.insert(var, lowercase); - // } - - let mut references = MutSet::default(); - - // Gather up all the symbols that were referenced across all the defs' lookups. - for symbol in output.references.lookups.iter() { - references.insert(*symbol); - } - - // Gather up all the symbols that were referenced across all the defs' calls. - for symbol in output.references.calls.iter() { - references.insert(*symbol); - } - - // Gather up all the symbols that were referenced from other modules. - for symbol in env.qualified_lookups.iter() { - references.insert(*symbol); - } - - // NOTE previously we inserted builtin defs into the list of defs here - // this is now done later, in file.rs. - - match sort_can_defs(&mut env, defs, Output::default()) { - (Ok(mut declarations), output) => { - use Declaration::*; - - for decl in declarations.iter() { - match decl { - Declare(def) => { - for symbol in def.symbols(env.pool) { - if exposed_symbols.contains(&symbol) { - // Remove this from exposed_symbols, - // so that at the end of the process, - // we can see if there were any - // exposed symbols which did not have - // corresponding defs. - exposed_symbols.remove(&symbol); - } - } - } - DeclareRec(defs) => { - for def in defs { - for symbol in def.symbols(env.pool) { - if exposed_symbols.contains(&symbol) { - // Remove this from exposed_symbols, - // so that at the end of the process, - // we can see if there were any - // exposed symbols which did not have - // corresponding defs. - exposed_symbols.remove(&symbol); - } - } - } - } - - InvalidCycle(identifiers, _) => { - panic!("TODO gracefully handle potentially attempting to expose invalid cyclic defs {:?}" , identifiers); - } - Builtin(def) => { - // Builtins cannot be exposed in module declarations. - // This should never happen! - debug_assert!(def - .symbols(env.pool) - .iter() - .all(|symbol| !exposed_symbols.contains(symbol))); - } - } - } - - let mut aliases = MutMap::default(); - - for (symbol, alias) in output.aliases { - // Remove this from exposed_symbols, - // so that at the end of the process, - // we can see if there were any - // exposed symbols which did not have - // corresponding defs. - exposed_symbols.remove(&symbol); - - aliases.insert(symbol, alias); - } - - // By this point, all exposed symbols should have been removed from - // exposed_symbols and added to exposed_vars_by_symbol. If any were - // not, that means they were declared as exposed but there was - // no actual declaration with that name! - for symbol in exposed_symbols { - env.problem(Problem::ExposedButNotDefined(symbol)); - - // In case this exposed value is referenced by other modules, - // create a decl for it whose implementation is a runtime error. - let mut pattern_vars = SendMap::default(); - pattern_vars.insert(symbol, env.var_store.fresh()); - - let runtime_error = RuntimeError::ExposedButNotDefined(symbol); - - let value_def = { - let pattern_id = env.pool.add(Pattern2::Identifier(symbol)); - let expr_id = env.pool.add(Expr2::RuntimeError()); - ValueDef::NoAnnotation { - pattern_id, - expr_id, - expr_var: env.var_store.fresh(), - } - }; - - let def = Def::Value(value_def); - - declarations.push(Declaration::Declare(def)); - } - - // Incorporate any remaining output.lookups entries into references. - for symbol in output.references.lookups { - references.insert(symbol); - } - - // Incorporate any remaining output.calls entries into references. - for symbol in output.references.calls { - references.insert(symbol); - } - - // Gather up all the symbols that were referenced from other modules. - for symbol in env.qualified_lookups.iter() { - references.insert(*symbol); - } - - // TODO find captured variables - // for declaration in declarations.iter_mut() { - // match declaration { - // Declare(def) => fix_values_captured_in_closure_def(def, &mut MutSet::default()), - // DeclareRec(defs) => { - // fix_values_captured_in_closure_defs(defs, &mut MutSet::default()) - // } - // InvalidCycle(_, _) | Builtin(_) => {} - // } - // } - - // TODO this loops over all symbols in the module, we can speed it up by having an - // iterator over all builtin symbols - - // TODO move over the builtins - // for symbol in references.iter() { - // if symbol.is_builtin() { - // // this can fail when the symbol is for builtin types, or has no implementation yet - // if let Some(def) = builtins::builtin_defs_map(*symbol, var_store) { - // declarations.push(Declaration::Builtin(def)); - // } - // } - // } - - Ok(ModuleOutput { - aliases, - rigid_variables, - declarations, - references, - exposed_imports: can_exposed_imports, - problems: vec![], // TODO env.problems, - lookups, - ident_ids: env.ident_ids, - }) - } - (Err(runtime_error), _) => Err(runtime_error), - } -} diff --git a/ast/src/lang/core/def/def.rs b/ast/src/lang/core/def/def.rs index 5ade55dcd0..16db18cd08 100644 --- a/ast/src/lang/core/def/def.rs +++ b/ast/src/lang/core/def/def.rs @@ -16,7 +16,7 @@ use roc_collections::all::{default_hasher, ImMap, MutMap, MutSet, SendMap}; use roc_error_macros::{todo_abilities, todo_opaques}; use roc_module::ident::Lowercase; use roc_module::symbol::Symbol; -use roc_parse::ast::{self, TypeDef, TypeHeader, ValueDef as AstValueDef}; +use roc_parse::ast::{self, Defs, TypeDef, TypeHeader, ValueDef as AstValueDef}; use roc_parse::pattern::PatternType; use roc_problem::can::{Problem, RuntimeError, ShadowKind}; use roc_region::all::{Loc, Region}; @@ -791,7 +791,7 @@ pub fn canonicalize_defs<'a>( env: &mut Env<'a>, mut output: Output, original_scope: &Scope, - loc_defs: &'a [&'a Loc>], + loc_defs: &'a Defs<'a>, pattern_type: PatternType, ) -> (CanDefs, Scope, Output, MutMap) { // Canonicalizing defs while detecting shadowing involves a multi-step process: @@ -822,8 +822,13 @@ pub fn canonicalize_defs<'a>( // Canonicalize all the patterns, record shadowing problems, and store // the ast::Expr values in pending_exprs for further canonicalization // once we've finished assembling the entire scope. - for loc_def in loc_defs { - match to_pending_def(env, &loc_def.value, &mut scope, pattern_type) { + for loc_def in loc_defs.defs() { + let def = match loc_def { + Ok(type_def) => roc_parse::ast::Def::Type(type_def.clone()), + Err(value_def) => roc_parse::ast::Def::Value(value_def.clone()), + }; + + match to_pending_def(env, env.arena.alloc(def), &mut scope, pattern_type) { None => (), Some((new_output, pending_def)) => { // store the top-level defs, used to ensure that closures won't capture them diff --git a/ast/src/lang/core/def/def_to_def2.rs b/ast/src/lang/core/def/def_to_def2.rs index 2e94b657ac..5106931693 100644 --- a/ast/src/lang/core/def/def_to_def2.rs +++ b/ast/src/lang/core/def/def_to_def2.rs @@ -1,4 +1,3 @@ -use bumpalo::collections::Vec as BumpVec; use bumpalo::Bump; use roc_parse::{ast::CommentOrNewline, parser::SyntaxError}; use roc_region::all::Region; @@ -90,19 +89,6 @@ pub fn toplevel_defs_to_defs2<'a>( result } -pub fn defs_to_defs2<'a>( - arena: &'a Bump, - env: &mut Env<'a>, - scope: &mut Scope, - parsed_defs: &'a BumpVec>>, - region: Region, -) -> Vec { - parsed_defs - .iter() - .map(|loc| def_to_def2(arena, env, scope, &loc.value, region)) - .collect() -} - pub fn def_to_def2<'a>( arena: &'a Bump, env: &mut Env<'a>, @@ -201,13 +187,7 @@ pub fn str_to_def2<'a>( region: Region, ) -> Result, SyntaxError<'a>> { match roc_parse::test_helpers::parse_defs_with(arena, input.trim()) { - Ok(vec_loc_def) => Ok(defs_to_defs2( - arena, - env, - scope, - arena.alloc(vec_loc_def), - region, - )), + Ok(defs) => Ok(toplevel_defs_to_defs2(arena, env, scope, defs, region)), Err(fail) => Err(fail), } } diff --git a/cli/src/format.rs b/cli/src/format.rs index 5a04bfa17a..844a2ae2b5 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use crate::FormatMode; use bumpalo::Bump; use roc_error_macros::{internal_error, user_error}; -use roc_fmt::def::fmt_toplevel_defs; +use roc_fmt::def::fmt_defs; use roc_fmt::module::fmt_module; use roc_fmt::spaces::RemoveSpaces; use roc_fmt::{Ast, Buf}; @@ -166,7 +166,7 @@ fn parse_all<'a>(arena: &'a Bump, src: &'a str) -> Result, SyntaxError<' fn fmt_all<'a>(buf: &mut Buf<'a>, ast: &'a Ast) { fmt_module(buf, &ast.module); - fmt_toplevel_defs(buf, &ast.defs, 0); + fmt_defs(buf, &ast.defs, 0); buf.fmt_end_of_file(); } diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index 3b101bae76..a22ccc5624 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -25,6 +25,7 @@ use roc_module::symbol::ModuleId; use roc_module::symbol::Symbol; use roc_parse::ast; use roc_parse::ast::AbilityMember; +use roc_parse::ast::Defs; use roc_parse::ast::ExtractSpaces; use roc_parse::ast::TypeHeader; use roc_parse::pattern::PatternType; @@ -457,72 +458,6 @@ fn canonicalize_opaque<'a>( #[inline(always)] pub(crate) fn canonicalize_defs<'a>( - env: &mut Env<'a>, - mut output: Output, - var_store: &mut VarStore, - scope: &mut Scope, - loc_defs: &'a [&'a Loc>], - pattern_type: PatternType, -) -> (CanDefs, Output, MutMap) { - // Canonicalizing defs while detecting shadowing involves a multi-step process: - // - // 1. Go through each of the patterns. - // 2. For each identifier pattern, get the scope.symbol() for the ident. (That symbol will use the home module for its module.) - // 3. If that symbol is already in scope, then we're about to shadow it. Error! - // 4. Otherwise, add it to the scope immediately, so we can detect shadowing within the same - // pattern (e.g. (Foo a a) = ...) - // 5. Add this canonicalized pattern and its corresponding ast::Expr to pending_exprs. - // 5. Once every pattern has been processed and added to scope, go back and canonicalize the exprs from - // pending_exprs, this time building up a canonical def for each one. - // - // This way, whenever any expr is doing lookups, it knows everything that's in scope - - // even defs that appear after it in the source. - // - // This naturally handles recursion too, because a given expr which refers - // to itself won't be processed until after its def has been added to scope. - - let num_defs = loc_defs.len(); - let mut pending_type_defs = Vec::with_capacity(num_defs); - let mut value_defs = Vec::with_capacity(num_defs); - - for loc_def in loc_defs { - match loc_def.value.unroll_def() { - Ok(type_def) => { - pending_type_defs.push(to_pending_type_def(env, type_def, scope, pattern_type)) - } - Err(value_def) => value_defs.push(Loc::at(loc_def.region, value_def)), - } - } - - if cfg!(debug_assertions) { - scope.register_debug_idents(); - } - - let (aliases, symbols_introduced) = canonicalize_type_defs( - env, - &mut output, - var_store, - scope, - pending_type_defs, - pattern_type, - ); - - // Now that we have the scope completely assembled, and shadowing resolved, - // we're ready to canonicalize any body exprs. - canonicalize_value_defs( - env, - output, - var_store, - scope, - &value_defs, - pattern_type, - aliases, - symbols_introduced, - ) -} - -#[inline(always)] -pub(crate) fn canonicalize_toplevel_defs<'a>( env: &mut Env<'a>, mut output: Output, var_store: &mut VarStore, @@ -1577,7 +1512,7 @@ pub fn can_defs_with_return<'a>( env: &mut Env<'a>, var_store: &mut VarStore, scope: &mut Scope, - loc_defs: &'a [&'a Loc>], + loc_defs: &'a mut Defs<'a>, loc_ret: &'a Loc>, ) -> (Expr, Output) { let (unsorted, defs_output, symbols_introduced) = canonicalize_defs( diff --git a/compiler/can/src/env.rs b/compiler/can/src/env.rs index 861afd16a9..b8b7250501 100644 --- a/compiler/can/src/env.rs +++ b/compiler/can/src/env.rs @@ -1,5 +1,6 @@ use crate::procedure::References; use crate::scope::Scope; +use bumpalo::Bump; use roc_collections::{MutMap, VecSet}; use roc_module::ident::{Ident, Lowercase, ModuleName}; use roc_module::symbol::{IdentIdsByModule, ModuleId, ModuleIds, Symbol}; @@ -32,15 +33,19 @@ pub struct Env<'a> { pub qualified_type_lookups: VecSet, pub top_level_symbols: VecSet, + + pub arena: &'a Bump, } impl<'a> Env<'a> { pub fn new( + arena: &'a Bump, home: ModuleId, dep_idents: &'a IdentIdsByModule, module_ids: &'a ModuleIds, ) -> Env<'a> { Env { + arena, home, dep_idents, module_ids, diff --git a/compiler/can/src/expr.rs b/compiler/can/src/expr.rs index 6dab856969..886e9a4875 100644 --- a/compiler/can/src/expr.rs +++ b/compiler/can/src/expr.rs @@ -15,7 +15,7 @@ use roc_module::called_via::CalledVia; use roc_module::ident::{ForeignSymbol, Lowercase, TagName}; use roc_module::low_level::LowLevel; use roc_module::symbol::Symbol; -use roc_parse::ast::{self, EscapedChar, StrLiteral}; +use roc_parse::ast::{self, Defs, EscapedChar, StrLiteral}; use roc_parse::pattern::PatternType::*; use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError}; use roc_region::all::{Loc, Region}; @@ -728,7 +728,8 @@ pub fn canonicalize_expr<'a>( ast::Expr::Defs(loc_defs, loc_ret) => { // The body expression gets a new scope for canonicalization, scope.inner_scope(|inner_scope| { - can_defs_with_return(env, var_store, inner_scope, loc_defs, loc_ret) + let defs: Defs = (*loc_defs).clone(); + can_defs_with_return(env, var_store, inner_scope, env.arena.alloc(defs), loc_ret) }) } ast::Expr::Backpassing(_, _, _) => { diff --git a/compiler/can/src/module.rs b/compiler/can/src/module.rs index 53171ea9ff..b25e5d49ea 100644 --- a/compiler/can/src/module.rs +++ b/compiler/can/src/module.rs @@ -1,10 +1,10 @@ use crate::abilities::PendingAbilitiesStore; use crate::annotation::canonicalize_annotation; -use crate::def::{canonicalize_toplevel_defs, sort_can_defs, Declaration, Def}; +use crate::def::{canonicalize_defs, sort_can_defs, Declaration, Def}; use crate::effect_module::HostedGeneratedFunctions; use crate::env::Env; use crate::expr::{ClosureData, Expr, Output, PendingDerives}; -use crate::operator::desugar_toplevel_defs; +use crate::operator::desugar_defs; use crate::pattern::Pattern; use crate::scope::Scope; use bumpalo::Bump; @@ -175,7 +175,7 @@ pub fn canonicalize_module_defs<'a>( ) -> ModuleOutput { let mut can_exposed_imports = MutMap::default(); let mut scope = Scope::new(home, exposed_ident_ids, imported_abilities_state); - let mut env = Env::new(home, dep_idents, module_ids); + let mut env = Env::new(arena, home, dep_idents, module_ids); let num_deps = dep_idents.len(); for (name, alias) in aliases.into_iter() { @@ -198,7 +198,7 @@ pub fn canonicalize_module_defs<'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. - desugar_toplevel_defs(arena, loc_defs); + desugar_defs(arena, loc_defs); let mut lookups = Vec::with_capacity(num_deps); let mut rigid_variables = RigidVariables::default(); @@ -274,7 +274,7 @@ pub fn canonicalize_module_defs<'a>( } } - let (defs, output, symbols_introduced) = canonicalize_toplevel_defs( + let (defs, output, symbols_introduced) = canonicalize_defs( &mut env, Output::default(), var_store, diff --git a/compiler/can/src/operator.rs b/compiler/can/src/operator.rs index 5dafc42c5f..40b454f76b 100644 --- a/compiler/can/src/operator.rs +++ b/compiler/can/src/operator.rs @@ -63,31 +63,6 @@ fn new_op_call_expr<'a>( Loc { region, value } } -fn desugar_def_helps<'a>( - arena: &'a Bump, - region: Region, - defs: &'a [&'a Loc>], - loc_ret: &'a Loc>, -) -> &'a Loc> { - let mut desugared_defs = Vec::with_capacity_in(defs.len(), arena); - - for loc_def in defs.iter() { - let loc_def = Loc { - value: desugar_def(arena, &loc_def.value), - region: loc_def.region, - }; - - desugared_defs.push(&*arena.alloc(loc_def)); - } - - let desugared_defs = desugared_defs.into_bump_slice(); - - arena.alloc(Loc { - value: Defs(desugared_defs, desugar_expr(arena, loc_ret)), - region, - }) -} - fn desugar_type_def<'a>(def: &'a TypeDef<'a>) -> TypeDef<'a> { use TypeDef::*; @@ -135,7 +110,7 @@ pub fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>) -> Def<'a> { } } -pub fn desugar_toplevel_defs<'a>(arena: &'a Bump, defs: &mut roc_parse::ast::Defs<'a>) { +pub fn desugar_defs<'a>(arena: &'a Bump, defs: &mut roc_parse::ast::Defs<'a>) { for value_def in defs.value_defs.iter_mut() { *value_def = desugar_value_def(arena, arena.alloc(*value_def)); } @@ -257,7 +232,14 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc>) -> &'a Loc } } BinOps(lefts, right) => desugar_bin_ops(arena, loc_expr.region, lefts, right), - Defs(defs, loc_ret) => desugar_def_helps(arena, loc_expr.region, *defs, loc_ret), + Defs(defs, loc_ret) => { + let mut defs = (*defs).clone(); + desugar_defs(arena, &mut defs); + + let loc_ret = desugar_expr(arena, loc_ret); + + arena.alloc(Loc::at(loc_expr.region, Defs(arena.alloc(defs), loc_ret))) + } Apply(loc_fn, loc_args, called_via) => { let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena); diff --git a/compiler/can/tests/helpers/mod.rs b/compiler/can/tests/helpers/mod.rs index 04903b266e..626517d498 100644 --- a/compiler/can/tests/helpers/mod.rs +++ b/compiler/can/tests/helpers/mod.rs @@ -68,7 +68,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut ); let dep_idents = IdentIds::exposed_builtins(0); - let mut env = Env::new(home, &dep_idents, &module_ids); + let mut env = Env::new(arena, home, &dep_idents, &module_ids); let (loc_expr, output) = canonicalize_expr( &mut env, &mut var_store, diff --git a/compiler/fmt/src/def.rs b/compiler/fmt/src/def.rs index 02fcbc1394..c96c223973 100644 --- a/compiler/fmt/src/def.rs +++ b/compiler/fmt/src/def.rs @@ -348,10 +348,6 @@ fn fmt_expect<'a, 'buf>( condition.format(buf, return_indent); } -pub fn fmt_def<'a, 'buf>(buf: &mut Buf<'buf>, def: &Def<'a>, indent: u16) { - def.format(buf, indent); -} - pub fn fmt_value_def<'a, 'buf>( buf: &mut Buf<'buf>, def: &roc_parse::ast::ValueDef<'a>, @@ -364,7 +360,7 @@ pub fn fmt_type_def<'a, 'buf>(buf: &mut Buf<'buf>, def: &roc_parse::ast::TypeDef def.format(buf, indent); } -pub fn fmt_toplevel_defs<'a, 'buf>(buf: &mut Buf<'buf>, defs: &Defs<'a>, indent: u16) { +pub fn fmt_defs<'a, 'buf>(buf: &mut Buf<'buf>, defs: &Defs<'a>, indent: u16) { defs.format(buf, indent); } diff --git a/compiler/fmt/src/expr.rs b/compiler/fmt/src/expr.rs index d8befe4d2f..61b8f1e1a2 100644 --- a/compiler/fmt/src/expr.rs +++ b/compiler/fmt/src/expr.rs @@ -1,6 +1,6 @@ use crate::annotation::{Formattable, Newlines, Parens}; use crate::collection::{fmt_collection, Braces}; -use crate::def::fmt_def; +use crate::def::fmt_defs; use crate::pattern::fmt_pattern; use crate::spaces::{count_leading_newlines, fmt_comments_only, fmt_spaces, NewlineAt, INDENT}; use crate::Buf; @@ -325,9 +325,7 @@ impl<'a> Formattable for Expr<'a> { // (Canonicalization can remove defs later, but that hasn't happened yet!) debug_assert!(!defs.is_empty()); - for loc_def in defs.iter() { - fmt_def(buf, &loc_def.value, indent); - } + fmt_defs(buf, defs, indent); match &ret.value { SpaceBefore(sub_expr, spaces) => { diff --git a/compiler/fmt/src/spaces.rs b/compiler/fmt/src/spaces.rs index 5752777dd3..f3b7e72dc0 100644 --- a/compiler/fmt/src/spaces.rs +++ b/compiler/fmt/src/spaces.rs @@ -617,7 +617,21 @@ impl<'a> RemoveSpaces<'a> for Expr<'a> { arena.alloc(b.remove_spaces(arena)), ), Expr::Defs(a, b) => { - Expr::Defs(a.remove_spaces(arena), arena.alloc(b.remove_spaces(arena))) + let mut defs = a.clone(); + defs.space_before = vec![Default::default(); defs.len()]; + defs.space_after = vec![Default::default(); defs.len()]; + defs.regions = vec![Region::zero(); defs.len()]; + defs.spaces.clear(); + + for type_def in defs.type_defs.iter_mut() { + *type_def = type_def.remove_spaces(arena); + } + + for value_def in defs.value_defs.iter_mut() { + *value_def = value_def.remove_spaces(arena); + } + + Expr::Defs(arena.alloc(defs), arena.alloc(b.remove_spaces(arena))) } Expr::Backpassing(a, b, c) => Expr::Backpassing( arena.alloc(a.remove_spaces(arena)), diff --git a/compiler/fmt/tests/test_fmt.rs b/compiler/fmt/tests/test_fmt.rs index 8ca31cf62b..795741b91f 100644 --- a/compiler/fmt/tests/test_fmt.rs +++ b/compiler/fmt/tests/test_fmt.rs @@ -7,7 +7,7 @@ extern crate roc_fmt; mod test_fmt { use bumpalo::Bump; use roc_fmt::annotation::{Formattable, Newlines, Parens}; - use roc_fmt::def::fmt_toplevel_defs; + use roc_fmt::def::fmt_defs; use roc_fmt::module::fmt_module; use roc_fmt::Buf; use roc_parse::ast::Module; @@ -88,7 +88,7 @@ mod test_fmt { match module_defs().parse(arena, state) { Ok((_, loc_defs, _)) => { - fmt_toplevel_defs(buf, &loc_defs, 0); + fmt_defs(buf, &loc_defs, 0); } Err(error) => panic!( r"Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", diff --git a/compiler/parse/src/ast.rs b/compiler/parse/src/ast.rs index 6ba4a5b509..89949c4426 100644 --- a/compiler/parse/src/ast.rs +++ b/compiler/parse/src/ast.rs @@ -197,7 +197,7 @@ pub enum Expr<'a> { // Pattern Matching Closure(&'a [Loc>], &'a Loc>), /// Multiple defs in a row - Defs(&'a [&'a Loc>], &'a Loc>), + Defs(&'a Defs<'a>, &'a Loc>), Backpassing(&'a [Loc>], &'a Loc>, &'a Loc>), Expect(&'a Loc>, &'a Loc>), @@ -346,6 +346,14 @@ pub struct Defs<'a> { } impl<'a> Defs<'a> { + pub fn is_empty(&self) -> bool { + self.tags.is_empty() + } + + pub fn len(&self) -> usize { + self.tags.len() + } + pub fn defs(&self) -> impl Iterator, &ValueDef<'a>>> { self.tags.iter().map(|tag| match tag.split() { Ok(type_index) => Ok(&self.type_defs[type_index.index()]), diff --git a/compiler/parse/src/expr.rs b/compiler/parse/src/expr.rs index 20e2ce0ef4..df3c001bf4 100644 --- a/compiler/parse/src/expr.rs +++ b/compiler/parse/src/expr.rs @@ -568,251 +568,7 @@ fn numeric_negate_expression<'a, T>( } } -fn append_body_definition<'a>( - arena: &'a Bump, - defs: &mut Vec<'a, &'a Loc>>, - spaces: &'a [CommentOrNewline<'a>], - loc_pattern: Loc>, - loc_def_body: Loc>, -) { - let region = Region::span_across(&loc_pattern.region, &loc_def_body.region); - - if spaces.len() <= 1 { - let last = defs.pop(); - match last.map(|d| d.value.unroll_spaces_before()) { - Some((before_ann_spaces, Def::Value(ValueDef::Annotation(ann_pattern, ann_type)))) => { - return append_body_definition_help( - arena, - defs, - region, - before_ann_spaces, - spaces, - loc_pattern, - loc_def_body, - ann_pattern, - ann_type, - ); - } - Some(( - before_ann_spaces, - Def::Type(TypeDef::Alias { - header, - ann: ann_type, - }), - )) => { - // This is a case like - // UserId x : [UserId Int] - // UserId x = UserId 42 - // We optimistically parsed the first line as an alias; we now turn it - // into an annotation. - let loc_name = arena.alloc(header.name.map(|x| Pattern::Tag(x))); - let ann_pattern = Pattern::Apply(loc_name, header.vars); - let vars_region = Region::across_all(header.vars.iter().map(|v| &v.region)); - let region_ann_pattern = Region::span_across(&loc_name.region, &vars_region); - let loc_ann_pattern = Loc::at(region_ann_pattern, ann_pattern); - - return append_body_definition_help( - arena, - defs, - region, - before_ann_spaces, - spaces, - loc_pattern, - loc_def_body, - arena.alloc(loc_ann_pattern), - ann_type, - ); - } - _ => { - defs.extend(last); - } - } - } - - // the previous and current def can't be joined up - let mut loc_def = Loc::at( - region, - Def::Value(ValueDef::Body( - arena.alloc(loc_pattern), - &*arena.alloc(loc_def_body), - )), - ); - - if !spaces.is_empty() { - loc_def = arena - .alloc(loc_def.value) - .with_spaces_before(spaces, loc_def.region); - } - - defs.push(arena.alloc(loc_def)); -} - -#[allow(clippy::too_many_arguments)] -fn append_body_definition_help<'a>( - arena: &'a Bump, - defs: &mut Vec<'a, &'a Loc>>, - region: Region, - before_ann_spaces: &'a [CommentOrNewline<'a>], - before_body_spaces: &'a [CommentOrNewline<'a>], - loc_pattern_body: Loc>, - loc_def_body: Loc>, - loc_pattern_ann: &'a Loc>, - loc_ann: &'a Loc>, -) { - let comment = match before_body_spaces.get(0) { - Some(CommentOrNewline::LineComment(s)) => Some(*s), - Some(CommentOrNewline::DocComment(s)) => Some(*s), - _ => None, - }; - - let mut loc_def = Loc::at( - region, - Def::Value(ValueDef::AnnotatedBody { - ann_pattern: loc_pattern_ann, - ann_type: loc_ann, - comment, - body_pattern: arena.alloc(loc_pattern_body), - body_expr: &*arena.alloc(loc_def_body), - }), - ); - - if !before_ann_spaces.is_empty() { - loc_def = arena - .alloc(loc_def.value) - .with_spaces_before(before_ann_spaces, loc_def.region); - } - - defs.push(arena.alloc(loc_def)); -} - -fn append_annotation_definition<'a>( - arena: &'a Bump, - defs: &mut Vec<'a, &'a Loc>>, - spaces: &'a [CommentOrNewline<'a>], - loc_pattern: Loc>, - loc_ann: Loc>, - - // If this turns out to be an alias - kind: AliasOrOpaque, - opt_derived: Option>>, -) { - let region = Region::span_across(&loc_pattern.region, &loc_ann.region); - - // the previous and current def can't be joined up - match &loc_pattern.value { - Pattern::Apply( - Loc { - value: Pattern::Tag(name), - .. - }, - alias_arguments, - ) => append_alias_or_opaque_definition( - arena, - defs, - region, - spaces, - Loc::at(loc_pattern.region, name), - alias_arguments, - loc_ann, - kind, - opt_derived, - ), - Pattern::Tag(name) => append_alias_or_opaque_definition( - arena, - defs, - region, - spaces, - Loc::at(loc_pattern.region, name), - &[], - loc_ann, - kind, - opt_derived, - ), - _ => { - let mut loc_def = Loc::at( - region, - Def::Value(ValueDef::Annotation(loc_pattern, loc_ann)), - ); - if !spaces.is_empty() { - loc_def = arena - .alloc(loc_def.value) - .with_spaces_before(spaces, loc_def.region); - } - - defs.push(arena.alloc(loc_def)); - } - } -} - -fn append_expect_definition<'a>( - arena: &'a Bump, - defs: &mut Vec<'a, &'a Loc>>, - start: Position, - spaces: &'a [CommentOrNewline<'a>], - loc_expect_body: Loc>, -) { - let def: Def = ValueDef::Expect(arena.alloc(loc_expect_body)).into(); - - let end = loc_expect_body.region.end(); - let region = Region::new(start, end); - - let mut loc_def = Loc::at(region, def); - - if !spaces.is_empty() { - loc_def = arena - .alloc(loc_def.value) - .with_spaces_before(spaces, loc_def.region); - } - - defs.push(arena.alloc(loc_def)); -} - -#[allow(clippy::too_many_arguments)] -fn append_alias_or_opaque_definition<'a>( - arena: &'a Bump, - defs: &mut Vec<'a, &'a Loc>>, - region: Region, - spaces: &'a [CommentOrNewline<'a>], - name: Loc<&'a str>, - pattern_arguments: &'a [Loc>], - loc_ann: Loc>, - kind: AliasOrOpaque, - opt_derived: Option>>, -) { - let header = TypeHeader { - name, - vars: pattern_arguments, - }; - - let type_def = match kind { - AliasOrOpaque::Alias => TypeDef::Alias { - header, - ann: loc_ann, - }, - AliasOrOpaque::Opaque => TypeDef::Opaque { - header, - typ: loc_ann, - derived: opt_derived, - }, - }; - let mut loc_def = Loc::at(region, Def::Type(type_def)); - - if !spaces.is_empty() { - loc_def = arena - .alloc(loc_def.value) - .with_spaces_before(spaces, loc_def.region); - } - - defs.push(arena.alloc(loc_def)); -} - -#[derive(Debug)] -struct DefState<'a> { - defs: Vec<'a, &'a Loc>>, - spaces_after: &'a [CommentOrNewline<'a>], -} - -fn parse_toplevel_defs_end<'a>( +fn parse_defs_end<'a>( _options: ExprParseOptions, start_column: u32, mut defs: Defs<'a>, @@ -1143,175 +899,16 @@ fn parse_toplevel_defs_end<'a>( } } -fn parse_defs_end<'a>( - options: ExprParseOptions, - start_column: u32, - mut def_state: DefState<'a>, - arena: &'a Bump, - state: State<'a>, -) -> ParseResult<'a, DefState<'a>, EExpr<'a>> { - let min_indent = start_column; - let initial = state.clone(); - - let state = match space0_e(min_indent, EExpr::IndentStart).parse(arena, state) { - Err((MadeProgress, _, s)) => { - return Err((MadeProgress, EExpr::DefMissingFinalExpr(s.pos()), s)); - } - Ok((_, spaces, state)) => { - def_state.spaces_after = spaces; - state - } - Err((NoProgress, _, state)) => state, - }; - - let start = state.pos(); - let column = state.column(); - - match space0_after_e( - crate::pattern::loc_pattern_help(min_indent), - min_indent, - EPattern::IndentEnd, - ) - .parse(arena, state.clone()) - { - Err((NoProgress, _, _)) => { - match crate::parser::keyword_e(crate::keyword::EXPECT, EExpect::Expect) - .parse(arena, state) - { - Err((_, _, _)) => { - // a hacky way to get expression-based error messages. TODO fix this - Ok((NoProgress, def_state, initial)) - } - Ok((_, _, state)) => { - let parse_def_expr = space0_before_e( - move |a, s| parse_loc_expr(min_indent + 1, a, s), - min_indent, - EExpr::IndentEnd, - ); - - let (_, loc_def_expr, state) = parse_def_expr.parse(arena, state)?; - - append_expect_definition( - arena, - &mut def_state.defs, - start, - def_state.spaces_after, - loc_def_expr, - ); - - parse_defs_end(options, column, def_state, arena, state) - } - } - } - Err((MadeProgress, _, _)) => { - // a hacky way to get expression-based error messages. TODO fix this - Ok((NoProgress, def_state, initial)) - } - Ok((_, loc_pattern, state)) => { - // First let's check whether this is an ability definition. - let opt_tag_and_args: Option<(&str, Region, &[Loc])> = match loc_pattern.value - { - Pattern::Apply( - Loc { - value: Pattern::Tag(name), - region, - }, - args, - ) => Some((name, *region, args)), - Pattern::Tag(name) => Some((name, loc_pattern.region, &[])), - _ => None, - }; - - if let Some((name, name_region, args)) = opt_tag_and_args { - if let Ok((_, loc_has, state)) = - loc_has_parser(min_indent).parse(arena, state.clone()) - { - let (_, loc_def, state) = finish_parsing_ability_def( - start_column, - Loc::at(name_region, name), - args, - loc_has, - def_state.spaces_after, - arena, - state, - )?; - - def_state.defs.push(loc_def); - - return parse_defs_end(options, column, def_state, arena, state); - } - } - - // Otherwise, this is a def or alias. - match operator().parse(arena, state) { - Ok((_, BinOp::Assignment, state)) => { - let parse_def_expr = space0_before_e( - move |a, s| parse_loc_expr(min_indent + 1, a, s), - min_indent, - EExpr::IndentEnd, - ); - - let (_, loc_def_expr, state) = parse_def_expr.parse(arena, state)?; - - append_body_definition( - arena, - &mut def_state.defs, - def_state.spaces_after, - loc_pattern, - loc_def_expr, - ); - - parse_defs_end(options, column, def_state, arena, state) - } - Ok((_, BinOp::IsAliasType, state)) => { - let (_, ann_type, state) = - alias_signature_with_space_before(min_indent + 1).parse(arena, state)?; - - append_annotation_definition( - arena, - &mut def_state.defs, - def_state.spaces_after, - loc_pattern, - ann_type, - AliasOrOpaque::Alias, - None, - ); - - parse_defs_end(options, column, def_state, arena, state) - } - Ok((_, BinOp::IsOpaqueType, state)) => { - let (_, (signature, derived), state) = - opaque_signature_with_space_before(min_indent + 1).parse(arena, state)?; - - append_annotation_definition( - arena, - &mut def_state.defs, - def_state.spaces_after, - loc_pattern, - signature, - AliasOrOpaque::Opaque, - derived, - ); - - parse_defs_end(options, column, def_state, arena, state) - } - - _ => Ok((MadeProgress, def_state, initial)), - } - } - } -} - fn parse_defs_expr<'a>( options: ExprParseOptions, start_column: u32, - def_state: DefState<'a>, + defs: Defs<'a>, arena: &'a Bump, state: State<'a>, ) -> ParseResult<'a, Expr<'a>, EExpr<'a>> { let min_indent = start_column; - match parse_defs_end(options, start_column, def_state, arena, state) { + match parse_defs_end(options, start_column, defs, arena, state) { Err(bad) => Err(bad), Ok((_, def_state, state)) => { // this is no def, because there is no `=` or `:`; parse as an expr @@ -1332,7 +929,7 @@ fn parse_defs_expr<'a>( Ok((_, loc_ret, state)) => { return Ok(( MadeProgress, - Expr::Defs(def_state.defs.into_bump_slice(), arena.alloc(loc_ret)), + Expr::Defs(arena.alloc(def_state), arena.alloc(loc_ret)), state, )); } @@ -1505,12 +1102,17 @@ fn finish_parsing_alias_or_opaque<'a>( } }; - let def_state = DefState { - defs: bumpalo::vec![in arena; loc_def], - spaces_after: &[], - }; + let mut defs = Defs::default(); - parse_defs_expr(options, start_column, def_state, arena, state) + match loc_def.value { + Def::Type(type_def) => defs.push_type_def(type_def, loc_def.region, &[], &[]), + Def::Value(value_def) => defs.push_value_def(value_def, loc_def.region, &[], &[]), + Def::SpaceBefore(_, _) => todo!(), + Def::SpaceAfter(_, _) => todo!(), + Def::NotYetImplemented(_) => todo!(), + } + + parse_defs_expr(options, start_column, defs, arena, state) } mod ability { @@ -1632,33 +1234,6 @@ mod ability { } } -fn finish_parsing_ability_def<'a>( - start_column: u32, - name: Loc<&'a str>, - args: &'a [Loc>], - loc_has: Loc>, - spaces_before: &'a [CommentOrNewline<'a>], - arena: &'a Bump, - state: State<'a>, -) -> ParseResult<'a, &'a Loc>, EExpr<'a>> { - let (_, (type_def, def_region), state) = - finish_parsing_ability_def_help(start_column, name, args, loc_has, arena, state)?; - - let def = Def::Type(type_def); - - let loc_def = &*(if spaces_before.is_empty() { - arena.alloc(Loc::at(def_region, def)) - } else { - arena.alloc( - arena - .alloc(def) - .with_spaces_before(spaces_before, def_region), - ) - }); - - Ok((MadeProgress, loc_def, state)) -} - fn finish_parsing_ability_def_help<'a>( start_column: u32, name: Loc<&'a str>, @@ -1714,26 +1289,6 @@ fn finish_parsing_ability_def_help<'a>( Ok((MadeProgress, (type_def, def_region), state)) } -fn finish_parsing_ability<'a>( - start_column: u32, - options: ExprParseOptions, - name: Loc<&'a str>, - args: &'a [Loc>], - loc_has: Loc>, - arena: &'a Bump, - state: State<'a>, -) -> ParseResult<'a, Expr<'a>, EExpr<'a>> { - let (_, loc_def, state) = - finish_parsing_ability_def(start_column, name, args, loc_has, &[], arena, state)?; - - let def_state = DefState { - defs: bumpalo::vec![in arena; loc_def], - spaces_after: &[], - }; - - parse_defs_expr(options, start_column, def_state, arena, state) -} - fn parse_expr_operator<'a>( min_indent: u32, options: ExprParseOptions, @@ -1788,7 +1343,7 @@ fn parse_expr_operator<'a>( .validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction) .map_err(|fail| (MadeProgress, fail, state.clone()))?; - let (loc_def, state) = { + let (value_def, def_region, state) = { match expr_to_pattern_help(arena, &call.value) { Ok(good) => { let (_, mut body, state) = parse_loc_expr(indented_more, arena, state)?; @@ -1805,10 +1360,9 @@ fn parse_expr_operator<'a>( let alias = ValueDef::Body( arena.alloc(Loc::at(expr_region, good)), arena.alloc(body), - ) - .into(); + ); - (&*arena.alloc(Loc::at(body_region, alias)), state) + (alias, body_region, state) } Err(_) => { // this `=` likely occurred inline; treat it as an invalid operator @@ -1819,12 +1373,10 @@ fn parse_expr_operator<'a>( } }; - let def_state = DefState { - defs: bumpalo::vec![in arena; loc_def], - spaces_after: &[], - }; + let mut defs = Defs::default(); + defs.push_value_def(value_def, def_region, &[], &[]); - parse_defs_expr(options, start_column, def_state, arena, state) + parse_defs_expr(options, start_column, defs, arena, state) } BinOp::Backpassing => { let expr_region = expr_state.expr.region; @@ -2000,15 +1552,15 @@ fn parse_expr_end<'a>( Loc::at(has.region, Has::Has) }; - finish_parsing_ability( - start_column, - options, - name, - arguments.into_bump_slice(), - has, - arena, - state, - ) + let args = arguments.into_bump_slice(); + let (_, (type_def, def_region), state) = + finish_parsing_ability_def_help(start_column, name, args, has, arena, state)?; + + let mut defs = Defs::default(); + + defs.push_type_def(type_def, def_region, &[], &[]); + + parse_defs_expr(options, start_column, defs, arena, state) } Ok((_, mut arg, state)) => { let new_end = state.pos(); @@ -2323,8 +1875,7 @@ pub fn toplevel_defs<'a>(min_indent: u32) -> impl Parser<'a, Defs<'a>, EExpr<'a> let mut output = Defs::default(); let before = Slice::extend_new(&mut output.spaces, initial_space.iter().copied()); - let (_, mut output, state) = - parse_toplevel_defs_end(options, start_column, output, arena, state)?; + let (_, mut output, state) = parse_defs_end(options, start_column, output, arena, state)?; let (_, final_space, state) = space0_e(start_column, EExpr::IndentEnd).parse(arena, state)?; @@ -2345,57 +1896,6 @@ pub fn toplevel_defs<'a>(min_indent: u32) -> impl Parser<'a, Defs<'a>, EExpr<'a> } } -pub fn defs<'a>(min_indent: u32) -> impl Parser<'a, Vec<'a, Loc>>, EExpr<'a>> { - move |arena, state: State<'a>| { - let def_state = DefState { - defs: Vec::new_in(arena), - spaces_after: &[], - }; - - let (_, initial_space, state) = - space0_e(min_indent, EExpr::IndentEnd).parse(arena, state)?; - - let start_column = state.column(); - - let options = ExprParseOptions { - accept_multi_backpassing: false, - check_for_arrow: true, - }; - - let (_, def_state, state) = parse_defs_end(options, start_column, def_state, arena, state)?; - - let (_, final_space, state) = - space0_e(start_column, EExpr::IndentEnd).parse(arena, state)?; - - let mut output = Vec::with_capacity_in(def_state.defs.len(), arena); - - if !def_state.defs.is_empty() { - let first = 0; - let last = def_state.defs.len() - 1; - - for (i, ref_def) in def_state.defs.into_iter().enumerate() { - let mut def = *ref_def; - - if i == first { - def = arena - .alloc(def.value) - .with_spaces_before(initial_space, def.region) - } - - if i == last { - def = arena - .alloc(def.value) - .with_spaces_after(final_space, def.region) - } - - output.push(def); - } - } - - Ok((MadeProgress, output, state)) - } -} - // PARSER HELPERS fn closure_help<'a>( diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index e5bc7c259d..cbbf5e2b02 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -1,4 +1,4 @@ -use crate::ast::{Collection, CommentOrNewline, Def, Defs, Module, Spaced}; +use crate::ast::{Collection, CommentOrNewline, Defs, Module, Spaced}; use crate::blankspace::{space0_around_ee, space0_before_e, space0_e}; use crate::header::{ package_entry, package_name, AppHeader, ExposedName, HostedHeader, ImportsEntry, @@ -14,7 +14,6 @@ use crate::parser::{ use crate::state::State; use crate::string_literal; use crate::type_annotation; -use bumpalo::collections::Vec; use roc_region::all::{Loc, Position}; fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> { @@ -39,19 +38,6 @@ pub fn module_defs<'a>() -> impl Parser<'a, Defs<'a>, SyntaxError<'a>> { ) } -#[inline(always)] -pub fn module_defs_help<'a>() -> impl Parser<'a, Vec<'a, Loc>>, SyntaxError<'a>> { - // force that we parse until the end of the input - let min_indent = 0; - skip_second!( - specialize_region( - |e, r| SyntaxError::Expr(e, r.start()), - crate::expr::defs(min_indent), - ), - end_of_file() - ) -} - pub fn parse_header<'a>( arena: &'a bumpalo::Bump, state: State<'a>, diff --git a/compiler/parse/src/test_helpers.rs b/compiler/parse/src/test_helpers.rs index 0128465506..6cf9c756e8 100644 --- a/compiler/parse/src/test_helpers.rs +++ b/compiler/parse/src/test_helpers.rs @@ -1,7 +1,6 @@ use crate::ast; -use crate::ast::Def; -use crate::module::module_defs_help; -// use crate::module::module_defs; +use crate::ast::Defs; +use crate::module::module_defs; use crate::parser::Parser; use crate::parser::SourceError; use crate::parser::SyntaxError; @@ -32,13 +31,10 @@ pub fn parse_loc_with<'a>( } } -pub fn parse_defs_with<'a>( - arena: &'a Bump, - input: &'a str, -) -> Result>>, SyntaxError<'a>> { +pub fn parse_defs_with<'a>(arena: &'a Bump, input: &'a str) -> Result, SyntaxError<'a>> { let state = State::new(input.trim().as_bytes()); - match module_defs_help().parse(arena, state) { + match module_defs().parse(arena, state) { Ok(tuple) => Ok(tuple.1), Err(tuple) => Err(tuple.1), } diff --git a/compiler/parse/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast b/compiler/parse/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast index 89c0bd7b00..71ddc0e3a7 100644 --- a/compiler/parse/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast @@ -1,6 +1,19 @@ Defs( - [ - @0-36 Type( + Defs { + tags: [ + Index(0), + ], + regions: [ + @0-36, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [ Ability { header: TypeHeader { name: @0-4 "Hash", @@ -30,8 +43,9 @@ Defs( }, ], }, - ), - ], + ], + value_defs: [], + }, @38-39 SpaceBefore( Num( "1", diff --git a/compiler/parse/tests/snapshots/pass/ability_multi_line.expr.result-ast b/compiler/parse/tests/snapshots/pass/ability_multi_line.expr.result-ast index c650e71f0e..35bbb58f04 100644 --- a/compiler/parse/tests/snapshots/pass/ability_multi_line.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/ability_multi_line.expr.result-ast @@ -1,6 +1,19 @@ Defs( - [ - @0-45 Type( + Defs { + tags: [ + Index(0), + ], + regions: [ + @0-45, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [ Ability { header: TypeHeader { name: @0-4 "Hash", @@ -50,8 +63,9 @@ Defs( }, ], }, - ), - ], + ], + value_defs: [], + }, @47-48 SpaceBefore( Num( "1", diff --git a/compiler/parse/tests/snapshots/pass/ability_single_line.expr.result-ast b/compiler/parse/tests/snapshots/pass/ability_single_line.expr.result-ast index f97c020789..78bc7bb229 100644 --- a/compiler/parse/tests/snapshots/pass/ability_single_line.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/ability_single_line.expr.result-ast @@ -1,6 +1,19 @@ Defs( - [ - @0-37 Type( + Defs { + tags: [ + Index(0), + ], + regions: [ + @0-37, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [ Ability { header: TypeHeader { name: @0-4 "Hash", @@ -37,8 +50,9 @@ Defs( }, ], }, - ), - ], + ], + value_defs: [], + }, @39-40 SpaceBefore( Num( "1", diff --git a/compiler/parse/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast b/compiler/parse/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast index dc6057152e..c169f89997 100644 --- a/compiler/parse/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast @@ -1,6 +1,26 @@ Defs( - [ - @0-33 Type( + Defs { + tags: [ + Index(0), + Index(1), + ], + regions: [ + @0-33, + @35-68, + ], + space_before: [ + Slice(start = 0, length = 0), + Slice(start = 0, length = 2), + ], + space_after: [ + Slice(start = 0, length = 0), + Slice(start = 2, length = 0), + ], + spaces: [ + Newline, + Newline, + ], + type_defs: [ Ability { header: TypeHeader { name: @0-3 "Ab1", @@ -36,51 +56,44 @@ Defs( }, ], }, - ), - @35-68 SpaceBefore( - Type( - Ability { - header: TypeHeader { - name: @35-38 "Ab2", - vars: [], - }, - loc_has: @39-42 Has, - members: [ - AbilityMember { - name: @43-46 "ab2", - typ: @49-68 Where( - @49-56 Function( - [ - @49-50 BoundVariable( - "a", - ), - ], - @54-56 Record { - fields: [], - ext: None, - }, - ), - [ - @59-68 HasClause { - var: @59-60 "a", - ability: @65-68 Apply( - "", - "Ab2", - [], - ), - }, - ], - ), - }, - ], + Ability { + header: TypeHeader { + name: @35-38 "Ab2", + vars: [], }, - ), - [ - Newline, - Newline, - ], - ), - ], + loc_has: @39-42 Has, + members: [ + AbilityMember { + name: @43-46 "ab2", + typ: @49-68 Where( + @49-56 Function( + [ + @49-50 BoundVariable( + "a", + ), + ], + @54-56 Record { + fields: [], + ext: None, + }, + ), + [ + @59-68 HasClause { + var: @59-60 "a", + ability: @65-68 Apply( + "", + "Ab2", + [], + ), + }, + ], + ), + }, + ], + }, + ], + value_defs: [], + }, @70-71 SpaceBefore( Num( "1", diff --git a/compiler/parse/tests/snapshots/pass/annotated_record_destructure.expr.result-ast b/compiler/parse/tests/snapshots/pass/annotated_record_destructure.expr.result-ast index 3b87b36828..9c1dd29c5d 100644 --- a/compiler/parse/tests/snapshots/pass/annotated_record_destructure.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/annotated_record_destructure.expr.result-ast @@ -1,6 +1,37 @@ Defs( - [ - @15-49 Value( + Defs { + tags: [ + Index(2147483649), + ], + regions: [ + @0-49, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @0-8 RecordDestructure( + [ + @2-3 Identifier( + "x", + ), + @5-7 Identifier( + "y", + ), + ], + ), + @11-14 Apply( + "", + "Foo", + [], + ), + ), AnnotatedBody { ann_pattern: @0-8 RecordDestructure( [ @@ -49,8 +80,8 @@ Defs( ], ), }, - ), - ], + ], + }, @51-52 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/annotated_tag_destructure.expr.result-ast b/compiler/parse/tests/snapshots/pass/annotated_tag_destructure.expr.result-ast index eec49d33ac..65c42d1c6f 100644 --- a/compiler/parse/tests/snapshots/pass/annotated_tag_destructure.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/annotated_tag_destructure.expr.result-ast @@ -1,6 +1,46 @@ Defs( - [ - @26-46 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-46, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [ + Alias { + header: TypeHeader { + name: @0-6 "UserId", + vars: [ + @7-8 Identifier( + "x", + ), + ], + }, + ann: @11-25 TagUnion { + ext: None, + tags: [ + @13-23 Apply { + name: @13-19 "UserId", + args: [ + @20-23 Apply( + "", + "I64", + [], + ), + ], + }, + ], + }, + }, + ], + value_defs: [ AnnotatedBody { ann_pattern: @0-8 Apply( @0-6 Tag( @@ -50,8 +90,8 @@ Defs( Space, ), }, - ), - ], + ], + }, @48-49 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/basic_docs.expr.result-ast b/compiler/parse/tests/snapshots/pass/basic_docs.expr.result-ast index e457bb7705..092348adc6 100644 --- a/compiler/parse/tests/snapshots/pass/basic_docs.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/basic_docs.expr.result-ast @@ -1,7 +1,21 @@ SpaceBefore( Defs( - [ - @107-112 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @107-112, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @107-108 Identifier( "x", @@ -10,8 +24,8 @@ SpaceBefore( "5", ), ), - ), - ], + ], + }, @114-116 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/destructure_tag_assignment.expr.result-ast b/compiler/parse/tests/snapshots/pass/destructure_tag_assignment.expr.result-ast index 95c8fc9192..5f71aa1375 100644 --- a/compiler/parse/tests/snapshots/pass/destructure_tag_assignment.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/destructure_tag_assignment.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-36 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-36, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-5 Apply( @0-5 Tag( @@ -26,8 +40,8 @@ Defs( Space, ), ), - ), - ], + ], + }, @37-40 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/if_def.expr.result-ast b/compiler/parse/tests/snapshots/pass/if_def.expr.result-ast index 61962aa8bc..9ee7f02bd7 100644 --- a/compiler/parse/tests/snapshots/pass/if_def.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/if_def.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-6 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-6, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-4 Identifier( "iffy", @@ -9,8 +23,8 @@ Defs( "5", ), ), - ), - ], + ], + }, @8-10 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/list_closing_indent_not_enough.expr.result-ast b/compiler/parse/tests/snapshots/pass/list_closing_indent_not_enough.expr.result-ast index d51238a4c5..514b7e0deb 100644 --- a/compiler/parse/tests/snapshots/pass/list_closing_indent_not_enough.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/list_closing_indent_not_enough.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-58 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-58, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-7 Malformed( "my_list", @@ -63,8 +77,8 @@ Defs( }, ), ), - ), - ], + ], + }, @59-61 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/list_closing_same_indent_no_trailing_comma.expr.result-ast b/compiler/parse/tests/snapshots/pass/list_closing_same_indent_no_trailing_comma.expr.result-ast index ffe535c03f..5348fee243 100644 --- a/compiler/parse/tests/snapshots/pass/list_closing_same_indent_no_trailing_comma.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/list_closing_same_indent_no_trailing_comma.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-26 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-26, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-7 Malformed( "my_list", @@ -31,8 +45,8 @@ Defs( }, ), ), - ), - ], + ], + }, @27-29 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/list_closing_same_indent_with_trailing_comma.expr.result-ast b/compiler/parse/tests/snapshots/pass/list_closing_same_indent_with_trailing_comma.expr.result-ast index e526c773d2..294546c42b 100644 --- a/compiler/parse/tests/snapshots/pass/list_closing_same_indent_with_trailing_comma.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/list_closing_same_indent_with_trailing_comma.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-27 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-27, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-7 Malformed( "my_list", @@ -31,8 +45,8 @@ Defs( }, ), ), - ), - ], + ], + }, @28-30 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/mixed_docs.expr.result-ast b/compiler/parse/tests/snapshots/pass/mixed_docs.expr.result-ast index 9b61bffafa..fca8774ccb 100644 --- a/compiler/parse/tests/snapshots/pass/mixed_docs.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/mixed_docs.expr.result-ast @@ -1,7 +1,21 @@ SpaceBefore( Defs( - [ - @113-118 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @113-118, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @113-114 Identifier( "x", @@ -10,8 +24,8 @@ SpaceBefore( "5", ), ), - ), - ], + ], + }, @120-122 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/module_def_newline.module.result-ast b/compiler/parse/tests/snapshots/pass/module_def_newline.module.result-ast index 63fd8f31d3..82e5ea9cd0 100644 --- a/compiler/parse/tests/snapshots/pass/module_def_newline.module.result-ast +++ b/compiler/parse/tests/snapshots/pass/module_def_newline.module.result-ast @@ -22,8 +22,22 @@ Defs { ), @11-24 SpaceBefore( Defs( - [ - @11-17 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @11-17, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @11-12 Identifier( "i", @@ -32,8 +46,8 @@ Defs { "64", ), ), - ), - ], + ], + }, @23-24 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/multiline_type_signature.expr.result-ast b/compiler/parse/tests/snapshots/pass/multiline_type_signature.expr.result-ast index d3519069ff..a970a99825 100644 --- a/compiler/parse/tests/snapshots/pass/multiline_type_signature.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/multiline_type_signature.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-10 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-10, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -15,8 +29,8 @@ Defs( ], ), ), - ), - ], + ], + }, @12-14 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/multiline_type_signature_with_comment.expr.result-ast b/compiler/parse/tests/snapshots/pass/multiline_type_signature_with_comment.expr.result-ast index d989a361e4..ac30efb60b 100644 --- a/compiler/parse/tests/snapshots/pass/multiline_type_signature_with_comment.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/multiline_type_signature_with_comment.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-19 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-19, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -17,8 +31,8 @@ Defs( ], ), ), - ), - ], + ], + }, @21-23 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/nested_def_annotation.module.result-ast b/compiler/parse/tests/snapshots/pass/nested_def_annotation.module.result-ast index 2ff84db367..a245e100ad 100644 --- a/compiler/parse/tests/snapshots/pass/nested_def_annotation.module.result-ast +++ b/compiler/parse/tests/snapshots/pass/nested_def_annotation.module.result-ast @@ -22,8 +22,42 @@ Defs { ), @11-115 SpaceBefore( Defs( - [ - @43-93 Value( + Defs { + tags: [ + Index(2147483649), + ], + regions: [ + @11-93, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ + Annotation( + @11-23 Identifier( + "wrappedNotEq", + ), + @26-38 Function( + [ + @26-27 BoundVariable( + "a", + ), + @29-30 BoundVariable( + "a", + ), + ], + @34-38 Apply( + "", + "Bool", + [], + ), + ), + ), AnnotatedBody { ann_pattern: @11-23 Identifier( "wrappedNotEq", @@ -78,8 +112,8 @@ Defs { ), ), }, - ), - ], + ], + }, @99-115 SpaceBefore( Apply( @99-111 Var { diff --git a/compiler/parse/tests/snapshots/pass/newline_after_equals.expr.result-ast b/compiler/parse/tests/snapshots/pass/newline_after_equals.expr.result-ast index a62f3cc138..736d5c346f 100644 --- a/compiler/parse/tests/snapshots/pass/newline_after_equals.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/newline_after_equals.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-9 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-9, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-1 Identifier( "x", @@ -14,8 +28,8 @@ Defs( ], ), ), - ), - ], + ], + }, @11-13 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/newline_and_spaces_before_less_than.expr.result-ast b/compiler/parse/tests/snapshots/pass/newline_and_spaces_before_less_than.expr.result-ast index 2fd5007e3d..3b0ec5bb38 100644 --- a/compiler/parse/tests/snapshots/pass/newline_and_spaces_before_less_than.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/newline_and_spaces_before_less_than.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-13 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-13, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-1 Identifier( "x", @@ -24,8 +38,8 @@ Defs( ), ), ), - ), - ], + ], + }, @15-17 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/not_docs.expr.result-ast b/compiler/parse/tests/snapshots/pass/not_docs.expr.result-ast index 0df9d829d3..fbbe2716cc 100644 --- a/compiler/parse/tests/snapshots/pass/not_docs.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/not_docs.expr.result-ast @@ -1,7 +1,21 @@ SpaceBefore( Defs( - [ - @46-51 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @46-51, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @46-47 Identifier( "x", @@ -10,8 +24,8 @@ SpaceBefore( "5", ), ), - ), - ], + ], + }, @53-55 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/one_def.expr.result-ast b/compiler/parse/tests/snapshots/pass/one_def.expr.result-ast index a8af60df37..7bdcc24ced 100644 --- a/compiler/parse/tests/snapshots/pass/one_def.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/one_def.expr.result-ast @@ -1,7 +1,21 @@ SpaceBefore( Defs( - [ - @18-21 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @18-21, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @18-19 Identifier( "x", @@ -10,8 +24,8 @@ SpaceBefore( "5", ), ), - ), - ], + ], + }, @23-25 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/one_spaced_def.expr.result-ast b/compiler/parse/tests/snapshots/pass/one_spaced_def.expr.result-ast index 7e47e88173..6159c8ac84 100644 --- a/compiler/parse/tests/snapshots/pass/one_spaced_def.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/one_spaced_def.expr.result-ast @@ -1,7 +1,21 @@ SpaceBefore( Defs( - [ - @18-23 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @18-23, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @18-19 Identifier( "x", @@ -10,8 +24,8 @@ SpaceBefore( "5", ), ), - ), - ], + ], + }, @25-27 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/opaque_has_abilities.expr.result-ast b/compiler/parse/tests/snapshots/pass/opaque_has_abilities.expr.result-ast index da465ced6d..d0fd4f8423 100644 --- a/compiler/parse/tests/snapshots/pass/opaque_has_abilities.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/opaque_has_abilities.expr.result-ast @@ -1,6 +1,32 @@ Defs( - [ - @0-7 Type( + Defs { + tags: [ + Index(0), + Index(1), + Index(2), + ], + regions: [ + @0-7, + @24-44, + @61-81, + ], + space_before: [ + Slice(start = 0, length = 0), + Slice(start = 0, length = 2), + Slice(start = 2, length = 2), + ], + space_after: [ + Slice(start = 0, length = 0), + Slice(start = 2, length = 0), + Slice(start = 4, length = 0), + ], + spaces: [ + Newline, + Newline, + Newline, + Newline, + ], + type_defs: [ Opaque { header: TypeHeader { name: @0-1 "A", @@ -28,103 +54,88 @@ Defs( ), ), }, - ), - @24-44 SpaceBefore( - Type( - Opaque { - header: TypeHeader { - name: @24-25 "A", - vars: [], - }, - typ: @29-44 Where( - @29-30 BoundVariable( - "a", - ), + Opaque { + header: TypeHeader { + name: @24-25 "A", + vars: [], + }, + typ: @29-44 Where( + @29-30 BoundVariable( + "a", + ), + [ + @33-44 HasClause { + var: @33-34 "a", + ability: @39-44 Apply( + "", + "Other", + [], + ), + }, + ], + ), + derived: Some( + @49-59 Has( [ - @33-44 HasClause { - var: @33-34 "a", - ability: @39-44 Apply( - "", - "Other", - [], - ), - }, + @50-52 Apply( + "", + "Eq", + [], + ), + @54-58 Apply( + "", + "Hash", + [], + ), ], ), - derived: Some( - @49-59 Has( + ), + }, + Opaque { + header: TypeHeader { + name: @61-62 "A", + vars: [], + }, + typ: @66-81 Where( + @66-67 BoundVariable( + "a", + ), + [ + @70-81 HasClause { + var: @70-71 "a", + ability: @76-81 Apply( + "", + "Other", + [], + ), + }, + ], + ), + derived: Some( + @91-101 SpaceBefore( + Has( [ - @50-52 Apply( + @92-94 Apply( "", "Eq", [], ), - @54-58 Apply( + @96-100 Apply( "", "Hash", [], ), ], ), - ), - }, - ), - [ - Newline, - Newline, - ], - ), - @61-81 SpaceBefore( - Type( - Opaque { - header: TypeHeader { - name: @61-62 "A", - vars: [], - }, - typ: @66-81 Where( - @66-67 BoundVariable( - "a", - ), [ - @70-81 HasClause { - var: @70-71 "a", - ability: @76-81 Apply( - "", - "Other", - [], - ), - }, + Newline, ], ), - derived: Some( - @91-101 SpaceBefore( - Has( - [ - @92-94 Apply( - "", - "Eq", - [], - ), - @96-100 Apply( - "", - "Hash", - [], - ), - ], - ), - [ - Newline, - ], - ), - ), - }, - ), - [ - Newline, - Newline, - ], - ), - ], + ), + }, + ], + value_defs: [], + }, @103-104 SpaceBefore( Num( "0", diff --git a/compiler/parse/tests/snapshots/pass/outdented_app_with_record.expr.result-ast b/compiler/parse/tests/snapshots/pass/outdented_app_with_record.expr.result-ast index 4df43e0d86..73315d43df 100644 --- a/compiler/parse/tests/snapshots/pass/outdented_app_with_record.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/outdented_app_with_record.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-29 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-29, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-1 Identifier( "x", @@ -48,8 +62,8 @@ Defs( Space, ), ), - ), - ], + ], + }, @30-31 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/outdented_list.expr.result-ast b/compiler/parse/tests/snapshots/pass/outdented_list.expr.result-ast index d7db49650a..07da076403 100644 --- a/compiler/parse/tests/snapshots/pass/outdented_list.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/outdented_list.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-17 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-17, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-1 Identifier( "a", @@ -29,8 +43,8 @@ Defs( }, ), ), - ), - ], + ], + }, @18-19 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/outdented_record.expr.result-ast b/compiler/parse/tests/snapshots/pass/outdented_record.expr.result-ast index 119d0dc5be..45af94810a 100644 --- a/compiler/parse/tests/snapshots/pass/outdented_record.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/outdented_record.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-23 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-23, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Body( @0-1 Identifier( "x", @@ -37,8 +51,8 @@ Defs( Space, ), ), - ), - ], + ], + }, @24-25 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/parse_alias.expr.result-ast b/compiler/parse/tests/snapshots/pass/parse_alias.expr.result-ast index 7db0abac4a..69a37e0110 100644 --- a/compiler/parse/tests/snapshots/pass/parse_alias.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/parse_alias.expr.result-ast @@ -1,6 +1,19 @@ Defs( - [ - @0-26 Type( + Defs { + tags: [ + Index(0), + ], + regions: [ + @0-26, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [ Alias { header: TypeHeader { name: @0-4 "Blah", @@ -26,8 +39,9 @@ Defs( ], ), }, - ), - ], + ], + value_defs: [], + }, @28-30 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/parse_as_ann.expr.result-ast b/compiler/parse/tests/snapshots/pass/parse_as_ann.expr.result-ast index b6faae0f69..6a195906dd 100644 --- a/compiler/parse/tests/snapshots/pass/parse_as_ann.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/parse_as_ann.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-33 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-33, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-3 Identifier( "foo", @@ -32,8 +46,8 @@ Defs( }, ), ), - ), - ], + ], + }, @35-37 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/record_destructure_def.expr.result-ast b/compiler/parse/tests/snapshots/pass/record_destructure_def.expr.result-ast index b2cbb9bbca..cf98c00b21 100644 --- a/compiler/parse/tests/snapshots/pass/record_destructure_def.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/record_destructure_def.expr.result-ast @@ -1,7 +1,27 @@ SpaceBefore( Defs( - [ - @18-30 Value( + Defs { + tags: [ + Index(2147483648), + Index(2147483649), + ], + regions: [ + @18-30, + @31-36, + ], + space_before: [ + Slice(start = 0, length = 0), + Slice(start = 0, length = 1), + ], + space_after: [ + Slice(start = 0, length = 0), + Slice(start = 1, length = 0), + ], + spaces: [ + Newline, + ], + type_defs: [], + value_defs: [ Body( @18-26 RecordDestructure( [ @@ -17,23 +37,16 @@ SpaceBefore( "5", ), ), - ), - @31-36 SpaceBefore( - Value( - Body( - @31-32 Identifier( - "y", - ), - @35-36 Num( - "6", - ), + Body( + @31-32 Identifier( + "y", + ), + @35-36 Num( + "6", ), ), - [ - Newline, - ], - ), - ], + ], + }, @38-40 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/record_func_type_decl.expr.result-ast b/compiler/parse/tests/snapshots/pass/record_func_type_decl.expr.result-ast index 4f2719f360..a8a7141892 100644 --- a/compiler/parse/tests/snapshots/pass/record_func_type_decl.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/record_func_type_decl.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-122 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-122, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -100,8 +114,8 @@ Defs( ], ), ), - ), - ], + ], + }, @124-126 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/record_type_with_function.expr.result-ast b/compiler/parse/tests/snapshots/pass/record_type_with_function.expr.result-ast index 82720a8cee..93e3d13c0b 100644 --- a/compiler/parse/tests/snapshots/pass/record_type_with_function.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/record_type_with_function.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-77 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-77, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "x", @@ -69,8 +83,8 @@ Defs( ext: None, }, ), - ), - ], + ], + }, @79-81 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/two_spaced_def.expr.result-ast b/compiler/parse/tests/snapshots/pass/two_spaced_def.expr.result-ast index 27cab84f39..29ce334a6c 100644 --- a/compiler/parse/tests/snapshots/pass/two_spaced_def.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/two_spaced_def.expr.result-ast @@ -1,7 +1,27 @@ SpaceBefore( Defs( - [ - @18-23 Value( + Defs { + tags: [ + Index(2147483648), + Index(2147483649), + ], + regions: [ + @18-23, + @24-29, + ], + space_before: [ + Slice(start = 0, length = 0), + Slice(start = 0, length = 1), + ], + space_after: [ + Slice(start = 0, length = 0), + Slice(start = 1, length = 0), + ], + spaces: [ + Newline, + ], + type_defs: [], + value_defs: [ Body( @18-19 Identifier( "x", @@ -10,23 +30,16 @@ SpaceBefore( "5", ), ), - ), - @24-29 SpaceBefore( - Value( - Body( - @24-25 Identifier( - "y", - ), - @28-29 Num( - "6", - ), + Body( + @24-25 Identifier( + "y", + ), + @28-29 Num( + "6", ), ), - [ - Newline, - ], - ), - ], + ], + }, @31-33 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/type_decl_with_underscore.expr.result-ast b/compiler/parse/tests/snapshots/pass/type_decl_with_underscore.expr.result-ast index 4575da7337..9e2082f0d8 100644 --- a/compiler/parse/tests/snapshots/pass/type_decl_with_underscore.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/type_decl_with_underscore.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-30 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-30, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-7 Identifier( "doStuff", @@ -27,8 +41,8 @@ Defs( ), ), ), - ), - ], + ], + }, @31-33 SpaceBefore( Num( "42", diff --git a/compiler/parse/tests/snapshots/pass/where_clause_function.expr.result-ast b/compiler/parse/tests/snapshots/pass/where_clause_function.expr.result-ast index d404a9cd7a..05be1444fc 100644 --- a/compiler/parse/tests/snapshots/pass/where_clause_function.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/where_clause_function.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-27 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-27, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -35,8 +49,8 @@ Defs( ], ), ), - ), - ], + ], + }, @29-30 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast b/compiler/parse/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast index 753ced4c9f..c2db4018eb 100644 --- a/compiler/parse/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-48 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-48, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -51,8 +65,8 @@ Defs( ], ), ), - ), - ], + ], + }, @50-51 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast b/compiler/parse/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast index 2a5ad71478..727ca1021c 100644 --- a/compiler/parse/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-67 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-67, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -66,8 +80,8 @@ Defs( ], ), ), - ), - ], + ], + }, @69-70 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/where_clause_non_function.expr.result-ast b/compiler/parse/tests/snapshots/pass/where_clause_non_function.expr.result-ast index 841d963271..64d9e8cadc 100644 --- a/compiler/parse/tests/snapshots/pass/where_clause_non_function.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/where_clause_non_function.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-15 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-15, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -21,8 +35,8 @@ Defs( ], ), ), - ), - ], + ], + }, @17-18 SpaceBefore( Var { module_name: "", diff --git a/compiler/parse/tests/snapshots/pass/where_clause_on_newline.expr.result-ast b/compiler/parse/tests/snapshots/pass/where_clause_on_newline.expr.result-ast index d554d5cf2b..c216d31d1b 100644 --- a/compiler/parse/tests/snapshots/pass/where_clause_on_newline.expr.result-ast +++ b/compiler/parse/tests/snapshots/pass/where_clause_on_newline.expr.result-ast @@ -1,6 +1,20 @@ Defs( - [ - @0-29 Value( + Defs { + tags: [ + Index(2147483648), + ], + regions: [ + @0-29, + ], + space_before: [ + Slice(start = 0, length = 0), + ], + space_after: [ + Slice(start = 0, length = 0), + ], + spaces: [], + type_defs: [], + value_defs: [ Annotation( @0-1 Identifier( "f", @@ -35,8 +49,8 @@ Defs( ], ), ), - ), - ], + ], + }, @31-32 SpaceBefore( Var { module_name: "", diff --git a/reporting/tests/helpers/mod.rs b/reporting/tests/helpers/mod.rs index cf87f0d8a6..1a270b89be 100644 --- a/reporting/tests/helpers/mod.rs +++ b/reporting/tests/helpers/mod.rs @@ -159,7 +159,7 @@ pub fn can_expr_with<'a>( add_aliases(&mut scope, &mut var_store); let dep_idents = IdentIds::exposed_builtins(0); - let mut env = Env::new(home, &dep_idents, &module_ids); + let mut env = Env::new(arena, home, &dep_idents, &module_ids); let (loc_expr, output) = canonicalize_expr( &mut env, &mut var_store,