mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Move PNC apply to separate Expr/Pattern variant
This commit is contained in:
parent
96fc573b6b
commit
898b3f55e5
70 changed files with 873 additions and 555 deletions
|
@ -554,6 +554,7 @@ pub enum Expr<'a> {
|
|||
/// To apply by name, do Apply(Var(...), ...)
|
||||
/// To apply a tag by name, do Apply(Tag(...), ...)
|
||||
Apply(&'a Loc<Expr<'a>>, &'a [&'a Loc<Expr<'a>>], CalledVia),
|
||||
PncApply(&'a Loc<Expr<'a>>, Collection<'a, &'a Loc<Expr<'a>>>),
|
||||
BinOps(&'a [(Loc<Expr<'a>>, Loc<BinOp>)], &'a Loc<Expr<'a>>),
|
||||
UnaryOp(&'a Loc<Expr<'a>>, Loc<UnaryOp>),
|
||||
|
||||
|
@ -631,6 +632,7 @@ pub fn is_top_level_suffixed(expr: &Expr) -> bool {
|
|||
match expr {
|
||||
Expr::TrySuffix { .. } => true,
|
||||
Expr::Apply(a, _, _) => is_top_level_suffixed(&a.value),
|
||||
Expr::PncApply(a, _) => is_top_level_suffixed(&a.value),
|
||||
Expr::SpaceBefore(a, _) => is_top_level_suffixed(a),
|
||||
Expr::SpaceAfter(a, _) => is_top_level_suffixed(a),
|
||||
_ => false,
|
||||
|
@ -653,6 +655,15 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
any_args_suffixed || is_function_suffixed
|
||||
}
|
||||
|
||||
Expr::PncApply(sub_loc_expr, apply_arg_collection) => {
|
||||
let is_function_suffixed = is_expr_suffixed(&sub_loc_expr.value);
|
||||
let any_args_suffixed = apply_arg_collection
|
||||
.iter()
|
||||
.any(|arg| is_expr_suffixed(&arg.value));
|
||||
|
||||
any_args_suffixed || is_function_suffixed
|
||||
}
|
||||
|
||||
// expression in a pipeline, `"hi" |> say!`
|
||||
Expr::BinOps(firsts, last) => {
|
||||
firsts
|
||||
|
@ -1021,6 +1032,14 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
expr_stack.push(&loc_expr.value);
|
||||
}
|
||||
}
|
||||
PncApply(fun, args) => {
|
||||
expr_stack.reserve(args.len() + 1);
|
||||
expr_stack.push(&fun.value);
|
||||
|
||||
for loc_expr in args.iter() {
|
||||
expr_stack.push(&loc_expr.value);
|
||||
}
|
||||
}
|
||||
BinOps(ops, expr) => {
|
||||
expr_stack.reserve(ops.len() + 1);
|
||||
|
||||
|
@ -1725,12 +1744,6 @@ impl<'a> PatternAs<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum PatternApplyStyle {
|
||||
Whitespace,
|
||||
ParensAndCommas,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Pattern<'a> {
|
||||
// Identifier
|
||||
|
@ -1746,11 +1759,9 @@ pub enum Pattern<'a> {
|
|||
|
||||
OpaqueRef(&'a str),
|
||||
|
||||
Apply(
|
||||
&'a Loc<Pattern<'a>>,
|
||||
&'a [Loc<Pattern<'a>>],
|
||||
PatternApplyStyle,
|
||||
),
|
||||
Apply(&'a Loc<Pattern<'a>>, &'a [Loc<Pattern<'a>>]),
|
||||
|
||||
PncApply(&'a Loc<Pattern<'a>>, Collection<'a, Loc<Pattern<'a>>>),
|
||||
|
||||
/// This is Located<Pattern> rather than Located<str> so we can record comments
|
||||
/// around the destructured names, e.g. { x ### x does stuff ###, y }
|
||||
|
@ -1831,8 +1842,34 @@ impl<'a> Pattern<'a> {
|
|||
false
|
||||
}
|
||||
}
|
||||
Apply(constructor_x, args_x, _) => {
|
||||
if let Apply(constructor_y, args_y, _) = other {
|
||||
Apply(constructor_x, args_x) => {
|
||||
if let Apply(constructor_y, args_y) = other {
|
||||
let equivalent_args = args_x
|
||||
.iter()
|
||||
.zip(args_y.iter())
|
||||
.all(|(p, q)| p.value.equivalent(&q.value));
|
||||
|
||||
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
||||
} else if let PncApply(constructor_y, args_y) = other {
|
||||
let equivalent_args = args_x
|
||||
.iter()
|
||||
.zip(args_y.iter())
|
||||
.all(|(p, q)| p.value.equivalent(&q.value));
|
||||
|
||||
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
PncApply(constructor_x, args_x) => {
|
||||
if let PncApply(constructor_y, args_y) = other {
|
||||
let equivalent_args = args_x
|
||||
.iter()
|
||||
.zip(args_y.iter())
|
||||
.all(|(p, q)| p.value.equivalent(&q.value));
|
||||
|
||||
constructor_x.value.equivalent(&constructor_y.value) && equivalent_args
|
||||
} else if let Apply(constructor_y, args_y) = other {
|
||||
let equivalent_args = args_x
|
||||
.iter()
|
||||
.zip(args_y.iter())
|
||||
|
@ -2554,6 +2591,7 @@ impl<'a> Malformed for Expr<'a> {
|
|||
LowLevelTry(loc_expr, _) => loc_expr.is_malformed(),
|
||||
Return(return_value, after_return) => return_value.is_malformed() || after_return.is_some_and(|ar| ar.is_malformed()),
|
||||
Apply(func, args, _) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()),
|
||||
PncApply(func, args) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()),
|
||||
BinOps(firsts, last) => firsts.iter().any(|(expr, _)| expr.is_malformed()) || last.is_malformed(),
|
||||
UnaryOp(expr, _) => expr.is_malformed(),
|
||||
If { if_thens, final_else, ..} => if_thens.iter().any(|(cond, body)| cond.is_malformed() || body.is_malformed()) || final_else.is_malformed(),
|
||||
|
@ -2650,7 +2688,8 @@ impl<'a> Malformed for Pattern<'a> {
|
|||
Identifier{ .. } |
|
||||
Tag(_) |
|
||||
OpaqueRef(_) => false,
|
||||
Apply(func, args, _) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()),
|
||||
Apply(func, args) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()),
|
||||
PncApply(func, args) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()),
|
||||
RecordDestructure(items) => items.iter().any(|item| item.is_malformed()),
|
||||
RequiredField(_, pat) => pat.is_malformed(),
|
||||
OptionalField(_, expr) => expr.is_malformed(),
|
||||
|
|
|
@ -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, PatternApplyStyle, Spaceable, Spaced, Spaces, SpacesBefore,
|
||||
TryTarget, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
ModuleImportParams, Pattern, 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,
|
||||
|
@ -233,12 +233,40 @@ fn loc_term<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
|||
),
|
||||
zero_or_more(pnc_args()),
|
||||
),
|
||||
|arena, (expr, arg_locs_vec)| {
|
||||
|arena,
|
||||
(expr, arg_locs_with_suffixes_vec): (
|
||||
Loc<Expr<'a>>,
|
||||
bumpalo::collections::Vec<
|
||||
'a,
|
||||
(
|
||||
Loc<Collection<'a, &'a Loc<Expr>>>,
|
||||
Option<Vec<'a, Suffix<'a>>>,
|
||||
),
|
||||
>,
|
||||
)| {
|
||||
let mut e = expr;
|
||||
for args_loc in arg_locs_vec.iter() {
|
||||
let orig_region = e.region;
|
||||
for (args_loc, maybe_suffixes) in arg_locs_with_suffixes_vec.iter() {
|
||||
let value = if matches!(
|
||||
e,
|
||||
Loc {
|
||||
value: Expr::Dbg,
|
||||
..
|
||||
}
|
||||
) {
|
||||
Expr::Apply(arena.alloc(e), args_loc.value.items, CalledVia::Space)
|
||||
} else if let Some(suffixes) = maybe_suffixes {
|
||||
apply_expr_access_chain(
|
||||
arena,
|
||||
Expr::PncApply(arena.alloc(e), args_loc.value),
|
||||
suffixes.clone(),
|
||||
)
|
||||
} else {
|
||||
Expr::PncApply(arena.alloc(e), args_loc.value)
|
||||
};
|
||||
e = Loc {
|
||||
value: Expr::Apply(arena.alloc(e), args_loc.value, CalledVia::ParensAndCommas),
|
||||
region: Region::span_across(&expr.region, &args_loc.region),
|
||||
value,
|
||||
region: Region::span_across(&orig_region, &args_loc.region),
|
||||
};
|
||||
}
|
||||
e
|
||||
|
@ -247,9 +275,16 @@ fn loc_term<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
|||
.trace("term")
|
||||
}
|
||||
|
||||
fn pnc_args<'a>() -> impl Parser<'a, Loc<&'a [&'a Loc<Expr<'a>>]>, EExpr<'a>> {
|
||||
fn pnc_args<'a>() -> impl Parser<
|
||||
'a,
|
||||
(
|
||||
Loc<Collection<'a, &'a Loc<Expr<'a>>>>,
|
||||
Option<Vec<'a, Suffix<'a>>>,
|
||||
),
|
||||
EExpr<'a>,
|
||||
> {
|
||||
|arena: &'a Bump, state: State<'a>, min_indent: u32| {
|
||||
map_with_arena(
|
||||
let args_then_suffixes = and(
|
||||
specialize_err(
|
||||
EExpr::InParens,
|
||||
loc(collection_trailing_sep_e(
|
||||
|
@ -260,32 +295,23 @@ fn pnc_args<'a>() -> impl Parser<'a, Loc<&'a [&'a Loc<Expr<'a>>]>, EExpr<'a>> {
|
|||
Expr::SpaceBefore,
|
||||
)),
|
||||
),
|
||||
|arena, arg_loc: Loc<Collection<'a, Loc<Expr<'a>>>>| {
|
||||
let mut args_vec = Vec::new_in(arena);
|
||||
let args_len = arg_loc.value.items.len();
|
||||
for (i, arg) in arg_loc.value.items.iter().enumerate() {
|
||||
if i == (args_len - 1) {
|
||||
let last_comments = arg_loc.value.final_comments();
|
||||
if !last_comments.is_empty() {
|
||||
let sa = Expr::SpaceAfter(arena.alloc(arg.value), last_comments);
|
||||
let arg_with_spaces: &Loc<Expr<'a>> = arena.alloc(Loc {
|
||||
value: sa,
|
||||
region: arg.region,
|
||||
});
|
||||
args_vec.push(arg_with_spaces);
|
||||
} else {
|
||||
let a: &Loc<Expr<'a>> = arena.alloc(arg);
|
||||
args_vec.push(a);
|
||||
}
|
||||
} else {
|
||||
let a: &Loc<Expr<'a>> = arena.alloc(arg);
|
||||
args_vec.push(a);
|
||||
}
|
||||
}
|
||||
Loc {
|
||||
value: args_vec.into_bump_slice(),
|
||||
region: arg_loc.region,
|
||||
}
|
||||
optional(record_field_access_chain()),
|
||||
);
|
||||
map_with_arena(
|
||||
args_then_suffixes,
|
||||
|arena: &'a Bump,
|
||||
(loc_args_coll, maybe_suffixes): (
|
||||
Loc<Collection<'a, Loc<Expr<'a>>>>,
|
||||
Option<Vec<'a, Suffix<'a>>>,
|
||||
)| {
|
||||
let args = loc_args_coll.value.ptrify_items(arena);
|
||||
(
|
||||
Loc {
|
||||
region: loc_args_coll.region,
|
||||
value: args,
|
||||
},
|
||||
maybe_suffixes,
|
||||
)
|
||||
},
|
||||
)
|
||||
.parse(arena, state, min_indent)
|
||||
|
@ -2117,7 +2143,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, called_via) => {
|
||||
Expr::Apply(loc_val, loc_args, _) => {
|
||||
let region = loc_val.region;
|
||||
let value = expr_to_pattern_help(arena, &loc_val.value)?;
|
||||
let val_pattern = arena.alloc(Loc { region, value });
|
||||
|
@ -2131,18 +2157,22 @@ 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(),
|
||||
if matches!(called_via, CalledVia::ParensAndCommas) {
|
||||
PatternApplyStyle::ParensAndCommas
|
||||
} else {
|
||||
PatternApplyStyle::Whitespace
|
||||
},
|
||||
);
|
||||
let pattern = Pattern::Apply(val_pattern, arg_patterns.into_bump_slice());
|
||||
|
||||
pattern
|
||||
}
|
||||
Expr::PncApply(loc_val, args) => {
|
||||
let region = loc_val.region;
|
||||
let value = expr_to_pattern_help(arena, &loc_val.value)?;
|
||||
let val_pattern = arena.alloc(Loc { region, value });
|
||||
let pattern_args = args.map_items_result(arena, |arg| {
|
||||
let region = arg.region;
|
||||
let value = expr_to_pattern_help(arena, &arg.value)?;
|
||||
Ok(Loc { region, value })
|
||||
})?;
|
||||
|
||||
Pattern::PncApply(val_pattern, pattern_args)
|
||||
}
|
||||
|
||||
Expr::Try => Pattern::Identifier { ident: "try" },
|
||||
|
||||
|
@ -3143,6 +3173,31 @@ fn stmts_to_defs<'a>(
|
|||
|
||||
last_expr = Some(Loc::at(sp_stmt.item.region, e));
|
||||
|
||||
// don't re-process the rest of the statements; they got consumed by the dbg expr
|
||||
break;
|
||||
} else if let Expr::PncApply(
|
||||
Loc {
|
||||
value: Expr::Dbg, ..
|
||||
},
|
||||
args,
|
||||
) = e
|
||||
{
|
||||
let condition = &args.items[0];
|
||||
let rest = stmts_to_expr(&stmts[i + 1..], arena)?;
|
||||
let e = Expr::DbgStmt {
|
||||
first: condition,
|
||||
extra_args: &args.items[1..],
|
||||
continuation: arena.alloc(rest),
|
||||
};
|
||||
|
||||
let e = if sp_stmt.before.is_empty() {
|
||||
e
|
||||
} else {
|
||||
arena.alloc(e).before(sp_stmt.before)
|
||||
};
|
||||
|
||||
last_expr = Some(Loc::at(sp_stmt.item.region, e));
|
||||
|
||||
// don't re-process the rest of the statements; they got consumed by the dbg expr
|
||||
break;
|
||||
} else {
|
||||
|
@ -3313,7 +3368,8 @@ 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::PncApply(left, _) => starts_with_spaces_conservative(&left.value),
|
||||
Pattern::RecordDestructure(_) => false,
|
||||
Pattern::RequiredField(_, _) | Pattern::OptionalField(_, _) => false,
|
||||
Pattern::SpaceBefore(_, _) => true,
|
||||
|
@ -3329,7 +3385,6 @@ 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -3380,8 +3435,8 @@ fn pat_ends_with_spaces_conservative(pat: &Pattern<'_>) -> bool {
|
|||
| Pattern::ListRest(_)
|
||||
| Pattern::As(_, _)
|
||||
| Pattern::OpaqueRef(_)
|
||||
| Pattern::Apply(_, _, PatternApplyStyle::ParensAndCommas) => false,
|
||||
Pattern::Apply(_, args, _) => args
|
||||
| Pattern::PncApply(_, _) => false,
|
||||
Pattern::Apply(_, args) => args
|
||||
.last()
|
||||
.map_or(false, |a| pat_ends_with_spaces_conservative(&a.value)),
|
||||
Pattern::RecordDestructure(_) => false,
|
||||
|
@ -3403,7 +3458,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, PatternApplyStyle::Whitespace);
|
||||
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);
|
||||
|
|
|
@ -737,8 +737,13 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
arena.alloc(a.normalize(arena)),
|
||||
b.map(|loc_b| &*arena.alloc(loc_b.normalize(arena))),
|
||||
),
|
||||
Expr::Apply(a, b, c) => {
|
||||
Expr::Apply(arena.alloc(a.normalize(arena)), b.normalize(arena), c)
|
||||
Expr::Apply(a, b, called_via) => Expr::Apply(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
b.normalize(arena),
|
||||
called_via,
|
||||
),
|
||||
Expr::PncApply(a, b) => {
|
||||
Expr::PncApply(arena.alloc(a.normalize(arena)), b.normalize(arena))
|
||||
}
|
||||
Expr::BinOps(a, b) => Expr::BinOps(a.normalize(arena), arena.alloc(b.normalize(arena))),
|
||||
Expr::UnaryOp(a, b) => {
|
||||
|
@ -835,6 +840,30 @@ fn fold_defs<'a>(
|
|||
arena.alloc(Loc::at_zero(new_final)),
|
||||
);
|
||||
}
|
||||
ValueDef::Stmt(&Loc {
|
||||
value:
|
||||
Expr::PncApply(
|
||||
&Loc {
|
||||
value: Expr::Dbg, ..
|
||||
},
|
||||
args,
|
||||
),
|
||||
..
|
||||
}) => {
|
||||
let rest = fold_defs(arena, defs, final_expr);
|
||||
let new_final = Expr::DbgStmt {
|
||||
first: args.items[0],
|
||||
extra_args: &args.items[1..],
|
||||
continuation: arena.alloc(Loc::at_zero(rest)),
|
||||
};
|
||||
if new_defs.is_empty() {
|
||||
return new_final;
|
||||
}
|
||||
return Expr::Defs(
|
||||
arena.alloc(new_defs),
|
||||
arena.alloc(Loc::at_zero(new_final)),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
new_defs.push_value_def(vd, Region::zero(), &[], &[]);
|
||||
}
|
||||
|
@ -879,11 +908,13 @@ impl<'a> Normalize<'a> for Pattern<'a> {
|
|||
Pattern::Identifier { ident } => Pattern::Identifier { ident },
|
||||
Pattern::Tag(a) => Pattern::Tag(a),
|
||||
Pattern::OpaqueRef(a) => Pattern::OpaqueRef(a),
|
||||
Pattern::Apply(a, b, c) => Pattern::Apply(
|
||||
Pattern::Apply(a, b) => Pattern::Apply(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
arena.alloc(b.normalize(arena)),
|
||||
c,
|
||||
),
|
||||
Pattern::PncApply(a, b) => {
|
||||
Pattern::PncApply(arena.alloc(a.normalize(arena)), b.normalize(arena))
|
||||
}
|
||||
Pattern::RecordDestructure(a) => Pattern::RecordDestructure(a.normalize(arena)),
|
||||
Pattern::RequiredField(a, b) => {
|
||||
Pattern::RequiredField(a, arena.alloc(b.normalize(arena)))
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use crate::ast::{
|
||||
Collection, ExtractSpaces, Implements, Pattern, PatternApplyStyle, PatternAs, Spaceable,
|
||||
};
|
||||
use crate::ast::{Collection, ExtractSpaces, Implements, Pattern, PatternAs, Spaceable};
|
||||
use crate::blankspace::{space0_before_optional_after, space0_e, spaces, spaces_before};
|
||||
use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident};
|
||||
use crate::keyword;
|
||||
|
@ -337,35 +335,30 @@ fn loc_ident_pattern_help<'a>(
|
|||
let (_, loc_ident, state) = specialize_err(|_, pos| EPattern::Start(pos), loc(parse_ident))
|
||||
.parse(arena, state, min_indent)?;
|
||||
|
||||
let commas_and_paren_args_help = map_with_arena(
|
||||
collection_trailing_sep_e(
|
||||
enum ArgType<'a> {
|
||||
PncArgs(Loc<Collection<'a, Loc<Pattern<'a>>>>),
|
||||
WhitespaceArgs(&'a [Loc<Pattern<'a>>]),
|
||||
}
|
||||
|
||||
let commas_and_paren_args_help = map(
|
||||
loc(collection_trailing_sep_e(
|
||||
byte(b'(', EPattern::ParenStart),
|
||||
loc_tag_pattern_arg(false),
|
||||
byte(b',', EPattern::NotAPattern),
|
||||
byte(b')', EPattern::ParenEnd),
|
||||
Pattern::SpaceBefore,
|
||||
),
|
||||
|arena, args| {
|
||||
let mut args_vec = Vec::new_in(arena);
|
||||
for arg in args.iter() {
|
||||
let a: &Loc<Pattern<'a>> = arena.alloc(arg);
|
||||
args_vec.push(*a);
|
||||
}
|
||||
(
|
||||
args_vec.into_bump_slice(),
|
||||
PatternApplyStyle::ParensAndCommas,
|
||||
)
|
||||
},
|
||||
)),
|
||||
|args| ArgType::PncArgs(args),
|
||||
);
|
||||
|
||||
let whitespace_args =
|
||||
map_with_arena(loc_type_def_tag_pattern_args_help(), |arena, args| {
|
||||
let mut args_vec = Vec::new_in(arena);
|
||||
let mut args_vec = Vec::with_capacity_in(args.len(), arena);
|
||||
for arg in args.iter() {
|
||||
let a: &Loc<Pattern<'a>> = arena.alloc(arg);
|
||||
args_vec.push(*a);
|
||||
}
|
||||
(args_vec.into_bump_slice(), PatternApplyStyle::Whitespace)
|
||||
ArgType::WhitespaceArgs(args_vec.into_bump_slice())
|
||||
});
|
||||
|
||||
match loc_ident.value {
|
||||
|
@ -376,7 +369,7 @@ fn loc_ident_pattern_help<'a>(
|
|||
};
|
||||
|
||||
// Make sure `Foo Bar 1` is parsed as `Foo (Bar) 1`, and not `Foo (Bar 1)`
|
||||
let (_, (args, style), state) = if can_have_arguments {
|
||||
let (_, arg_type, state) = if can_have_arguments {
|
||||
one_of!(commas_and_paren_args_help, whitespace_args)
|
||||
.parse(arena, state, min_indent)?
|
||||
} else {
|
||||
|
@ -386,19 +379,27 @@ fn loc_ident_pattern_help<'a>(
|
|||
Err((MadeProgress, e)) => return Err((MadeProgress, e)),
|
||||
}
|
||||
};
|
||||
match arg_type {
|
||||
ArgType::PncArgs(args) => {
|
||||
let pnc_args = args.value;
|
||||
let value = Pattern::PncApply(&*arena.alloc(loc_tag), pnc_args);
|
||||
let region = Region::span_across(&loc_ident.region, &args.region);
|
||||
Ok((MadeProgress, Loc { region, value }, state))
|
||||
}
|
||||
ArgType::WhitespaceArgs(args) => {
|
||||
let loc_args: &[Loc<Pattern<'_>>] = { args };
|
||||
if loc_args.is_empty() {
|
||||
Ok((MadeProgress, loc_tag, state))
|
||||
} else {
|
||||
let region = Region::across_all(
|
||||
std::iter::once(&loc_ident.region)
|
||||
.chain(loc_args.iter().map(|loc_arg| &loc_arg.region)),
|
||||
);
|
||||
let value = Pattern::Apply(&*arena.alloc(loc_tag), loc_args);
|
||||
|
||||
let loc_args: &[Loc<Pattern<'_>>] = { args };
|
||||
|
||||
if loc_args.is_empty() {
|
||||
Ok((MadeProgress, loc_tag, state))
|
||||
} else {
|
||||
let region = Region::across_all(
|
||||
std::iter::once(&loc_ident.region)
|
||||
.chain(loc_args.iter().map(|loc_arg| &loc_arg.region)),
|
||||
);
|
||||
let value = Pattern::Apply(&*arena.alloc(loc_tag), loc_args, style);
|
||||
|
||||
Ok((MadeProgress, Loc { region, value }, state))
|
||||
Ok((MadeProgress, Loc { region, value }, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ident::OpaqueRef(name) => {
|
||||
|
@ -408,25 +409,37 @@ fn loc_ident_pattern_help<'a>(
|
|||
};
|
||||
|
||||
// Make sure `@Foo Bar 1` is parsed as `@Foo (Bar) 1`, and not `@Foo (Bar 1)`
|
||||
let (_, (args, style), state) = if can_have_arguments {
|
||||
let (_, arg_type, state) = if can_have_arguments {
|
||||
one_of!(commas_and_paren_args_help, whitespace_args)
|
||||
.parse(arena, state, min_indent)?
|
||||
} else {
|
||||
commas_and_paren_args_help.parse(arena, state, min_indent)?
|
||||
match commas_and_paren_args_help.parse(arena, state.clone(), min_indent) {
|
||||
Ok((_, res, new_state)) => (MadeProgress, res, new_state),
|
||||
Err((NoProgress, _)) => return Ok((MadeProgress, loc_pat, state)),
|
||||
Err((MadeProgress, e)) => return Err((MadeProgress, e)),
|
||||
}
|
||||
};
|
||||
match arg_type {
|
||||
ArgType::PncArgs(args) => {
|
||||
let pnc_args = args.value;
|
||||
let value = Pattern::PncApply(&*arena.alloc(loc_pat), pnc_args);
|
||||
let region = Region::span_across(&loc_ident.region, &args.region);
|
||||
Ok((MadeProgress, Loc { region, value }, state))
|
||||
}
|
||||
ArgType::WhitespaceArgs(args) => {
|
||||
let loc_args: &[Loc<Pattern<'_>>] = { args };
|
||||
if loc_args.is_empty() {
|
||||
Ok((MadeProgress, loc_pat, state))
|
||||
} else {
|
||||
let region = Region::across_all(
|
||||
std::iter::once(&loc_ident.region)
|
||||
.chain(loc_args.iter().map(|loc_arg| &loc_arg.region)),
|
||||
);
|
||||
let value = Pattern::Apply(&*arena.alloc(loc_pat), loc_args);
|
||||
|
||||
let loc_args: &[Loc<Pattern<'_>>] = { args };
|
||||
|
||||
if loc_args.is_empty() {
|
||||
Ok((MadeProgress, loc_pat, state))
|
||||
} else {
|
||||
let region = Region::across_all(
|
||||
std::iter::once(&loc_ident.region)
|
||||
.chain(loc_args.iter().map(|loc_arg| &loc_arg.region)),
|
||||
);
|
||||
let value = Pattern::Apply(&*arena.alloc(loc_pat), loc_args, style);
|
||||
|
||||
Ok((MadeProgress, Loc { region, value }, state))
|
||||
Ok((MadeProgress, Loc { region, value }, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ident::Access {
|
||||
|
@ -683,7 +696,7 @@ mod test_parse_pattern {
|
|||
region: new_region(3, 4),
|
||||
}];
|
||||
let expected = Loc {
|
||||
value: Pattern::Apply(&expected_tag, &expected_args, PatternApplyStyle::Whitespace),
|
||||
value: Pattern::Apply(&expected_tag, &expected_args),
|
||||
region: new_region(0, 4),
|
||||
};
|
||||
assert_eq!(format!("{res:#?}"), format!("{expected:#?}"));
|
||||
|
@ -699,17 +712,13 @@ mod test_parse_pattern {
|
|||
value: Pattern::Tag("Ok"),
|
||||
region: new_region(0, 2),
|
||||
};
|
||||
let expected_args = [Loc {
|
||||
let expected_args = Collection::with_items(arena.alloc([Loc {
|
||||
value: Pattern::Identifier { ident: "a" },
|
||||
region: new_region(3, 4),
|
||||
}];
|
||||
}]));
|
||||
let expected = Loc {
|
||||
value: Pattern::Apply(
|
||||
&expected_tag,
|
||||
&expected_args,
|
||||
PatternApplyStyle::ParensAndCommas,
|
||||
),
|
||||
region: new_region(0, 4),
|
||||
value: Pattern::PncApply(&expected_tag, expected_args),
|
||||
region: new_region(0, 5),
|
||||
};
|
||||
assert_eq!(format!("{res:#?}"), format!("{expected:#?}"));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue