Merge branch 'main' into issue-7425

This commit is contained in:
Ian McLerran 2025-01-03 14:00:30 -06:00 committed by GitHub
commit acf8e33e2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
110 changed files with 1538 additions and 485 deletions

View file

@ -8,7 +8,7 @@
use roc_error_macros::internal_error;
use roc_module::{called_via::CalledVia, symbol::Symbol};
use roc_parse::ast::{self, Collection};
use roc_parse::ast::{self, Collection, PatternApplyStyle};
use roc_region::all::{Loc, Region};
use crate::{env::Env, pattern::Pattern, scope::Scope};
@ -27,6 +27,7 @@ fn to_encoder<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
DERIVED_REGION,
ast::Pattern::Identifier { ident: payload },
)]),
ast::PatternApplyStyle::Whitespace,
);
// Encode.toEncoder payload
@ -132,6 +133,7 @@ fn hash<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
DERIVED_REGION,
ast::Pattern::Identifier { ident: payload },
)]),
PatternApplyStyle::Whitespace,
);
// Hash.hash hasher payload
@ -178,6 +180,7 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
DERIVED_REGION,
ast::Pattern::Identifier { ident: payload1 },
)]),
PatternApplyStyle::Whitespace,
);
// \@Opaq payload2
let opaque2 = ast::Pattern::Apply(
@ -186,6 +189,7 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
DERIVED_REGION,
ast::Pattern::Identifier { ident: payload2 },
)]),
PatternApplyStyle::Whitespace,
);
// Bool.isEq payload1 payload2
@ -232,6 +236,7 @@ fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
DERIVED_REGION,
ast::Pattern::Identifier { ident: payload },
)]),
PatternApplyStyle::Whitespace,
);
// Inspect.toInspector payload

View file

