Split up Defs into TypeDef and ValueDef

Just a refactoring PR. This is useful because during canonicalization
we always process type defs first, then value defs. With abilities this
distinction continues to grow; in that case, we have patterns associated
with types that we want to process before patterns from values.
This commit is contained in:
Ayaz Hafiz 2022-04-06 22:18:57 -04:00
parent 37729c08cc
commit a3ac68a41f
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
46 changed files with 1611 additions and 1407 deletions

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, TypeHeader}; use roc_parse::ast::{self, TypeDef, TypeHeader, ValueDef as AstValueDef};
use roc_parse::pattern::PatternType; use roc_parse::pattern::PatternType;
use roc_problem::can::{Problem, RuntimeError}; use roc_problem::can::{Problem, RuntimeError};
use roc_region::all::{Loc, Region}; use roc_region::all::{Loc, Region};
@ -133,7 +133,7 @@ fn to_pending_def<'a>(
use roc_parse::ast::Def::*; use roc_parse::ast::Def::*;
match def { match def {
Annotation(loc_pattern, loc_ann) => { Value(AstValueDef::Annotation(loc_pattern, loc_ann)) => {
// This takes care of checking for shadowing and adding idents to scope. // This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = pattern::to_pattern_id( let (output, loc_can_pattern) = pattern::to_pattern_id(
env, env,
@ -148,7 +148,7 @@ fn to_pending_def<'a>(
PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann), PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann),
)) ))
} }
Body(loc_pattern, loc_expr) => { Value(AstValueDef::Body(loc_pattern, loc_expr)) => {
// This takes care of checking for shadowing and adding idents to scope. // This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = pattern::to_pattern_id( let (output, loc_can_pattern) = pattern::to_pattern_id(
env, env,
@ -164,13 +164,13 @@ fn to_pending_def<'a>(
)) ))
} }
AnnotatedBody { Value(AstValueDef::AnnotatedBody {
ann_pattern, ann_pattern,
ann_type, ann_type,
comment: _, comment: _,
body_pattern, body_pattern,
body_expr, body_expr,
} => { }) => {
if ann_pattern.value.equivalent(&body_pattern.value) { if ann_pattern.value.equivalent(&body_pattern.value) {
// NOTE: Pick the body pattern, picking the annotation one is // NOTE: Pick the body pattern, picking the annotation one is
// incorrect in the presence of optional record fields! // incorrect in the presence of optional record fields!
@ -199,10 +199,10 @@ fn to_pending_def<'a>(
} }
} }
roc_parse::ast::Def::Alias { Type(TypeDef::Alias {
header: TypeHeader { name, vars }, header: TypeHeader { name, vars },
ann, ann,
} => { }) => {
let region = Region::span_across(&name.region, &ann.region); let region = Region::span_across(&name.region, &ann.region);
match scope.introduce( match scope.introduce(
@ -261,10 +261,10 @@ fn to_pending_def<'a>(
} }
} }
Opaque { .. } => todo_opaques!(), Type(TypeDef::Opaque { .. }) => todo_opaques!(),
Ability { .. } => todo_abilities!(), Type(TypeDef::Ability { .. }) => todo_abilities!(),
Expect(_) => todo!(), Value(AstValueDef::Expect(_)) => todo!(),
SpaceBefore(sub_def, _) | SpaceAfter(sub_def, _) => { SpaceBefore(sub_def, _) | SpaceAfter(sub_def, _) => {
to_pending_def(env, sub_def, scope, pattern_type) to_pending_def(env, sub_def, scope, pattern_type)
@ -608,7 +608,7 @@ fn canonicalize_pending_def<'a>(
pattern_id: loc_can_pattern, pattern_id: loc_can_pattern,
expr_id: env.pool.add(loc_can_expr), expr_id: env.pool.add(loc_can_expr),
type_id: annotation, type_id: annotation,
rigids: rigids, rigids,
expr_var: env.var_store.fresh(), expr_var: env.var_store.fresh(),
}; };

View file

