mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Several fixes found in fuzzing
This commit is contained in:
parent
e9caada3f1
commit
b9862b47dc
49 changed files with 1060 additions and 523 deletions
|
@ -43,6 +43,7 @@ pub enum Parens {
|
||||||
InApply,
|
InApply,
|
||||||
InOperator,
|
InOperator,
|
||||||
InAsPattern,
|
InAsPattern,
|
||||||
|
InApplyLastArg,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In an AST node, do we show newlines around it
|
/// In an AST node, do we show newlines around it
|
||||||
|
@ -238,6 +239,7 @@ fn fmt_ty_ann(
|
||||||
let is_first = index == 0;
|
let is_first = index == 0;
|
||||||
|
|
||||||
if !is_first {
|
if !is_first {
|
||||||
|
buf.indent(indent);
|
||||||
buf.push_str(",");
|
buf.push_str(",");
|
||||||
if !self_is_multiline {
|
if !self_is_multiline {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
|
|
|
@ -1009,7 +1009,7 @@ pub fn fmt_body<'a>(
|
||||||
return body.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
|
return body.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
|
pattern.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(" =");
|
buf.push_str(" =");
|
||||||
|
|
||||||
|
|
|
@ -29,27 +29,42 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
|
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
|
||||||
use self::Expr::*;
|
|
||||||
|
|
||||||
let me = expr_lift_spaces(parens, buf.text.bump(), self);
|
let me = expr_lift_spaces(parens, buf.text.bump(), self);
|
||||||
|
|
||||||
if !me.before.is_empty() {
|
if !me.before.is_empty() {
|
||||||
format_spaces(buf, me.before, newlines, indent);
|
format_spaces(buf, me.before, newlines, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
match &me.item {
|
format_expr_only(&me.item, buf, parens, newlines, indent);
|
||||||
SpaceBefore(_sub_expr, _spaces) | SpaceAfter(_sub_expr, _spaces) => unreachable!(),
|
|
||||||
ParensAround(sub_expr) => {
|
if !me.after.is_empty() {
|
||||||
|
format_spaces(buf, me.after, newlines, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_expr_only(
|
||||||
|
item: &Expr<'_>,
|
||||||
|
buf: &mut Buf,
|
||||||
|
parens: Parens,
|
||||||
|
newlines: Newlines,
|
||||||
|
indent: u16,
|
||||||
|
) {
|
||||||
|
match &item {
|
||||||
|
Expr::SpaceBefore(_sub_expr, _spaces) | Expr::SpaceAfter(_sub_expr, _spaces) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
Expr::ParensAround(sub_expr) => {
|
||||||
if parens == Parens::NotNeeded && !sub_expr_requests_parens(sub_expr) {
|
if parens == Parens::NotNeeded && !sub_expr_requests_parens(sub_expr) {
|
||||||
sub_expr.format_with_options(buf, Parens::NotNeeded, newlines, indent);
|
sub_expr.format_with_options(buf, Parens::NotNeeded, newlines, indent);
|
||||||
} else {
|
} else {
|
||||||
fmt_parens(sub_expr, buf, indent);
|
fmt_parens(sub_expr, buf, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Str(literal) => {
|
Expr::Str(literal) => {
|
||||||
fmt_str_literal(buf, *literal, indent);
|
fmt_str_literal(buf, *literal, indent);
|
||||||
}
|
}
|
||||||
Var { module_name, ident } => {
|
Expr::Var { module_name, ident } => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
if !module_name.is_empty() {
|
if !module_name.is_empty() {
|
||||||
buf.push_str(module_name);
|
buf.push_str(module_name);
|
||||||
|
@ -58,47 +73,52 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
|
|
||||||
buf.push_str(ident);
|
buf.push_str(ident);
|
||||||
}
|
}
|
||||||
Underscore(name) => {
|
Expr::Underscore(name) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push('_');
|
buf.push('_');
|
||||||
buf.push_str(name);
|
buf.push_str(name);
|
||||||
}
|
}
|
||||||
Crash => {
|
Expr::Crash => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str("crash");
|
buf.push_str("crash");
|
||||||
}
|
}
|
||||||
Apply(loc_expr, loc_args, _) => {
|
Expr::Try => {
|
||||||
let apply_needs_parens = parens == Parens::InApply;
|
buf.indent(indent);
|
||||||
|
buf.push_str("try");
|
||||||
|
}
|
||||||
|
Expr::Apply(loc_expr, loc_args, _) => {
|
||||||
|
let apply_needs_parens = parens == Parens::InApply || parens == Parens::InApplyLastArg;
|
||||||
|
// || (parens == Parens::InOperator && apply_has_closure(self));
|
||||||
|
|
||||||
if apply_needs_parens && !loc_args.is_empty() {
|
if apply_needs_parens && !loc_args.is_empty() {
|
||||||
fmt_parens(self, buf, indent);
|
fmt_parens(item, buf, indent);
|
||||||
} else {
|
} else {
|
||||||
fmt_apply(loc_expr, loc_args, indent, buf);
|
fmt_apply(loc_expr, loc_args, indent, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Num(string) => {
|
&Expr::Num(string) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(string);
|
buf.push_str(string);
|
||||||
}
|
}
|
||||||
&Float(string) => {
|
&Expr::Float(string) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(string);
|
buf.push_str(string);
|
||||||
}
|
}
|
||||||
Tag(string) | OpaqueRef(string) => {
|
Expr::Tag(string) | Expr::OpaqueRef(string) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(string)
|
buf.push_str(string)
|
||||||
}
|
}
|
||||||
SingleQuote(string) => {
|
Expr::SingleQuote(string) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
format_sq_literal(buf, string);
|
format_sq_literal(buf, string);
|
||||||
}
|
}
|
||||||
&NonBase10Int {
|
Expr::NonBase10Int {
|
||||||
base,
|
base,
|
||||||
string,
|
string,
|
||||||
is_negative,
|
is_negative,
|
||||||
} => {
|
} => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
if is_negative {
|
if *is_negative {
|
||||||
buf.push('-');
|
buf.push('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,47 +131,47 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
|
|
||||||
buf.push_str(string);
|
buf.push_str(string);
|
||||||
}
|
}
|
||||||
Record(fields) => {
|
Expr::Record(fields) => {
|
||||||
fmt_record_like(
|
fmt_record_like(
|
||||||
buf,
|
buf,
|
||||||
None,
|
None,
|
||||||
*fields,
|
*fields,
|
||||||
indent,
|
indent,
|
||||||
format_assigned_field_multiline,
|
format_assigned_field_multiline,
|
||||||
assigned_field_to_space_before,
|
assigned_field_to_spaces,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
RecordUpdate { update, fields } => {
|
Expr::RecordUpdate { update, fields } => {
|
||||||
fmt_record_like(
|
fmt_record_like(
|
||||||
buf,
|
buf,
|
||||||
Some(RecordPrefix::Update(update)),
|
Some(RecordPrefix::Update(update)),
|
||||||
*fields,
|
*fields,
|
||||||
indent,
|
indent,
|
||||||
format_assigned_field_multiline,
|
format_assigned_field_multiline,
|
||||||
assigned_field_to_space_before,
|
assigned_field_to_spaces,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
RecordBuilder { mapper, fields } => {
|
Expr::RecordBuilder { mapper, fields } => {
|
||||||
fmt_record_like(
|
fmt_record_like(
|
||||||
buf,
|
buf,
|
||||||
Some(RecordPrefix::Mapper(mapper)),
|
Some(RecordPrefix::Mapper(mapper)),
|
||||||
*fields,
|
*fields,
|
||||||
indent,
|
indent,
|
||||||
format_assigned_field_multiline,
|
format_assigned_field_multiline,
|
||||||
assigned_field_to_space_before,
|
assigned_field_to_spaces,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Closure(loc_patterns, loc_ret) => {
|
Expr::Closure(loc_patterns, loc_ret) => {
|
||||||
fmt_closure(buf, loc_patterns, loc_ret, indent);
|
fmt_closure(buf, loc_patterns, loc_ret, indent);
|
||||||
}
|
}
|
||||||
Backpassing(loc_patterns, loc_body, loc_ret) => {
|
Expr::Backpassing(loc_patterns, loc_body, loc_ret) => {
|
||||||
fmt_backpassing(buf, loc_patterns, loc_body, loc_ret, indent);
|
fmt_backpassing(buf, loc_patterns, loc_body, loc_ret, indent);
|
||||||
}
|
}
|
||||||
Defs(defs, ret) => {
|
Expr::Defs(defs, ret) => {
|
||||||
let defs_needs_parens = parens == Parens::InOperator || parens == Parens::InApply;
|
let defs_needs_parens = parens == Parens::InOperator || parens == Parens::InApply;
|
||||||
|
|
||||||
if defs_needs_parens {
|
if defs_needs_parens {
|
||||||
fmt_parens(self, buf, indent)
|
fmt_parens(item, buf, indent)
|
||||||
} else {
|
} else {
|
||||||
// It should theoretically be impossible to *parse* an empty defs list.
|
// It should theoretically be impossible to *parse* an empty defs list.
|
||||||
// (Canonicalization can remove defs later, but that hasn't happened yet!)
|
// (Canonicalization can remove defs later, but that hasn't happened yet!)
|
||||||
|
@ -160,18 +180,13 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
fmt_defs(buf, defs, indent);
|
fmt_defs(buf, defs, indent);
|
||||||
|
|
||||||
match &ret.value {
|
match &ret.value {
|
||||||
SpaceBefore(sub_expr, spaces) => {
|
Expr::SpaceBefore(sub_expr, spaces) => {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
fmt_spaces(buf, spaces.iter(), indent);
|
fmt_spaces(buf, spaces.iter(), indent);
|
||||||
|
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
|
|
||||||
sub_expr.format_with_options(
|
sub_expr.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
|
||||||
buf,
|
|
||||||
Parens::NotNeeded,
|
|
||||||
Newlines::Yes,
|
|
||||||
indent,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
buf.ensure_ends_with_newline();
|
buf.ensure_ends_with_newline();
|
||||||
|
@ -183,31 +198,27 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dbg => {
|
Expr::Dbg => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str("dbg");
|
buf.push_str("dbg");
|
||||||
}
|
}
|
||||||
DbgStmt {
|
Expr::DbgStmt {
|
||||||
first,
|
first: condition,
|
||||||
extra_args,
|
extra_args,
|
||||||
continuation,
|
continuation,
|
||||||
} => {
|
} => {
|
||||||
fmt_dbg_stmt(buf, first, extra_args, continuation, parens, indent);
|
fmt_dbg_stmt(buf, condition, extra_args, continuation, parens, indent);
|
||||||
}
|
}
|
||||||
LowLevelDbg(_, _, _) => unreachable!(
|
Expr::LowLevelDbg(_, _, _) => {
|
||||||
"LowLevelDbg should only exist after desugaring, not during formatting"
|
unreachable!("LowLevelDbg should only exist after desugaring, not during formatting")
|
||||||
),
|
|
||||||
Try => {
|
|
||||||
buf.indent(indent);
|
|
||||||
buf.push_str("try");
|
|
||||||
}
|
}
|
||||||
LowLevelTry(_, _) => unreachable!(
|
Expr::LowLevelTry(..) => {
|
||||||
"LowLevelTry should only exist after desugaring, not during formatting"
|
unreachable!("LowLevelTry should only exist after desugaring, not during formatting")
|
||||||
),
|
}
|
||||||
Return(return_value, after_return) => {
|
Expr::Return(return_value, after_return) => {
|
||||||
fmt_return(buf, return_value, after_return, parens, newlines, indent);
|
fmt_return(buf, return_value, after_return, parens, newlines, indent);
|
||||||
}
|
}
|
||||||
If {
|
Expr::If {
|
||||||
if_thens: branches,
|
if_thens: branches,
|
||||||
final_else,
|
final_else,
|
||||||
indented_else,
|
indented_else,
|
||||||
|
@ -216,16 +227,16 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
buf,
|
buf,
|
||||||
branches,
|
branches,
|
||||||
final_else,
|
final_else,
|
||||||
self.is_multiline(),
|
item.is_multiline(),
|
||||||
*indented_else,
|
*indented_else,
|
||||||
indent,
|
indent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
When(loc_condition, branches) => fmt_when(buf, loc_condition, branches, indent),
|
Expr::When(loc_condition, branches) => fmt_when(buf, loc_condition, branches, indent),
|
||||||
Tuple(items) => fmt_expr_collection(buf, indent, Braces::Round, *items, Newlines::No),
|
Expr::Tuple(items) => fmt_expr_collection(buf, indent, Braces::Round, *items, Newlines::No),
|
||||||
List(items) => fmt_expr_collection(buf, indent, Braces::Square, *items, Newlines::No),
|
Expr::List(items) => fmt_expr_collection(buf, indent, Braces::Square, *items, Newlines::No),
|
||||||
BinOps(lefts, right) => fmt_binops(buf, lefts, right, indent),
|
Expr::BinOps(lefts, right) => fmt_binops(buf, lefts, right, indent),
|
||||||
UnaryOp(sub_expr, unary_op) => {
|
Expr::UnaryOp(sub_expr, unary_op) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
match &unary_op.value {
|
match &unary_op.value {
|
||||||
called_via::UnaryOp::Negate => {
|
called_via::UnaryOp::Negate => {
|
||||||
|
@ -242,7 +253,7 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
|
|
||||||
let needs_newline = !before_all_newlines
|
let needs_newline = !before_all_newlines
|
||||||
|| match &lifted.item {
|
|| match &lifted.item {
|
||||||
Str(text) => is_str_multiline(text),
|
Expr::Str(text) => is_str_multiline(text),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -290,7 +301,7 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
format_spaces(buf, lifted.after, newlines, inner_indent);
|
format_spaces(buf, lifted.after, newlines, inner_indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AccessorFunction(key) => {
|
Expr::AccessorFunction(key) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push('.');
|
buf.push('.');
|
||||||
match key {
|
match key {
|
||||||
|
@ -298,45 +309,40 @@ impl<'a> Formattable for Expr<'a> {
|
||||||
Accessor::TupleIndex(key) => buf.push_str(key),
|
Accessor::TupleIndex(key) => buf.push_str(key),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RecordUpdater(key) => {
|
Expr::RecordUpdater(key) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push('&');
|
buf.push('&');
|
||||||
buf.push_str(key);
|
buf.push_str(key);
|
||||||
}
|
}
|
||||||
RecordAccess(expr, key) => {
|
Expr::RecordAccess(expr, key) => {
|
||||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||||
buf.push('.');
|
buf.push('.');
|
||||||
buf.push_str(key);
|
buf.push_str(key);
|
||||||
}
|
}
|
||||||
TupleAccess(expr, key) => {
|
Expr::TupleAccess(expr, key) => {
|
||||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||||
buf.push('.');
|
buf.push('.');
|
||||||
buf.push_str(key);
|
buf.push_str(key);
|
||||||
}
|
}
|
||||||
TrySuffix { expr, target } => {
|
Expr::TrySuffix { expr, target } => {
|
||||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||||
match target {
|
match target {
|
||||||
TryTarget::Task => buf.push('!'),
|
TryTarget::Task => buf.push('!'),
|
||||||
TryTarget::Result => buf.push('?'),
|
TryTarget::Result => buf.push('?'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MalformedIdent(str, _) => {
|
Expr::MalformedIdent(str, _) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
buf.push_str(str)
|
buf.push_str(str)
|
||||||
}
|
}
|
||||||
MalformedSuffixed(loc_expr) => {
|
Expr::MalformedSuffixed(loc_expr) => {
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
loc_expr.format_with_options(buf, parens, newlines, indent);
|
loc_expr.format_with_options(buf, parens, newlines, indent);
|
||||||
}
|
}
|
||||||
PrecedenceConflict { .. } => {}
|
Expr::PrecedenceConflict { .. } => {}
|
||||||
EmptyRecordBuilder { .. } => {}
|
Expr::EmptyRecordBuilder { .. } => {}
|
||||||
SingleFieldRecordBuilder { .. } => {}
|
Expr::SingleFieldRecordBuilder { .. } => {}
|
||||||
OptionalFieldInRecordBuilder(_, _) => {}
|
Expr::OptionalFieldInRecordBuilder(_, _) => {}
|
||||||
}
|
|
||||||
|
|
||||||
if !me.after.is_empty() {
|
|
||||||
format_spaces(buf, me.after, newlines, indent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,8 +398,15 @@ pub fn expr_is_multiline(me: &Expr<'_>, comments_only: bool) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::DbgStmt {
|
Expr::DbgStmt {
|
||||||
first: condition, ..
|
first: condition,
|
||||||
} => expr_is_multiline(&condition.value, comments_only),
|
extra_args,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
expr_is_multiline(&condition.value, comments_only)
|
||||||
|
|| extra_args
|
||||||
|
.iter()
|
||||||
|
.any(|loc_arg| expr_is_multiline(&loc_arg.value, comments_only))
|
||||||
|
}
|
||||||
Expr::LowLevelDbg(_, _, _) => {
|
Expr::LowLevelDbg(_, _, _) => {
|
||||||
unreachable!("LowLevelDbg should only exist after desugaring, not during formatting")
|
unreachable!("LowLevelDbg should only exist after desugaring, not during formatting")
|
||||||
}
|
}
|
||||||
|
@ -572,16 +585,41 @@ fn fmt_apply(
|
||||||
indent
|
indent
|
||||||
};
|
};
|
||||||
|
|
||||||
let expr_needs_parens = (expr_ends_in_closure(&loc_expr.value) && !loc_args.is_empty())
|
let expr = expr_lift_spaces(Parens::InApply, buf.text.bump(), &loc_expr.value);
|
||||||
|| expr_needs_parens_in_apply(&loc_expr.value);
|
|
||||||
|
|
||||||
if expr_needs_parens {
|
if !expr.before.is_empty() {
|
||||||
fmt_parens(&loc_expr.value, buf, indent);
|
format_spaces(buf, expr.before, Newlines::Yes, indent);
|
||||||
} else {
|
|
||||||
loc_expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for loc_arg in loc_args.iter() {
|
expr.item
|
||||||
|
.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||||
|
|
||||||
|
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 arg = expr_lift_spaces(
|
||||||
|
if is_last_arg {
|
||||||
|
Parens::InApplyLastArg
|
||||||
|
} else {
|
||||||
|
Parens::InApply
|
||||||
|
},
|
||||||
|
buf.text.bump(),
|
||||||
|
&loc_arg.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
if !should_reflow_outdentable {
|
||||||
|
if !last_after.is_empty() {
|
||||||
|
format_spaces(buf, last_after, Newlines::Yes, arg_indent);
|
||||||
|
}
|
||||||
|
if !arg.before.is_empty() {
|
||||||
|
format_spaces(buf, arg.before, Newlines::Yes, arg_indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_after = arg.after;
|
||||||
|
|
||||||
if should_reflow_outdentable {
|
if should_reflow_outdentable {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
|
|
||||||
|
@ -589,30 +627,18 @@ fn fmt_apply(
|
||||||
// We checked above that there's only a single newline before the last arg,
|
// We checked above that there's only a single newline before the last arg,
|
||||||
// which we're intentionally ignoring.
|
// which we're intentionally ignoring.
|
||||||
|
|
||||||
let arg = loc_arg.extract_spaces();
|
format_expr_only(&arg.item, buf, Parens::InApply, Newlines::Yes, arg_indent);
|
||||||
arg.item
|
|
||||||
.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
|
|
||||||
} else if needs_indent {
|
} else if needs_indent {
|
||||||
let arg = loc_arg.extract_spaces();
|
|
||||||
fmt_spaces(buf, arg.before.iter(), arg_indent);
|
|
||||||
buf.ensure_ends_with_newline();
|
buf.ensure_ends_with_newline();
|
||||||
arg.item
|
format_expr_only(&arg.item, buf, Parens::InApply, Newlines::Yes, arg_indent);
|
||||||
.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
|
|
||||||
fmt_spaces(buf, arg.after.iter(), arg_indent);
|
|
||||||
} else {
|
} else {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
loc_arg.format_with_options(buf, Parens::InApply, Newlines::Yes, arg_indent);
|
format_expr_only(&arg.item, buf, Parens::InApply, Newlines::Yes, arg_indent);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_needs_parens_in_apply(expr: &Expr<'_>) -> bool {
|
if !last_after.is_empty() {
|
||||||
match expr {
|
format_spaces(buf, last_after, Newlines::Yes, arg_indent);
|
||||||
Expr::SpaceBefore(inner, _) | Expr::SpaceAfter(inner, _) => {
|
|
||||||
expr_needs_parens_in_apply(inner)
|
|
||||||
}
|
|
||||||
Expr::If { .. } | Expr::When(_, _) | Expr::Return(_, _) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,14 +651,6 @@ fn is_outdentable_collection(expr: &Expr<'_>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_ends_in_closure(expr: &Expr<'_>) -> bool {
|
|
||||||
match expr.extract_spaces().item {
|
|
||||||
Expr::Closure(..) => true,
|
|
||||||
Expr::UnaryOp(expr, _) => expr_ends_in_closure(&expr.value),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_parens(sub_expr: &Expr<'_>, buf: &mut Buf<'_>, indent: u16) {
|
fn fmt_parens(sub_expr: &Expr<'_>, buf: &mut Buf<'_>, indent: u16) {
|
||||||
let should_add_newlines = match sub_expr {
|
let should_add_newlines = match sub_expr {
|
||||||
Expr::Closure(..) | Expr::SpaceBefore(..) | Expr::SpaceAfter(Expr::Closure(..), ..) => {
|
Expr::Closure(..) | Expr::SpaceBefore(..) | Expr::SpaceAfter(Expr::Closure(..), ..) => {
|
||||||
|
@ -776,11 +794,12 @@ fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
|
||||||
Interpolated(loc_expr) => {
|
Interpolated(loc_expr) => {
|
||||||
buf.push_str("$(");
|
buf.push_str("$(");
|
||||||
// e.g. (name) in "Hi, $(name)!"
|
// e.g. (name) in "Hi, $(name)!"
|
||||||
|
let min_indent = buf.cur_line_indent() + INDENT;
|
||||||
loc_expr.value.format_with_options(
|
loc_expr.value.format_with_options(
|
||||||
buf,
|
buf,
|
||||||
Parens::NotNeeded, // We already printed parens!
|
Parens::NotNeeded, // We already printed parens!
|
||||||
Newlines::No, // Interpolations can never have newlines
|
Newlines::No, // Interpolations can never have newlines
|
||||||
indent,
|
min_indent,
|
||||||
);
|
);
|
||||||
buf.push(')');
|
buf.push(')');
|
||||||
}
|
}
|
||||||
|
@ -884,8 +903,8 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
|
||||||
Expr::Apply(func, args, called_via) => {
|
Expr::Apply(func, args, called_via) => {
|
||||||
let func_lifted = expr_lift_spaces(Parens::InApply, arena, &func.value);
|
let func_lifted = expr_lift_spaces(Parens::InApply, arena, &func.value);
|
||||||
let args = arena.alloc_slice_copy(args);
|
let args = arena.alloc_slice_copy(args);
|
||||||
if let Some(last) = args.last_mut() {
|
let mut res = if let Some(last) = args.last_mut() {
|
||||||
let last_lifted = expr_lift_spaces(Parens::InApply, arena, &last.value);
|
let last_lifted = expr_lift_spaces(Parens::InApplyLastArg, arena, &last.value);
|
||||||
if last_lifted.before.is_empty() {
|
if last_lifted.before.is_empty() {
|
||||||
*last = arena.alloc(Loc::at(last.region, last_lifted.item));
|
*last = arena.alloc(Loc::at(last.region, last_lifted.item));
|
||||||
} else {
|
} else {
|
||||||
|
@ -920,7 +939,16 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
|
||||||
),
|
),
|
||||||
after: func_lifted.after,
|
after: func_lifted.after,
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if parens == Parens::InApply || parens == Parens::InApplyLastArg {
|
||||||
|
res = Spaces {
|
||||||
|
before: &[],
|
||||||
|
item: Expr::ParensAround(arena.alloc(lower(arena, res))),
|
||||||
|
after: &[],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
res
|
||||||
}
|
}
|
||||||
Expr::Defs(defs, final_expr) => {
|
Expr::Defs(defs, final_expr) => {
|
||||||
let mut defs = (*defs).clone();
|
let mut defs = (*defs).clone();
|
||||||
|
@ -969,6 +997,24 @@ pub fn expr_lift_spaces<'a, 'b: 'a>(
|
||||||
after: final_expr_lifted.after,
|
after: final_expr_lifted.after,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Expr::If { .. } | Expr::When(_, _) | Expr::Return(_, _) | Expr::Closure(..) => {
|
||||||
|
let res = if parens == Parens::InApply
|
||||||
|
|| (parens == Parens::InApplyLastArg && !matches!(expr, Expr::Closure(..)))
|
||||||
|
{
|
||||||
|
Spaces {
|
||||||
|
before: &[],
|
||||||
|
item: Expr::ParensAround(arena.alloc(*expr)),
|
||||||
|
after: &[],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Spaces {
|
||||||
|
before: &[],
|
||||||
|
item: *expr,
|
||||||
|
after: &[],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dbg!(res)
|
||||||
|
}
|
||||||
Expr::SpaceBefore(expr, spaces) => {
|
Expr::SpaceBefore(expr, spaces) => {
|
||||||
let mut inner = expr_lift_spaces(parens, arena, expr);
|
let mut inner = expr_lift_spaces(parens, arena, expr);
|
||||||
inner.before = merge_spaces_conservative(arena, spaces, inner.before);
|
inner.before = merge_spaces_conservative(arena, spaces, inner.before);
|
||||||
|
@ -1443,59 +1489,21 @@ fn fmt_if<'a>(
|
||||||
buf.push_str("if");
|
buf.push_str("if");
|
||||||
|
|
||||||
if is_multiline_condition {
|
if is_multiline_condition {
|
||||||
match &loc_condition.value {
|
let condition =
|
||||||
Expr::SpaceBefore(expr_below, spaces_before_expr) => {
|
expr_lift_spaces(Parens::NotNeeded, buf.text.bump(), &loc_condition.value);
|
||||||
|
fmt_comments_only(buf, condition.before.iter(), NewlineAt::Both, return_indent);
|
||||||
|
buf.ensure_ends_with_newline();
|
||||||
|
condition.item.format(buf, return_indent);
|
||||||
|
if condition.after.iter().any(|s| s.is_newline()) {
|
||||||
|
buf.ensure_ends_with_newline();
|
||||||
|
}
|
||||||
fmt_comments_only(
|
fmt_comments_only(
|
||||||
buf,
|
buf,
|
||||||
spaces_before_expr.iter(),
|
condition.after.iter(),
|
||||||
NewlineAt::Top,
|
NewlineAt::Bottom,
|
||||||
return_indent,
|
return_indent,
|
||||||
);
|
);
|
||||||
buf.newline();
|
buf.ensure_ends_with_newline();
|
||||||
|
|
||||||
match &expr_below {
|
|
||||||
Expr::SpaceAfter(expr_above, spaces_after_expr) => {
|
|
||||||
expr_above.format(buf, return_indent);
|
|
||||||
|
|
||||||
// If any of the spaces is a newline, add a newline at the top.
|
|
||||||
// Otherwise leave it as just a comment.
|
|
||||||
let newline_at = if spaces_after_expr
|
|
||||||
.iter()
|
|
||||||
.any(|spaces| matches!(spaces, CommentOrNewline::Newline))
|
|
||||||
{
|
|
||||||
NewlineAt::Top
|
|
||||||
} else {
|
|
||||||
NewlineAt::None
|
|
||||||
};
|
|
||||||
|
|
||||||
fmt_comments_only(
|
|
||||||
buf,
|
|
||||||
spaces_after_expr.iter(),
|
|
||||||
newline_at,
|
|
||||||
return_indent,
|
|
||||||
);
|
|
||||||
buf.newline();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
expr_below.format(buf, return_indent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr::SpaceAfter(expr_above, spaces_below_expr) => {
|
|
||||||
buf.newline();
|
|
||||||
expr_above.format(buf, return_indent);
|
|
||||||
fmt_comments_only(buf, spaces_below_expr.iter(), NewlineAt::Top, return_indent);
|
|
||||||
buf.newline();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
buf.newline();
|
|
||||||
loc_condition.format(buf, return_indent);
|
|
||||||
buf.newline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.indent(indent);
|
buf.indent(indent);
|
||||||
} else {
|
} else {
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
|
@ -1506,42 +1514,15 @@ fn fmt_if<'a>(
|
||||||
buf.push_str("then");
|
buf.push_str("then");
|
||||||
|
|
||||||
if is_multiline {
|
if is_multiline {
|
||||||
match &loc_then.value {
|
let then = expr_lift_spaces(Parens::NotNeeded, buf.text.bump(), &loc_then.value);
|
||||||
Expr::SpaceBefore(expr_below, spaces_below) => {
|
fmt_comments_only(buf, then.before.iter(), NewlineAt::Both, return_indent);
|
||||||
// we want exactly one newline, user-inserted extra newlines are ignored.
|
buf.ensure_ends_with_newline();
|
||||||
buf.newline();
|
then.item.format(buf, return_indent);
|
||||||
fmt_comments_only(buf, spaces_below.iter(), NewlineAt::Bottom, return_indent);
|
if then.after.iter().any(|s| s.is_newline()) {
|
||||||
|
buf.ensure_ends_with_newline();
|
||||||
match &expr_below {
|
|
||||||
Expr::SpaceAfter(expr_above, spaces_above) => {
|
|
||||||
expr_above.format(buf, return_indent);
|
|
||||||
|
|
||||||
// If any of the spaces is a newline, add a newline at the top.
|
|
||||||
// Otherwise leave it as just a comment.
|
|
||||||
let newline_at = if spaces_above
|
|
||||||
.iter()
|
|
||||||
.any(|spaces| matches!(spaces, CommentOrNewline::Newline))
|
|
||||||
{
|
|
||||||
NewlineAt::Top
|
|
||||||
} else {
|
|
||||||
NewlineAt::None
|
|
||||||
};
|
|
||||||
|
|
||||||
fmt_comments_only(buf, spaces_above.iter(), newline_at, return_indent);
|
|
||||||
buf.newline();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
expr_below.format(buf, return_indent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
buf.newline();
|
|
||||||
loc_then.format(buf, return_indent);
|
|
||||||
buf.newline();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
fmt_comments_only(buf, then.after.iter(), NewlineAt::Bottom, return_indent);
|
||||||
|
buf.ensure_ends_with_newline();
|
||||||
} else {
|
} else {
|
||||||
buf.push_str("");
|
buf.push_str("");
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
|
@ -1793,17 +1774,17 @@ enum RecordPrefix<'a> {
|
||||||
Mapper(&'a Loc<Expr<'a>>),
|
Mapper(&'a Loc<Expr<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
|
fn fmt_record_like<'a, 'b: 'a, Field, Format, ToSpacesAround>(
|
||||||
buf: &mut Buf,
|
buf: &'a mut Buf,
|
||||||
prefix: Option<RecordPrefix<'a>>,
|
prefix: Option<RecordPrefix<'b>>,
|
||||||
fields: Collection<'a, Loc<Field>>,
|
fields: Collection<'b, Loc<Field>>,
|
||||||
indent: u16,
|
indent: u16,
|
||||||
format_field_multiline: Format,
|
format_field_multiline: Format,
|
||||||
to_space_before: ToSpaceBefore,
|
to_space_around: ToSpacesAround,
|
||||||
) where
|
) where
|
||||||
Field: Formattable,
|
Field: Formattable,
|
||||||
Format: Fn(&mut Buf, &Field, u16, &str),
|
Format: Fn(&mut Buf, &Field, u16, &str),
|
||||||
ToSpaceBefore: Fn(&'a Field) -> Option<(&'a Field, &'a [CommentOrNewline<'a>])>,
|
ToSpacesAround: Fn(&'a Bump, &'b Field) -> Spaces<'a, Field>,
|
||||||
{
|
{
|
||||||
let loc_fields = fields.items;
|
let loc_fields = fields.items;
|
||||||
let final_comments = fields.final_comments();
|
let final_comments = fields.final_comments();
|
||||||
|
@ -1847,30 +1828,50 @@ fn fmt_record_like<'a, Field, Format, ToSpaceBefore>(
|
||||||
// In this case, we have to move the comma before the comment.
|
// In this case, we have to move the comma before the comment.
|
||||||
|
|
||||||
let is_first_item = index == 0;
|
let is_first_item = index == 0;
|
||||||
if let Some((_sub_field, spaces)) = to_space_before(&field.value) {
|
let field_lifted = to_space_around(buf.text.bump(), &field.value);
|
||||||
let is_only_newlines = spaces.iter().all(|s| s.is_newline());
|
if !field_lifted.before.is_empty() {
|
||||||
|
let is_only_newlines = field_lifted.before.iter().all(|s| s.is_newline());
|
||||||
if !is_first_item
|
if !is_first_item
|
||||||
&& !is_only_newlines
|
&& !is_only_newlines
|
||||||
&& count_leading_newlines(spaces.iter()) > 1
|
&& count_leading_newlines(field_lifted.before.iter()) > 1
|
||||||
{
|
{
|
||||||
buf.newline();
|
buf.newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt_comments_only(buf, spaces.iter(), NewlineAt::Top, field_indent);
|
fmt_comments_only(
|
||||||
|
buf,
|
||||||
|
field_lifted.before.iter(),
|
||||||
|
NewlineAt::Top,
|
||||||
|
field_indent,
|
||||||
|
);
|
||||||
|
|
||||||
if !is_only_newlines && count_leading_newlines(spaces.iter().rev()) > 0 {
|
if !is_only_newlines
|
||||||
|
&& count_leading_newlines(field_lifted.before.iter().rev()) > 0
|
||||||
|
{
|
||||||
buf.newline();
|
buf.newline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
format_field_multiline(buf, &field.value, field_indent, "");
|
fmt_comments_only(
|
||||||
|
buf,
|
||||||
|
field_lifted.before.iter(),
|
||||||
|
NewlineAt::Bottom,
|
||||||
|
field_indent,
|
||||||
|
);
|
||||||
|
format_field_multiline(buf, &field_lifted.item, field_indent, "");
|
||||||
|
fmt_comments_only(
|
||||||
|
buf,
|
||||||
|
field_lifted.after.iter(),
|
||||||
|
NewlineAt::Bottom,
|
||||||
|
field_indent,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if count_leading_newlines(final_comments.iter()) > 1 {
|
if count_leading_newlines(final_comments.iter()) > 1 {
|
||||||
buf.newline();
|
buf.newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt_comments_only(buf, final_comments.iter(), NewlineAt::Top, field_indent);
|
fmt_comments_only(buf, final_comments.iter(), NewlineAt::Bottom, field_indent);
|
||||||
|
|
||||||
buf.newline();
|
buf.newline();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1992,12 +1993,26 @@ fn format_assigned_field_multiline<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assigned_field_to_space_before<'a, T>(
|
fn assigned_field_to_spaces<'a, 'b: 'a, T: Copy>(
|
||||||
field: &'a AssignedField<'a, T>,
|
arena: &'a Bump,
|
||||||
) -> Option<(&AssignedField<'a, T>, &'a [CommentOrNewline<'a>])> {
|
field: &'b AssignedField<'b, T>,
|
||||||
|
) -> Spaces<'a, AssignedField<'a, T>> {
|
||||||
match field {
|
match field {
|
||||||
AssignedField::SpaceBefore(sub_field, spaces) => Some((sub_field, spaces)),
|
AssignedField::SpaceBefore(sub_field, spaces) => {
|
||||||
_ => None,
|
let mut inner = assigned_field_to_spaces(arena, sub_field);
|
||||||
|
inner.before = merge_spaces(arena, spaces, inner.before);
|
||||||
|
inner
|
||||||
|
}
|
||||||
|
AssignedField::SpaceAfter(sub_field, spaces) => {
|
||||||
|
let mut inner = assigned_field_to_spaces(arena, sub_field);
|
||||||
|
inner.after = merge_spaces(arena, inner.after, spaces);
|
||||||
|
inner
|
||||||
|
}
|
||||||
|
_ => Spaces {
|
||||||
|
before: &[],
|
||||||
|
item: *field,
|
||||||
|
after: &[],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,7 +204,6 @@ fn fmt_pattern_inner(
|
||||||
|
|
||||||
if it.peek().is_some() {
|
if it.peek().is_some() {
|
||||||
buf.push_str(",");
|
buf.push_str(",");
|
||||||
buf.spaces(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !item.after.is_empty() {
|
if !item.after.is_empty() {
|
||||||
|
@ -218,6 +217,9 @@ fn fmt_pattern_inner(
|
||||||
fmt_spaces(buf, item.after.iter(), indent);
|
fmt_spaces(buf, item.after.iter(), indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if it.peek().is_some() {
|
||||||
|
buf.ensure_ends_with_whitespace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf.spaces(1);
|
buf.spaces(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,13 +294,18 @@ fn crash_kw<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> {
|
||||||
|
|
||||||
fn loc_possibly_negative_or_negated_term<'a>(
|
fn loc_possibly_negative_or_negated_term<'a>(
|
||||||
options: ExprParseOptions,
|
options: ExprParseOptions,
|
||||||
|
allow_negate: bool,
|
||||||
) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||||
let parse_unary_negate = move |arena, state: State<'a>, min_indent: u32| {
|
let parse_unary_negate = move |arena, state: State<'a>, min_indent: u32| {
|
||||||
let initial = state.clone();
|
let initial = state.clone();
|
||||||
|
|
||||||
|
if !allow_negate {
|
||||||
|
return Err((NoProgress, EExpr::UnaryNegate(state.pos())));
|
||||||
|
}
|
||||||
|
|
||||||
let (_, (loc_op, loc_expr), state) = and(
|
let (_, (loc_op, loc_expr), state) = and(
|
||||||
loc(unary_negate()),
|
loc(unary_negate()),
|
||||||
loc_possibly_negative_or_negated_term(options),
|
loc_possibly_negative_or_negated_term(options, true),
|
||||||
)
|
)
|
||||||
.parse(arena, state, min_indent)?;
|
.parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
|
@ -310,24 +315,26 @@ fn loc_possibly_negative_or_negated_term<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
one_of![
|
one_of![
|
||||||
parse_unary_negate.trace("d"),
|
parse_unary_negate.trace("negate_expr"),
|
||||||
// this will parse negative numbers, which the unary negate thing up top doesn't (for now)
|
// this will parse negative numbers, which the unary negate thing up top doesn't (for now)
|
||||||
loc(specialize_err(EExpr::Number, number_literal_help())).trace("c"),
|
// loc(specialize_err(EExpr::Number, number_literal_help())),
|
||||||
loc(map_with_arena(
|
loc(map_with_arena(
|
||||||
and(
|
and(
|
||||||
loc(byte(b'!', EExpr::Start)),
|
loc(unary_not()).trace("not"),
|
||||||
space0_before_e(
|
space0_before_e(
|
||||||
loc_possibly_negative_or_negated_term(options),
|
loc_possibly_negative_or_negated_term(options, true),
|
||||||
EExpr::IndentStart
|
EExpr::IndentStart
|
||||||
)
|
)
|
||||||
|
.trace("not_expr")
|
||||||
),
|
),
|
||||||
|arena: &'a Bump, (loc_op, loc_expr): (Loc<_>, _)| {
|
|arena: &'a Bump, (loc_op, loc_expr): (Loc<_>, _)| {
|
||||||
Expr::UnaryOp(arena.alloc(loc_expr), Loc::at(loc_op.region, UnaryOp::Not))
|
Expr::UnaryOp(arena.alloc(loc_expr), Loc::at(loc_op.region, UnaryOp::Not))
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
.trace("b"),
|
.trace("not_expr"),
|
||||||
loc_term_or_underscore_or_conditional(options).trace("a")
|
loc_term_or_underscore_or_conditional(options)
|
||||||
]
|
]
|
||||||
|
.trace("loc_possibly_negative_or_negated_term")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fail_expr_start_e<'a, T: 'a>() -> impl Parser<'a, T, EExpr<'a>> {
|
fn fail_expr_start_e<'a, T: 'a>() -> impl Parser<'a, T, EExpr<'a>> {
|
||||||
|
@ -340,14 +347,15 @@ fn unary_negate<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||||
//
|
//
|
||||||
// - it is preceded by whitespace (spaces, newlines, comments)
|
// - it is preceded by whitespace (spaces, newlines, comments)
|
||||||
// - it is not followed by whitespace
|
// - it is not followed by whitespace
|
||||||
let followed_by_whitespace = state
|
// - it is not followed by >, making ->
|
||||||
|
let followed_by_illegal_char = state
|
||||||
.bytes()
|
.bytes()
|
||||||
.get(1)
|
.get(1)
|
||||||
.map(|c| c.is_ascii_whitespace() || *c == b'#')
|
.map(|c| c.is_ascii_whitespace() || *c == b'#' || *c == b'>')
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if state.bytes().starts_with(b"-")
|
if state.bytes().starts_with(b"-")
|
||||||
&& !followed_by_whitespace
|
&& !followed_by_illegal_char
|
||||||
&& state.column() >= min_indent
|
&& state.column() >= min_indent
|
||||||
{
|
{
|
||||||
// the negate is only unary if it is not followed by whitespace
|
// the negate is only unary if it is not followed by whitespace
|
||||||
|
@ -360,6 +368,19 @@ fn unary_negate<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unary_not<'a>() -> impl Parser<'a, (), EExpr<'a>> {
|
||||||
|
move |_arena: &'a Bump, state: State<'a>, min_indent: u32| {
|
||||||
|
let followed_by_equals = state.bytes().get(1).map(|c| *c == b'=').unwrap_or(false);
|
||||||
|
|
||||||
|
if state.bytes().starts_with(b"!") && !followed_by_equals && state.column() >= min_indent {
|
||||||
|
let state = state.advance(1);
|
||||||
|
Ok((MadeProgress, (), state))
|
||||||
|
} else {
|
||||||
|
Err((NoProgress, EExpr::UnaryNot(state.pos())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Entry point for parsing an expression.
|
/// Entry point for parsing an expression.
|
||||||
fn expr_start<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
fn expr_start<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EExpr<'a>> {
|
||||||
one_of![
|
one_of![
|
||||||
|
@ -389,7 +410,7 @@ fn parse_expr_operator_chain<'a>(
|
||||||
let line_indent = state.line_indent();
|
let line_indent = state.line_indent();
|
||||||
|
|
||||||
let (_, expr, state) =
|
let (_, expr, state) =
|
||||||
loc_possibly_negative_or_negated_term(options).parse(arena, state, min_indent)?;
|
loc_possibly_negative_or_negated_term(options, true).parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
let mut initial_state = state.clone();
|
let mut initial_state = state.clone();
|
||||||
|
|
||||||
|
@ -415,7 +436,8 @@ fn parse_expr_operator_chain<'a>(
|
||||||
let parser = skip_first(
|
let parser = skip_first(
|
||||||
crate::blankspace::check_indent(EExpr::IndentEnd),
|
crate::blankspace::check_indent(EExpr::IndentEnd),
|
||||||
loc_term_or_underscore(options),
|
loc_term_or_underscore(options),
|
||||||
);
|
)
|
||||||
|
.trace("term_or_underscore");
|
||||||
match parser.parse(arena, state.clone(), call_min_indent) {
|
match parser.parse(arena, state.clone(), call_min_indent) {
|
||||||
Err((MadeProgress, f)) => return Err((MadeProgress, f)),
|
Err((MadeProgress, f)) => return Err((MadeProgress, f)),
|
||||||
Err((NoProgress, _)) => {
|
Err((NoProgress, _)) => {
|
||||||
|
@ -583,7 +605,7 @@ fn parse_stmt_operator_chain<'a>(
|
||||||
let line_indent = state.line_indent();
|
let line_indent = state.line_indent();
|
||||||
|
|
||||||
let (_, expr, state) =
|
let (_, expr, state) =
|
||||||
loc_possibly_negative_or_negated_term(options).parse(arena, state, min_indent)?;
|
loc_possibly_negative_or_negated_term(options, true).parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
let mut initial_state = state.clone();
|
let mut initial_state = state.clone();
|
||||||
let end = state.pos();
|
let end = state.pos();
|
||||||
|
@ -594,6 +616,8 @@ fn parse_stmt_operator_chain<'a>(
|
||||||
Ok((_, spaces_before_op, state)) => (spaces_before_op, state),
|
Ok((_, spaces_before_op, state)) => (spaces_before_op, state),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let allow_negate = state.pos() > end;
|
||||||
|
|
||||||
let mut expr_state = ExprState {
|
let mut expr_state = ExprState {
|
||||||
operators: Vec::new_in(arena),
|
operators: Vec::new_in(arena),
|
||||||
arguments: Vec::new_in(arena),
|
arguments: Vec::new_in(arena),
|
||||||
|
@ -609,7 +633,7 @@ fn parse_stmt_operator_chain<'a>(
|
||||||
loop {
|
loop {
|
||||||
let parser = skip_first(
|
let parser = skip_first(
|
||||||
crate::blankspace::check_indent(EExpr::IndentEnd),
|
crate::blankspace::check_indent(EExpr::IndentEnd),
|
||||||
loc_term_or_underscore(options),
|
loc_possibly_negative_or_negated_term(options, allow_negate),
|
||||||
);
|
);
|
||||||
match parser.parse(arena, state.clone(), call_min_indent) {
|
match parser.parse(arena, state.clone(), call_min_indent) {
|
||||||
Err((MadeProgress, f)) => return Err((MadeProgress, f)),
|
Err((MadeProgress, f)) => return Err((MadeProgress, f)),
|
||||||
|
@ -1566,10 +1590,10 @@ fn parse_after_binop<'a>(
|
||||||
mut expr_state: ExprState<'a>,
|
mut expr_state: ExprState<'a>,
|
||||||
loc_op: Loc<BinOp>,
|
loc_op: Loc<BinOp>,
|
||||||
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
) -> ParseResult<'a, Expr<'a>, EExpr<'a>> {
|
||||||
match loc_possibly_negative_or_negated_term(options).parse(
|
match loc_possibly_negative_or_negated_term(options, true).parse(
|
||||||
arena,
|
arena,
|
||||||
state.clone(),
|
state.clone(),
|
||||||
call_min_indent,
|
min_indent,
|
||||||
) {
|
) {
|
||||||
Err((MadeProgress, f)) => Err((MadeProgress, f)),
|
Err((MadeProgress, f)) => Err((MadeProgress, f)),
|
||||||
Ok((_, mut new_expr, state)) => {
|
Ok((_, mut new_expr, state)) => {
|
||||||
|
@ -2596,7 +2620,8 @@ fn if_branch<'a>() -> impl Parser<'a, (Loc<Expr<'a>>, Loc<Expr<'a>>), EIf<'a>> {
|
||||||
specialize_err_ref(EIf::Condition, loc_expr(true)),
|
specialize_err_ref(EIf::Condition, loc_expr(true)),
|
||||||
EIf::IndentCondition,
|
EIf::IndentCondition,
|
||||||
EIf::IndentThenToken,
|
EIf::IndentThenToken,
|
||||||
),
|
)
|
||||||
|
.trace("if_condition"),
|
||||||
parser::keyword(keyword::THEN, EIf::Then),
|
parser::keyword(keyword::THEN, EIf::Then),
|
||||||
),
|
),
|
||||||
map_with_arena(
|
map_with_arena(
|
||||||
|
@ -2614,6 +2639,7 @@ fn if_branch<'a>() -> impl Parser<'a, (Loc<Expr<'a>>, Loc<Expr<'a>>), EIf<'a>> {
|
||||||
),
|
),
|
||||||
parser::keyword(keyword::ELSE, EIf::Else),
|
parser::keyword(keyword::ELSE, EIf::Else),
|
||||||
)
|
)
|
||||||
|
.trace("if_branch")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_help<'a>(
|
fn expect_help<'a>(
|
||||||
|
@ -2702,9 +2728,10 @@ fn import<'a>() -> impl Parser<'a, ValueDef<'a>, EImport<'a>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn if_expr_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EIf<'a>> {
|
fn if_expr_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EIf<'a>> {
|
||||||
move |arena: &'a Bump, state, min_indent| {
|
(move |arena: &'a Bump, state, min_indent| {
|
||||||
let (_, _, state) =
|
let (_, _, state) = parser::keyword(keyword::IF, EIf::If)
|
||||||
parser::keyword(keyword::IF, EIf::If).parse(arena, state, min_indent)?;
|
.trace("if_kw")
|
||||||
|
.parse(arena, state, min_indent)?;
|
||||||
|
|
||||||
let if_indent = state.line_indent();
|
let if_indent = state.line_indent();
|
||||||
|
|
||||||
|
@ -2713,8 +2740,9 @@ fn if_expr_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EIf<
|
||||||
let mut loop_state = state;
|
let mut loop_state = state;
|
||||||
|
|
||||||
let state_final_else = loop {
|
let state_final_else = loop {
|
||||||
let (_, (cond, then_branch), state) =
|
let (_, (cond, then_branch), state) = if_branch()
|
||||||
if_branch().parse(arena, loop_state, min_indent)?;
|
.parse(arena, loop_state, min_indent)
|
||||||
|
.map_err(|(_p, err)| (MadeProgress, err))?;
|
||||||
|
|
||||||
branches.push((cond, then_branch));
|
branches.push((cond, then_branch));
|
||||||
|
|
||||||
|
@ -2767,7 +2795,8 @@ fn if_expr_help<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a>, EIf<
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((MadeProgress, expr, state))
|
Ok((MadeProgress, expr, state))
|
||||||
}
|
})
|
||||||
|
.trace("if")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a block of statements (parser combinator version of `parse_block`)
|
/// Parse a block of statements (parser combinator version of `parse_block`)
|
||||||
|
@ -3761,26 +3790,6 @@ fn positive_number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, ENumber> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn number_literal_help<'a>() -> impl Parser<'a, Expr<'a>, ENumber> {
|
|
||||||
map(crate::number_literal::number_literal(), |literal| {
|
|
||||||
use crate::number_literal::NumLiteral::*;
|
|
||||||
|
|
||||||
match literal {
|
|
||||||
Num(s) => Expr::Num(s),
|
|
||||||
Float(s) => Expr::Float(s),
|
|
||||||
NonBase10Int {
|
|
||||||
string,
|
|
||||||
base,
|
|
||||||
is_negative,
|
|
||||||
} => Expr::NonBase10Int {
|
|
||||||
string,
|
|
||||||
base,
|
|
||||||
is_negative,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const BINOP_CHAR_SET: &[u8] = b"+-/*=.<>:&|^?%!";
|
const BINOP_CHAR_SET: &[u8] = b"+-/*=.<>:&|^?%!";
|
||||||
|
|
||||||
const BINOP_CHAR_MASK: [bool; 125] = {
|
const BINOP_CHAR_MASK: [bool; 125] = {
|
||||||
|
|
|
@ -456,7 +456,8 @@ pub fn parse_str_like_literal<'a>() -> impl Parser<'a, StrLikeLiteral<'a>, EStri
|
||||||
let (_progress, loc_expr, new_state) = skip_second(
|
let (_progress, loc_expr, new_state) = skip_second(
|
||||||
specialize_err_ref(
|
specialize_err_ref(
|
||||||
EString::Format,
|
EString::Format,
|
||||||
loc(allocated(reset_min_indent(expr::expr_help()))),
|
loc(allocated(reset_min_indent(expr::expr_help())))
|
||||||
|
.trace("str_interpolation"),
|
||||||
),
|
),
|
||||||
byte(b')', EString::FormatEnd),
|
byte(b')', EString::FormatEnd),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Expr(When(IfGuard(Start(@28), @27), @0), @0)
|
Expr(When(IfGuard(Start(@27), @27), @0), @0)
|
|
@ -0,0 +1 @@
|
||||||
|
Expr(If(Condition(Start(@2), @2), @0), @0)
|
|
@ -0,0 +1 @@
|
||||||
|
if!==9
|
|
@ -1,4 +1,4 @@
|
||||||
UserId x : [UserId I64]
|
UserId x : [UserId I64]
|
||||||
(UserId x) = UserId 42
|
UserId x = UserId 42
|
||||||
|
|
||||||
x
|
x
|
|
@ -0,0 +1,4 @@
|
||||||
|
d
|
||||||
|
+
|
||||||
|
(\w -> x)
|
||||||
|
x
|
|
@ -0,0 +1,41 @@
|
||||||
|
BinOps(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
@0-1 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "d",
|
||||||
|
},
|
||||||
|
@1-2 Plus,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@4-12 Apply(
|
||||||
|
@4-9 SpaceBefore(
|
||||||
|
Closure(
|
||||||
|
[
|
||||||
|
@5-6 Identifier {
|
||||||
|
ident: "w",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
@8-9 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "x",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@11-12 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "x",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
d+
|
||||||
|
\w->x
|
||||||
|
x
|
|
@ -0,0 +1,7 @@
|
||||||
|
r
|
||||||
|
^
|
||||||
|
(
|
||||||
|
-f
|
||||||
|
#
|
||||||
|
-P
|
||||||
|
)
|
|
@ -0,0 +1,42 @@
|
||||||
|
BinOps(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
@0-1 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "r",
|
||||||
|
},
|
||||||
|
@1-2 Caret,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@3-11 Apply(
|
||||||
|
@3-5 SpaceAfter(
|
||||||
|
SpaceBefore(
|
||||||
|
UnaryOp(
|
||||||
|
@4-5 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "f",
|
||||||
|
},
|
||||||
|
@3-4 Negate,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
LineComment(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@9-11 UnaryOp(
|
||||||
|
@10-11 Tag(
|
||||||
|
"P",
|
||||||
|
),
|
||||||
|
@9-10 Negate,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
r^
|
||||||
|
-f
|
||||||
|
#
|
||||||
|
-P
|
|
@ -0,0 +1,3 @@
|
||||||
|
\{ i, #
|
||||||
|
e }
|
||||||
|
-> a
|
|
@ -0,0 +1,25 @@
|
||||||
|
Closure(
|
||||||
|
[
|
||||||
|
@1-8 RecordDestructure(
|
||||||
|
[
|
||||||
|
@2-3 SpaceAfter(
|
||||||
|
Identifier {
|
||||||
|
ident: "i",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
LineComment(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@6-7 Identifier {
|
||||||
|
ident: "e",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
@10-11 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "a",
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
\{i#
|
||||||
|
,e}->a
|
|
@ -0,0 +1,8 @@
|
||||||
|
1 : (
|
||||||
|
M,
|
||||||
|
b # ,
|
||||||
|
,
|
||||||
|
h
|
||||||
|
-> g,
|
||||||
|
)e
|
||||||
|
h
|
|
@ -0,0 +1,74 @@
|
||||||
|
SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(2147483648),
|
||||||
|
],
|
||||||
|
regions: [
|
||||||
|
@0-16,
|
||||||
|
],
|
||||||
|
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: [
|
||||||
|
Annotation(
|
||||||
|
@0-1 NumLiteral(
|
||||||
|
"1",
|
||||||
|
),
|
||||||
|
@2-16 Tuple {
|
||||||
|
elems: [
|
||||||
|
@3-14 Function(
|
||||||
|
[
|
||||||
|
@3-4 Apply(
|
||||||
|
"",
|
||||||
|
"M",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
@5-6 SpaceAfter(
|
||||||
|
BoundVariable(
|
||||||
|
"b",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
LineComment(
|
||||||
|
",",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@10-11 BoundVariable(
|
||||||
|
"h",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Pure,
|
||||||
|
@13-14 BoundVariable(
|
||||||
|
"g",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ext: Some(
|
||||||
|
@15-16 BoundVariable(
|
||||||
|
"e",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@17-18 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "h",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
1:(M,b#,
|
||||||
|
,h->g)e
|
||||||
|
h
|
|
@ -0,0 +1,6 @@
|
||||||
|
(
|
||||||
|
dbg
|
||||||
|
D
|
||||||
|
q
|
||||||
|
h
|
||||||
|
)
|
|
@ -0,0 +1,27 @@
|
||||||
|
ParensAround(
|
||||||
|
DbgStmt {
|
||||||
|
first: @5-6 Tag(
|
||||||
|
"D",
|
||||||
|
),
|
||||||
|
extra_args: [
|
||||||
|
@8-9 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "q",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
continuation: @10-11 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "h",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
(dbg D
|
||||||
|
q
|
||||||
|
h)
|
|
@ -1,2 +1,2 @@
|
||||||
(Email str) = Email "blah@example.com"
|
Email str = Email "blah@example.com"
|
||||||
str
|
str
|
|
@ -1,3 +1,4 @@
|
||||||
|
SpaceAfter(
|
||||||
BinOps(
|
BinOps(
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
|
@ -8,9 +9,9 @@ BinOps(
|
||||||
@1-2 Slash,
|
@1-2 Slash,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@3-7 SpaceBefore(
|
@4-8 SpaceBefore(
|
||||||
UnaryOp(
|
UnaryOp(
|
||||||
@6-7 SpaceBefore(
|
@7-8 SpaceBefore(
|
||||||
Var {
|
Var {
|
||||||
module_name: "",
|
module_name: "",
|
||||||
ident: "g",
|
ident: "g",
|
||||||
|
@ -19,10 +20,14 @@ BinOps(
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@3-4 Not,
|
@4-5 Not,
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
Newline,
|
Newline,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
if
|
||||||
|
h
|
||||||
|
then
|
||||||
|
!f #
|
||||||
|
else
|
||||||
|
&m
|
|
@ -0,0 +1,43 @@
|
||||||
|
SpaceAfter(
|
||||||
|
If {
|
||||||
|
if_thens: [
|
||||||
|
(
|
||||||
|
@3-4 SpaceBefore(
|
||||||
|
SpaceAfter(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "h",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@9-11 SpaceAfter(
|
||||||
|
UnaryOp(
|
||||||
|
@10-11 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "f",
|
||||||
|
},
|
||||||
|
@9-10 Not,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
LineComment(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
final_else: @17-19 RecordUpdater(
|
||||||
|
"m",
|
||||||
|
),
|
||||||
|
indented_else: false,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
if
|
||||||
|
h
|
||||||
|
then!f#
|
||||||
|
else&m
|
|
@ -1,3 +1,3 @@
|
||||||
(MT q) = g
|
MT q = g
|
||||||
q
|
q
|
||||||
dbgT
|
dbgT
|
|
@ -0,0 +1,5 @@
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
"$(i
|
||||||
|
"""
|
||||||
|
""")"
|
|
@ -0,0 +1,32 @@
|
||||||
|
Apply(
|
||||||
|
@0-6 Str(
|
||||||
|
Block(
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
@6-18 Str(
|
||||||
|
Line(
|
||||||
|
[
|
||||||
|
Interpolated(
|
||||||
|
@9-16 Apply(
|
||||||
|
@9-10 Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "i",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
@10-16 Str(
|
||||||
|
Block(
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Space,
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
"""""""$(i"""""")"
|
|
@ -0,0 +1,2 @@
|
||||||
|
N -0 T : A
|
||||||
|
zT
|
|
@ -0,0 +1,52 @@
|
||||||
|
SpaceAfter(
|
||||||
|
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 "N",
|
||||||
|
vars: [
|
||||||
|
@2-4 NumLiteral(
|
||||||
|
"-0",
|
||||||
|
),
|
||||||
|
@5-6 Tag(
|
||||||
|
"T",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
ann: @7-8 Apply(
|
||||||
|
"",
|
||||||
|
"A",
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
value_defs: [],
|
||||||
|
},
|
||||||
|
@9-11 SpaceBefore(
|
||||||
|
Var {
|
||||||
|
module_name: "",
|
||||||
|
ident: "zT",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,2 @@
|
||||||
|
N -0 T:A
|
||||||
|
zT
|
|
@ -1,2 +1,2 @@
|
||||||
(@Thunk it) = id (@A {})
|
@Thunk it = id (@A {})
|
||||||
it {}
|
it {}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{ i, p } = 5
|
||||||
|
Q
|
|
@ -0,0 +1,53 @@
|
||||||
|
SpaceAfter(
|
||||||
|
Defs(
|
||||||
|
Defs {
|
||||||
|
tags: [
|
||||||
|
EitherIndex(2147483648),
|
||||||
|
],
|
||||||
|
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: [],
|
||||||
|
value_defs: [
|
||||||
|
Body(
|
||||||
|
@0-6 RecordDestructure(
|
||||||
|
[
|
||||||
|
@1-3 SpaceAfter(
|
||||||
|
Identifier {
|
||||||
|
ident: "i",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@4-5 Identifier {
|
||||||
|
ident: "p",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
@7-8 Num(
|
||||||
|
"5",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
@9-10 SpaceBefore(
|
||||||
|
Tag(
|
||||||
|
"Q",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,3 @@
|
||||||
|
{i
|
||||||
|
,p}=5
|
||||||
|
Q
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
t, #
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
SpaceAfter(
|
||||||
|
Record(
|
||||||
|
Collection {
|
||||||
|
items: [
|
||||||
|
@1-4 SpaceAfter(
|
||||||
|
LabelOnly(
|
||||||
|
@1-2 "t",
|
||||||
|
),
|
||||||
|
[
|
||||||
|
LineComment(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
final_comments: [
|
||||||
|
Newline,
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[
|
||||||
|
Newline,
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
{t#
|
||||||
|
,
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
(Config launchTheNukes! code) = cfg
|
Config launchTheNukes! code = cfg
|
||||||
|
|
||||||
launchTheNukes! code
|
launchTheNukes! code
|
|
@ -1,3 +1,3 @@
|
||||||
(Config launchTheNukes! code) = cfg
|
Config launchTheNukes! code = cfg
|
||||||
|
|
||||||
launchTheNukes! code
|
launchTheNukes! code
|
|
@ -1,7 +1,7 @@
|
||||||
(Pair x _) = Pair 0 1
|
Pair x _ = Pair 0 1
|
||||||
(Pair _ y) = Pair 0 1
|
Pair _ y = Pair 0 1
|
||||||
(Pair _ _) = Pair 0 1
|
Pair _ _ = Pair 0 1
|
||||||
_ = Pair 0 1
|
_ = Pair 0 1
|
||||||
(Pair (Pair x _) (Pair _ y)) = Pair (Pair 0 1) (Pair 2 3)
|
Pair (Pair x _) (Pair _ y) = Pair (Pair 0 1) (Pair 2 3)
|
||||||
|
|
||||||
0
|
0
|
|
@ -207,6 +207,7 @@ mod test_snapshots {
|
||||||
fail/if_missing_else.expr,
|
fail/if_missing_else.expr,
|
||||||
fail/if_outdented_else_branch.expr,
|
fail/if_outdented_else_branch.expr,
|
||||||
fail/if_outdented_then.expr,
|
fail/if_outdented_then.expr,
|
||||||
|
fail/ifbang_eqeq.expr,
|
||||||
fail/import_with_lowercase_alias.moduledefs,
|
fail/import_with_lowercase_alias.moduledefs,
|
||||||
fail/imports_missing_comma.header,
|
fail/imports_missing_comma.header,
|
||||||
fail/inline_hastype.expr,
|
fail/inline_hastype.expr,
|
||||||
|
@ -317,6 +318,8 @@ mod test_snapshots {
|
||||||
pass/basic_var.expr,
|
pass/basic_var.expr,
|
||||||
pass/binop_apply_complex.expr,
|
pass/binop_apply_complex.expr,
|
||||||
pass/binop_assign_defs_nested.expr,
|
pass/binop_assign_defs_nested.expr,
|
||||||
|
pass/binop_closure_apply.expr,
|
||||||
|
pass/binops_comment_indent_change.expr,
|
||||||
pass/block_string_ann.expr,
|
pass/block_string_ann.expr,
|
||||||
pass/body_block_string_apply_string.expr,
|
pass/body_block_string_apply_string.expr,
|
||||||
pass/body_with_unneeded_parens.expr,
|
pass/body_with_unneeded_parens.expr,
|
||||||
|
@ -324,6 +327,7 @@ mod test_snapshots {
|
||||||
pass/call_bang_no_space.expr,
|
pass/call_bang_no_space.expr,
|
||||||
pass/closure_in_apply_in_binop.expr,
|
pass/closure_in_apply_in_binop.expr,
|
||||||
pass/closure_in_binop_with_spaces.expr,
|
pass/closure_in_binop_with_spaces.expr,
|
||||||
|
pass/closure_pat_reccord_comment.expr,
|
||||||
pass/closure_with_underscores.expr,
|
pass/closure_with_underscores.expr,
|
||||||
pass/comma_prefixed_indented_record.expr,
|
pass/comma_prefixed_indented_record.expr,
|
||||||
pass/comment_after_annotation.expr,
|
pass/comment_after_annotation.expr,
|
||||||
|
@ -331,6 +335,7 @@ mod test_snapshots {
|
||||||
pass/comment_after_expr_in_parens.expr,
|
pass/comment_after_expr_in_parens.expr,
|
||||||
pass/comment_after_op.expr,
|
pass/comment_after_op.expr,
|
||||||
pass/comment_before_colon_def.expr,
|
pass/comment_before_colon_def.expr,
|
||||||
|
pass/comment_before_comma_in_tuple_type_with_func.expr,
|
||||||
pass/comment_before_equals_def.expr,
|
pass/comment_before_equals_def.expr,
|
||||||
pass/comment_before_op.expr,
|
pass/comment_before_op.expr,
|
||||||
pass/comment_before_pat_in_parens.expr,
|
pass/comment_before_pat_in_parens.expr,
|
||||||
|
@ -353,6 +358,7 @@ mod test_snapshots {
|
||||||
pass/dbg_extra_parens.expr,
|
pass/dbg_extra_parens.expr,
|
||||||
pass/dbg_newline_apply.expr,
|
pass/dbg_newline_apply.expr,
|
||||||
pass/dbg_stmt.expr,
|
pass/dbg_stmt.expr,
|
||||||
|
pass/dbg_stmt_in_parens.expr,
|
||||||
pass/dbg_stmt_multiline.expr,
|
pass/dbg_stmt_multiline.expr,
|
||||||
pass/dbg_stmt_two_exprs.expr,
|
pass/dbg_stmt_two_exprs.expr,
|
||||||
pass/def_bang.expr,
|
pass/def_bang.expr,
|
||||||
|
@ -396,6 +402,7 @@ mod test_snapshots {
|
||||||
pass/highest_int.expr,
|
pass/highest_int.expr,
|
||||||
pass/i_over_not_g.expr,
|
pass/i_over_not_g.expr,
|
||||||
pass/if_def.expr,
|
pass/if_def.expr,
|
||||||
|
pass/if_newline_then_negate_else_recordupdater.expr,
|
||||||
pass/implements_newlines_comments.expr,
|
pass/implements_newlines_comments.expr,
|
||||||
pass/import.moduledefs,
|
pass/import.moduledefs,
|
||||||
pass/import_from_package.moduledefs,
|
pass/import_from_package.moduledefs,
|
||||||
|
@ -447,6 +454,7 @@ mod test_snapshots {
|
||||||
pass/multiline_apply_equals_multiline_apply.expr,
|
pass/multiline_apply_equals_multiline_apply.expr,
|
||||||
pass/multiline_backpassing.expr,
|
pass/multiline_backpassing.expr,
|
||||||
pass/multiline_binop_when_with_comments.expr,
|
pass/multiline_binop_when_with_comments.expr,
|
||||||
|
pass/multiline_str_crazyness.expr,
|
||||||
pass/multiline_str_in_pat.expr,
|
pass/multiline_str_in_pat.expr,
|
||||||
pass/multiline_string.expr,
|
pass/multiline_string.expr,
|
||||||
pass/multiline_string_in_apply.expr,
|
pass/multiline_string_in_apply.expr,
|
||||||
|
@ -464,6 +472,7 @@ mod test_snapshots {
|
||||||
pass/negative_float.expr,
|
pass/negative_float.expr,
|
||||||
pass/negative_in_apply_def.expr,
|
pass/negative_in_apply_def.expr,
|
||||||
pass/negative_int.expr,
|
pass/negative_int.expr,
|
||||||
|
pass/negative_number_in_pattern.expr,
|
||||||
pass/negative_single_quote.expr,
|
pass/negative_single_quote.expr,
|
||||||
pass/nested_def_annotation.moduledefs,
|
pass/nested_def_annotation.moduledefs,
|
||||||
pass/nested_if.expr,
|
pass/nested_if.expr,
|
||||||
|
@ -530,6 +539,7 @@ mod test_snapshots {
|
||||||
pass/parenthetical_var.expr,
|
pass/parenthetical_var.expr,
|
||||||
pass/parse_alias.expr,
|
pass/parse_alias.expr,
|
||||||
pass/parse_as_ann.expr,
|
pass/parse_as_ann.expr,
|
||||||
|
pass/pat_space_after_comma.expr,
|
||||||
pass/pattern_as.expr,
|
pass/pattern_as.expr,
|
||||||
pass/pattern_as_list_rest.expr,
|
pass/pattern_as_list_rest.expr,
|
||||||
pass/pattern_as_spaces.expr,
|
pass/pattern_as_spaces.expr,
|
||||||
|
@ -560,6 +570,7 @@ mod test_snapshots {
|
||||||
pass/record_updater_literal_apply.expr,
|
pass/record_updater_literal_apply.expr,
|
||||||
pass/record_updater_var_apply.expr,
|
pass/record_updater_var_apply.expr,
|
||||||
pass/record_with_if.expr,
|
pass/record_with_if.expr,
|
||||||
|
pass/record_with_lots_of_newlines.expr,
|
||||||
pass/requires_type.header,
|
pass/requires_type.header,
|
||||||
pass/return_apply_newline.expr,
|
pass/return_apply_newline.expr,
|
||||||
pass/return_field_access_in_parens.expr,
|
pass/return_field_access_in_parens.expr,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue