Merge pull request #3158 from rtfeldman/parse-expr-defs-soa

Parse expr defs soa
This commit is contained in:
Folkert de Vries 2022-06-15 18:54:30 +02:00 committed by GitHub
commit b99d7dba67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 989 additions and 1278 deletions

View file

@ -40,287 +40,3 @@ pub struct ModuleOutput {
pub ident_ids: IdentIds, pub ident_ids: IdentIds,
pub references: MutSet<Symbol>, pub references: MutSet<Symbol>,
} }
// TODO trim these down
#[allow(clippy::too_many_arguments)]
pub fn canonicalize_module_defs<'a>(
arena: &Bump,
loc_defs: &'a [Loc<ast::Def<'a>>],
home: ModuleId,
module_ids: &ModuleIds,
exposed_ident_ids: IdentIds,
dep_idents: IdentIdsByModule,
aliases: MutMap<Symbol, Alias>,
exposed_imports: MutMap<Ident, (Symbol, Region)>,
mut exposed_symbols: MutSet<Symbol>,
var_store: &mut VarStore,
) -> Result<ModuleOutput, RuntimeError> {
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),
}
}

View file

@ -16,7 +16,7 @@ use roc_collections::all::{default_hasher, ImMap, MutMap, MutSet, SendMap};
use roc_error_macros::{todo_abilities, todo_opaques}; use roc_error_macros::{todo_abilities, todo_opaques};
use roc_module::ident::Lowercase; use roc_module::ident::Lowercase;
use roc_module::symbol::Symbol; 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_parse::pattern::PatternType;
use roc_problem::can::{Problem, RuntimeError, ShadowKind}; use roc_problem::can::{Problem, RuntimeError, ShadowKind};
use roc_region::all::{Loc, Region}; use roc_region::all::{Loc, Region};
@ -791,7 +791,7 @@ pub fn canonicalize_defs<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,
mut output: Output, mut output: Output,
original_scope: &Scope, original_scope: &Scope,
loc_defs: &'a [&'a Loc<ast::Def<'a>>], loc_defs: &'a Defs<'a>,
pattern_type: PatternType, pattern_type: PatternType,
) -> (CanDefs, Scope, Output, MutMap<Symbol, Region>) { ) -> (CanDefs, Scope, Output, MutMap<Symbol, Region>) {
// Canonicalizing defs while detecting shadowing involves a multi-step process: // 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 // Canonicalize all the patterns, record shadowing problems, and store
// the ast::Expr values in pending_exprs for further canonicalization // the ast::Expr values in pending_exprs for further canonicalization
// once we've finished assembling the entire scope. // once we've finished assembling the entire scope.
for loc_def in loc_defs { for loc_def in loc_defs.defs() {
match to_pending_def(env, &loc_def.value, &mut scope, pattern_type) { 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 => (), None => (),
Some((new_output, pending_def)) => { Some((new_output, pending_def)) => {
// store the top-level defs, used to ensure that closures won't capture them // store the top-level defs, used to ensure that closures won't capture them

View file

@ -1,4 +1,3 @@
use bumpalo::collections::Vec as BumpVec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_parse::{ast::CommentOrNewline, parser::SyntaxError}; use roc_parse::{ast::CommentOrNewline, parser::SyntaxError};
use roc_region::all::Region; use roc_region::all::Region;
@ -90,19 +89,6 @@ pub fn toplevel_defs_to_defs2<'a>(
result result
} }
pub fn defs_to_defs2<'a>(
arena: &'a Bump,
env: &mut Env<'a>,
scope: &mut Scope,
parsed_defs: &'a BumpVec<roc_region::all::Loc<roc_parse::ast::Def<'a>>>,
region: Region,
) -> Vec<Def2> {
parsed_defs
.iter()
.map(|loc| def_to_def2(arena, env, scope, &loc.value, region))
.collect()
}
pub fn def_to_def2<'a>( pub fn def_to_def2<'a>(
arena: &'a Bump, arena: &'a Bump,
env: &mut Env<'a>, env: &mut Env<'a>,
@ -201,13 +187,7 @@ pub fn str_to_def2<'a>(
region: Region, region: Region,
) -> Result<Vec<Def2>, SyntaxError<'a>> { ) -> Result<Vec<Def2>, SyntaxError<'a>> {
match roc_parse::test_helpers::parse_defs_with(arena, input.trim()) { match roc_parse::test_helpers::parse_defs_with(arena, input.trim()) {
Ok(vec_loc_def) => Ok(defs_to_defs2( Ok(defs) => Ok(toplevel_defs_to_defs2(arena, env, scope, defs, region)),
arena,
env,
scope,
arena.alloc(vec_loc_def),
region,
)),
Err(fail) => Err(fail), Err(fail) => Err(fail),
} }
} }

View file

@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
use crate::FormatMode; use crate::FormatMode;
use bumpalo::Bump; use bumpalo::Bump;
use roc_error_macros::{internal_error, user_error}; 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::module::fmt_module;
use roc_fmt::spaces::RemoveSpaces; use roc_fmt::spaces::RemoveSpaces;
use roc_fmt::{Ast, Buf}; use roc_fmt::{Ast, Buf};
@ -166,7 +166,7 @@ fn parse_all<'a>(arena: &'a Bump, src: &'a str) -> Result<Ast<'a>, SyntaxError<'
fn fmt_all<'a>(buf: &mut Buf<'a>, ast: &'a Ast) { fn fmt_all<'a>(buf: &mut Buf<'a>, ast: &'a Ast) {
fmt_module(buf, &ast.module); fmt_module(buf, &ast.module);
fmt_toplevel_defs(buf, &ast.defs, 0); fmt_defs(buf, &ast.defs, 0);
buf.fmt_end_of_file(); buf.fmt_end_of_file();
} }

View file

@ -25,6 +25,7 @@ use roc_module::symbol::ModuleId;
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
use roc_parse::ast; use roc_parse::ast;
use roc_parse::ast::AbilityMember; use roc_parse::ast::AbilityMember;
use roc_parse::ast::Defs;
use roc_parse::ast::ExtractSpaces; use roc_parse::ast::ExtractSpaces;
use roc_parse::ast::TypeHeader; use roc_parse::ast::TypeHeader;
use roc_parse::pattern::PatternType; use roc_parse::pattern::PatternType;
@ -457,72 +458,6 @@ fn canonicalize_opaque<'a>(
#[inline(always)] #[inline(always)]
pub(crate) fn canonicalize_defs<'a>( 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<ast::Def<'a>>],
pattern_type: PatternType,
) -> (CanDefs, Output, MutMap<Symbol, Region>) {
// 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>, env: &mut Env<'a>,
mut output: Output, mut output: Output,
var_store: &mut VarStore, var_store: &mut VarStore,
@ -1577,7 +1512,7 @@ pub fn can_defs_with_return<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,
var_store: &mut VarStore, var_store: &mut VarStore,
scope: &mut Scope, scope: &mut Scope,
loc_defs: &'a [&'a Loc<ast::Def<'a>>], loc_defs: &'a mut Defs<'a>,
loc_ret: &'a Loc<ast::Expr<'a>>, loc_ret: &'a Loc<ast::Expr<'a>>,
) -> (Expr, Output) { ) -> (Expr, Output) {
let (unsorted, defs_output, symbols_introduced) = canonicalize_defs( let (unsorted, defs_output, symbols_introduced) = canonicalize_defs(

View file

@ -1,5 +1,6 @@
use crate::procedure::References; use crate::procedure::References;
use crate::scope::Scope; use crate::scope::Scope;
use bumpalo::Bump;
use roc_collections::{MutMap, VecSet}; use roc_collections::{MutMap, VecSet};
use roc_module::ident::{Ident, Lowercase, ModuleName}; use roc_module::ident::{Ident, Lowercase, ModuleName};
use roc_module::symbol::{IdentIdsByModule, ModuleId, ModuleIds, Symbol}; use roc_module::symbol::{IdentIdsByModule, ModuleId, ModuleIds, Symbol};
@ -32,15 +33,19 @@ pub struct Env<'a> {
pub qualified_type_lookups: VecSet<Symbol>, pub qualified_type_lookups: VecSet<Symbol>,
pub top_level_symbols: VecSet<Symbol>, pub top_level_symbols: VecSet<Symbol>,
pub arena: &'a Bump,
} }
impl<'a> Env<'a> { impl<'a> Env<'a> {
pub fn new( pub fn new(
arena: &'a Bump,
home: ModuleId, home: ModuleId,
dep_idents: &'a IdentIdsByModule, dep_idents: &'a IdentIdsByModule,
module_ids: &'a ModuleIds, module_ids: &'a ModuleIds,
) -> Env<'a> { ) -> Env<'a> {
Env { Env {
arena,
home, home,
dep_idents, dep_idents,
module_ids, module_ids,

View file

@ -15,7 +15,7 @@ use roc_module::called_via::CalledVia;
use roc_module::ident::{ForeignSymbol, Lowercase, TagName}; use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
use roc_module::low_level::LowLevel; use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol; 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_parse::pattern::PatternType::*;
use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError}; use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
use roc_region::all::{Loc, Region}; use roc_region::all::{Loc, Region};
@ -728,7 +728,8 @@ pub fn canonicalize_expr<'a>(
ast::Expr::Defs(loc_defs, loc_ret) => { ast::Expr::Defs(loc_defs, loc_ret) => {
// The body expression gets a new scope for canonicalization, // The body expression gets a new scope for canonicalization,
scope.inner_scope(|inner_scope| { 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(_, _, _) => { ast::Expr::Backpassing(_, _, _) => {

View file

@ -1,10 +1,10 @@
use crate::abilities::PendingAbilitiesStore; use crate::abilities::PendingAbilitiesStore;
use crate::annotation::canonicalize_annotation; 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::effect_module::HostedGeneratedFunctions;
use crate::env::Env; use crate::env::Env;
use crate::expr::{ClosureData, Expr, Output, PendingDerives}; use crate::expr::{ClosureData, Expr, Output, PendingDerives};
use crate::operator::desugar_toplevel_defs; use crate::operator::desugar_defs;
use crate::pattern::Pattern; use crate::pattern::Pattern;
use crate::scope::Scope; use crate::scope::Scope;
use bumpalo::Bump; use bumpalo::Bump;
@ -175,7 +175,7 @@ pub fn canonicalize_module_defs<'a>(
) -> ModuleOutput { ) -> ModuleOutput {
let mut can_exposed_imports = MutMap::default(); let mut can_exposed_imports = MutMap::default();
let mut scope = Scope::new(home, exposed_ident_ids, imported_abilities_state); 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(); let num_deps = dep_idents.len();
for (name, alias) in aliases.into_iter() { 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 // 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 // operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily. // 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 lookups = Vec::with_capacity(num_deps);
let mut rigid_variables = RigidVariables::default(); 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, &mut env,
Output::default(), Output::default(),
var_store, var_store,

View file

@ -63,31 +63,6 @@ fn new_op_call_expr<'a>(
Loc { region, value } Loc { region, value }
} }
fn desugar_def_helps<'a>(
arena: &'a Bump,
region: Region,
defs: &'a [&'a Loc<Def<'a>>],
loc_ret: &'a Loc<Expr<'a>>,
) -> &'a Loc<Expr<'a>> {
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> { fn desugar_type_def<'a>(def: &'a TypeDef<'a>) -> TypeDef<'a> {
use TypeDef::*; 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() { for value_def in defs.value_defs.iter_mut() {
*value_def = desugar_value_def(arena, arena.alloc(*value_def)); *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<Expr<'a>>) -> &'a Loc
} }
} }
BinOps(lefts, right) => desugar_bin_ops(arena, loc_expr.region, lefts, right), 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) => { Apply(loc_fn, loc_args, called_via) => {
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena); let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena);

View file

@ -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 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( let (loc_expr, output) = canonicalize_expr(
&mut env, &mut env,
&mut var_store, &mut var_store,

View file

@ -348,10 +348,6 @@ fn fmt_expect<'a, 'buf>(
condition.format(buf, return_indent); 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>( pub fn fmt_value_def<'a, 'buf>(
buf: &mut Buf<'buf>, buf: &mut Buf<'buf>,
def: &roc_parse::ast::ValueDef<'a>, 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); 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); defs.format(buf, indent);
} }

View file

@ -1,6 +1,6 @@
use crate::annotation::{Formattable, Newlines, Parens}; use crate::annotation::{Formattable, Newlines, Parens};
use crate::collection::{fmt_collection, Braces}; use crate::collection::{fmt_collection, Braces};
use crate::def::fmt_def; use crate::def::fmt_defs;
use crate::pattern::fmt_pattern; use crate::pattern::fmt_pattern;
use crate::spaces::{count_leading_newlines, fmt_comments_only, fmt_spaces, NewlineAt, INDENT}; use crate::spaces::{count_leading_newlines, fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
use crate::Buf; use crate::Buf;
@ -325,9 +325,7 @@ impl<'a> Formattable for Expr<'a> {
// (Canonicalization can remove defs later, but that hasn't happened yet!) // (Canonicalization can remove defs later, but that hasn't happened yet!)
debug_assert!(!defs.is_empty()); debug_assert!(!defs.is_empty());
for loc_def in defs.iter() { fmt_defs(buf, defs, indent);
fmt_def(buf, &loc_def.value, indent);
}
match &ret.value { match &ret.value {
SpaceBefore(sub_expr, spaces) => { SpaceBefore(sub_expr, spaces) => {

View file

@ -617,7 +617,21 @@ impl<'a> RemoveSpaces<'a> for Expr<'a> {
arena.alloc(b.remove_spaces(arena)), arena.alloc(b.remove_spaces(arena)),
), ),
Expr::Defs(a, b) => { 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( Expr::Backpassing(a, b, c) => Expr::Backpassing(
arena.alloc(a.remove_spaces(arena)), arena.alloc(a.remove_spaces(arena)),

View file

@ -7,7 +7,7 @@ extern crate roc_fmt;
mod test_fmt { mod test_fmt {
use bumpalo::Bump; use bumpalo::Bump;
use roc_fmt::annotation::{Formattable, Newlines, Parens}; 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::module::fmt_module;
use roc_fmt::Buf; use roc_fmt::Buf;
use roc_parse::ast::Module; use roc_parse::ast::Module;
@ -88,7 +88,7 @@ mod test_fmt {
match module_defs().parse(arena, state) { match module_defs().parse(arena, state) {
Ok((_, loc_defs, _)) => { Ok((_, loc_defs, _)) => {
fmt_toplevel_defs(buf, &loc_defs, 0); fmt_defs(buf, &loc_defs, 0);
} }
Err(error) => panic!( Err(error) => panic!(
r"Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", r"Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n",

View file

@ -197,7 +197,7 @@ pub enum Expr<'a> {
// Pattern Matching // Pattern Matching
Closure(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>), Closure(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>),
/// Multiple defs in a row /// Multiple defs in a row
Defs(&'a [&'a Loc<Def<'a>>], &'a Loc<Expr<'a>>), Defs(&'a Defs<'a>, &'a Loc<Expr<'a>>),
Backpassing(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>), Backpassing(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
Expect(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>), Expect(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
@ -346,6 +346,14 @@ pub struct Defs<'a> {
} }
impl<'a> 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<Item = Result<&TypeDef<'a>, &ValueDef<'a>>> { pub fn defs(&self) -> impl Iterator<Item = Result<&TypeDef<'a>, &ValueDef<'a>>> {
self.tags.iter().map(|tag| match tag.split() { self.tags.iter().map(|tag| match tag.split() {
Ok(type_index) => Ok(&self.type_defs[type_index.index()]), Ok(type_index) => Ok(&self.type_defs[type_index.index()]),

View file

@ -568,251 +568,7 @@ fn numeric_negate_expression<'a, T>(
} }
} }
fn append_body_definition<'a>( fn parse_defs_end<'a>(
arena: &'a Bump,
defs: &mut Vec<'a, &'a Loc<Def<'a>>>,
spaces: &'a [CommentOrNewline<'a>],
loc_pattern: Loc<Pattern<'a>>,
loc_def_body: Loc<Expr<'a>>,
) {
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<Def<'a>>>,
region: Region,
before_ann_spaces: &'a [CommentOrNewline<'a>],
before_body_spaces: &'a [CommentOrNewline<'a>],
loc_pattern_body: Loc<Pattern<'a>>,
loc_def_body: Loc<Expr<'a>>,
loc_pattern_ann: &'a Loc<Pattern<'a>>,
loc_ann: &'a Loc<TypeAnnotation<'a>>,
) {
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<Def<'a>>>,
spaces: &'a [CommentOrNewline<'a>],
loc_pattern: Loc<Pattern<'a>>,
loc_ann: Loc<TypeAnnotation<'a>>,
// If this turns out to be an alias
kind: AliasOrOpaque,
opt_derived: Option<Loc<Derived<'a>>>,
) {
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<Def<'a>>>,
start: Position,
spaces: &'a [CommentOrNewline<'a>],
loc_expect_body: Loc<Expr<'a>>,
) {
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<Def<'a>>>,
region: Region,
spaces: &'a [CommentOrNewline<'a>],
name: Loc<&'a str>,
pattern_arguments: &'a [Loc<Pattern<'a>>],
loc_ann: Loc<TypeAnnotation<'a>>,
kind: AliasOrOpaque,
opt_derived: Option<Loc<Derived<'a>>>,
) {
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<Def<'a>>>,
spaces_after: &'a [CommentOrNewline<'a>],
}
fn parse_toplevel_defs_end<'a>(
_options: ExprParseOptions, _options: ExprParseOptions,
start_column: u32, start_column: u32,
mut defs: Defs<'a>, 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<Pattern>])> = 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>( fn parse_defs_expr<'a>(
options: ExprParseOptions, options: ExprParseOptions,
start_column: u32, start_column: u32,
def_state: DefState<'a>, defs: Defs<'a>,
arena: &'a Bump, arena: &'a Bump,
state: State<'a>, state: State<'a>,
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> { ) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
let min_indent = start_column; 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), Err(bad) => Err(bad),
Ok((_, def_state, state)) => { Ok((_, def_state, state)) => {
// this is no def, because there is no `=` or `:`; parse as an expr // 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)) => { Ok((_, loc_ret, state)) => {
return Ok(( return Ok((
MadeProgress, MadeProgress,
Expr::Defs(def_state.defs.into_bump_slice(), arena.alloc(loc_ret)), Expr::Defs(arena.alloc(def_state), arena.alloc(loc_ret)),
state, state,
)); ));
} }
@ -1505,12 +1102,17 @@ fn finish_parsing_alias_or_opaque<'a>(
} }
}; };
let def_state = DefState { let mut defs = Defs::default();
defs: bumpalo::vec![in arena; loc_def],
spaces_after: &[],
};
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 { mod ability {
@ -1632,33 +1234,6 @@ mod ability {
} }
} }
fn finish_parsing_ability_def<'a>(
start_column: u32,
name: Loc<&'a str>,
args: &'a [Loc<Pattern<'a>>],
loc_has: Loc<Has<'a>>,
spaces_before: &'a [CommentOrNewline<'a>],
arena: &'a Bump,
state: State<'a>,
) -> ParseResult<'a, &'a Loc<Def<'a>>, 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>( fn finish_parsing_ability_def_help<'a>(
start_column: u32, start_column: u32,
name: Loc<&'a str>, name: Loc<&'a str>,
@ -1714,26 +1289,6 @@ fn finish_parsing_ability_def_help<'a>(
Ok((MadeProgress, (type_def, def_region), state)) Ok((MadeProgress, (type_def, def_region), state))
} }
fn finish_parsing_ability<'a>(
start_column: u32,
options: ExprParseOptions,
name: Loc<&'a str>,
args: &'a [Loc<Pattern<'a>>],
loc_has: Loc<Has<'a>>,
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>( fn parse_expr_operator<'a>(
min_indent: u32, min_indent: u32,
options: ExprParseOptions, options: ExprParseOptions,
@ -1788,7 +1343,7 @@ fn parse_expr_operator<'a>(
.validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction) .validate_assignment_or_backpassing(arena, loc_op, EExpr::ElmStyleFunction)
.map_err(|fail| (MadeProgress, fail, state.clone()))?; .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) { match expr_to_pattern_help(arena, &call.value) {
Ok(good) => { Ok(good) => {
let (_, mut body, state) = parse_loc_expr(indented_more, arena, state)?; let (_, mut body, state) = parse_loc_expr(indented_more, arena, state)?;
@ -1805,10 +1360,9 @@ fn parse_expr_operator<'a>(
let alias = ValueDef::Body( let alias = ValueDef::Body(
arena.alloc(Loc::at(expr_region, good)), arena.alloc(Loc::at(expr_region, good)),
arena.alloc(body), arena.alloc(body),
) );
.into();
(&*arena.alloc(Loc::at(body_region, alias)), state) (alias, body_region, state)
} }
Err(_) => { Err(_) => {
// this `=` likely occurred inline; treat it as an invalid operator // this `=` likely occurred inline; treat it as an invalid operator
@ -1819,12 +1373,10 @@ fn parse_expr_operator<'a>(
} }
}; };
let def_state = DefState { let mut defs = Defs::default();
defs: bumpalo::vec![in arena; loc_def], defs.push_value_def(value_def, def_region, &[], &[]);
spaces_after: &[],
};
parse_defs_expr(options, start_column, def_state, arena, state) parse_defs_expr(options, start_column, defs, arena, state)
} }
BinOp::Backpassing => { BinOp::Backpassing => {
let expr_region = expr_state.expr.region; let expr_region = expr_state.expr.region;
@ -2000,15 +1552,15 @@ fn parse_expr_end<'a>(
Loc::at(has.region, Has::Has) Loc::at(has.region, Has::Has)
}; };
finish_parsing_ability( let args = arguments.into_bump_slice();
start_column, let (_, (type_def, def_region), state) =
options, finish_parsing_ability_def_help(start_column, name, args, has, arena, state)?;
name,
arguments.into_bump_slice(), let mut defs = Defs::default();
has,
arena, defs.push_type_def(type_def, def_region, &[], &[]);
state,
) parse_defs_expr(options, start_column, defs, arena, state)
} }
Ok((_, mut arg, state)) => { Ok((_, mut arg, state)) => {
let new_end = state.pos(); 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 mut output = Defs::default();
let before = Slice::extend_new(&mut output.spaces, initial_space.iter().copied()); let before = Slice::extend_new(&mut output.spaces, initial_space.iter().copied());
let (_, mut output, state) = let (_, mut output, state) = parse_defs_end(options, start_column, output, arena, state)?;
parse_toplevel_defs_end(options, start_column, output, arena, state)?;
let (_, final_space, state) = let (_, final_space, state) =
space0_e(start_column, EExpr::IndentEnd).parse(arena, 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<Def<'a>>>, 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 // PARSER HELPERS
fn closure_help<'a>( fn closure_help<'a>(

View file

@ -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::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::header::{ use crate::header::{
package_entry, package_name, AppHeader, ExposedName, HostedHeader, ImportsEntry, package_entry, package_name, AppHeader, ExposedName, HostedHeader, ImportsEntry,
@ -14,7 +14,6 @@ use crate::parser::{
use crate::state::State; use crate::state::State;
use crate::string_literal; use crate::string_literal;
use crate::type_annotation; use crate::type_annotation;
use bumpalo::collections::Vec;
use roc_region::all::{Loc, Position}; use roc_region::all::{Loc, Position};
fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> { 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<Def<'a>>>, 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>( pub fn parse_header<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
state: State<'a>, state: State<'a>,

View file

@ -1,7 +1,6 @@
use crate::ast; use crate::ast;
use crate::ast::Def; use crate::ast::Defs;
use crate::module::module_defs_help; use crate::module::module_defs;
// use crate::module::module_defs;
use crate::parser::Parser; use crate::parser::Parser;
use crate::parser::SourceError; use crate::parser::SourceError;
use crate::parser::SyntaxError; use crate::parser::SyntaxError;
@ -32,13 +31,10 @@ pub fn parse_loc_with<'a>(
} }
} }
pub fn parse_defs_with<'a>( pub fn parse_defs_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Defs<'a>, SyntaxError<'a>> {
arena: &'a Bump,
input: &'a str,
) -> Result<bumpalo::collections::Vec<'a, Loc<Def<'a>>>, SyntaxError<'a>> {
let state = State::new(input.trim().as_bytes()); 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), Ok(tuple) => Ok(tuple.1),
Err(tuple) => Err(tuple.1), Err(tuple) => Err(tuple.1),
} }

View file

@ -1,6 +1,19 @@
Defs( Defs(
[ Defs {
@0-36 Type( tags: [
Index(0),
],
regions: [
@0-36,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [
Ability { Ability {
header: TypeHeader { header: TypeHeader {
name: @0-4 "Hash", name: @0-4 "Hash",
@ -30,8 +43,9 @@ Defs(
}, },
], ],
}, },
), ],
], value_defs: [],
},
@38-39 SpaceBefore( @38-39 SpaceBefore(
Num( Num(
"1", "1",

View file

@ -1,6 +1,19 @@
Defs( Defs(
[ Defs {
@0-45 Type( tags: [
Index(0),
],
regions: [
@0-45,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [
Ability { Ability {
header: TypeHeader { header: TypeHeader {
name: @0-4 "Hash", name: @0-4 "Hash",
@ -50,8 +63,9 @@ Defs(
}, },
], ],
}, },
), ],
], value_defs: [],
},
@47-48 SpaceBefore( @47-48 SpaceBefore(
Num( Num(
"1", "1",

View file

@ -1,6 +1,19 @@
Defs( Defs(
[ Defs {
@0-37 Type( tags: [
Index(0),
],
regions: [
@0-37,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [
Ability { Ability {
header: TypeHeader { header: TypeHeader {
name: @0-4 "Hash", name: @0-4 "Hash",
@ -37,8 +50,9 @@ Defs(
}, },
], ],
}, },
), ],
], value_defs: [],
},
@39-40 SpaceBefore( @39-40 SpaceBefore(
Num( Num(
"1", "1",

View file

@ -1,6 +1,26 @@
Defs( Defs(
[ Defs {
@0-33 Type( 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 { Ability {
header: TypeHeader { header: TypeHeader {
name: @0-3 "Ab1", name: @0-3 "Ab1",
@ -36,51 +56,44 @@ Defs(
}, },
], ],
}, },
), Ability {
@35-68 SpaceBefore( header: TypeHeader {
Type( name: @35-38 "Ab2",
Ability { vars: [],
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",
[],
),
},
],
),
},
],
}, },
), loc_has: @39-42 Has,
[ members: [
Newline, AbilityMember {
Newline, 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( @70-71 SpaceBefore(
Num( Num(
"1", "1",

View file

@ -1,6 +1,37 @@
Defs( Defs(
[ Defs {
@15-49 Value( 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 { AnnotatedBody {
ann_pattern: @0-8 RecordDestructure( ann_pattern: @0-8 RecordDestructure(
[ [
@ -49,8 +80,8 @@ Defs(
], ],
), ),
}, },
), ],
], },
@51-52 SpaceBefore( @51-52 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,46 @@
Defs( Defs(
[ Defs {
@26-46 Value( 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 { AnnotatedBody {
ann_pattern: @0-8 Apply( ann_pattern: @0-8 Apply(
@0-6 Tag( @0-6 Tag(
@ -50,8 +90,8 @@ Defs(
Space, Space,
), ),
}, },
), ],
], },
@48-49 SpaceBefore( @48-49 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,7 +1,21 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@107-112 Value( 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( Body(
@107-108 Identifier( @107-108 Identifier(
"x", "x",
@ -10,8 +24,8 @@ SpaceBefore(
"5", "5",
), ),
), ),
), ],
], },
@114-116 SpaceBefore( @114-116 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-36 Value( 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( Body(
@0-5 Apply( @0-5 Apply(
@0-5 Tag( @0-5 Tag(
@ -26,8 +40,8 @@ Defs(
Space, Space,
), ),
), ),
), ],
], },
@37-40 SpaceBefore( @37-40 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-6 Value( 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( Body(
@0-4 Identifier( @0-4 Identifier(
"iffy", "iffy",
@ -9,8 +23,8 @@ Defs(
"5", "5",
), ),
), ),
), ],
], },
@8-10 SpaceBefore( @8-10 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-58 Value( 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( Body(
@0-7 Malformed( @0-7 Malformed(
"my_list", "my_list",
@ -63,8 +77,8 @@ Defs(
}, },
), ),
), ),
), ],
], },
@59-61 SpaceBefore( @59-61 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-26 Value( 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( Body(
@0-7 Malformed( @0-7 Malformed(
"my_list", "my_list",
@ -31,8 +45,8 @@ Defs(
}, },
), ),
), ),
), ],
], },
@27-29 SpaceBefore( @27-29 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-27 Value( 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( Body(
@0-7 Malformed( @0-7 Malformed(
"my_list", "my_list",
@ -31,8 +45,8 @@ Defs(
}, },
), ),
), ),
), ],
], },
@28-30 SpaceBefore( @28-30 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,7 +1,21 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@113-118 Value( 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( Body(
@113-114 Identifier( @113-114 Identifier(
"x", "x",
@ -10,8 +24,8 @@ SpaceBefore(
"5", "5",
), ),
), ),
), ],
], },
@120-122 SpaceBefore( @120-122 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -22,8 +22,22 @@ Defs {
), ),
@11-24 SpaceBefore( @11-24 SpaceBefore(
Defs( Defs(
[ Defs {
@11-17 Value( 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( Body(
@11-12 Identifier( @11-12 Identifier(
"i", "i",
@ -32,8 +46,8 @@ Defs {
"64", "64",
), ),
), ),
), ],
], },
@23-24 SpaceBefore( @23-24 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-10 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -15,8 +29,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@12-14 SpaceBefore( @12-14 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-19 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -17,8 +31,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@21-23 SpaceBefore( @21-23 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -22,8 +22,42 @@ Defs {
), ),
@11-115 SpaceBefore( @11-115 SpaceBefore(
Defs( Defs(
[ Defs {
@43-93 Value( 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 { AnnotatedBody {
ann_pattern: @11-23 Identifier( ann_pattern: @11-23 Identifier(
"wrappedNotEq", "wrappedNotEq",
@ -78,8 +112,8 @@ Defs {
), ),
), ),
}, },
), ],
], },
@99-115 SpaceBefore( @99-115 SpaceBefore(
Apply( Apply(
@99-111 Var { @99-111 Var {

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-9 Value( 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( Body(
@0-1 Identifier( @0-1 Identifier(
"x", "x",
@ -14,8 +28,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@11-13 SpaceBefore( @11-13 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-13 Value( 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( Body(
@0-1 Identifier( @0-1 Identifier(
"x", "x",
@ -24,8 +38,8 @@ Defs(
), ),
), ),
), ),
), ],
], },
@15-17 SpaceBefore( @15-17 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,7 +1,21 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@46-51 Value( 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( Body(
@46-47 Identifier( @46-47 Identifier(
"x", "x",
@ -10,8 +24,8 @@ SpaceBefore(
"5", "5",
), ),
), ),
), ],
], },
@53-55 SpaceBefore( @53-55 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,7 +1,21 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@18-21 Value( 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( Body(
@18-19 Identifier( @18-19 Identifier(
"x", "x",
@ -10,8 +24,8 @@ SpaceBefore(
"5", "5",
), ),
), ),
), ],
], },
@23-25 SpaceBefore( @23-25 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,7 +1,21 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@18-23 Value( 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( Body(
@18-19 Identifier( @18-19 Identifier(
"x", "x",
@ -10,8 +24,8 @@ SpaceBefore(
"5", "5",
), ),
), ),
), ],
], },
@25-27 SpaceBefore( @25-27 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,32 @@
Defs( Defs(
[ Defs {
@0-7 Type( 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 { Opaque {
header: TypeHeader { header: TypeHeader {
name: @0-1 "A", name: @0-1 "A",
@ -28,103 +54,88 @@ Defs(
), ),
), ),
}, },
), Opaque {
@24-44 SpaceBefore( header: TypeHeader {
Type( name: @24-25 "A",
Opaque { vars: [],
header: TypeHeader { },
name: @24-25 "A", typ: @29-44 Where(
vars: [], @29-30 BoundVariable(
}, "a",
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 { @50-52 Apply(
var: @33-34 "a", "",
ability: @39-44 Apply( "Eq",
"", [],
"Other", ),
[], @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", "Eq",
[], [],
), ),
@54-58 Apply( @96-100 Apply(
"", "",
"Hash", "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 { Newline,
var: @70-71 "a",
ability: @76-81 Apply(
"",
"Other",
[],
),
},
], ],
), ),
derived: Some( ),
@91-101 SpaceBefore( },
Has( ],
[ value_defs: [],
@92-94 Apply( },
"",
"Eq",
[],
),
@96-100 Apply(
"",
"Hash",
[],
),
],
),
[
Newline,
],
),
),
},
),
[
Newline,
Newline,
],
),
],
@103-104 SpaceBefore( @103-104 SpaceBefore(
Num( Num(
"0", "0",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-29 Value( 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( Body(
@0-1 Identifier( @0-1 Identifier(
"x", "x",
@ -48,8 +62,8 @@ Defs(
Space, Space,
), ),
), ),
), ],
], },
@30-31 SpaceBefore( @30-31 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-17 Value( 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( Body(
@0-1 Identifier( @0-1 Identifier(
"a", "a",
@ -29,8 +43,8 @@ Defs(
}, },
), ),
), ),
), ],
], },
@18-19 SpaceBefore( @18-19 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-23 Value( 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( Body(
@0-1 Identifier( @0-1 Identifier(
"x", "x",
@ -37,8 +51,8 @@ Defs(
Space, Space,
), ),
), ),
), ],
], },
@24-25 SpaceBefore( @24-25 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,19 @@
Defs( Defs(
[ Defs {
@0-26 Type( tags: [
Index(0),
],
regions: [
@0-26,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [
Alias { Alias {
header: TypeHeader { header: TypeHeader {
name: @0-4 "Blah", name: @0-4 "Blah",
@ -26,8 +39,9 @@ Defs(
], ],
), ),
}, },
), ],
], value_defs: [],
},
@28-30 SpaceBefore( @28-30 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-33 Value( 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( Annotation(
@0-3 Identifier( @0-3 Identifier(
"foo", "foo",
@ -32,8 +46,8 @@ Defs(
}, },
), ),
), ),
), ],
], },
@35-37 SpaceBefore( @35-37 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,7 +1,27 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@18-30 Value( 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( Body(
@18-26 RecordDestructure( @18-26 RecordDestructure(
[ [
@ -17,23 +37,16 @@ SpaceBefore(
"5", "5",
), ),
), ),
), Body(
@31-36 SpaceBefore( @31-32 Identifier(
Value( "y",
Body( ),
@31-32 Identifier( @35-36 Num(
"y", "6",
),
@35-36 Num(
"6",
),
), ),
), ),
[ ],
Newline, },
],
),
],
@38-40 SpaceBefore( @38-40 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-122 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -100,8 +114,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@124-126 SpaceBefore( @124-126 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-77 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"x", "x",
@ -69,8 +83,8 @@ Defs(
ext: None, ext: None,
}, },
), ),
), ],
], },
@79-81 SpaceBefore( @79-81 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,7 +1,27 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ Defs {
@18-23 Value( 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( Body(
@18-19 Identifier( @18-19 Identifier(
"x", "x",
@ -10,23 +30,16 @@ SpaceBefore(
"5", "5",
), ),
), ),
), Body(
@24-29 SpaceBefore( @24-25 Identifier(
Value( "y",
Body( ),
@24-25 Identifier( @28-29 Num(
"y", "6",
),
@28-29 Num(
"6",
),
), ),
), ),
[ ],
Newline, },
],
),
],
@31-33 SpaceBefore( @31-33 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-30 Value( 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( Annotation(
@0-7 Identifier( @0-7 Identifier(
"doStuff", "doStuff",
@ -27,8 +41,8 @@ Defs(
), ),
), ),
), ),
), ],
], },
@31-33 SpaceBefore( @31-33 SpaceBefore(
Num( Num(
"42", "42",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-27 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -35,8 +49,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@29-30 SpaceBefore( @29-30 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-48 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -51,8 +65,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@50-51 SpaceBefore( @50-51 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-67 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -66,8 +80,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@69-70 SpaceBefore( @69-70 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-15 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -21,8 +35,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@17-18 SpaceBefore( @17-18 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -1,6 +1,20 @@
Defs( Defs(
[ Defs {
@0-29 Value( 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( Annotation(
@0-1 Identifier( @0-1 Identifier(
"f", "f",
@ -35,8 +49,8 @@ Defs(
], ],
), ),
), ),
), ],
], },
@31-32 SpaceBefore( @31-32 SpaceBefore(
Var { Var {
module_name: "", module_name: "",

View file

@ -159,7 +159,7 @@ pub fn can_expr_with<'a>(
add_aliases(&mut scope, &mut var_store); add_aliases(&mut scope, &mut var_store);
let dep_idents = IdentIds::exposed_builtins(0); 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( let (loc_expr, output) = canonicalize_expr(
&mut env, &mut env,
&mut var_store, &mut var_store,