@ -11,8 +11,9 @@ use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName;
use roc_parse::ast::Expr::{self, *};
use roc_parse::ast::{
is_expr_suffixed, AssignedField, Collection, Defs, ModuleImportParams, Pattern, ResultTryKind,
StrLiteral, StrSegment, TryTarget, TypeAnnotation, ValueDef, WhenBranch,
is_expr_suffixed, AssignedField, Collection, Defs, ModuleImportParams, Pattern,
PatternApplyStyle, ResultTryKind, StrLiteral, StrSegment, TryTarget, TypeAnnotation, ValueDef,
WhenBranch,
};
use roc_problem::can::Problem;
use roc_region::all::{Loc, Region};
@ -177,7 +178,11 @@ fn new_op_call_expr<'a>(
env.arena.alloc(Loc::at(left.region, Pattern::Tag("Ok")));
branch_1_patts.push(Loc::at(
left.region,
Pattern::Apply(branch_1_tag, branch_1_patts_args.into_bump_slice()),
Pattern::Apply(
branch_1_tag,
branch_1_patts_args.into_bump_slice(),
PatternApplyStyle::ParensAndCommas,
),
));
let branch_one: &WhenBranch<'_> = env.arena.alloc(WhenBranch {
patterns: branch_1_patts.into_bump_slice(),
@ -198,7 +203,11 @@ fn new_op_call_expr<'a>(
env.arena.alloc(Loc::at(left.region, Pattern::Tag("Err")));
branch_2_patts.push(Loc::at(
right.region,
Pattern::Apply(branch_2_tag, branch_2_patts_args.into_bump_slice()),
Pattern::Apply(
branch_2_tag,
branch_2_patts_args.into_bump_slice(),
PatternApplyStyle::ParensAndCommas,
),
));
let branch_two: &WhenBranch<'_> = env.arena.alloc(WhenBranch {
patterns: branch_2_patts.into_bump_slice(),
@ -1413,7 +1422,7 @@ fn desugar_pattern<'a>(env: &mut Env<'a>, scope: &mut Scope, pattern: Pattern<'a
| MalformedIdent(_, _)
| QualifiedIdentifier { .. } => pattern,
Apply(tag, arg_patterns) => {
Apply(tag, arg_patterns, style) => {
// Skip desugaring the tag, it should either be a Tag or OpaqueRef
let mut desugared_arg_patterns = Vec::with_capacity_in(arg_patterns.len(), env.arena);
for arg_pattern in arg_patterns.iter() {
@ -1423,7 +1432,7 @@ fn desugar_pattern<'a>(env: &mut Env<'a>, scope: &mut Scope, pattern: Pattern<'a
});
}
Apply(tag, desugared_arg_patterns.into_bump_slice())
Apply(tag, desugared_arg_patterns.into_bump_slice(), style)
}
RecordDestructure(field_patterns) => {
RecordDestructure(desugar_record_destructures(env, scope, field_patterns))

View file

@ -411,7 +411,7 @@ pub fn canonicalize_pattern<'a>(
)));
Pattern::UnsupportedPattern(region)
}
Apply(tag, patterns) => {
Apply(tag, patterns, _) => {
let mut can_patterns = Vec::with_capacity(patterns.len());
for loc_pattern in *patterns {
let can_pattern = canonicalize_pattern(

View file

@ -1,6 +1,7 @@
---
source: crates/compiler/can/tests/test_suffixed.rs
expression: snapshot
snapshot_kind: text
---
Defs {
tags: [
@ -96,6 +97,7 @@ Defs {
ident: "success_BRANCH1_24_32",
},
],
ParensAndCommas,
),
],
value: @24-32 Var {
@ -115,6 +117,7 @@ Defs {
"",
),
],
ParensAndCommas,
),
],
value: @36-39 Num(

View file

@ -78,6 +78,7 @@ Defs {
ident: "name",
},
],
Whitespace,
),
],
value: @125-154 Apply(

View file

@ -13,14 +13,14 @@ use crate::pattern::{pattern_lift_spaces, pattern_lift_spaces_before};
use crate::spaces::{
fmt_comments_only, fmt_default_newline, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT,
};
use crate::Buf;
use crate::{Buf, MigrationFlags};
use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_parse::ast::{
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
ModuleImportParams, Pattern, Spaceable, Spaces, SpacesAfter, SpacesBefore, StrLiteral,
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
ModuleImportParams, Pattern, PatternApplyStyle, Spaceable, Spaces, SpacesAfter, SpacesBefore,
StrLiteral, TypeAnnotation, TypeDef, TypeHeader, ValueDef,
};
use roc_parse::expr::merge_spaces;
use roc_parse::header::Keyword;
@ -564,6 +564,11 @@ impl<'a> Formattable for TypeHeader<'a> {
_newlines: Newlines,
indent: u16,
) {
let old_flags = buf.flags;
buf.flags = MigrationFlags {
parens_and_commas: false,
..old_flags
};
pattern_fmt_apply(
buf,
Pattern::Tag(self.name.value),
@ -571,7 +576,9 @@ impl<'a> Formattable for TypeHeader<'a> {
Parens::NotNeeded,
indent,
self.vars.iter().any(|v| v.is_multiline()),
PatternApplyStyle::Whitespace,
);
buf.flags = old_flags;
}
}
@ -582,6 +589,7 @@ fn type_head_lift_spaces<'a, 'b: 'a>(
let pat = Pattern::Apply(
arena.alloc(Loc::at(head.name.region, Pattern::Tag(head.name.value))),
head.vars,
PatternApplyStyle::Whitespace,
);
pattern_lift_spaces(arena, &pat)
@ -903,7 +911,9 @@ impl<'a> Formattable for ValueDef<'a> {
fn ann_pattern_needs_parens(value: &Pattern<'_>) -> bool {
match value.extract_spaces().item {
Pattern::Tag(_) => true,
Pattern::Apply(func, _args) if matches!(func.extract_spaces().item, Pattern::Tag(..)) => {
Pattern::Apply(func, _args, _style)
if matches!(func.extract_spaces().item, Pattern::Tag(..)) =>
{
true
}
_ => false,

View file

@ -11,7 +11,7 @@ use crate::spaces::{
use crate::Buf;
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_module::called_via::{self, BinOp, UnaryOp};
use roc_module::called_via::{self, BinOp, CalledVia, UnaryOp};
use roc_parse::ast::{
AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces, Pattern, Spaceable,
Spaces, SpacesAfter, SpacesBefore, TryTarget, WhenBranch,
@ -91,13 +91,15 @@ fn format_expr_only(
buf.indent(indent);
buf.push_str("try");
}
Expr::Apply(loc_expr, loc_args, called_via::CalledVia::ParensAndCommas) => {
fmt_apply(loc_expr, loc_args, indent, buf, true);
}
Expr::Apply(loc_expr, loc_args, _) => {
let apply_needs_parens = parens == Parens::InApply || parens == Parens::InApplyLastArg;
if apply_needs_parens && !loc_args.is_empty() {
fmt_parens(item, buf, indent);
if buf.flags().parens_and_commas || !apply_needs_parens || loc_args.is_empty() {
fmt_apply(loc_expr, loc_args, indent, buf, false);
} else {
fmt_apply(loc_expr, loc_args, indent, buf);
fmt_parens(item, buf, indent);
}
}
&Expr::Num(string) => {
@ -643,6 +645,7 @@ fn fmt_apply(
indent: u16,
buf: &mut Buf<'_>,
expr_used_commas_and_parens: bool,
) {
// should_reflow_outdentable, aka should we transform this:
//
@ -662,6 +665,7 @@ fn fmt_apply(
// 2,
// ]
// ```
let use_commas_and_parens = expr_used_commas_and_parens || buf.flags().parens_and_commas;
let should_reflow_outdentable = loc_expr.extract_spaces().after.is_empty()
&& except_last(loc_args).all(|a| !a.is_multiline())
&& loc_args
@ -697,17 +701,31 @@ fn fmt_apply(
if !expr.before.is_empty() {
format_spaces(buf, expr.before, Newlines::Yes, indent);
}
expr.item.format_with_options(
buf,
if use_commas_and_parens {
Parens::NotNeeded
} else {
Parens::InApply
},
Newlines::Yes,
indent,
);
expr.item
.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
if use_commas_and_parens {
buf.push('(');
}
let mut last_after = expr.after;
for (i, loc_arg) in loc_args.iter().enumerate() {
let is_last_arg = i == loc_args.len() - 1;
let is_first_arg = i == 0;
let arg = expr_lift_spaces(
if is_last_arg {
if use_commas_and_parens {
Parens::NotNeeded
} else if is_last_arg {
Parens::InApplyLastArg
} else {
Parens::InApply
@ -728,7 +746,7 @@ fn fmt_apply(
last_after = arg.after;
if needs_indent {
buf.ensure_ends_with_newline();
} else {
} else if !(is_first_arg && use_commas_and_parens) {
buf.spaces(1);
}
@ -736,13 +754,34 @@ fn fmt_apply(
{
fmt_parens(&arg.item, buf, arg_indent);
} else {
format_expr_only(&arg.item, buf, Parens::InApply, Newlines::Yes, arg_indent);
format_expr_only(
&arg.item,
buf,
if use_commas_and_parens {
Parens::NotNeeded
} else {
Parens::InApply
},
Newlines::Yes,
arg_indent,
);
}
if use_commas_and_parens && (!is_last_arg || needs_indent) {
buf.push(',');
}
}
if !last_after.is_empty() {
format_spaces(buf, last_after, Newlines::Yes, arg_indent);
}
if use_commas_and_parens {
if needs_indent {
buf.ensure_ends_with_newline();
buf.indent(indent);
}
buf.push(')');
}
}
fn is_outdentable_collection(expr: &Expr<'_>) -> bool {
@ -1007,6 +1046,19 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
expr: &Expr<'b>,
) -> Spaces<'a, Expr<'a>> {
match expr {
Expr::Apply(func, args, CalledVia::ParensAndCommas) => {
let lifted = expr_lift_spaces_before(Parens::NotNeeded, arena, &func.value);
Spaces {
before: lifted.before,
item: Expr::Apply(
arena.alloc(Loc::at(func.region, lifted.item)),
args,
CalledVia::ParensAndCommas,
),
after: arena.alloc([]),
}
}
Expr::Apply(func, args, called_via) => {
if args.is_empty() {
return expr_lift_spaces(Parens::NotNeeded, arena, &func.value);

View file

@ -25,16 +25,13 @@ pub struct Buf<'a> {
#[derive(Debug, Copy, Clone)]
pub struct MigrationFlags {
pub(crate) snakify: bool,
pub snakify: bool,
pub parens_and_commas: bool,
}
impl MigrationFlags {
pub fn new(snakify: bool) -> Self {
MigrationFlags { snakify }
}
pub fn at_least_one_active(&self) -> bool {
self.snakify
self.snakify || self.parens_and_commas
}
}

View file

@ -7,7 +7,8 @@ use crate::spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
use crate::Buf;
use bumpalo::Bump;
use roc_parse::ast::{
Base, CommentOrNewline, Pattern, PatternAs, Spaceable, Spaces, SpacesAfter, SpacesBefore,
Base, CommentOrNewline, Pattern, PatternApplyStyle, PatternAs, Spaceable, Spaces, SpacesAfter,
SpacesBefore,
};
use roc_parse::expr::merge_spaces;
use roc_region::all::Loc;
@ -72,7 +73,7 @@ impl<'a> Formattable for Pattern<'a> {
}
},
Pattern::StrLiteral(literal) => is_str_multiline(literal),
Pattern::Apply(pat, args) => {
Pattern::Apply(pat, args, _) => {
pat.is_multiline() || args.iter().any(|a| a.is_multiline())
}
@ -162,7 +163,22 @@ fn fmt_pattern_only(
buf.indent(indent);
buf.push_str(name);
}
Pattern::Apply(loc_pattern, loc_arg_patterns) => {
Pattern::Apply(
loc_pattern,
loc_arg_patterns,
style @ PatternApplyStyle::ParensAndCommas,
) => {
pattern_fmt_apply(
buf,
loc_pattern.value,
loc_arg_patterns,
Parens::NotNeeded,
indent,
is_multiline,
*style,
);
}
Pattern::Apply(loc_pattern, loc_arg_patterns, style) => {
pattern_fmt_apply(
buf,
loc_pattern.value,
@ -170,6 +186,7 @@ fn fmt_pattern_only(
parens,
indent,
is_multiline,
*style,
);
}
Pattern::RecordDestructure(loc_patterns) => {
@ -445,11 +462,14 @@ pub fn pattern_fmt_apply(
parens: Parens,
indent: u16,
is_multiline: bool,
style: PatternApplyStyle,
) {
let use_commas_and_parens =
matches!(style, PatternApplyStyle::ParensAndCommas) || buf.flags().parens_and_commas;
buf.indent(indent);
// Sometimes, an Apply pattern needs parens around it.
// In particular when an Apply's argument is itself an Apply (> 0) arguments
let parens = !args.is_empty() && parens == Parens::InApply;
let parens = !args.is_empty() && parens == Parens::InApply && !use_commas_and_parens;
let indent_more = if is_multiline {
indent + INDENT
@ -473,14 +493,27 @@ pub fn pattern_fmt_apply(
fmt_pattern_only(&func.item, buf, Parens::InApply, indent, is_multiline);
if use_commas_and_parens {
buf.push('(');
}
let mut last_after = func.after;
let mut add_newlines = is_multiline;
for loc_arg in args.iter() {
buf.spaces(1);
for (i, loc_arg) in args.iter().enumerate() {
let is_last_arg = i == args.len() - 1;
let is_first_arg = i == 0;
let parens = Parens::InApply;
if !(is_first_arg && use_commas_and_parens) {
buf.spaces(1);
}
let parens = if use_commas_and_parens {
Parens::NotNeeded
} else {
Parens::InApply
};
let arg = pattern_lift_spaces(buf.text.bump(), &loc_arg.value);
let mut was_multiline = arg.item.is_multiline();
@ -527,6 +560,9 @@ pub fn pattern_fmt_apply(
buf.push_str("(implements)");
} else {
fmt_pattern_only(&arg.item, buf, parens, indent_more, arg.item.is_multiline());
if use_commas_and_parens && (!is_last_arg || add_newlines) {
buf.push(',');
}
}
last_after = arg.after;
@ -542,7 +578,7 @@ pub fn pattern_fmt_apply(
}
}
if parens {
if parens || use_commas_and_parens {
buf.push(')');
}
}
@ -597,7 +633,7 @@ fn pattern_prec(pat: Pattern<'_>) -> Prec {
| Pattern::Tuple(..)
| Pattern::List(..)
| Pattern::ListRest(_) => Prec::Term,
Pattern::Apply(_, _) | Pattern::As(_, _) => Prec::Apply,
Pattern::Apply(_, _, _) | Pattern::As(_, _) => Prec::Apply,
Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => pattern_prec(*inner),
Pattern::Malformed(_) | Pattern::MalformedIdent(..) => Prec::Term,
}
@ -617,7 +653,7 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>(
pat: &Pattern<'b>,
) -> Spaces<'a, Pattern<'a>> {
match pat {
Pattern::Apply(func, args) => {
Pattern::Apply(func, args, style) => {
let func_lifted = pattern_lift_spaces(arena, &func.value);
let args = arena.alloc_slice_copy(args);
@ -652,7 +688,7 @@ pub fn pattern_lift_spaces<'a, 'b: 'a>(
};
Spaces {
before,
item: Pattern::Apply(arena.alloc(func), args),
item: Pattern::Apply(arena.alloc(func), args, *style),
after,
}
}
@ -712,7 +748,7 @@ fn handle_multiline_str_spaces<'a>(pat: &Pattern<'_>, before: &mut &'a [CommentO
fn starts_with_block_str(item: &Pattern<'_>) -> bool {
match item {
Pattern::As(inner, _) | Pattern::Apply(inner, _) => starts_with_block_str(&inner.value),
Pattern::As(inner, _) | Pattern::Apply(inner, _, _) => starts_with_block_str(&inner.value),
Pattern::SpaceBefore(inner, _) | Pattern::SpaceAfter(inner, _) => {
starts_with_block_str(inner)
}
@ -791,7 +827,10 @@ mod snakify_test {
use crate::{Buf, MigrationFlags};
fn check_snakify(arena: &Bump, original: &str) -> String {
let flags = MigrationFlags::new(true);
let flags = MigrationFlags {
snakify: true,
parens_and_commas: false,
};
let mut buf = Buf::new_in(arena, flags);
buf.indent(0);
snakify_camel_ident(&mut buf, original);

View file

@ -6432,6 +6432,82 @@ All branches in an `if` must have the same type!
)
}
#[test]
fn exposes_start() {
report_header_problem_as(
indoc!(
r"
module foobar []
"
),
indoc!(
r#"
WEIRD EXPOSES in /code/proj/Main.roc
I am partway through parsing a header, but I got stuck here:
1 module foobar []
^
I was expecting an `exposes` list like
[Animal, default, tame]
"#
),
)
}
#[test]
fn exposes_missing_comma() {
report_header_problem_as(
indoc!(
r"
module [value func]
"
),
indoc!(
r#"
WEIRD EXPOSES in /code/proj/Main.roc
I am partway through parsing an `exposes` list, but I got stuck here:
1 module [value func]
^
I was expecting a type name, value name or function name next, like
[Animal, default, tame]
"#
),
)
}
#[test]
fn exposes_end() {
report_header_problem_as(
indoc!(
r"
module [value
"
),
indoc!(
r#"
WEIRD EXPOSES in /code/proj/Main.roc
I am partway through parsing an `exposes` list, but I got stuck here:
1 module [value
2
^
I was expecting a type name, value name or function name next, like
[Animal, default, tame]
"#
),
)
}
#[test]
fn invalid_app_name() {
report_header_problem_as(

View file

@ -68,6 +68,9 @@ pub enum CalledVia {
/// Calling with space, e.g. (foo bar)
Space,
/// Calling parens-and-comms style, e.g. foo(bar)
ParensAndCommas,
/// Calling with an operator, e.g. (bar |> foo) or (1 + 2)
BinOp(BinOp),

View file

@ -1745,6 +1745,12 @@ impl<'a> PatternAs<'a> {
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PatternApplyStyle {
Whitespace,
ParensAndCommas,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Pattern<'a> {
// Identifier
@ -1760,7 +1766,11 @@ pub enum Pattern<'a> {
OpaqueRef(&'a str),
Apply(&'a Loc<Pattern<'a>>, &'a [Loc<Pattern<'a>>]),
Apply(
&'a Loc<Pattern<'a>>,
&'a [Loc<Pattern<'a>>],
PatternApplyStyle,
),
/// This is Located<Pattern> rather than Located<str> so we can record comments
/// around the destructured names, e.g. { x ### x does stuff ###, y }
@ -1841,8 +1851,8 @@ 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())
@ -2670,7 +2680,7 @@ 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()),
RecordDestructure(items) => items.iter().any(|item| item.is_malformed()),
RequiredField(_, pat) => pat.is_malformed(),
OptionalField(_, expr) => expr.is_malformed(),

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,50 +198,98 @@ 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())),
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())),
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()),
// In some contexts we want to parse the `_` as an expression, so it can then be turned into a
// pattern later
loc(underscore_expression()),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
ident_seq(),
),
zero_or_more(pnc_args()),
),
|arena, (expr, arg_locs_vec)| {
let mut e = expr;
for args_loc in arg_locs_vec.iter() {
e = Loc {
value: Expr::Apply(arena.alloc(e), args_loc.value, CalledVia::ParensAndCommas),
region: Region::span_across(&expr.region, &args_loc.region),
};
}
e
},
)
.trace("term")
}
fn pnc_args<'a>() -> impl Parser<'a, Loc<&'a [&'a Loc<Expr<'a>>]>, EExpr<'a>> {
|arena: &'a Bump, state: State<'a>, min_indent: u32| {
map_with_arena(
specialize_err(
EExpr::InParens,
loc(collection_trailing_sep_e(
byte(b'(', EInParens::Open),
specialize_err_ref(EInParens::Expr, loc_expr(true)),
byte(b',', EInParens::End),
byte(b')', EInParens::End),
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,
}
},
)
.parse(arena, state, min_indent)
}
}
fn ident_seq<'a>() -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
@ -1708,7 +1756,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(
@ -1758,7 +1807,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) {
@ -2054,7 +2103,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 });
@ -2068,7 +2117,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
}
@ -3242,7 +3299,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,
@ -3258,6 +3315,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,
)
}
}
@ -3307,8 +3365,9 @@ fn pat_ends_with_spaces_conservative(pat: &Pattern<'_>) -> bool {
| Pattern::NonBase10Literal { .. }
| Pattern::ListRest(_)
| Pattern::As(_, _)
| Pattern::OpaqueRef(_) => false,
Pattern::Apply(_, args) => args
| Pattern::OpaqueRef(_)
| Pattern::Apply(_, _, PatternApplyStyle::ParensAndCommas) => false,
Pattern::Apply(_, args, _) => args
.last()
.map_or(false, |a| pat_ends_with_spaces_conservative(&a.value)),
Pattern::RecordDestructure(_) => false,
@ -3330,7 +3389,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);

View file

@ -879,9 +879,10 @@ 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) => Pattern::Apply(
Pattern::Apply(a, b, c) => Pattern::Apply(
arena.alloc(a.normalize(arena)),
arena.alloc(b.normalize(arena)),
c,
),
Pattern::RecordDestructure(a) => Pattern::RecordDestructure(a.normalize(arena)),
Pattern::RequiredField(a, b) => {
@ -1257,6 +1258,8 @@ impl<'a> Normalize<'a> for EPattern<'a> {
EPattern::AccessorFunction(_) => EPattern::AccessorFunction(Position::zero()),
EPattern::RecordUpdaterFunction(_) => EPattern::RecordUpdaterFunction(Position::zero()),
EPattern::Str(e, _) => EPattern::Str(e.normalize(arena), Position::zero()),
EPattern::ParenStart(_) => EPattern::ParenStart(Position::zero()),
EPattern::ParenEnd(_) => EPattern::ParenEnd(Position::zero()),
}
}
}

View file

@ -1066,6 +1066,9 @@ pub enum EPattern<'a> {
AccessorFunction(Position),
RecordUpdaterFunction(Position),
Str(EString<'a>, Position),
ParenStart(Position),
ParenEnd(Position),
}
impl<'a> EPattern<'a> {
@ -1090,7 +1093,9 @@ impl<'a> EPattern<'a> {
| EPattern::IndentEnd(position)
| EPattern::AsIndentStart(position)
| EPattern::AccessorFunction(position)
| EPattern::RecordUpdaterFunction(position) => Region::from_pos(*position),
| EPattern::RecordUpdaterFunction(position)
| EPattern::ParenStart(position)
| EPattern::ParenEnd(position) => Region::from_pos(*position),
}
}
}

View file

@ -1,11 +1,13 @@
use crate::ast::{Collection, ExtractSpaces, Implements, Pattern, PatternAs, Spaceable};
use crate::blankspace::{space0_e, spaces, spaces_before};
use crate::ast::{
Collection, ExtractSpaces, Implements, Pattern, PatternApplyStyle, 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;
use crate::parser::{
self, backtrackable, byte, collection_trailing_sep_e, fail_when, loc, map, optional,
skip_first, specialize_err, specialize_err_ref, then, three_bytes, two_bytes, zero_or_more,
EPattern, PInParens, PList, PRecord, Parser,
self, backtrackable, byte, collection_trailing_sep_e, fail_when, loc, map, map_with_arena,
optional, skip_first, skip_second, specialize_err, specialize_err_ref, then, three_bytes,
two_bytes, zero_or_more, EPattern, PInParens, PList, PRecord, Parser,
};
use crate::parser::{either, Progress::*};
use crate::state::State;
@ -85,15 +87,15 @@ fn loc_pattern_help_help<'a>(
) -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>> {
one_of!(
specialize_err(EPattern::PInParens, loc_pattern_in_parens_help()),
loc(string_like_pattern_help()),
loc(number_pattern_help()),
loc(underscore_pattern_help()),
loc_ident_pattern_help(can_have_arguments),
loc(specialize_err(
EPattern::Record,
crate::pattern::record_pattern_help()
)),
loc(specialize_err(EPattern::List, list_pattern_help())),
loc(number_pattern_help()),
loc(string_like_pattern_help()),
loc_ident_pattern_help(can_have_arguments),
)
}
@ -121,10 +123,6 @@ fn pattern_as<'a>() -> impl Parser<'a, PatternAs<'a>, EPattern<'a>> {
}
}
fn loc_tag_pattern_args_help<'a>() -> impl Parser<'a, Vec<'a, Loc<Pattern<'a>>>, EPattern<'a>> {
zero_or_more(loc_tag_pattern_arg(false))
}
/// Like `loc_tag_pattern_args_help`, but stops if a "implements" keyword is seen (indicating an ability).
fn loc_type_def_tag_pattern_args_help<'a>(
) -> impl Parser<'a, Vec<'a, Loc<Pattern<'a>>>, EPattern<'a>> {
@ -339,6 +337,37 @@ 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(
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,
)
},
);
let whitespace_args =
map_with_arena(loc_type_def_tag_pattern_args_help(), |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::Whitespace)
});
match loc_ident.value {
Ident::Tag(tag) => {
let loc_tag = Loc {
@ -347,24 +376,29 @@ fn loc_ident_pattern_help<'a>(
};
// Make sure `Foo Bar 1` is parsed as `Foo (Bar) 1`, and not `Foo (Bar 1)`
if can_have_arguments {
let (_, loc_args, state) =
loc_type_def_tag_pattern_args_help().parse(arena, state, min_indent)?;
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.into_bump_slice());
Ok((MadeProgress, Loc { region, value }, state))
}
let (_, (args, style), state) = if can_have_arguments {
one_of!(commas_and_paren_args_help, whitespace_args)
.parse(arena, state, min_indent)?
} else {
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_tag, state)),
Err((MadeProgress, e)) => return Err((MadeProgress, e)),
}
};
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))
}
}
Ident::OpaqueRef(name) => {
@ -374,24 +408,25 @@ fn loc_ident_pattern_help<'a>(
};
// Make sure `@Foo Bar 1` is parsed as `@Foo (Bar) 1`, and not `@Foo (Bar 1)`
if can_have_arguments {
let (_, loc_args, state) =
loc_tag_pattern_args_help().parse(arena, state, min_indent)?;
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.into_bump_slice());
Ok((MadeProgress, Loc { region, value }, state))
}
let (_, (args, style), 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)?
};
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))
}
}
Ident::Access {
@ -589,3 +624,90 @@ fn record_pattern_field<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, PRecord<'a>>
}
}
}
pub fn pattern_end<'a>() -> impl Parser<'a, (), EPattern<'a>> {
|_arena, state: State<'a>, _min_indent: u32| {
if state.has_reached_end() {
Ok((NoProgress, (), state))
} else {
Err((NoProgress, EPattern::End(state.pos())))
}
}
}
pub fn test_parse_pattern<'a>(
min_indent: u32,
arena: &'a bumpalo::Bump,
state: State<'a>,
) -> Result<Loc<Pattern<'a>>, EPattern<'a>> {
let parser = skip_second(
space0_before_optional_after(
loc_pattern_help(),
EPattern::IndentStart,
EPattern::IndentEnd,
),
pattern_end(),
);
match parser.parse(arena, state, min_indent) {
Ok((_, expression, _)) => Ok(expression),
Err((_, fail)) => Err(fail),
}
}
#[cfg(test)]
mod test_parse_pattern {
use super::*;
use pretty_assertions::assert_eq;
use roc_region::all::Position;
fn new_region(start: u32, end: u32) -> Region {
Region::new(Position::new(start), Position::new(end))
}
#[test]
fn test_parse_ident_tag() {
let arena = Bump::new();
let state = State::new("Ok a".as_ref());
let min_indent = 0;
let (_, res, _) = loc_pattern_help().parse(&arena, state, min_indent).unwrap();
let expected_tag = Loc {
value: Pattern::Tag("Ok"),
region: new_region(0, 2),
};
let expected_args = [Loc {
value: Pattern::Identifier { ident: "a" },
region: new_region(3, 4),
}];
let expected = Loc {
value: Pattern::Apply(&expected_tag, &expected_args, PatternApplyStyle::Whitespace),
region: new_region(0, 4),
};
assert_eq!(format!("{res:#?}"), format!("{expected:#?}"));
}
#[test]
fn test_parse_ident_tag_pnc() {
let arena = Bump::new();
let state = State::new("Ok(a)".as_ref());
let min_indent = 0;
let (_, res, _) = loc_pattern_help().parse(&arena, state, min_indent).unwrap();
let expected_tag = Loc {
value: Pattern::Tag("Ok"),
region: new_region(0, 2),
};
let expected_args = [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),
};
assert_eq!(format!("{res:#?}"), format!("{expected:#?}"));
}
}

