PNC for Patterns, stabilize formatting

This commit is contained in:
Anthony Bullard 2024-12-31 08:25:11 -06:00
parent bac165fd99
commit 3b0db07fa1
No known key found for this signature in database
78 changed files with 789 additions and 332 deletions

View file

@ -2,8 +2,8 @@ use crate::ast::{
is_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces,
Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
ModuleImportParams, Pattern, Spaceable, Spaced, Spaces, SpacesBefore, TryTarget,
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
ModuleImportParams, Pattern, PatternApplyStyle, Spaceable, Spaced, Spaces, SpacesBefore,
TryTarget, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
};
use crate::blankspace::{
loc_space0_e, require_newline_or_eof, space0_after_e, space0_around_ee, space0_before_e,
@ -181,7 +181,7 @@ fn loc_term_or_underscore_or_conditional<'a>(
}
}
loc_term_or_underscore(check_for_arrow).parse(arena, state, min_indent)
loc_term_or_closure(check_for_arrow).parse(arena, state, min_indent)
}
}
fn loc_conditional<'a>(
@ -198,84 +198,80 @@ fn loc_conditional<'a>(
/// In some contexts we want to parse the `_` as an expression, so it can then be turned into a
/// pattern later
fn loc_term_or_underscore<'a>(
fn loc_term_or_closure<'a>(
check_for_arrow: CheckForArrow,
) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
one_of!(
loc_expr_in_parens_etc_help(),
loc(specialize_err(EExpr::Str, string_like_literal_help())),
loc(specialize_err(
EExpr::Number,
positive_number_literal_help()
)),
loc(specialize_err(
EExpr::Closure,
closure_help(check_for_arrow)
)),
loc(crash_kw()),
loc(specialize_err(EExpr::Dbg, dbg_kw())),
loc(try_kw()),
loc(underscore_expression()),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
loc(apply_with_pnc()),
ident_seq(),
loc_term(),
)
.trace("term_or_underscore")
}
fn loc_term<'a>(check_for_arrow: CheckForArrow) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
one_of!(
loc_expr_in_parens_etc_help(),
loc(specialize_err(EExpr::Str, string_like_literal_help())),
loc(specialize_err(
EExpr::Number,
positive_number_literal_help()
)),
loc(specialize_err(
EExpr::Closure,
closure_help(check_for_arrow)
)),
loc(crash_kw()),
loc(specialize_err(EExpr::Dbg, dbg_kw())),
loc(try_kw()),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
loc(apply_with_pnc()),
ident_seq(),
fn loc_term<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
map_with_arena(
and(
one_of!(
loc_expr_in_parens_etc_help(),
loc(specialize_err(EExpr::Str, string_like_literal_help())),
loc(specialize_err(
EExpr::Number,
positive_number_literal_help()
)),
loc(crash_kw()),
loc(specialize_err(EExpr::Dbg, dbg_kw())),
loc(try_kw()),
loc(underscore_expression()),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
ident_seq(),
),
optional(pnc_args()),
),
|arena, (expr, maybe_arg_loc)| {
if let Some(arg_loc) = maybe_arg_loc {
let e = Expr::Apply(arena.alloc(expr), arg_loc.value, CalledVia::ParensAndCommas);
Loc {
value: e,
region: Region::span_across(&expr.region, &arg_loc.region),
}
} else {
expr
}
},
)
.trace("term")
}
fn apply_with_pnc<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
fn pnc_args<'a>() -> impl Parser<'a, Loc<&'a [&'a Loc<Expr<'a>>]>, EExpr<'a>> {
|arena: &'a Bump, state: State<'a>, min_indent: u32| {
let (_, ident, new_state) = ident_seq().parse(arena, state, min_indent)?;
let (_, args, newer_state) = specialize_err(
EExpr::InParens,
collection_trailing_sep_e(
byte(b'(', EInParens::Open),
specialize_err_ref(EInParens::Expr, loc_expr_block(false, true)),
byte(b',', EInParens::End),
byte(b')', EInParens::End),
Expr::SpaceBefore,
map_with_arena(
specialize_err(
EExpr::InParens,
loc(collection_trailing_sep_e(
byte(b'(', EInParens::Open),
specialize_err_ref(EInParens::Expr, loc_expr_block(true)),
byte(b',', EInParens::End),
byte(b')', EInParens::End),
Expr::SpaceBefore,
)),
),
|arena, arg_loc| {
let mut args_vec = Vec::new_in(arena);
for arg in arg_loc.value.items.iter() {
let a: &Loc<Expr<'a>> = arena.alloc(arg);
args_vec.push(a);
}
Loc {
value: args_vec.into_bump_slice(),
region: arg_loc.region,
}
},
)
.parse(arena, new_state, min_indent)?;
let arg_slice: &[&Loc<Expr<'a>>] = {
let mut args_vec = Vec::new_in(arena);
for arg in args.items.iter() {
let a: &Loc<Expr<'a>> = arena.alloc(arg);
args_vec.push(a);
}
args_vec.into_bump_slice()
};
Ok((
Progress::MadeProgress,
Expr::Apply(arena.alloc(ident), arg_slice, CalledVia::ParensAndCommas),
newer_state,
))
.parse(arena, state, min_indent)
}
}
@ -1743,7 +1739,8 @@ fn parse_negated_term<'a>(
initial_state: State<'a>,
loc_op: Loc<BinOp>,
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
let (_, negated_expr, state) = loc_term(check_for_arrow).parse(arena, state, min_indent)?;
let (_, negated_expr, state) =
loc_term_or_closure(check_for_arrow).parse(arena, state, min_indent)?;
let new_end = state.pos();
let arg = numeric_negate_expression(
@ -1793,7 +1790,7 @@ fn parse_expr_end<'a>(
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
let parser = skip_first(
crate::blankspace::check_indent(EExpr::IndentEnd),
loc_term_or_underscore(check_for_arrow),
loc_term_or_closure(check_for_arrow),
);
match parser.parse(arena, state.clone(), call_min_indent) {
@ -2089,7 +2086,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
Expr::Underscore(opt_name) => Pattern::Underscore(opt_name),
Expr::Tag(value) => Pattern::Tag(value),
Expr::OpaqueRef(value) => Pattern::OpaqueRef(value),
Expr::Apply(loc_val, loc_args, _) => {
Expr::Apply(loc_val, loc_args, called_via) => {
let region = loc_val.region;
let value = expr_to_pattern_help(arena, &loc_val.value)?;
let val_pattern = arena.alloc(Loc { region, value });
@ -2103,7 +2100,15 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
arg_patterns.push(Loc { region, value });
}
let pattern = Pattern::Apply(val_pattern, arg_patterns.into_bump_slice());
let pattern = Pattern::Apply(
val_pattern,
arg_patterns.into_bump_slice(),
if matches!(called_via, CalledVia::ParensAndCommas) {
PatternApplyStyle::ParensAndCommas
} else {
PatternApplyStyle::Whitespace
},
);
pattern
}
@ -3277,7 +3282,7 @@ fn starts_with_spaces_conservative(value: &Pattern<'_>) -> bool {
| Pattern::ListRest(_)
| Pattern::OpaqueRef(_) => false,
Pattern::As(left, _) => starts_with_spaces_conservative(&left.value),
Pattern::Apply(left, _) => starts_with_spaces_conservative(&left.value),
Pattern::Apply(left, _, _) => starts_with_spaces_conservative(&left.value),
Pattern::RecordDestructure(_) => false,
Pattern::RequiredField(_, _) | Pattern::OptionalField(_, _) => false,
Pattern::SpaceBefore(_, _) => true,
@ -3293,6 +3298,7 @@ fn header_to_pat<'a>(arena: &'a Bump, header: TypeHeader<'a>) -> Pattern<'a> {
Pattern::Apply(
arena.alloc(Loc::at(header.name.region, Pattern::Tag(header.name.value))),
header.vars,
PatternApplyStyle::Whitespace,
)
}
}
@ -3343,7 +3349,7 @@ fn pat_ends_with_spaces_conservative(pat: &Pattern<'_>) -> bool {
| Pattern::ListRest(_)
| Pattern::As(_, _)
| Pattern::OpaqueRef(_) => false,
Pattern::Apply(_, args) => args
Pattern::Apply(_, args, _) => args
.last()
.map_or(false, |a| pat_ends_with_spaces_conservative(&a.value)),
Pattern::RecordDestructure(_) => false,
@ -3365,7 +3371,7 @@ pub fn join_alias_to_body<'a>(
body_expr: &'a Loc<Expr<'a>>,
) -> ValueDef<'a> {
let loc_name = arena.alloc(header.name.map(|x| Pattern::Tag(x)));
let ann_pattern = Pattern::Apply(loc_name, header.vars);
let ann_pattern = Pattern::Apply(loc_name, header.vars, PatternApplyStyle::Whitespace);
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);