@ -72,7 +72,7 @@ pub fn def_to_def2<'a>(
def_to_def2(arena, env, scope, inner_def, region) def_to_def2(arena, env, scope, inner_def, region)
} }
} }
Body(&loc_pattern, &loc_expr) => { Value(roc_parse::ast::ValueDef::Body(&loc_pattern, &loc_expr)) => {
let expr2 = loc_expr_to_expr2(arena, loc_expr, env, scope, region).0; let expr2 = loc_expr_to_expr2(arena, loc_expr, env, scope, region).0;
let expr_id = env.pool.add(expr2); let expr_id = env.pool.add(expr2);

View file

@ -11,7 +11,7 @@ use roc_fmt::Buf;
use roc_module::called_via::{BinOp, UnaryOp}; use roc_module::called_via::{BinOp, UnaryOp};
use roc_parse::ast::{ use roc_parse::ast::{
AbilityMember, AssignedField, Collection, Expr, Has, HasClause, Pattern, Spaced, StrLiteral, AbilityMember, AssignedField, Collection, Expr, Has, HasClause, Pattern, Spaced, StrLiteral,
StrSegment, Tag, TypeAnnotation, TypeHeader, WhenBranch, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch,
}; };
use roc_parse::header::{ use roc_parse::header::{
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry, AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
@ -445,54 +445,36 @@ impl<'a, T: RemoveSpaces<'a>> RemoveSpaces<'a> for &'a T {
} }
} }
impl<'a> RemoveSpaces<'a> for Def<'a> { impl<'a> RemoveSpaces<'a> for TypeDef<'a> {
fn remove_spaces(&self, arena: &'a Bump) -> Self { fn remove_spaces(&self, arena: &'a Bump) -> Self {
use TypeDef::*;
match *self { match *self {
Def::Annotation(a, b) => { Alias {
Def::Annotation(a.remove_spaces(arena), b.remove_spaces(arena))
}
Def::Alias {
header: TypeHeader { name, vars }, header: TypeHeader { name, vars },
ann, ann,
} => Def::Alias { } => Alias {
header: TypeHeader { header: TypeHeader {
name: name.remove_spaces(arena), name: name.remove_spaces(arena),
vars: vars.remove_spaces(arena), vars: vars.remove_spaces(arena),
}, },
ann: ann.remove_spaces(arena), ann: ann.remove_spaces(arena),
}, },
Def::Opaque { Opaque {
header: TypeHeader { name, vars }, header: TypeHeader { name, vars },
typ, typ,
} => Def::Opaque { } => Opaque {
header: TypeHeader { header: TypeHeader {
name: name.remove_spaces(arena), name: name.remove_spaces(arena),
vars: vars.remove_spaces(arena), vars: vars.remove_spaces(arena),
}, },
typ: typ.remove_spaces(arena), typ: typ.remove_spaces(arena),
}, },
Def::Body(a, b) => Def::Body( Ability {
arena.alloc(a.remove_spaces(arena)),
arena.alloc(b.remove_spaces(arena)),
),
Def::AnnotatedBody {
ann_pattern,
ann_type,
comment: _,
body_pattern,
body_expr,
} => Def::AnnotatedBody {
ann_pattern: arena.alloc(ann_pattern.remove_spaces(arena)),
ann_type: arena.alloc(ann_type.remove_spaces(arena)),
comment: None,
body_pattern: arena.alloc(body_pattern.remove_spaces(arena)),
body_expr: arena.alloc(body_expr.remove_spaces(arena)),
},
Def::Ability {
header: TypeHeader { name, vars }, header: TypeHeader { name, vars },
loc_has, loc_has,
members, members,
} => Def::Ability { } => Ability {
header: TypeHeader { header: TypeHeader {
name: name.remove_spaces(arena), name: name.remove_spaces(arena),
vars: vars.remove_spaces(arena), vars: vars.remove_spaces(arena),
@ -500,7 +482,43 @@ impl<'a> RemoveSpaces<'a> for Def<'a> {
loc_has: loc_has.remove_spaces(arena), loc_has: loc_has.remove_spaces(arena),
members: members.remove_spaces(arena), members: members.remove_spaces(arena),
}, },
Def::Expect(a) => Def::Expect(arena.alloc(a.remove_spaces(arena))), }
}
}
impl<'a> RemoveSpaces<'a> for ValueDef<'a> {
fn remove_spaces(&self, arena: &'a Bump) -> Self {
use ValueDef::*;
match *self {
Annotation(a, b) => Annotation(a.remove_spaces(arena), b.remove_spaces(arena)),
Body(a, b) => Body(
arena.alloc(a.remove_spaces(arena)),
arena.alloc(b.remove_spaces(arena)),
),
AnnotatedBody {
ann_pattern,
ann_type,
comment: _,
body_pattern,
body_expr,
} => AnnotatedBody {
ann_pattern: arena.alloc(ann_pattern.remove_spaces(arena)),
ann_type: arena.alloc(ann_type.remove_spaces(arena)),
comment: None,
body_pattern: arena.alloc(body_pattern.remove_spaces(arena)),
body_expr: arena.alloc(body_expr.remove_spaces(arena)),
},
Expect(a) => Expect(arena.alloc(a.remove_spaces(arena))),
}
}
}
impl<'a> RemoveSpaces<'a> for Def<'a> {
fn remove_spaces(&self, arena: &'a Bump) -> Self {
match *self {
Def::Type(def) => Def::Type(def.remove_spaces(arena)),
Def::Value(def) => Def::Value(def.remove_spaces(arena)),
Def::NotYetImplemented(a) => Def::NotYetImplemented(a), Def::NotYetImplemented(a) => Def::NotYetImplemented(a),
Def::SpaceBefore(a, _) | Def::SpaceAfter(a, _) => a.remove_spaces(arena), Def::SpaceBefore(a, _) | Def::SpaceAfter(a, _) => a.remove_spaces(arena),
} }

View file

@ -49,11 +49,12 @@ pub struct CanDefs {
pub can_defs_by_symbol: MutMap<Symbol, Def>, pub can_defs_by_symbol: MutMap<Symbol, Def>,
pub aliases: SendMap<Symbol, Alias>, pub aliases: SendMap<Symbol, Alias>,
} }
/// A Def that has had patterns and type annnotations canonicalized, /// A Def that has had patterns and type annnotations canonicalized,
/// but no Expr canonicalization has happened yet. Also, it has had spaces /// but no Expr canonicalization has happened yet. Also, it has had spaces
/// and nesting resolved, and knows whether annotations are standalone or not. /// and nesting resolved, and knows whether annotations are standalone or not.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
enum PendingDef<'a> { enum PendingValueDef<'a> {
/// A standalone annotation with no body /// A standalone annotation with no body
AnnotationOnly( AnnotationOnly(
&'a Loc<ast::Pattern<'a>>, &'a Loc<ast::Pattern<'a>>,
@ -73,7 +74,10 @@ enum PendingDef<'a> {
&'a Loc<ast::TypeAnnotation<'a>>, &'a Loc<ast::TypeAnnotation<'a>>,
&'a Loc<ast::Expr<'a>>, &'a Loc<ast::Expr<'a>>,
), ),
}
#[derive(Debug, Clone, PartialEq)]
enum PendingTypeDef<'a> {
/// A structural or opaque type alias, e.g. `Ints : List Int` or `Age := U32` respectively. /// A structural or opaque type alias, e.g. `Ints : List Int` or `Age := U32` respectively.
Alias { Alias {
name: Loc<Symbol>, name: Loc<Symbol>,
@ -206,56 +210,40 @@ pub fn canonicalize_defs<'a>(
let num_defs = loc_defs.len(); let num_defs = loc_defs.len();
let mut refs_by_symbol = MutMap::default(); let mut refs_by_symbol = MutMap::default();
let mut can_defs_by_symbol = HashMap::with_capacity_and_hasher(num_defs, default_hasher()); let mut can_defs_by_symbol = HashMap::with_capacity_and_hasher(num_defs, default_hasher());
let mut pending = Vec::with_capacity(num_defs); // TODO bump allocate this!
// Canonicalize all the patterns, record shadowing problems, and store let mut type_defs = Vec::with_capacity(num_defs);
// the ast::Expr values in pending_exprs for further canonicalization let mut value_defs = Vec::with_capacity(num_defs);
// once we've finished assembling the entire scope.
for loc_def in loc_defs { for loc_def in loc_defs {
match to_pending_def(env, var_store, &loc_def.value, &mut scope, pattern_type) { match loc_def.value.unroll_def() {
None => (), Ok(type_def) => type_defs.push(Loc::at(loc_def.region, type_def)),
Some((new_output, pending_def)) => { Err(value_def) => value_defs.push(Loc::at(loc_def.region, value_def)),
// store the top-level defs, used to ensure that closures won't capture them
if let PatternType::TopLevelDef = pattern_type {
match &pending_def {
PendingDef::AnnotationOnly(_, loc_can_pattern, _)
| PendingDef::Body(_, loc_can_pattern, _)
| PendingDef::TypedBody(_, loc_can_pattern, _, _) => {
env.top_level_symbols.extend(
bindings_from_patterns(std::iter::once(loc_can_pattern))
.iter()
.map(|t| t.0),
)
}
// Type definitions aren't value definitions, so we don't need to do
// anything for them here.
PendingDef::Alias { .. } | PendingDef::InvalidAlias { .. } => {}
}
}
// Record the ast::Expr for later. We'll do another pass through these
// once we have the entire scope assembled. If we were to canonicalize
// the exprs right now, they wouldn't have symbols in scope from defs
// that get would have gotten added later in the defs list!
pending.push(pending_def);
output.union(new_output);
}
} }
} }
// We need to canonicalize all the type defs first.
let pending_type_defs = type_defs
.into_iter()
.filter_map(|loc_def| {
to_pending_type_def(env, &loc_def.value, &mut scope).map(|(new_output, pending_def)| {
output.union(new_output);
pending_def
})
})
.collect::<Vec<_>>();
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
env.home.register_debug_idents(&env.ident_ids); env.home.register_debug_idents(&env.ident_ids);
} }
let mut aliases = SendMap::default(); let mut aliases = SendMap::default();
let mut value_defs = Vec::new();
let mut alias_defs = MutMap::default(); let mut alias_defs = MutMap::default();
let mut referenced_type_symbols = MutMap::default(); let mut referenced_type_symbols = MutMap::default();
for pending_def in pending.into_iter() { for pending_def in pending_type_defs.into_iter() {
match pending_def { match pending_def {
PendingDef::Alias { PendingTypeDef::Alias {
name, name,
vars, vars,
ann, ann,
@ -271,7 +259,7 @@ pub fn canonicalize_defs<'a>(
alias_defs.insert(name.value, (name, vars, ann, kind)); alias_defs.insert(name.value, (name, vars, ann, kind));
} }
other => value_defs.push(other), PendingTypeDef::InvalidAlias { .. } => { /* ignore */ }
} }
} }
@ -373,8 +361,41 @@ pub fn canonicalize_defs<'a>(
// Now that we have the scope completely assembled, and shadowing resolved, // Now that we have the scope completely assembled, and shadowing resolved,
// we're ready to canonicalize any body exprs. // we're ready to canonicalize any body exprs.
for pending_def in value_defs.into_iter() {
output = canonicalize_pending_def( // 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.
let mut pending_value_defs = Vec::with_capacity(value_defs.len());
for loc_def in value_defs.into_iter() {
match to_pending_value_def(env, var_store, &loc_def.value, &mut scope, pattern_type) {
None => { /* skip */ }
Some((new_output, pending_def)) => {
// store the top-level defs, used to ensure that closures won't capture them
if let PatternType::TopLevelDef = pattern_type {
match &pending_def {
PendingValueDef::AnnotationOnly(_, loc_can_pattern, _)
| PendingValueDef::Body(_, loc_can_pattern, _)
| PendingValueDef::TypedBody(_, loc_can_pattern, _, _) => {
env.top_level_symbols.extend(
bindings_from_patterns(std::iter::once(loc_can_pattern))
.iter()
.map(|t| t.0),
)
}
}
}
// Record the ast::Expr for later. We'll do another pass through these
// once we have the entire scope assembled. If we were to canonicalize
// the exprs right now, they wouldn't have symbols in scope from defs
// that get would have gotten added later in the defs list!
pending_value_defs.push(pending_def);
output.union(new_output);
}
}
}
for pending_def in pending_value_defs.into_iter() {
output = canonicalize_pending_value_def(
env, env,
pending_def, pending_def,
output, output,
@ -910,9 +931,9 @@ fn add_annotation_aliases(
// TODO trim down these arguments! // TODO trim down these arguments!
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
fn canonicalize_pending_def<'a>( fn canonicalize_pending_value_def<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,
pending_def: PendingDef<'a>, pending_def: PendingValueDef<'a>,
mut output: Output, mut output: Output,
scope: &mut Scope, scope: &mut Scope,
can_defs_by_symbol: &mut MutMap<Symbol, Def>, can_defs_by_symbol: &mut MutMap<Symbol, Def>,
@ -920,7 +941,7 @@ fn canonicalize_pending_def<'a>(
refs_by_symbol: &mut MutMap<Symbol, (Region, References)>, refs_by_symbol: &mut MutMap<Symbol, (Region, References)>,
aliases: &mut ImMap<Symbol, Alias>, aliases: &mut ImMap<Symbol, Alias>,
) -> Output { ) -> Output {
use PendingDef::*; use PendingValueDef::*;
// Make types for the body expr, even if we won't end up having a body. // Make types for the body expr, even if we won't end up having a body.
let expr_var = var_store.fresh(); let expr_var = var_store.fresh();
@ -1047,11 +1068,6 @@ fn canonicalize_pending_def<'a>(
} }
} }
Alias { .. } => unreachable!("Aliases are handled in a separate pass"),
InvalidAlias { .. } => {
// invalid aliases and opaques (shadowed, incorrect patterns) get ignored
}
TypedBody(_loc_pattern, loc_can_pattern, loc_ann, loc_expr) => { TypedBody(_loc_pattern, loc_can_pattern, loc_ann, loc_expr) => {
let type_annotation = let type_annotation =
canonicalize_annotation(env, scope, &loc_ann.value, loc_ann.region, var_store); canonicalize_annotation(env, scope, &loc_ann.value, loc_ann.region, var_store);
@ -1446,85 +1462,14 @@ fn closure_recursivity(symbol: Symbol, closures: &MutMap<Symbol, References>) ->
Recursive::NotRecursive Recursive::NotRecursive
} }
fn to_pending_def<'a>( fn to_pending_type_def<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,
var_store: &mut VarStore, def: &'a ast::TypeDef<'a>,
def: &'a ast::Def<'a>,
scope: &mut Scope, scope: &mut Scope,
pattern_type: PatternType, ) -> Option<(Output, PendingTypeDef<'a>)> {
) -> Option<(Output, PendingDef<'a>)> { use ast::TypeDef::*;
use roc_parse::ast::Def::*;
match def { match def {
Annotation(loc_pattern, loc_ann) => {
// This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = canonicalize_pattern(
env,
var_store,
scope,
pattern_type,
&loc_pattern.value,
loc_pattern.region,
);
Some((
output,
PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann),
))
}
Body(loc_pattern, loc_expr) => {
// This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = canonicalize_pattern(
env,
var_store,
scope,
pattern_type,
&loc_pattern.value,
loc_pattern.region,
);
Some((
output,
PendingDef::Body(loc_pattern, loc_can_pattern, loc_expr),
))
}
AnnotatedBody {
ann_pattern,
ann_type,
comment: _,
body_pattern,
body_expr,
} => {
if ann_pattern.value.equivalent(&body_pattern.value) {
// NOTE: Pick the body pattern, picking the annotation one is
// incorrect in the presence of optional record fields!
//
// { x, y } : { x : Int, y ? Bool }*
// { x, y ? False } = rec
Some(pending_typed_body(
env,
body_pattern,
ann_type,
body_expr,
var_store,
scope,
pattern_type,
))
} else {
// the pattern of the annotation does not match the pattern of the body direc
env.problems.push(Problem::SignatureDefMismatch {
annotation_pattern: ann_pattern.region,
def_pattern: body_pattern.region,
});
// TODO: Should we instead build some PendingDef::InvalidAnnotatedBody ? This would
// remove the `Option` on this function (and be probably more reliable for further
// problem/error reporting)
None
}
}
Alias { Alias {
header: TypeHeader { name, vars }, header: TypeHeader { name, vars },
ann, ann,
@ -1571,7 +1516,7 @@ fn to_pending_def<'a>(
return Some(( return Some((
Output::default(), Output::default(),
PendingDef::InvalidAlias { kind }, PendingTypeDef::InvalidAlias { kind },
)); ));
} }
} }
@ -1582,7 +1527,7 @@ fn to_pending_def<'a>(
value: symbol, value: symbol,
}; };
let pending_def = PendingDef::Alias { let pending_def = PendingTypeDef::Alias {
name, name,
vars: can_rigids, vars: can_rigids,
ann, ann,
@ -1598,20 +1543,12 @@ fn to_pending_def<'a>(
shadow: loc_shadowed_symbol, shadow: loc_shadowed_symbol,
}); });
Some((Output::default(), PendingDef::InvalidAlias { kind })) Some((Output::default(), PendingTypeDef::InvalidAlias { kind }))
} }
} }
} }
Ability { .. } => todo_abilities!(), Ability { .. } => todo_abilities!(),
Expect(_condition) => todo!(),
SpaceBefore(sub_def, _) | SpaceAfter(sub_def, _) => {
to_pending_def(env, var_store, sub_def, scope, pattern_type)
}
NotYetImplemented(s) => todo!("{}", s),
} }
} }
@ -1623,7 +1560,7 @@ fn pending_typed_body<'a>(
var_store: &mut VarStore, var_store: &mut VarStore,
scope: &mut Scope, scope: &mut Scope,
pattern_type: PatternType, pattern_type: PatternType,
) -> (Output, PendingDef<'a>) { ) -> (Output, PendingValueDef<'a>) {
// This takes care of checking for shadowing and adding idents to scope. // This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = canonicalize_pattern( let (output, loc_can_pattern) = canonicalize_pattern(
env, env,
@ -1636,10 +1573,93 @@ fn pending_typed_body<'a>(
( (
output, output,
PendingDef::TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr), PendingValueDef::TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr),
) )
} }
fn to_pending_value_def<'a>(
env: &mut Env<'a>,
var_store: &mut VarStore,
def: &'a ast::ValueDef<'a>,
scope: &mut Scope,
pattern_type: PatternType,
) -> Option<(Output, PendingValueDef<'a>)> {
use ast::ValueDef::*;
match def {
Annotation(loc_pattern, loc_ann) => {
// This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = canonicalize_pattern(
env,
var_store,
scope,
pattern_type,
&loc_pattern.value,
loc_pattern.region,
);
Some((
output,
PendingValueDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann),
))
}
Body(loc_pattern, loc_expr) => {
// This takes care of checking for shadowing and adding idents to scope.
let (output, loc_can_pattern) = canonicalize_pattern(
env,
var_store,
scope,
pattern_type,
&loc_pattern.value,
loc_pattern.region,
);
Some((
output,
PendingValueDef::Body(loc_pattern, loc_can_pattern, loc_expr),
))
}
AnnotatedBody {
ann_pattern,
ann_type,
comment: _,
body_pattern,
body_expr,
} => {
if ann_pattern.value.equivalent(&body_pattern.value) {
// NOTE: Pick the body pattern, picking the annotation one is
// incorrect in the presence of optional record fields!
//
// { x, y } : { x : Int, y ? Bool }*
// { x, y ? False } = rec
Some(pending_typed_body(
env,
body_pattern,
ann_type,
body_expr,
var_store,
scope,
pattern_type,
))
} else {
// the pattern of the annotation does not match the pattern of the body direc
env.problems.push(Problem::SignatureDefMismatch {
annotation_pattern: ann_pattern.region,
def_pattern: body_pattern.region,
});
// TODO: Should we instead build some PendingValueDef::InvalidAnnotatedBody ? This would
// remove the `Option` on this function (and be probably more reliable for further
// problem/error reporting)
None
}
}
Expect(_condition) => todo!(),
}
}
/// Make aliases recursive /// Make aliases recursive
fn correct_mutual_recursive_type_alias<'a>( fn correct_mutual_recursive_type_alias<'a>(
env: &mut Env<'a>, env: &mut Env<'a>,

View file

@ -6,7 +6,7 @@ use roc_module::called_via::BinOp::Pizza;
use roc_module::called_via::{BinOp, CalledVia}; use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName; use roc_module::ident::ModuleName;
use roc_parse::ast::Expr::{self, *}; use roc_parse::ast::Expr::{self, *};
use roc_parse::ast::{AssignedField, Def, WhenBranch}; use roc_parse::ast::{AssignedField, Def, TypeDef, ValueDef, WhenBranch};
use roc_region::all::{Loc, Region}; use roc_region::all::{Loc, Region};
// BinOp precedence logic adapted from Gluon by Markus Westerlind // BinOp precedence logic adapted from Gluon by Markus Westerlind
@ -88,15 +88,21 @@ fn desugar_def_helps<'a>(
}) })
} }
pub fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>) -> Def<'a> { fn desugar_type_def<'a>(def: &'a TypeDef<'a>) -> TypeDef<'a> {
use roc_parse::ast::Def::*; use TypeDef::*;
match def { match def {
Body(loc_pattern, loc_expr) => Body(loc_pattern, desugar_expr(arena, loc_expr)),
SpaceBefore(def, _) | SpaceAfter(def, _) => desugar_def(arena, def),
alias @ Alias { .. } => *alias, alias @ Alias { .. } => *alias,
opaque @ Opaque { .. } => *opaque, opaque @ Opaque { .. } => *opaque,
ability @ Ability { .. } => *ability, ability @ Ability { .. } => *ability,
}
}
fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a> {
use ValueDef::*;
match def {
Body(loc_pattern, loc_expr) => Body(loc_pattern, desugar_expr(arena, loc_expr)),
ann @ Annotation(_, _) => *ann, ann @ Annotation(_, _) => *ann,
AnnotatedBody { AnnotatedBody {
ann_pattern, ann_pattern,
@ -115,6 +121,16 @@ pub fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>) -> Def<'a> {
let desugared_condition = &*arena.alloc(desugar_expr(arena, condition)); let desugared_condition = &*arena.alloc(desugar_expr(arena, condition));
Expect(desugared_condition) Expect(desugared_condition)
} }
}
}
pub fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>) -> Def<'a> {
use roc_parse::ast::Def::*;
match def {
Type(type_def) => Type(desugar_type_def(type_def)),
Value(value_def) => Value(desugar_value_def(arena, value_def)),
SpaceBefore(def, _) | SpaceAfter(def, _) => desugar_def(arena, def),
NotYetImplemented(s) => todo!("{}", s), NotYetImplemented(s) => todo!("{}", s),
} }
} }