View file

@ -1,6 +1,7 @@
use crate::ast;
use crate::ast::Defs;
use crate::ast::Header;
use crate::ast::Pattern;
use crate::ast::SpacesBefore;
use crate::header::parse_module_defs;
use crate::parser::SourceError;
@ -32,6 +33,18 @@ pub fn parse_loc_with<'a>(
}
}
pub fn parse_pattern_with<'a>(
arena: &'a Bump,
input: &'a str,
) -> Result<Loc<Pattern<'a>>, SourceError<'a, SyntaxError<'a>>> {
let state = State::new(input.as_bytes());
match crate::pattern::test_parse_pattern(0, arena, state.clone()) {
Ok(loc_patt) => Ok(loc_patt),
Err(fail) => Err(SyntaxError::Pattern(fail).into_source_error(&state)),
}
}
pub fn parse_defs_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Defs<'a>, SyntaxError<'a>> {
let state = State::new(input.as_bytes());

View file

@ -10,6 +10,8 @@
//!
//! Note that `--release` is important, as this tool is very slow in debug mode.
use std::io::Read;
use test_syntax::{
minimize::{print_minimizations, Options},
test_helpers::InputKind,
@ -18,7 +20,7 @@ use test_syntax::{
fn main() {
let args = std::env::args().collect::<Vec<String>>();
if args.len() < 3 || args.len() > 5 {
eprintln!("Usage: {} [--minimize-full-error] [--minimize-initial-parse-error] [expr|full|moduledefs|header] <input>", args[0]);
eprintln!("Usage: {} [--minimize-full-error] [--minimize-initial-parse-error] [expr|full|moduledefs|header|pattern] <input>", args[0]);
std::process::exit(1);
}
@ -46,13 +48,21 @@ fn main() {
"full" => InputKind::Full,
"moduledefs" => InputKind::ModuleDefs,
"header" => InputKind::Header,
"pattern" => InputKind::Pattern,
_ => {
eprintln!("Invalid input kind: {}", args[index]);
std::process::exit(1);
}
};
let input = &args[index + 1];
let mut buf = String::new();
let text = if input == "-" {
std::io::stdin().read_to_string(&mut buf).unwrap();
buf.to_string()
} else {
std::fs::read_to_string(input).unwrap()
};
let text = std::fs::read_to_string(&args[index + 1]).unwrap();
let found_error = print_minimizations(&text, options);
std::process::exit(if found_error { 0 } else { 1 });
}

View file

@ -101,7 +101,10 @@ fn round_trip_once(input: Input<'_>, options: Options) -> Option<String> {
let arena = Bump::new();
let actual = match input.parse_in(&arena) {
Ok(a) => a,
Ok(a) => {
println!("actual {a:#?}");
a
}
Err(e) => {
if options.minimize_initial_parse_error {
return Some(format!("Initial parse failed: {:?}", e.normalize(&arena)));

View file

@ -9,13 +9,13 @@ use roc_error_macros::set_panic_not_exit;
use roc_fmt::{annotation::Formattable, header::fmt_header, MigrationFlags};
use roc_module::ident::QualifiedModuleName;
use roc_module::symbol::{IdentIds, Interns, ModuleIds, PackageModuleIds, Symbol};
use roc_parse::ast::RecursiveValueDefIter;
use roc_parse::ast::ValueDef;
use roc_parse::ast::{Pattern, RecursiveValueDefIter};
use roc_parse::header::parse_module_defs;
use roc_parse::parser::Parser;
use roc_parse::parser::SyntaxError;
use roc_parse::state::State;
use roc_parse::test_helpers::parse_loc_with;
use roc_parse::test_helpers::{parse_loc_with, parse_pattern_with};
use roc_parse::{ast::Malformed, normalize::Normalize};
use roc_parse::{
ast::{Defs, Expr, FullAst, Header, SpacesBefore},
@ -45,6 +45,9 @@ pub enum Input<'a> {
/// Both the header and the module defs
Full(&'a str),
/// A single pattern
Pattern(&'a str),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -53,6 +56,7 @@ pub enum InputKind {
ModuleDefs,
Expr,
Full,
Pattern,
}
impl InputKind {
@ -62,6 +66,7 @@ impl InputKind {
InputKind::ModuleDefs => Input::ModuleDefs(text),
InputKind::Expr => Input::Expr(text),
InputKind::Full => Input::Full(text),
InputKind::Pattern => Input::Pattern(text),
}
}
}
@ -73,6 +78,7 @@ pub enum InputOwned {
ModuleDefs(String),
Expr(String),
Full(String),
Pattern(String),
}
impl InputOwned {
@ -82,6 +88,7 @@ impl InputOwned {
InputOwned::ModuleDefs(s) => Input::ModuleDefs(s),
InputOwned::Expr(s) => Input::Expr(s),
InputOwned::Full(s) => Input::Full(s),
InputOwned::Pattern(s) => Input::Pattern(s),
}
}
}
@ -96,12 +103,17 @@ pub enum Output<'a> {
Expr(Loc<Expr<'a>>),
Full(FullAst<'a>),
Pattern(Loc<Pattern<'a>>),
}
impl<'a> Output<'a> {
pub fn format(&self) -> InputOwned {
let arena = Bump::new();
let flags = MigrationFlags::new(false);
let flags = MigrationFlags {
snakify: false,
parens_and_commas: false,
};
let mut buf = Buf::new_in(&arena, flags);
match self {
Output::Header(header) => {
@ -124,6 +136,10 @@ impl<'a> Output<'a> {
buf.fmt_end_of_file();
InputOwned::Full(buf.as_str().to_string())
}
Output::Pattern(patt) => {
patt.format(&mut buf, 0);
InputOwned::Pattern(buf.as_str().to_string())
}
}
}
@ -133,6 +149,7 @@ impl<'a> Output<'a> {
Output::ModuleDefs(defs) => format!("{defs:#?}\n"),
Output::Expr(expr) => format!("{expr:#?}\n"),
Output::Full { .. } => format!("{self:#?}\n"),
Output::Pattern(patt) => format!("{patt:#?}\n"),
}
}
@ -147,6 +164,7 @@ impl<'a> Output<'a> {
Output::Full(_) => {
// TODO: canonicalize full ast
}
Output::Pattern(_) => {}
Output::Expr(loc_expr) => {
let mut var_store = VarStore::default();
let mut imported: Vec<(QualifiedModuleName, Region)> = vec![];
@ -245,6 +263,7 @@ impl<'a> Malformed for Output<'a> {
Output::ModuleDefs(defs) => defs.is_malformed(),
Output::Expr(expr) => expr.is_malformed(),
Output::Full(full) => full.is_malformed(),
Output::Pattern(patt) => patt.is_malformed(),
}
}
}
@ -256,6 +275,7 @@ impl<'a> Normalize<'a> for Output<'a> {
Output::ModuleDefs(defs) => Output::ModuleDefs(defs.normalize(arena)),
Output::Expr(expr) => Output::Expr(expr.normalize(arena)),
Output::Full(full) => Output::Full(full.normalize(arena)),
Output::Pattern(patt) => Output::Pattern(patt.normalize(arena)),
}
}
}
@ -267,6 +287,7 @@ impl<'a> Input<'a> {
Input::ModuleDefs(s) => s,
Input::Expr(s) => s,
Input::Full(s) => s,
Input::Pattern(s) => s,
}
}
@ -305,6 +326,11 @@ impl<'a> Input<'a> {
Ok(Output::Full(FullAst { header, defs }))
}
Input::Pattern(input) => {
let patt = parse_pattern_with(arena, input).map_err(|e| e.problem)?;
Ok(Output::Pattern(patt))
}
}
}
@ -322,7 +348,7 @@ impl<'a> Input<'a> {
let arena = Bump::new();
let actual = self.parse_in(&arena).unwrap_or_else(|err| {
panic!("Unexpected parse failure when parsing this for formatting:\n\n{}\n\nParse error was:\n\n{:?}\n\n", self.as_str(), err);
panic!("Unexpected parse failure when parsing this for formatting:\n\n{}\n\nParse error was:\n\n{:#?}\n\n", self.as_str(), err);
});
let output = actual.format();

View file

@ -21,6 +21,7 @@
"E",
),
[],
Whitespace,
),
ann_type: @2-3 Apply(
"",

View file

@ -26,6 +26,7 @@
ident: "x",
},
],
Whitespace,
),
ann_type: @11-25 TagUnion {
ext: None,
@ -54,6 +55,7 @@
ident: "x",
},
],
Whitespace,
),
body_expr: @37-46 Apply(
@37-43 Tag(

View file

@ -0,0 +1,19 @@
@0-12 SpaceAfter(
Apply(
@0-4 Tag(
"Whee",
),
[
@5-7 Num(
"12",
),
@9-11 Num(
"34",
),
],
ParensAndCommas,
),
[
Newline,
],
)

View file

@ -0,0 +1 @@
Whee(12, 34)

View file

@ -0,0 +1,16 @@
@0-4 SpaceAfter(
Apply(
@0-2 Tag(
"Ok",
),
[
@3-4 Identifier {
ident: "a",
},
],
ParensAndCommas,
),
[
Newline,
],
)

View file

@ -0,0 +1,16 @@
@0-4 SpaceAfter(
Apply(
@0-2 Tag(
"Ok",
),
[
@3-4 Identifier {
ident: "a",
},
],
Whitespace,
),
[
Newline,
],
)

View file

@ -0,0 +1,20 @@
@0-13 SpaceAfter(
Apply(
@0-4 Var {
module_name: "",
ident: "whee",
},
[
@5-7 Num(
"12",
),
@10-12 Num(
"34",
),
],
ParensAndCommas,
),
[
Newline,
],
)

View file

@ -0,0 +1 @@
whee(12, 34)

View file

@ -27,6 +27,7 @@
ident: "inner",
},
],
Whitespace,
),
PatternAs {
spaces_before: [],

View file

@ -1,4 +1,4 @@
@0-8 SpaceAfter(
@0-9 SpaceAfter(
BinOps(
[
(
@ -8,24 +8,24 @@
@1-2 LessThan,
),
],
@2-7 Apply(
@2-8 Apply(
@2-3 Var {
module_name: "",
ident: "l",
},
[
@4-7 ParensAround(
@5-8 ParensAround(
BinOps(
[
(
@4-5 Var {
@5-6 Var {
module_name: "",
ident: "r",
},
@5-6 Star,
@6-7 Star,
),
],
@6-7 Tag(
@7-8 Tag(
"N",
),
),

View file

@ -38,6 +38,7 @@
},
),
],
Whitespace,
),
],
@17-18 SpaceBefore(

View file

@ -20,6 +20,7 @@
],
),
],
ParensAndCommas,
),
],
@11-13 Num(

View file

@ -0,0 +1,15 @@
PP(
P
@P(
P
P(
PPP(
P
PPP,
),
)
PP(
mport, # <|"P
),
),
)

View file

@ -0,0 +1,118 @@
@0-44 SpaceAfter(
Apply(
@0-2 Tag(
"PP",
),
[
@3-42 SpaceAfter(
Apply(
@3-4 Tag(
"P",
),
[
@4-42 Apply(
@4-6 OpaqueRef(
"@P",
),
[
@7-40 SpaceAfter(
Apply(
@7-8 Tag(
"P",
),
[
@9-24 SpaceBefore(
Apply(
@9-10 Tag(
"P",
),
[
@11-22 SpaceAfter(
Apply(
@11-14 Tag(
"PPP",
),
[
@15-20 SpaceAfter(
Apply(
@15-16 Tag(
"P",
),
[
@17-20 SpaceBefore(
Tag(
"PPP",
),
[
Newline,
],
),
],
Space,
),
[
Newline,
],
),
],
ParensAndCommas,
),
[
Newline,
],
),
],
ParensAndCommas,
),
[
Newline,
],
),
@25-40 SpaceBefore(
Apply(
@25-27 Tag(
"PP",
),
[
@28-33 SpaceAfter(
Var {
module_name: "",
ident: "mport",
},
[
LineComment(
"<|\"P",
),
],
),
],
ParensAndCommas,
),
[
Newline,
],
),
],
Space,
),
[
Newline,
],
),
],
ParensAndCommas,
),
],
Space,
),
[
Newline,
],
),
],
ParensAndCommas,
),
[
Newline,
],
)

View file

@ -0,0 +1,9 @@
PP(P@P(P
P(PPP(P
PPP
)
)
PP(mport#<|"P
)
)
)

View file

@ -16,6 +16,7 @@
],
),
],
Whitespace,
),
],
@8-10 UnaryOp(

View file

@ -19,6 +19,7 @@
],
),
],
Whitespace,
),
],
@10-12 Var {

View file

@ -16,7 +16,7 @@
type_defs: [],
value_defs: [
Annotation(
@0-1 Apply(
@0-10 Apply(
@0-1 NumLiteral(
"1",
),
@ -35,6 +35,7 @@
],
),
],
ParensAndCommas,
),
@11-13 BoundVariable(
"gi",

View file

@ -1,5 +1,5 @@
1
(0 #
0)
1(
0( #
0,),)
f : f
t

View file

@ -17,37 +17,44 @@
type_defs: [],
value_defs: [
Annotation(
@0-1 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-11 SpaceAfter(
Apply(
@3-4 NumLiteral(
"0",
@0-12 Apply(
@0-12 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-11 SpaceAfter(
Apply(
@3-4 NumLiteral(
"0",
),
[
@7-8 SpaceBefore(
NumLiteral(
"0",
),
[
LineComment(
"",
),
],
),
],
ParensAndCommas,
),
[
@7-8 SpaceBefore(
NumLiteral(
"0",
),
[
LineComment(
"",
),
],
),
Newline,
],
),
[
Newline,
],
),
],
ParensAndCommas,
),
[
@12-13 Identifier {
ident: "f",
},
],
Whitespace,
),
@14-15 BoundVariable(
"f",

View file

@ -16,39 +16,46 @@
type_defs: [],
value_defs: [
Annotation(
@0-1 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-13 SpaceAfter(
Apply(
@2-4 Identifier {
ident: "ts",
},
[
@5-9 SpaceAfter(
NumLiteral(
"0",
),
[
Newline,
Newline,
LineComment(
"",
@0-15 Apply(
@0-15 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-13 SpaceAfter(
Apply(
@2-4 Identifier {
ident: "ts",
},
[
@5-9 SpaceAfter(
NumLiteral(
"0",
),
],
),
[
Newline,
Newline,
LineComment(
"",
),
],
),
],
ParensAndCommas,
),
[
Newline,
],
),
[
Newline,
],
),
],
ParensAndCommas,
),
[
@15-16 Identifier {
ident: "f",
},
],
Whitespace,
),
@17-20 BoundVariable(
"i7f",

View file

@ -34,6 +34,7 @@
ident: "f",
},
],
Whitespace,
),
@14-15 BoundVariable(
"f",

View file

@ -26,6 +26,7 @@
ident: "str",
},
],
Whitespace,
),
@12-36 Apply(
@12-17 Tag(

View file

@ -35,6 +35,7 @@
ident: "e",
},
],
Whitespace,
),
@8-14 Apply(
@9-10 SpaceAfter(
@ -52,6 +53,7 @@
ident: "p",
},
],
Whitespace,
),
],
),

