Skip to content

Commit 6ba760b

Browse files
committed
Formatter surrounds operators with { } where required
Closes #432
1 parent e8fa378 commit 6ba760b

5 files changed

Lines changed: 132 additions & 14 deletions

File tree

src/ast.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,18 +231,25 @@ pub struct ExternalFnArg {
231231

232232
#[derive(Debug, Clone, PartialEq)]
233233
pub enum BinOp {
234+
// Boolean logic
234235
And,
235236
Or,
237+
238+
// Equality
239+
Eq,
240+
NotEq,
241+
242+
// Order comparison
236243
LtInt,
237244
LtEqInt,
238245
LtFloat,
239246
LtEqFloat,
240-
Eq,
241-
NotEq,
242247
GtEqInt,
243248
GtInt,
244249
GtEqFloat,
245250
GtFloat,
251+
252+
// Maths
246253
AddInt,
247254
AddFloat,
248255
SubInt,
@@ -254,6 +261,32 @@ pub enum BinOp {
254261
ModuloInt,
255262
}
256263

264+
impl BinOp {
265+
pub fn precedence(&self) -> u8 {
266+
match self {
267+
Self::Or => 1,
268+
269+
Self::And => 2,
270+
271+
Self::Eq | Self::NotEq => 3,
272+
273+
Self::LtInt
274+
| Self::LtEqInt
275+
| Self::LtFloat
276+
| Self::LtEqFloat
277+
| Self::GtEqInt
278+
| Self::GtInt
279+
| Self::GtEqFloat
280+
| Self::GtFloat => 4,
281+
282+
// Pipe is 5
283+
Self::AddInt | Self::AddFloat | Self::SubInt | Self::SubFloat => 6,
284+
285+
Self::MultInt | Self::MultFloat | Self::DivInt | Self::DivFloat | Self::ModuloInt => 7,
286+
}
287+
}
288+
}
289+
257290
#[derive(Debug, PartialEq, Clone)]
258291
pub struct CallArg<A> {
259292
pub label: Option<String>,

src/ast/untyped.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,12 @@ impl UntypedExpr {
130130
_ => self.location().start,
131131
}
132132
}
133+
134+
pub fn binop_precedence(&self) -> u8 {
135+
match self {
136+
Self::BinOp { name, .. } => name.precedence(),
137+
Self::Pipe { .. } => 5,
138+
_ => std::u8::MAX,
139+
}
140+
}
133141
}

src/format.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,7 @@ impl<'a> Formatter<'a> {
466466

467467
UntypedExpr::BinOp {
468468
name, left, right, ..
469-
} => self
470-
.expr(left)
471-
.append(name)
472-
.append(self.expr(right.as_ref())),
469+
} => self.bin_op(name, left, right),
473470

474471
UntypedExpr::Let {
475472
value,
@@ -515,7 +512,33 @@ impl<'a> Formatter<'a> {
515512
commented(document, comments)
516513
}
517514

515+
pub fn bin_op(&mut self, name: &BinOp, left: &UntypedExpr, right: &UntypedExpr) -> Document {
516+
let precedence = name.precedence();
517+
let left_precedence = left.binop_precedence();
518+
let right_precedence = right.binop_precedence();
519+
let left = self.expr(left);
520+
let right = self.expr(right);
521+
self.operator_side(left, precedence, left_precedence)
522+
.append(name)
523+
.append(self.operator_side(right, precedence, right_precedence))
524+
}
525+
526+
pub fn operator_side(&mut self, doc: Document, op: u8, side: u8) -> Document {
527+
if op > side {
528+
delim("{")
529+
.append(doc)
530+
.nest(INDENT)
531+
.append(break_("", " "))
532+
.append("}")
533+
.group()
534+
} else {
535+
doc
536+
}
537+
}
538+
518539
fn pipe(&mut self, left: &UntypedExpr, right: &UntypedExpr) -> Document {
540+
let left_precedence = left.binop_precedence();
541+
let right_precedence = right.binop_precedence();
519542
let left = self.expr(left);
520543
let right = match right {
521544
UntypedExpr::Fn {
@@ -527,10 +550,10 @@ impl<'a> Formatter<'a> {
527550
_ => self.expr(right),
528551
};
529552
force_break()
530-
.append(left)
553+
.append(self.operator_side(left, 4, left_precedence))
531554
.append(line())
532555
.append("|> ")
533-
.append(right)
556+
.append(self.operator_side(right, 4, right_precedence))
534557
}
535558

536559
fn pipe_capture_right_hand_side(&mut self, fun: &UntypedExpr) -> Document {

src/format/tests.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,60 @@ type X {
23802380
X
23812381
}
23822382
// Hello
2383+
"
2384+
);
2385+
2386+
//
2387+
// Binary operator precedence
2388+
//
2389+
2390+
assert_format!(
2391+
"fn main() {
2392+
{ 1 + 2 } * 3
2393+
}
2394+
"
2395+
);
2396+
2397+
assert_format!(
2398+
"fn main() {
2399+
3 * { 1 + 2 }
2400+
}
2401+
"
2402+
);
2403+
2404+
assert_format!(
2405+
"fn main() {
2406+
3 * {
2407+
1
2408+
|> inc
2409+
}
2410+
}
2411+
"
2412+
);
2413+
2414+
assert_format!(
2415+
"fn main() {
2416+
{
2417+
1
2418+
|> inc
2419+
} * 3
2420+
}
2421+
"
2422+
);
2423+
2424+
assert_format!(
2425+
"fn main() {
2426+
1
2427+
|> { a || b }
2428+
}
2429+
"
2430+
);
2431+
2432+
assert_format!(
2433+
"fn main() {
2434+
{ a || b }
2435+
|> go
2436+
}
23832437
"
23842438
);
23852439
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import should
22

3-
// pub fn precedence_test() {
4-
// should.equal(1 + 2 * 3, 7)
5-
// should.equal(3 * 1 + 2, 5)
6-
// should.equal({ 1 + 2 } * 3, 9)
7-
// should.equal(3 * { 1 + 2 }, 9)
8-
// }
3+
pub fn precedence_test() {
4+
should.equal(1 + 2 * 3, 7)
5+
should.equal(3 * 1 + 2, 5)
6+
should.equal({ 1 + 2 } * 3, 9)
7+
should.equal(3 * { 1 + 2 }, 9)
8+
}

0 commit comments

Comments
 (0)