View file

@ -9,20 +9,28 @@ use roc_region::all::Loc;
impl<'a> Formattable for Def<'a> { impl<'a> Formattable for Def<'a> {
fn is_multiline(&self) -> bool { fn is_multiline(&self) -> bool {
use roc_parse::ast::Def::*; use roc_parse::ast::Def::*;
use roc_parse::ast::TypeDef::*;
use roc_parse::ast::ValueDef::*;
match self { match self {
Alias { ann, .. } => ann.is_multiline(), Type(def) => match def {
Opaque { typ, .. } => typ.is_multiline(), Alias { ann, .. } => ann.is_multiline(),
Annotation(loc_pattern, loc_annotation) => { Opaque { typ, .. } => typ.is_multiline(),
loc_pattern.is_multiline() || loc_annotation.is_multiline() Ability { members, .. } => members.iter().any(|d| d.is_multiline()),
} },
Body(loc_pattern, loc_expr) => loc_pattern.is_multiline() || loc_expr.is_multiline(), Value(def) => match def {
AnnotatedBody { .. } => true, Annotation(loc_pattern, loc_annotation) => {
Expect(loc_expr) => loc_expr.is_multiline(), loc_pattern.is_multiline() || loc_annotation.is_multiline()
}
Body(loc_pattern, loc_expr) => {
loc_pattern.is_multiline() || loc_expr.is_multiline()
}
AnnotatedBody { .. } => true,
Expect(loc_expr) => loc_expr.is_multiline(),
},
SpaceBefore(sub_def, spaces) | SpaceAfter(sub_def, spaces) => { SpaceBefore(sub_def, spaces) | SpaceAfter(sub_def, spaces) => {
spaces.iter().any(|s| s.is_comment()) || sub_def.is_multiline() spaces.iter().any(|s| s.is_comment()) || sub_def.is_multiline()
} }
Ability { members, .. } => members.iter().any(|d| d.is_multiline()),
NotYetImplemented(s) => todo!("{}", s), NotYetImplemented(s) => todo!("{}", s),
} }
} }
@ -35,104 +43,110 @@ impl<'a> Formattable for Def<'a> {
indent: u16, indent: u16,
) { ) {
use roc_parse::ast::Def::*; use roc_parse::ast::Def::*;
use roc_parse::ast::TypeDef::*;
use roc_parse::ast::ValueDef::*;
match self { match self {
Annotation(loc_pattern, loc_annotation) => { Type(def) => match def {
loc_pattern.format(buf, indent); Alias {
if loc_annotation.is_multiline() { header: TypeHeader { name, vars },
buf.push_str(" :"); ann,
loc_annotation.format_with_options(
buf,
Parens::NotNeeded,
Newlines::Yes,
indent + INDENT,
);
} else {
buf.spaces(1);
buf.push_str(":");
buf.spaces(1);
loc_annotation.format_with_options(
buf,
Parens::NotNeeded,
Newlines::No,
indent,
);
} }
} | Opaque {
Alias { header: TypeHeader { name, vars },
header: TypeHeader { name, vars }, typ: ann,
ann, } => {
} buf.indent(indent);
| Opaque { buf.push_str(name.value);
header: TypeHeader { name, vars },
typ: ann,
} => {
buf.indent(indent);
buf.push_str(name.value);
for var in *vars { for var in *vars {
buf.spaces(1);
fmt_pattern(buf, &var.value, indent, Parens::NotNeeded);
}
buf.push_str(match def {
Alias { .. } => " :",
Opaque { .. } => " :=",
_ => unreachable!(),
});
buf.spaces(1); buf.spaces(1);
fmt_pattern(buf, &var.value, indent, Parens::NotNeeded);
ann.format(buf, indent + INDENT)
} }
Ability {
header: TypeHeader { name, vars },
loc_has: _,
members,
} => {
buf.indent(indent);
buf.push_str(name.value);
for var in *vars {
buf.spaces(1);
fmt_pattern(buf, &var.value, indent, Parens::NotNeeded);
}
buf.push_str(match self { buf.push_str(" has");
Alias { .. } => " :",
Opaque { .. } => " :=",
_ => unreachable!(),
});
buf.spaces(1);
ann.format(buf, indent + INDENT) if !self.is_multiline() {
} debug_assert_eq!(members.len(), 1);
Ability { buf.push_str(" ");
header: TypeHeader { name, vars }, members[0].format(buf, indent + INDENT);
loc_has: _, } else {
members, for demand in members.iter() {
} => { buf.newline();
buf.indent(indent); buf.indent(indent + INDENT);
buf.push_str(name.value); demand.format(buf, indent + INDENT);
for var in *vars { }
buf.spaces(1);
fmt_pattern(buf, &var.value, indent, Parens::NotNeeded);
}
buf.push_str(" has");
if !self.is_multiline() {
debug_assert_eq!(members.len(), 1);
buf.push_str(" ");
members[0].format(buf, indent + INDENT);
} else {
for demand in members.iter() {
buf.newline();
buf.indent(indent + INDENT);
demand.format(buf, indent + INDENT);
} }
} }
} },
Body(loc_pattern, loc_expr) => { Value(def) => match def {
fmt_body(buf, &loc_pattern.value, &loc_expr.value, indent); Annotation(loc_pattern, loc_annotation) => {
} loc_pattern.format(buf, indent);
Expect(condition) => fmt_expect(buf, condition, self.is_multiline(), indent), if loc_annotation.is_multiline() {
AnnotatedBody { buf.push_str(" :");
ann_pattern, loc_annotation.format_with_options(
ann_type, buf,
comment, Parens::NotNeeded,
body_pattern, Newlines::Yes,
body_expr, indent + INDENT,
} => { );
ann_pattern.format(buf, indent); } else {
buf.push_str(" :"); buf.spaces(1);
buf.spaces(1); buf.push_str(":");
ann_type.format(buf, indent); buf.spaces(1);
if let Some(comment_str) = comment { loc_annotation.format_with_options(
buf.push_str(" #"); buf,
buf.spaces(1); Parens::NotNeeded,
buf.push_str(comment_str.trim()); Newlines::No,
indent,
);
}
} }
buf.newline(); Body(loc_pattern, loc_expr) => {
fmt_body(buf, &body_pattern.value, &body_expr.value, indent); fmt_body(buf, &loc_pattern.value, &loc_expr.value, indent);
} }
Expect(condition) => fmt_expect(buf, condition, self.is_multiline(), indent),
AnnotatedBody {
ann_pattern,
ann_type,
comment,
body_pattern,
body_expr,
} => {
ann_pattern.format(buf, indent);
buf.push_str(" :");
buf.spaces(1);
ann_type.format(buf, indent);
if let Some(comment_str) = comment {
buf.push_str(" #");
buf.spaces(1);
buf.push_str(comment_str.trim());
}
buf.newline();
fmt_body(buf, &body_pattern.value, &body_expr.value, indent);
}
},
SpaceBefore(sub_def, spaces) => { SpaceBefore(sub_def, spaces) => {
fmt_spaces(buf, spaces.iter(), indent); fmt_spaces(buf, spaces.iter(), indent);

View file

@ -7,9 +7,9 @@ use roc_can::scope::Scope;
use roc_error_macros::todo_abilities; use roc_error_macros::todo_abilities;
use roc_module::ident::ModuleName; use roc_module::ident::ModuleName;
use roc_module::symbol::IdentIds; use roc_module::symbol::IdentIds;
use roc_parse::ast::CommentOrNewline;
use roc_parse::ast::{self, TypeHeader}; use roc_parse::ast::{self, TypeHeader};
use roc_parse::ast::{AssignedField, Def}; use roc_parse::ast::{AssignedField, Def};
use roc_parse::ast::{CommentOrNewline, TypeDef, ValueDef};
use roc_region::all::Loc; use roc_region::all::Loc;
// Documentation generation requirements // Documentation generation requirements
@ -166,98 +166,105 @@ fn generate_entry_doc<'a>(
(new_acc, Some(comments_or_new_lines)) (new_acc, Some(comments_or_new_lines))
} }
Def::Annotation(loc_pattern, loc_ann) => match loc_pattern.value { Def::Value(def) => match def {
Pattern::Identifier(identifier) => { ValueDef::Annotation(loc_pattern, loc_ann) => match loc_pattern.value {
// Check if the definition is exposed Pattern::Identifier(identifier) => {
if ident_ids.get_id(&identifier.into()).is_some() { // Check if the definition is exposed
let name = identifier.to_string(); if ident_ids.get_id(&identifier.into()).is_some() {
let doc_def = DocDef { let name = identifier.to_string();
name, let doc_def = DocDef {
type_annotation: type_to_docs(false, loc_ann.value), name,
type_vars: Vec::new(), type_annotation: type_to_docs(false, loc_ann.value),
docs: before_comments_or_new_lines.and_then(comments_or_new_lines_to_docs), type_vars: Vec::new(),
}; docs: before_comments_or_new_lines
acc.push(DocEntry::DocDef(doc_def)); .and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
}
(acc, None)
} }
_ => (acc, None),
},
ValueDef::AnnotatedBody {
ann_pattern,
ann_type,
..
} => match ann_pattern.value {
Pattern::Identifier(identifier) => {
// Check if the definition is exposed
if ident_ids.get_id(&identifier.into()).is_some() {
let doc_def = DocDef {
name: identifier.to_string(),
type_annotation: type_to_docs(false, ann_type.value),
type_vars: Vec::new(),
docs: before_comments_or_new_lines
.and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
}
(acc, None)
}
_ => (acc, None),
},
ValueDef::Body(_, _) => (acc, None),
ValueDef::Expect(c) => todo!("documentation for tests {:?}", c),
},
Def::Type(def) => match def {
TypeDef::Alias {
header: TypeHeader { name, vars },
ann,
} => {
let mut type_vars = Vec::new();
for var in vars.iter() {
if let Pattern::Identifier(ident_name) = var.value {
type_vars.push(ident_name.to_string());
}
}
let doc_def = DocDef {
name: name.value.to_string(),
type_annotation: type_to_docs(false, ann.value),
type_vars,
docs: before_comments_or_new_lines.and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
(acc, None) (acc, None)
} }
_ => (acc, None), TypeDef::Opaque {
}, header: TypeHeader { name, vars },
Def::AnnotatedBody { ..
ann_pattern, } => {
ann_type, let mut type_vars = Vec::new();
..
} => match ann_pattern.value { for var in vars.iter() {
Pattern::Identifier(identifier) => { if let Pattern::Identifier(ident_name) = var.value {
// Check if the definition is exposed type_vars.push(ident_name.to_string());
if ident_ids.get_id(&identifier.into()).is_some() { }
let doc_def = DocDef {
name: identifier.to_string(),
type_annotation: type_to_docs(false, ann_type.value),
type_vars: Vec::new(),
docs: before_comments_or_new_lines.and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
} }
let doc_def = DocDef {
name: name.value.to_string(),
type_annotation: TypeAnnotation::NoTypeAnn,
type_vars,
docs: before_comments_or_new_lines.and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
(acc, None) (acc, None)
} }
_ => (acc, None), TypeDef::Ability { .. } => todo_abilities!(),
}, },
Def::Alias {
header: TypeHeader { name, vars },
ann,
} => {
let mut type_vars = Vec::new();
for var in vars.iter() {
if let Pattern::Identifier(ident_name) = var.value {
type_vars.push(ident_name.to_string());
}
}
let doc_def = DocDef {
name: name.value.to_string(),
type_annotation: type_to_docs(false, ann.value),
type_vars,
docs: before_comments_or_new_lines.and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
(acc, None)
}
Def::Opaque {
header: TypeHeader { name, vars },
..
} => {
let mut type_vars = Vec::new();
for var in vars.iter() {
if let Pattern::Identifier(ident_name) = var.value {
type_vars.push(ident_name.to_string());
}
}
let doc_def = DocDef {
name: name.value.to_string(),
type_annotation: TypeAnnotation::NoTypeAnn,
type_vars,
docs: before_comments_or_new_lines.and_then(comments_or_new_lines_to_docs),
};
acc.push(DocEntry::DocDef(doc_def));
(acc, None)
}
Def::Ability { .. } => todo_abilities!(),
Def::Body(_, _) => (acc, None),
Def::Expect(c) => todo!("documentation for tests {:?}", c),
Def::NotYetImplemented(s) => todo!("{}", s), Def::NotYetImplemented(s) => todo!("{}", s),
} }
} }

View file

@ -279,11 +279,7 @@ pub struct AbilityMember<'a> {
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum Def<'a> { pub enum TypeDef<'a> {
// TODO in canonicalization, validate the pattern; only certain patterns
// are allowed in annotations.
Annotation(Loc<Pattern<'a>>, Loc<TypeAnnotation<'a>>),
/// A type alias. This is like a standalone annotation, except the pattern /// A type alias. This is like a standalone annotation, except the pattern
/// must be a capitalized Identifier, e.g. /// must be a capitalized Identifier, e.g.
/// ///
@ -307,6 +303,13 @@ pub enum Def<'a> {
loc_has: Loc<Has<'a>>, loc_has: Loc<Has<'a>>,
members: &'a [AbilityMember<'a>], members: &'a [AbilityMember<'a>],
}, },
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ValueDef<'a> {
// TODO in canonicalization, validate the pattern; only certain patterns
// are allowed in annotations.
Annotation(Loc<Pattern<'a>>, Loc<TypeAnnotation<'a>>),
// TODO in canonicalization, check to see if there are any newlines after the // TODO in canonicalization, check to see if there are any newlines after the
// annotation; if not, and if it's followed by a Body, then the annotation // annotation; if not, and if it's followed by a Body, then the annotation
@ -323,6 +326,12 @@ pub enum Def<'a> {
}, },
Expect(&'a Loc<Expr<'a>>), Expect(&'a Loc<Expr<'a>>),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Def<'a> {
Type(TypeDef<'a>),
Value(ValueDef<'a>),
// Blank Space (e.g. comments, spaces, newlines) before or after a def. // Blank Space (e.g. comments, spaces, newlines) before or after a def.
// We preserve this for the formatter; canonicalization ignores it. // We preserve this for the formatter; canonicalization ignores it.
@ -341,6 +350,30 @@ impl<'a> Def<'a> {
debug_assert!(!matches!(def, Def::SpaceBefore(_, _))); debug_assert!(!matches!(def, Def::SpaceBefore(_, _)));
(spaces, def) (spaces, def)
} }
pub fn unroll_def(&self) -> Result<&TypeDef<'a>, &ValueDef<'a>> {
let mut def = self;
loop {
match def {
Def::Type(type_def) => return Ok(type_def),
Def::Value(value_def) => return Err(value_def),
Def::SpaceBefore(def1, _) | Def::SpaceAfter(def1, _) => def = def1,
Def::NotYetImplemented(s) => todo!("{}", s),
}
}
}
}
impl<'a> From<TypeDef<'a>> for Def<'a> {
fn from(def: TypeDef<'a>) -> Self {
Self::Type(def)
}
}
impl<'a> From<ValueDef<'a>> for Def<'a> {
fn from(def: ValueDef<'a>) -> Self {
Self::Value(def)
}
} }
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]