View file

@ -1,11 +1,11 @@
@0-22 SpaceAfter(
@0-23 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-20,
@0-21,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
@ -19,23 +19,23 @@
header: TypeHeader {
name: @0-1 "C",
vars: [
@2-3 SpaceAfter(
NumLiteral(
"4",
),
[
LineComment(
"",
),
],
@2-3 NumLiteral(
"4",
),
],
},
loc_implements: @6-16 Implements,
loc_implements: @7-17 SpaceBefore(
Implements,
[
LineComment(
"",
),
],
),
members: [
AbilityMember {
name: @17-18 "e",
typ: @19-20 BoundVariable(
name: @18-19 "e",
typ: @20-21 BoundVariable(
"m",
),
},
@ -44,7 +44,7 @@
],
value_defs: [],
},
@21-22 SpaceBefore(
@22-23 SpaceBefore(
Tag(
"C",
),

View file

@ -0,0 +1,3 @@
C 4 #
implements e:m
C

View file

@ -33,6 +33,7 @@
],
),
],
Whitespace,
),
@15-16 BoundVariable(
"s",

View file

@ -0,0 +1,8 @@
combine(
mix(vodka, gin),
Juices({
color: Colors.orange,
flavor: Flavors.orange,
amount: 1 + 2,
}),
)

View file

@ -0,0 +1,96 @@
@0-109 SpaceAfter(
Apply(
@0-7 Var {
module_name: "",
ident: "combine",
},
[
@8-23 Apply(
@8-11 Var {
module_name: "",
ident: "mix",
},
[
@12-17 Var {
module_name: "",
ident: "vodka",
},
@19-22 Var {
module_name: "",
ident: "gin",
},
],
ParensAndCommas,
),
@25-108 Apply(
@25-31 Tag(
"Juices",
),
[
@32-107 Record(
[
@38-58 SpaceBefore(
RequiredValue(
@38-43 "color",
[],
@45-58 Var {
module_name: "Colors",
ident: "orange",
},
),
[
Newline,
],
),
@64-86 SpaceBefore(
RequiredValue(
@64-70 "flavor",
[],
@72-86 Var {
module_name: "Flavors",
ident: "orange",
},
),
[
Newline,
],
),
@92-105 SpaceBefore(
SpaceAfter(
RequiredValue(
@92-98 "amount",
[],
@100-105 BinOps(
[
(
@100-101 Num(
"1",
),
@102-103 Plus,
),
],
@104-105 Num(
"2",
),
),
),
[
Newline,
],
),
[
Newline,
],
),
],
),
],
ParensAndCommas,
),
],
ParensAndCommas,
),
[
Newline,
],
)

View file

@ -0,0 +1,5 @@
combine(mix(vodka, gin), Juices({
color: Colors.orange,
flavor: Flavors.orange,
amount: 1 + 2
}))

View file

@ -1,11 +1,11 @@
@0-21 SpaceAfter(
@0-24 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-19,
@0-22,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
@ -19,18 +19,18 @@
header: TypeHeader {
name: @0-1 "N",
vars: [
@2-12 Identifier {
@3-13 Identifier {
ident: "implements",
},
@13-14 Identifier {
@15-16 Identifier {
ident: "h",
},
@15-16 NumLiteral(
@18-19 NumLiteral(
"0",
),
],
},
ann: @18-19 Apply(
ann: @21-22 Apply(
"",
"B",
[],
@ -39,7 +39,7 @@
],
value_defs: [],
},
@20-21 SpaceBefore(
@23-24 SpaceBefore(
Tag(
"T",
),

View file

@ -1,2 +1,2 @@
N(implements)h(0):B
N (implements) h (0):B
T

View file

@ -1,6 +1,6 @@
1
(0 #
f)
(0 #
f) : f
1(
0 #
f,)(
0 #
f,) : f
e

View file

@ -17,28 +17,34 @@
type_defs: [],
value_defs: [
Annotation(
@0-1 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-8 Apply(
@3-4 SpaceAfter(
NumLiteral(
"0",
@0-17 Apply(
@0-9 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-8 Apply(
@3-4 SpaceAfter(
NumLiteral(
"0",
),
[
LineComment(
"",
),
],
),
[
LineComment(
"",
),
@7-8 Identifier {
ident: "f",
},
],
Whitespace,
),
[
@7-8 Identifier {
ident: "f",
},
],
),
],
ParensAndCommas,
),
[
@10-16 Apply(
@11-12 SpaceAfter(
NumLiteral(
@ -55,8 +61,10 @@
ident: "f",
},
],
Whitespace,
),
],
ParensAndCommas,
),
@18-19 BoundVariable(
"f",

View file

@ -34,6 +34,7 @@
),
),
],
Whitespace,
),
@12-13 Apply(
"",

View file

@ -42,12 +42,14 @@
),
),
],
Whitespace,
),
[
@12-13 Identifier {
ident: "f",
},
],
Whitespace,
),
@14-15 Apply(
"",

View file

@ -1,11 +1,11 @@
@0-16 SpaceAfter(
@0-18 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(2147483648),
],
regions: [
@0-14,
@0-16,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
@ -22,27 +22,29 @@
ident: "u",
},
[
@2-11 Apply(
@2-8 StrLiteral(
@3-13 Apply(
@3-9 StrLiteral(
Block(
[],
),
),
[
@9-10 NumLiteral(
@11-12 NumLiteral(
"0",
),
],
Whitespace,
),
],
Whitespace,
),
@13-14 BoundVariable(
@15-16 BoundVariable(
"f",
),
),
],
},
@15-16 SpaceBefore(
@17-18 SpaceBefore(
Var {
module_name: "",
ident: "s",

View file

@ -1,2 +1,2 @@
u(""""""(0)):f
u ("""""" (0)):f
s

View file

@ -36,6 +36,7 @@
"2",
),
],
Whitespace,
),
@12-13 Apply(
"",

View file

@ -5,31 +5,11 @@
"0",
),
[
@4-7 ParensAround(
Defs(
Defs {
tags: [
EitherIndex(2147483648),
],
regions: [
@4-5,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [],
value_defs: [
Stmt(
@4-5 Num(
"1",
),
),
],
},
@4-7 Apply(
@4-5 Num(
"1",
),
[
@6-7 SpaceBefore(
Var {
module_name: "",
@ -39,10 +19,11 @@
Newline,
],
),
),
],
Space,
),
],
Space,
ParensAndCommas,
),
),
@0-1 Negate,

View file

@ -32,6 +32,7 @@
],
),
],
Whitespace,
),
],
@14-15 Var {

View file

@ -25,6 +25,7 @@
ident: "x",
},
],
Whitespace,
),
@7-8 BoundVariable(
"i",

View file

@ -23,6 +23,7 @@
],
),
],
Whitespace,
),
[
Newline,

View file

@ -26,6 +26,7 @@
ident: "it",
},
],
Whitespace,
),
@12-22 Apply(
@12-14 Var {

View file

@ -20,6 +20,7 @@
ident: "m",
},
],
Whitespace,
),
[
Newline,

View file

@ -1,52 +1,57 @@
@0-12 Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-10,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [
Alias {
header: TypeHeader {
name: @0-2 "Zx",
vars: [
@3-4 SpaceAfter(
Identifier {
ident: "e",
@0-13 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-11,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [
Alias {
header: TypeHeader {
name: @0-2 "Zx",
vars: [
@4-5 SpaceAfter(
Identifier {
ident: "e",
},
[
LineComment(
"",
),
],
),
@8-9 Identifier {
ident: "f",
},
[
LineComment(
"",
),
],
),
@7-8 Identifier {
ident: "f",
},
],
],
},
ann: @10-11 BoundVariable(
"i",
),
},
ann: @9-10 BoundVariable(
"i",
),
},
],
value_defs: [],
},
@11-12 SpaceBefore(
Var {
module_name: "",
ident: "s",
],
value_defs: [],
},
[
Newline,
],
@12-13 SpaceBefore(
Var {
module_name: "",
ident: "s",
},
[
Newline,
],
),
),
[
Newline,
],
)

View file

@ -1,49 +1,55 @@
@0-10 Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-8,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [
Alias {
header: TypeHeader {
name: @0-1 "U",
vars: [
@2-5 Apply(
@2-3 Identifier {
ident: "b",
},
[
@4-5 Identifier {
ident: "a",
@0-11 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-9,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [
Alias {
header: TypeHeader {
name: @0-1 "U",
vars: [
@3-6 Apply(
@3-4 Identifier {
ident: "b",
},
],
),
],
[
@5-6 Identifier {
ident: "a",
},
],
Whitespace,
),
],
},
ann: @8-9 BoundVariable(
"b",
),
},
ann: @7-8 BoundVariable(
"b",
),
},
],
value_defs: [],
},
@9-10 SpaceBefore(
Var {
module_name: "",
ident: "a",
],
value_defs: [],
},
[
Newline,
],
@10-11 SpaceBefore(
Var {
module_name: "",
ident: "a",
},
[
Newline,
],
),
),
[
Newline,
],
)

View file

@ -1,4 +1,3 @@
1
(i, p #
) : f
1(i, p) #
: f
n

View file

@ -16,29 +16,26 @@
type_defs: [],
value_defs: [
Annotation(
@0-1 Apply(
@0-8 Apply(
@0-1 NumLiteral(
"1",
),
[
@1-8 Tuple(
@2-3 Identifier {
ident: "i",
},
@4-5 SpaceAfter(
Identifier {
ident: "p",
},
[
@2-3 Identifier {
ident: "i",
},
@4-5 SpaceAfter(
Identifier {
ident: "p",
},
[
LineComment(
"",
),
],
LineComment(
"",
),
],
),
],
ParensAndCommas,
),
@9-10 BoundVariable(
"f",

View file

@ -37,6 +37,7 @@
],
),
],
Whitespace,
),
@7-8 BoundVariable(
"s",

View file

@ -23,6 +23,7 @@
},
),
],
Whitespace,
),
[
Newline,

View file

@ -43,11 +43,13 @@
ident: "ry",
},
],
Whitespace,
),
@47-48 Underscore(
"",
),
],
Whitespace,
),
[
Newline,

View file

@ -1,11 +1,11 @@
@0-15 SpaceAfter(
@0-16 SpaceAfter(
Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@0-13,
@0-14,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
@ -19,30 +19,31 @@
header: TypeHeader {
name: @0-1 "Q",
vars: [
@2-10 Apply(
@2-8 StrLiteral(
@3-11 Apply(
@3-9 StrLiteral(
Block(
[],
),
),
[
@8-10 StrLiteral(
@9-11 StrLiteral(
PlainLine(
"",
),
),
],
Whitespace,
),
],
},
ann: @12-13 BoundVariable(
ann: @13-14 BoundVariable(
"a",
),
},
],
value_defs: [],
},
@14-15 SpaceBefore(
@15-16 SpaceBefore(
Var {
module_name: "",
ident: "q",

View file

@ -1,2 +1,2 @@
Q(""""""""):a
Q (""""""""):a
q

View file

@ -37,6 +37,7 @@
ident: "a",
},
],
Whitespace,
),
@10-11 BoundVariable(
"t",

View file

@ -1,24 +1,24 @@
@0-31 SpaceAfter(
@0-32 SpaceAfter(
Apply(
@0-3 Var {
module_name: "",
ident: "il3",
},
[
@3-31 Closure(
@3-32 Closure(
[
@4-5 Identifier {
ident: "k",
},
],
@13-31 SpaceBefore(
@13-32 SpaceBefore(
Defs(
Defs {
tags: [
EitherIndex(0),
],
regions: [
@13-28,
@13-29,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
@ -35,16 +35,17 @@
@16-18 OpaqueRef(
"@C",
),
@22-25 SpaceBefore(
@23-26 SpaceBefore(
Apply(
@22-24 Identifier {
@23-25 Identifier {
ident: "t!",
},
[
@24-25 Tag(
@25-26 Tag(
"K",
),
],
Whitespace,
),
[
LineComment(
@ -54,14 +55,14 @@
),
],
},
ann: @27-28 BoundVariable(
ann: @28-29 BoundVariable(
"i",
),
},
],
value_defs: [],
},
@30-31 SpaceBefore(
@31-32 SpaceBefore(
Tag(
"C",
),

View file

@ -1,4 +1,4 @@
il3\k->#w#z
CCC@C(#i
CCC@C (#i
t!K):i
C

View file

@ -29,6 +29,7 @@
ident: "code",
},
],
Whitespace,
),
@30-33 Var {
module_name: "",

View file

@ -29,6 +29,7 @@
ident: "code",
},
],
Whitespace,
),
@29-32 Var {
module_name: "",

View file

@ -1,2 +1,2 @@
1 (0 0) f : f
1(0(0)) f : f
i

View file

@ -17,30 +17,37 @@
type_defs: [],
value_defs: [
Annotation(
@0-1 Apply(
@0-1 NumLiteral(
"1",
@0-10 Apply(
@0-10 Apply(
@0-1 NumLiteral(
"1",
),
[
@2-9 Apply(
@3-4 NumLiteral(
"0",
),
[
@5-6 SpaceAfter(
NumLiteral(
"0",
),
[
Newline,
],
),
],
ParensAndCommas,
),
],
ParensAndCommas,
),
[
@2-9 Apply(
@3-4 NumLiteral(
"0",
),
[
@5-6 SpaceAfter(
NumLiteral(
"0",
),
[
Newline,
],
),
],
),
@10-11 Identifier {
ident: "f",
},
],
Whitespace,
),
@12-13 BoundVariable(
"f",

View file

@ -28,6 +28,7 @@
),
),
],
Whitespace,
),
@8-15 Apply(
@8-9 Var {

View file

@ -50,6 +50,7 @@
"",
),
],
Whitespace,
),
@11-19 Apply(
@11-15 Tag(
@ -79,6 +80,7 @@
ident: "y",
},
],
Whitespace,
),
@31-39 Apply(
@31-35 Tag(
@ -108,6 +110,7 @@
"",
),
],
Whitespace,
),
@51-59 Apply(
@51-55 Tag(
@ -161,6 +164,7 @@
"",
),
],
Whitespace,
),
@90-98 Apply(
@90-94 Tag(
@ -174,8 +178,10 @@
ident: "y",
},
],
Whitespace,
),
],
Whitespace,
),
@102-128 Apply(
@102-106 Tag(

View file

@ -23,6 +23,7 @@
[],
),
],
Whitespace,
),
[
Newline,

Some files were not shown because too many files have changed in this diff Show more