View file

@ -1,6 +1,6 @@
use crate::ast::{ use crate::ast::{
AssignedField, Collection, CommentOrNewline, Def, Expr, ExtractSpaces, Has, Pattern, Spaceable, AssignedField, Collection, CommentOrNewline, Def, Expr, ExtractSpaces, Has, Pattern, Spaceable,
TypeAnnotation, TypeHeader, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
}; };
use crate::blankspace::{space0_after_e, space0_around_ee, space0_before_e, space0_e}; use crate::blankspace::{space0_after_e, space0_around_ee, space0_before_e, space0_e};
use crate::ident::{lowercase_ident, parse_ident, Ident}; use crate::ident::{lowercase_ident, parse_ident, Ident};
@ -576,7 +576,7 @@ fn append_body_definition<'a>(
if spaces.len() <= 1 { if spaces.len() <= 1 {
let last = defs.pop(); let last = defs.pop();
match last.map(|d| d.value.unroll_spaces_before()) { match last.map(|d| d.value.unroll_spaces_before()) {
Some((before_ann_spaces, Def::Annotation(ann_pattern, ann_type))) => { Some((before_ann_spaces, Def::Value(ValueDef::Annotation(ann_pattern, ann_type)))) => {
return append_body_definition_help( return append_body_definition_help(
arena, arena,
defs, defs,
@ -591,10 +591,10 @@ fn append_body_definition<'a>(
} }
Some(( Some((
before_ann_spaces, before_ann_spaces,
Def::Alias { Def::Type(TypeDef::Alias {
header, header,
ann: ann_type, ann: ann_type,
}, }),
)) => { )) => {
// This is a case like // This is a case like
// UserId x : [ UserId Int ] // UserId x : [ UserId Int ]
@ -628,7 +628,10 @@ fn append_body_definition<'a>(
// the previous and current def can't be joined up // the previous and current def can't be joined up
let mut loc_def = Loc::at( let mut loc_def = Loc::at(
region, region,
Def::Body(arena.alloc(loc_pattern), &*arena.alloc(loc_def_body)), Def::Value(ValueDef::Body(
arena.alloc(loc_pattern),
&*arena.alloc(loc_def_body),
)),
); );
if !spaces.is_empty() { if !spaces.is_empty() {
@ -660,13 +663,13 @@ fn append_body_definition_help<'a>(
let mut loc_def = Loc::at( let mut loc_def = Loc::at(
region, region,
Def::AnnotatedBody { Def::Value(ValueDef::AnnotatedBody {
ann_pattern: loc_pattern_ann, ann_pattern: loc_pattern_ann,
ann_type: loc_ann, ann_type: loc_ann,
comment, comment,
body_pattern: arena.alloc(loc_pattern_body), body_pattern: arena.alloc(loc_pattern_body),
body_expr: &*arena.alloc(loc_def_body), body_expr: &*arena.alloc(loc_def_body),
}, }),
); );
if !before_ann_spaces.is_empty() { if !before_ann_spaces.is_empty() {
@ -717,7 +720,10 @@ fn append_annotation_definition<'a>(
kind, kind,
), ),
_ => { _ => {
let mut loc_def = Loc::at(region, Def::Annotation(loc_pattern, loc_ann)); let mut loc_def = Loc::at(
region,
Def::Value(ValueDef::Annotation(loc_pattern, loc_ann)),
);
if !spaces.is_empty() { if !spaces.is_empty() {
loc_def = arena loc_def = arena
.alloc(loc_def.value) .alloc(loc_def.value)
@ -736,7 +742,7 @@ fn append_expect_definition<'a>(
spaces: &'a [CommentOrNewline<'a>], spaces: &'a [CommentOrNewline<'a>],
loc_expect_body: Loc<Expr<'a>>, loc_expect_body: Loc<Expr<'a>>,
) { ) {
let def = Def::Expect(arena.alloc(loc_expect_body)); let def: Def = ValueDef::Expect(arena.alloc(loc_expect_body)).into();
let end = loc_expect_body.region.end(); let end = loc_expect_body.region.end();
let region = Region::new(start, end); let region = Region::new(start, end);
@ -768,16 +774,16 @@ fn append_type_definition<'a>(
vars: pattern_arguments, vars: pattern_arguments,
}; };
let def = match kind { let def = match kind {
TypeKind::Alias => Def::Alias { TypeKind::Alias => TypeDef::Alias {
header, header,
ann: loc_ann, ann: loc_ann,
}, },
TypeKind::Opaque => Def::Opaque { TypeKind::Opaque => TypeDef::Opaque {
header, header,
typ: loc_ann, typ: loc_ann,
}, },
}; };
let mut loc_def = Loc::at(region, def); let mut loc_def = Loc::at(region, Def::Type(def));
if !spaces.is_empty() { if !spaces.is_empty() {
loc_def = arena loc_def = arena
@ -1038,17 +1044,17 @@ fn finish_parsing_alias_or_opaque<'a>(
vars: type_arguments.into_bump_slice(), vars: type_arguments.into_bump_slice(),
}; };
let type_def = match kind { let type_def = match kind {
TypeKind::Alias => Def::Alias { TypeKind::Alias => TypeDef::Alias {
header, header,
ann: ann_type, ann: ann_type,
}, },
TypeKind::Opaque => Def::Opaque { TypeKind::Opaque => TypeDef::Opaque {
header, header,
typ: ann_type, typ: ann_type,
}, },
}; };
(&*arena.alloc(Loc::at(def_region, type_def)), state) (&*arena.alloc(Loc::at(def_region, type_def.into())), state)
} }
_ => { _ => {
@ -1077,9 +1083,9 @@ fn finish_parsing_alias_or_opaque<'a>(
let def_region = Region::span_across(&call.region, &ann_type.region); let def_region = Region::span_across(&call.region, &ann_type.region);
let alias = Def::Annotation(Loc::at(expr_region, good), ann_type); let alias = ValueDef::Annotation(Loc::at(expr_region, good), ann_type);
(&*arena.alloc(Loc::at(def_region, alias)), state) (&*arena.alloc(Loc::at(def_region, alias.into())), state)
} }
} }
} }
@ -1270,11 +1276,12 @@ fn finish_parsing_ability_def<'a>(
} }
let def_region = Region::span_across(&name.region, &demands.last().unwrap().typ.region); let def_region = Region::span_across(&name.region, &demands.last().unwrap().typ.region);
let def = Def::Ability { let def = TypeDef::Ability {
header: TypeHeader { name, vars: args }, header: TypeHeader { name, vars: args },
loc_has, loc_has,
members: demands.into_bump_slice(), members: demands.into_bump_slice(),
}; }
.into();
let loc_def = &*(arena.alloc(Loc::at(def_region, def))); let loc_def = &*(arena.alloc(Loc::at(def_region, def)));
Ok((MadeProgress, loc_def, state)) Ok((MadeProgress, loc_def, state))
@ -1357,23 +1364,24 @@ fn parse_expr_operator<'a>(
let (loc_def, state) = { let (loc_def, state) = {
match expr_to_pattern_help(arena, &call.value) { match expr_to_pattern_help(arena, &call.value) {
Ok(good) => { Ok(good) => {
let (_, mut ann_type, state) = parse_loc_expr(indented_more, arena, state)?; let (_, mut body, state) = parse_loc_expr(indented_more, arena, state)?;
// put the spaces from after the operator in front of the call // put the spaces from after the operator in front of the call
if !spaces_after_operator.is_empty() { if !spaces_after_operator.is_empty() {
ann_type = arena body = arena
.alloc(ann_type.value) .alloc(body.value)
.with_spaces_before(spaces_after_operator, ann_type.region); .with_spaces_before(spaces_after_operator, body.region);
} }
let alias_region = Region::span_across(&call.region, &ann_type.region); let body_region = Region::span_across(&call.region, &body.region);
let alias = Def::Body( let alias = ValueDef::Body(
arena.alloc(Loc::at(expr_region, good)), arena.alloc(Loc::at(expr_region, good)),
arena.alloc(ann_type), arena.alloc(body),
); )
.into();
(&*arena.alloc(Loc::at(alias_region, alias)), state) (&*arena.alloc(Loc::at(body_region, alias)), state)
} }
Err(_) => { Err(_) => {
// this `=` likely occurred inline; treat it as an invalid operator // this `=` likely occurred inline; treat it as an invalid operator

View file

@ -1,34 +1,36 @@
Defs( Defs(
[ [
@0-36 Ability { @0-36 Type(
header: TypeHeader { Ability {
name: @0-4 "Hash", header: TypeHeader {
vars: [], name: @0-4 "Hash",
}, vars: [],
loc_has: @5-8 Has,
members: [
AbilityMember {
name: @11-15 SpaceBefore(
"hash",
[
Newline,
],
),
typ: @33-36 Function(
[
@18-19 BoundVariable(
"a",
),
],
@33-36 Apply(
"",
"U64",
[],
),
),
}, },
], loc_has: @5-8 Has,
}, members: [
AbilityMember {
name: @11-15 SpaceBefore(
"hash",
[
Newline,
],
),
typ: @33-36 Function(
[
@18-19 BoundVariable(
"a",
),
],
@33-36 Apply(
"",
"U64",
[],
),
),
},
],
},
),
], ],
@38-39 SpaceBefore( @38-39 SpaceBefore(
Num( Num(

View file

@ -1,54 +1,56 @@
Defs( Defs(
[ [
@0-45 Ability { @0-45 Type(
header: TypeHeader { Ability {
name: @0-4 "Hash", header: TypeHeader {
vars: [], name: @0-4 "Hash",
vars: [],
},
loc_has: @5-8 Has,
members: [
AbilityMember {
name: @11-15 SpaceBefore(
"hash",
[
Newline,
],
),
typ: @23-26 Function(
[
@18-19 BoundVariable(
"a",
),
],
@23-26 Apply(
"",
"U64",
[],
),
),
},
AbilityMember {
name: @29-34 SpaceBefore(
"hash2",
[
Newline,
],
),
typ: @42-45 Function(
[
@37-38 BoundVariable(
"a",
),
],
@42-45 Apply(
"",
"U64",
[],
),
),
},
],
}, },
loc_has: @5-8 Has, ),
members: [
AbilityMember {
name: @11-15 SpaceBefore(
"hash",
[
Newline,
],
),
typ: @23-26 Function(
[
@18-19 BoundVariable(
"a",
),
],
@23-26 Apply(
"",
"U64",
[],
),
),
},
AbilityMember {
name: @29-34 SpaceBefore(
"hash2",
[
Newline,
],
),
typ: @42-45 Function(
[
@37-38 BoundVariable(
"a",
),
],
@42-45 Apply(
"",
"U64",
[],
),
),
},
],
},
], ],
@47-48 SpaceBefore( @47-48 SpaceBefore(
Num( Num(

View file

@ -1,41 +1,43 @@
Defs( Defs(
[ [
@0-37 Ability { @0-37 Type(
header: TypeHeader { Ability {
name: @0-4 "Hash", header: TypeHeader {
vars: [], name: @0-4 "Hash",
}, vars: [],
loc_has: @5-8 Has, },
members: [ loc_has: @5-8 Has,
AbilityMember { members: [
name: @9-13 "hash", AbilityMember {
typ: @21-37 Where( name: @9-13 "hash",
@21-24 Function( typ: @21-37 Where(
[ @21-24 Function(
@16-17 BoundVariable( [
"a", @16-17 BoundVariable(
), "a",
], ),
@21-24 Apply( ],
"", @21-24 Apply(
"U64",
[],
),
),
[
@27-37 HasClause {
var: @27-28 "a",
ability: @33-37 Apply(
"", "",
"Hash", "U64",
[], [],
), ),
}, ),
], [
), @27-37 HasClause {
}, var: @27-28 "a",
], ability: @33-37 Apply(
}, "",
"Hash",
[],
),
},
],
),
},
],
},
),
], ],
@39-40 SpaceBefore( @39-40 SpaceBefore(
Num( Num(

View file

@ -1,79 +1,83 @@
Defs( Defs(
[ [
@0-33 Ability { @0-33 Type(
header: TypeHeader { Ability {
name: @0-3 "Ab1", header: TypeHeader {
vars: [], name: @0-3 "Ab1",
}, vars: [],
loc_has: @4-7 Has,
members: [
AbilityMember {
name: @8-11 "ab1",
typ: @19-33 Where(
@19-21 Function(
[
@14-15 BoundVariable(
"a",
),
],
@19-21 Record {
fields: [],
ext: None,
},
),
[
@24-33 HasClause {
var: @24-25 "a",
ability: @30-33 Apply(
"",
"Ab1",
[],
),
},
],
),
}, },
], loc_has: @4-7 Has,
}, members: [
AbilityMember {
name: @8-11 "ab1",
typ: @19-33 Where(
@19-21 Function(
[
@14-15 BoundVariable(
"a",
),
],
@19-21 Record {
fields: [],
ext: None,
},
),
[
@24-33 HasClause {
var: @24-25 "a",
ability: @30-33 Apply(
"",
"Ab1",
[],
),
},
],
),
},
],
},
),
], ],
@35-71 SpaceBefore( @35-71 SpaceBefore(
Defs( Defs(
[ [
@35-68 Ability { @35-68 Type(
header: TypeHeader { Ability {
name: @35-38 "Ab2", header: TypeHeader {
vars: [], name: @35-38 "Ab2",
}, vars: [],
loc_has: @39-42 Has,
members: [
AbilityMember {
name: @43-46 "ab2",
typ: @54-68 Where(
@54-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: [
AbilityMember {
name: @43-46 "ab2",
typ: @54-68 Where(
@54-56 Function(
[
@49-50 BoundVariable(
"a",
),
],
@54-56 Record {
fields: [],
ext: None,
},
),
[
@59-68 HasClause {
var: @59-60 "a",
ability: @65-68 Apply(
"",
"Ab2",
[],
),
},
],
),
},
],
},
),
], ],
@70-71 SpaceBefore( @70-71 SpaceBefore(
Num( Num(

View file

@ -1,53 +1,55 @@
Defs( Defs(
[ [
@15-49 AnnotatedBody { @15-49 Value(
ann_pattern: @0-8 RecordDestructure( AnnotatedBody {
[ ann_pattern: @0-8 RecordDestructure(
@2-3 Identifier( [
"x", @2-3 Identifier(
), "x",
@5-7 Identifier( ),
"y", @5-7 Identifier(
), "y",
], ),
), ],
ann_type: @11-14 Apply( ),
"", ann_type: @11-14 Apply(
"Foo", "",
[], "Foo",
), [],
comment: None, ),
body_pattern: @15-23 RecordDestructure( comment: None,
[ body_pattern: @15-23 RecordDestructure(
@17-18 Identifier( [
"x", @17-18 Identifier(
), "x",
@20-21 Identifier( ),
"y", @20-21 Identifier(
), "y",
], ),
), ],
body_expr: @26-49 Record( ),
[ body_expr: @26-49 Record(
@28-37 RequiredValue( [
@28-29 "x", @28-37 RequiredValue(
[], @28-29 "x",
@32-37 Str( [],
PlainLine( @32-37 Str(
"foo", PlainLine(
"foo",
),
), ),
), ),
), @39-47 RequiredValue(
@39-47 RequiredValue( @39-40 "y",
@39-40 "y", [],
[], @43-47 Float(
@43-47 Float( "3.14",
"3.14", ),
), ),
), ],
], ),
), },
}, ),
], ],
@51-52 SpaceBefore( @51-52 SpaceBefore(
Var { Var {

View file

@ -1,54 +1,56 @@
Defs( Defs(
[ [
@26-46 AnnotatedBody { @26-46 Value(
ann_pattern: @0-8 Apply( AnnotatedBody {
@0-6 GlobalTag( ann_pattern: @0-8 Apply(
"UserId", @0-6 GlobalTag(
), "UserId",
[
@7-8 Identifier(
"x",
), ),
], [
), @7-8 Identifier(
ann_type: @11-25 TagUnion { "x",
ext: None, ),
tags: [ ],
@13-23 Global { ),
name: @13-19 "UserId", ann_type: @11-25 TagUnion {
args: [ ext: None,
@20-23 Apply( tags: [
"", @13-23 Global {
"I64", name: @13-19 "UserId",
[], args: [
), @20-23 Apply(
], "",
}, "I64",
], [],
),
],
},
],
},
comment: None,
body_pattern: @26-34 Apply(
@26-32 GlobalTag(
"UserId",
),
[
@33-34 Identifier(
"x",
),
],
),
body_expr: @37-46 Apply(
@37-43 GlobalTag(
"UserId",
),
[
@44-46 Num(
"42",
),
],
Space,
),
}, },
comment: None, ),
body_pattern: @26-34 Apply(
@26-32 GlobalTag(
"UserId",
),
[
@33-34 Identifier(
"x",
),
],
),
body_expr: @37-46 Apply(
@37-43 GlobalTag(
"UserId",
),
[
@44-46 Num(
"42",
),
],
Space,
),
},
], ],
@48-49 SpaceBefore( @48-49 SpaceBefore(
Var { Var {

View file

@ -1,12 +1,14 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@107-112 Body( @107-112 Value(
@107-108 Identifier( Body(
"x", @107-108 Identifier(
), "x",
@111-112 Num( ),
"5", @111-112 Num(
"5",
),
), ),
), ),
], ],

View file

@ -1,12 +1,14 @@
[ [
@0-7 SpaceAfter( @0-7 SpaceAfter(
SpaceBefore( SpaceBefore(
Body( Value(
@0-3 Identifier( Body(
"foo", @0-3 Identifier(
), "foo",
@6-7 Num( ),
"1", @6-7 Num(
"1",
),
), ),
), ),
[], [],

View file

@ -1,28 +1,30 @@
Defs( Defs(
[ [
@0-36 Body( @0-36 Value(
@0-5 Apply( Body(
@0-5 GlobalTag( @0-5 Apply(
"Email", @0-5 GlobalTag(
), "Email",
[
@6-9 Identifier(
"str",
), ),
], [
), @6-9 Identifier(
@12-36 Apply( "str",
@12-17 GlobalTag(
"Email",
),
[
@18-36 Str(
PlainLine(
"blah@example.com",
), ),
],
),
@12-36 Apply(
@12-17 GlobalTag(
"Email",
), ),
], [
Space, @18-36 Str(
PlainLine(
"blah@example.com",
),
),
],
Space,
),
), ),
), ),
], ],

View file

@ -1,11 +1,13 @@
Defs( Defs(
[ [
@0-6 Body( @0-6 Value(
@0-4 Identifier( Body(
"iffy", @0-4 Identifier(
), "iffy",
@5-6 Num( ),
"5", @5-6 Num(
"5",
),
), ),
), ),
], ],

View file

@ -1,65 +1,67 @@
Defs( Defs(
[ [
@0-58 Body( @0-58 Value(
@0-7 Malformed( Body(
"my_list", @0-7 Malformed(
), "my_list",
@10-58 List( ),
Collection { @10-58 List(
items: [ Collection {
@16-17 SpaceBefore( items: [
Num( @16-17 SpaceBefore(
"0", Num(
"0",
),
[
Newline,
],
), ),
[ @23-48 SpaceBefore(
Newline, List(
], Collection {
), items: [
@23-48 SpaceBefore( @33-34 SpaceBefore(
List( Var {
Collection { module_name: "",
items: [ ident: "a",
@33-34 SpaceBefore( },
Var { [
module_name: "", Newline,
ident: "a", ],
}, ),
[ @44-45 SpaceBefore(
Newline, Var {
], module_name: "",
), ident: "b",
@44-45 SpaceBefore( },
Var { [
module_name: "", Newline,
ident: "b", ],
}, ),
[ ],
Newline, final_comments: [
], Newline,
), ],
], },
final_comments: [ ),
Newline, [
], Newline,
}, ],
), ),
[ @54-55 SpaceBefore(
Newline, Num(
], "1",
), ),
@54-55 SpaceBefore( [
Num( Newline,
"1", ],
), ),
[ ],
Newline, final_comments: [
], Newline,
), ],
], },
final_comments: [ ),
Newline,
],
},
), ),
), ),
], ],

View file

@ -1,33 +1,35 @@
Defs( Defs(
[ [
@0-26 Body( @0-26 Value(
@0-7 Malformed( Body(
"my_list", @0-7 Malformed(
), "my_list",
@10-26 List( ),
Collection { @10-26 List(
items: [ Collection {
@16-17 SpaceBefore( items: [
Num( @16-17 SpaceBefore(
"0", Num(
"0",
),
[
Newline,
],
), ),
[ @23-24 SpaceBefore(
Newline, Num(
], "1",
), ),
@23-24 SpaceBefore( [
Num( Newline,
"1", ],
), ),
[ ],
Newline, final_comments: [
], Newline,
), ],
], },
final_comments: [ ),
Newline,
],
},
), ),
), ),
], ],

View file

@ -1,33 +1,35 @@
Defs( Defs(
[ [
@0-27 Body( @0-27 Value(
@0-7 Malformed( Body(
"my_list", @0-7 Malformed(
), "my_list",
@10-27 List( ),
Collection { @10-27 List(
items: [ Collection {
@16-17 SpaceBefore( items: [
Num( @16-17 SpaceBefore(
"0", Num(
"0",
),
[
Newline,
],
), ),
[ @23-24 SpaceBefore(
Newline, Num(
], "1",
), ),
@23-24 SpaceBefore( [
Num( Newline,
"1", ],
), ),
[ ],
Newline, final_comments: [
], Newline,
), ],
], },
final_comments: [ ),
Newline,
],
},
), ),
), ),
], ],

View file

@ -1,12 +1,14 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@113-118 Body( @113-118 Value(
@113-114 Identifier( Body(
"x", @113-114 Identifier(
), "x",
@117-118 Num( ),
"5", @117-118 Num(
"5",
),
), ),
), ),
], ],

View file

@ -1,36 +1,40 @@
[ [
@0-24 SpaceAfter( @0-24 SpaceAfter(
SpaceBefore( SpaceBefore(
Body( Value(
@0-4 Identifier( Body(
"main", @0-4 Identifier(
), "main",
@11-24 SpaceBefore( ),
Defs( @11-24 SpaceBefore(
[ Defs(
@11-17 Body( [
@11-12 Identifier( @11-17 Value(
"i", Body(
), @11-12 Identifier(
@15-17 Num( "i",
"64", ),
), @15-17 Num(
), "64",
], ),
@23-24 SpaceBefore( ),
Var { ),
module_name: "", ],
ident: "i", @23-24 SpaceBefore(
}, Var {
[ module_name: "",
Newline, ident: "i",
Newline, },
], [
), Newline,
Newline,
],
),
),
[
Newline,
],
), ),
[
Newline,
],
), ),
), ),
[], [],

View file

@ -1,17 +1,19 @@
Defs( Defs(
[ [
@0-10 Annotation( @0-10 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@8-10 SpaceBefore( ),
Record { @8-10 SpaceBefore(
fields: [], Record {
ext: None, fields: [],
}, ext: None,
[ },
Newline, [
], Newline,
],
),
), ),
), ),
], ],

View file

@ -1,19 +1,21 @@
Defs( Defs(
[ [
@0-19 Annotation( @0-19 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@17-19 SpaceBefore( ),
Record { @17-19 SpaceBefore(
fields: [], Record {
ext: None, fields: [],
}, ext: None,
[ },
LineComment( [
" comment", LineComment(
), " comment",
], ),
],
),
), ),
), ),
], ],

View file

@ -1,93 +1,97 @@
[ [
@0-115 SpaceAfter( @0-115 SpaceAfter(
SpaceBefore( SpaceBefore(
Body( Value(
@0-4 Identifier( Body(
"main", @0-4 Identifier(
), "main",
@11-115 SpaceBefore( ),
Defs( @11-115 SpaceBefore(
[ Defs(
@43-93 AnnotatedBody { [
ann_pattern: @11-23 Identifier( @43-93 Value(
"wrappedNotEq", AnnotatedBody {
), ann_pattern: @11-23 Identifier(
ann_type: @34-38 Function( "wrappedNotEq",
[
@26-27 BoundVariable(
"a",
), ),
@29-30 BoundVariable( ann_type: @34-38 Function(
"a",
),
],
@34-38 Apply(
"",
"Bool",
[],
),
),
comment: None,
body_pattern: @43-55 Identifier(
"wrappedNotEq",
),
body_expr: @58-93 Closure(
[
@59-63 Identifier(
"num1",
),
@65-69 Identifier(
"num2",
),
],
@81-93 SpaceBefore(
BinOps(
[ [
( @26-27 BoundVariable(
@81-85 Var { "a",
module_name: "", ),
ident: "num1", @29-30 BoundVariable(
}, "a",
@86-88 NotEquals,
), ),
], ],
@89-93 Var { @34-38 Apply(
module_name: "", "",
ident: "num2", "Bool",
}, [],
),
), ),
[ comment: None,
Newline, body_pattern: @43-55 Identifier(
], "wrappedNotEq",
), ),
body_expr: @58-93 Closure(
[
@59-63 Identifier(
"num1",
),
@65-69 Identifier(
"num2",
),
],
@81-93 SpaceBefore(
BinOps(
[
(
@81-85 Var {
module_name: "",
ident: "num1",
},
@86-88 NotEquals,
),
],
@89-93 Var {
module_name: "",
ident: "num2",
},
),
[
Newline,
],
),
),
},
), ),
},
],
@99-115 SpaceBefore(
Apply(
@99-111 Var {
module_name: "",
ident: "wrappedNotEq",
},
[
@112-113 Num(
"2",
),
@114-115 Num(
"3",
),
],
Space,
),
[
Newline,
Newline,
], ],
@99-115 SpaceBefore(
Apply(
@99-111 Var {
module_name: "",
ident: "wrappedNotEq",
},
[
@112-113 Num(
"2",
),
@114-115 Num(
"3",
),
],
Space,
),
[
Newline,
Newline,
],
),
), ),
[
Newline,
],
), ),
[
Newline,
],
), ),
), ),
[], [],

View file

@ -1,16 +1,18 @@
Defs( Defs(
[ [
@0-9 Body( @0-9 Value(
@0-1 Identifier( Body(
"x", @0-1 Identifier(
), "x",
@8-9 SpaceBefore( ),
Num( @8-9 SpaceBefore(
"5", Num(
"5",
),
[
Newline,
],
), ),
[
Newline,
],
), ),
), ),
], ],

View file

@ -1,25 +1,27 @@
Defs( Defs(
[ [
@0-13 Body( @0-13 Value(
@0-1 Identifier( Body(
"x", @0-1 Identifier(
), "x",
@4-13 BinOps( ),
[ @4-13 BinOps(
( [
@4-5 SpaceAfter( (
Num( @4-5 SpaceAfter(
"1", Num(
"1",
),
[
Newline,
],
), ),
[ @10-11 LessThan,
Newline,
],
), ),
@10-11 LessThan, ],
@12-13 Num(
"2",
), ),
],
@12-13 Num(
"2",
), ),
), ),
), ),

View file

@ -1,12 +1,14 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@46-51 Body( @46-51 Value(
@46-47 Identifier( Body(
"x", @46-47 Identifier(
), "x",
@50-51 Num( ),
"5", @50-51 Num(
"5",
),
), ),
), ),
], ],

View file

@ -1,12 +1,14 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@18-21 Body( @18-21 Value(
@18-19 Identifier( Body(
"x", @18-19 Identifier(
), "x",
@20-21 Num( ),
"5", @20-21 Num(
"5",
),
), ),
), ),
], ],

View file

@ -1,12 +1,14 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@18-23 Body( @18-23 Value(
@18-19 Identifier( Body(
"x", @18-19 Identifier(
), "x",
@22-23 Num( ),
"5", @22-23 Num(
"5",
),
), ),
), ),
], ],

View file

@ -1,17 +1,19 @@
[ [
@0-9 SpaceAfter( @0-9 SpaceAfter(
SpaceBefore( SpaceBefore(
Opaque { Type(
header: TypeHeader { Opaque {
name: @0-3 "Age", header: TypeHeader {
vars: [], name: @0-3 "Age",
vars: [],
},
typ: @7-9 Apply(
"",
"U8",
[],
),
}, },
typ: @7-9 Apply( ),
"",
"U8",
[],
),
},
[], [],
), ),
[ [

View file

@ -1,46 +1,48 @@
[ [
@0-53 SpaceAfter( @0-53 SpaceAfter(
SpaceBefore( SpaceBefore(
Opaque { Type(
header: TypeHeader { Opaque {
name: @0-10 "Bookmark", header: TypeHeader {
vars: [ name: @0-10 "Bookmark",
@9-10 Identifier( vars: [
"a", @9-10 Identifier(
),
],
},
typ: @14-53 Record {
fields: [
@16-28 RequiredValue(
@16-23 "chapter",
[],
@25-28 Apply(
"",
"Str",
[],
),
),
@30-41 RequiredValue(
@30-36 "stanza",
[],
@38-41 Apply(
"",
"Str",
[],
),
),
@43-51 RequiredValue(
@43-48 "notes",
[],
@50-51 BoundVariable(
"a", "a",
), ),
), ],
], },
ext: None, typ: @14-53 Record {
fields: [
@16-28 RequiredValue(
@16-23 "chapter",
[],
@25-28 Apply(
"",
"Str",
[],
),
),
@30-41 RequiredValue(
@30-36 "stanza",
[],
@38-41 Apply(
"",
"Str",
[],
),
),
@43-51 RequiredValue(
@43-48 "notes",
[],
@50-51 BoundVariable(
"a",
),
),
],
ext: None,
},
}, },
}, ),
[], [],
), ),
[ [

View file

@ -1,30 +1,32 @@
Defs( Defs(
[ [
@0-26 Alias { @0-26 Type(
header: TypeHeader { Alias {
name: @0-4 "Blah", header: TypeHeader {
vars: [ name: @0-4 "Blah",
@5-6 Identifier( vars: [
"a", @5-6 Identifier(
), "a",
@7-8 Identifier( ),
"b", @7-8 Identifier(
), "b",
], ),
],
},
ann: @11-26 Apply(
"Foo.Bar",
"Baz",
[
@23-24 BoundVariable(
"x",
),
@25-26 BoundVariable(
"y",
),
],
),
}, },
ann: @11-26 Apply( ),
"Foo.Bar",
"Baz",
[
@23-24 BoundVariable(
"x",
),
@25-26 BoundVariable(
"y",
),
],
),
},
], ],
@28-30 SpaceBefore( @28-30 SpaceBefore(
Num( Num(

View file

@ -1,34 +1,36 @@
Defs( Defs(
[ [
@0-33 Annotation( @0-33 Value(
@0-3 Identifier( Annotation(
"foo", @0-3 Identifier(
), "foo",
@6-33 As( ),
@6-21 Apply( @6-33 As(
"Foo.Bar", @6-21 Apply(
"Baz", "Foo.Bar",
[ "Baz",
@18-19 BoundVariable( [
"x", @18-19 BoundVariable(
), "x",
@20-21 BoundVariable( ),
"y", @20-21 BoundVariable(
), "y",
], ),
],
),
[],
TypeHeader {
name: @25-29 "Blah",
vars: [
@30-31 Identifier(
"a",
),
@32-33 Identifier(
"b",
),
],
},
), ),
[],
TypeHeader {
name: @25-29 "Blah",
vars: [
@30-31 Identifier(
"a",
),
@32-33 Identifier(
"b",
),
],
},
), ),
), ),
], ],

View file

@ -1,28 +1,32 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@18-30 Body( @18-30 Value(
@18-26 RecordDestructure( Body(
[ @18-26 RecordDestructure(
@20-21 Identifier( [
"x", @20-21 Identifier(
), "x",
@23-25 Identifier( ),
"y", @23-25 Identifier(
), "y",
], ),
), ],
@29-30 Num( ),
"5", @29-30 Num(
"5",
),
), ),
), ),
@31-36 SpaceBefore( @31-36 SpaceBefore(
Body( Value(
@31-32 Identifier( Body(
"y", @31-32 Identifier(
), "y",
@35-36 Num( ),
"6", @35-36 Num(
"6",
),
), ),
), ),
[ [

View file

@ -1,102 +1,104 @@
Defs( Defs(
[ [
@0-122 Annotation( @0-122 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@8-122 SpaceBefore( ),
Record { @8-122 SpaceBefore(
fields: [ Record {
@18-38 SpaceBefore( fields: [
RequiredValue( @18-38 SpaceBefore(
@18-25 "getLine", RequiredValue(
[], @18-25 "getLine",
@28-38 Apply( [],
"", @28-38 Apply(
"Effect",
[
@35-38 Apply(
"",
"Str",
[],
),
],
),
),
[
Newline,
],
),
@48-75 SpaceBefore(
RequiredValue(
@48-55 "putLine",
[],
@65-75 Function(
[
@58-61 Apply(
"",
"Str",
[],
),
],
@65-75 Apply(
"", "",
"Effect", "Effect",
[ [
@72-75 Apply( @35-38 Apply(
"", "",
"Int", "Str",
[], [],
), ),
], ],
), ),
), ),
),
[
Newline,
],
),
@85-94 SpaceBefore(
RequiredValue(
@85-89 "text",
[],
@91-94 Apply(
"",
"Str",
[],
),
),
[
Newline,
],
),
@104-116 SpaceBefore(
SpaceAfter(
RequiredValue(
@104-109 "value",
[],
@111-116 Apply(
"",
"Int",
[
@115-116 Wildcard,
],
),
),
[ [
Newline, Newline,
], ],
), ),
[ @48-75 SpaceBefore(
Newline, RequiredValue(
], @48-55 "putLine",
), [],
@65-75 Function(
[
@58-61 Apply(
"",
"Str",
[],
),
],
@65-75 Apply(
"",
"Effect",
[
@72-75 Apply(
"",
"Int",
[],
),
],
),
),
),
[
Newline,
],
),
@85-94 SpaceBefore(
RequiredValue(
@85-89 "text",
[],
@91-94 Apply(
"",
"Str",
[],
),
),
[
Newline,
],
),
@104-116 SpaceBefore(
SpaceAfter(
RequiredValue(
@104-109 "value",
[],
@111-116 Apply(
"",
"Int",
[
@115-116 Wildcard,
],
),
),
[
Newline,
],
),
[
Newline,
],
),
],
ext: None,
},
[
Newline,
], ],
ext: None, ),
},
[
Newline,
],
), ),
), ),
], ],

View file

@ -1,11 +1,13 @@
[ [
@12-19 SpaceBefore( @12-19 SpaceBefore(
Body( Value(
@12-15 Identifier( Body(
"foo", @12-15 Identifier(
), "foo",
@18-19 Num( ),
"1", @18-19 Num(
"1",
),
), ),
), ),
[ [
@ -15,13 +17,15 @@
], ],
), ),
@33-43 SpaceBefore( @33-43 SpaceBefore(
Body( Value(
@33-36 Identifier( Body(
"bar", @33-36 Identifier(
), "bar",
@39-43 Str( ),
PlainLine( @39-43 Str(
"hi", PlainLine(
"hi",
),
), ),
), ),
), ),
@ -35,13 +39,15 @@
), ),
@44-57 SpaceAfter( @44-57 SpaceAfter(
SpaceBefore( SpaceBefore(
Body( Value(
@44-47 Identifier( Body(
"baz", @44-47 Identifier(
), "baz",
@50-57 Str( ),
PlainLine( @50-57 Str(
"stuff", PlainLine(
"stuff",
),
), ),
), ),
), ),

View file

@ -1,21 +1,25 @@
SpaceBefore( SpaceBefore(
Defs( Defs(
[ [
@18-23 Body( @18-23 Value(
@18-19 Identifier( Body(
"x", @18-19 Identifier(
), "x",
@22-23 Num( ),
"5", @22-23 Num(
"5",
),
), ),
), ),
@24-29 SpaceBefore( @24-29 SpaceBefore(
Body( Value(
@24-25 Identifier( Body(
"y", @24-25 Identifier(
), "y",
@28-29 Num( ),
"6", @28-29 Num(
"6",
),
), ),
), ),
[ [

View file

@ -1,28 +1,30 @@
Defs( Defs(
[ [
@0-30 Annotation( @0-30 Value(
@0-7 Identifier( Annotation(
"doStuff", @0-7 Identifier(
), "doStuff",
@20-30 Function( ),
[ @20-30 Function(
@10-16 Apply(
"",
"UserId",
[],
),
],
@20-30 Apply(
"",
"Task",
[ [
@25-28 Apply( @10-16 Apply(
"", "",
"Str", "UserId",
[], [],
), ),
@29-30 Inferred,
], ],
@20-30 Apply(
"",
"Task",
[
@25-28 Apply(
"",
"Str",
[],
),
@29-30 Inferred,
],
),
), ),
), ),
), ),

View file

@ -1,37 +1,39 @@
Defs( Defs(
[ [
@0-27 Annotation( @0-27 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@15-27 Where( ),
@15-16 Function( @15-27 Where(
[
@4-5 BoundVariable(
"a",
),
],
@15-16 Function( @15-16 Function(
[ [
@10-11 BoundVariable( @4-5 BoundVariable(
"b", "a",
), ),
], ],
@15-16 BoundVariable( @15-16 Function(
"c", [
@10-11 BoundVariable(
"b",
),
],
@15-16 BoundVariable(
"c",
),
), ),
), ),
[
@20-27 HasClause {
var: @20-21 "a",
ability: @26-27 Apply(
"",
"A",
[],
),
},
],
), ),
[
@20-27 HasClause {
var: @20-21 "a",
ability: @26-27 Apply(
"",
"A",
[],
),
},
],
), ),
), ),
], ],

View file

@ -1,53 +1,55 @@
Defs( Defs(
[ [
@0-48 Annotation( @0-48 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@15-48 Where( ),
@15-16 Function( @15-48 Where(
[
@4-5 BoundVariable(
"a",
),
],
@15-16 Function( @15-16 Function(
[ [
@10-11 BoundVariable( @4-5 BoundVariable(
"b", "a",
), ),
], ],
@15-16 BoundVariable( @15-16 Function(
"c", [
@10-11 BoundVariable(
"b",
),
],
@15-16 BoundVariable(
"c",
),
), ),
), ),
[
@20-27 HasClause {
var: @20-21 "a",
ability: @26-27 Apply(
"",
"A",
[],
),
},
@29-37 HasClause {
var: @29-30 "b",
ability: @35-37 Apply(
"",
"Eq",
[],
),
},
@39-48 HasClause {
var: @39-40 "c",
ability: @45-48 Apply(
"",
"Ord",
[],
),
},
],
), ),
[
@20-27 HasClause {
var: @20-21 "a",
ability: @26-27 Apply(
"",
"A",
[],
),
},
@29-37 HasClause {
var: @29-30 "b",
ability: @35-37 Apply(
"",
"Eq",
[],
),
},
@39-48 HasClause {
var: @39-40 "c",
ability: @45-48 Apply(
"",
"Ord",
[],
),
},
],
), ),
), ),
], ],

View file

@ -1,68 +1,70 @@
Defs( Defs(
[ [
@0-67 Annotation( @0-67 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@15-67 Where( ),
@15-16 SpaceBefore( @15-67 Where(
Function( @15-16 SpaceBefore(
[ Function(
@4-5 BoundVariable(
"a",
),
],
@15-16 Function(
[ [
@10-11 BoundVariable( @4-5 BoundVariable(
"b", "a",
), ),
], ],
@15-16 BoundVariable( @15-16 Function(
"c", [
@10-11 BoundVariable(
"b",
),
],
@15-16 BoundVariable(
"c",
),
), ),
), ),
[
Newline,
],
), ),
[ [
Newline, @24-34 HasClause {
var: @24-25 "a",
ability: @30-34 Apply(
"",
"Hash",
[],
),
},
@42-50 HasClause {
var: @42-43 SpaceBefore(
"b",
[
Newline,
],
),
ability: @48-50 Apply(
"",
"Eq",
[],
),
},
@58-67 HasClause {
var: @58-59 SpaceBefore(
"c",
[
Newline,
],
),
ability: @64-67 Apply(
"",
"Ord",
[],
),
},
], ],
), ),
[
@24-34 HasClause {
var: @24-25 "a",
ability: @30-34 Apply(
"",
"Hash",
[],
),
},
@42-50 HasClause {
var: @42-43 SpaceBefore(
"b",
[
Newline,
],
),
ability: @48-50 Apply(
"",
"Eq",
[],
),
},
@58-67 HasClause {
var: @58-59 SpaceBefore(
"c",
[
Newline,
],
),
ability: @64-67 Apply(
"",
"Ord",
[],
),
},
],
), ),
), ),
], ],

View file

@ -1,23 +1,25 @@
Defs( Defs(
[ [
@0-15 Annotation( @0-15 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@4-15 Where( ),
@4-5 BoundVariable( @4-15 Where(
"a", @4-5 BoundVariable(
"a",
),
[
@8-15 HasClause {
var: @8-9 "a",
ability: @14-15 Apply(
"",
"A",
[],
),
},
],
), ),
[
@8-15 HasClause {
var: @8-9 "a",
ability: @14-15 Apply(
"",
"A",
[],
),
},
],
), ),
), ),
], ],

View file

@ -1,37 +1,39 @@
Defs( Defs(
[ [
@0-29 Annotation( @0-29 Value(
@0-1 Identifier( Annotation(
"f", @0-1 Identifier(
), "f",
@9-29 Where( ),
@9-12 SpaceBefore( @9-29 Where(
Function( @9-12 SpaceBefore(
[ Function(
@4-5 BoundVariable( [
"a", @4-5 BoundVariable(
"a",
),
],
@9-12 Apply(
"",
"U64",
[],
), ),
],
@9-12 Apply(
"",
"U64",
[],
), ),
[
Newline,
],
), ),
[ [
Newline, @19-29 HasClause {
var: @19-20 "a",
ability: @25-29 Apply(
"",
"Hash",
[],
),
},
], ],
), ),
[
@19-29 HasClause {
var: @19-20 "a",
ability: @25-29 Apply(
"",
"Hash",
[],
),
},
],
), ),
), ),
], ],