Skip to content

Commit

Permalink
Formatter surrounds operators with { } where required
Browse files Browse the repository at this point in the history
Closes #432
  • Loading branch information
lpil committed Apr 28, 2020
1 parent e8fa378 commit 6ba760b
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 14 deletions.
37 changes: 35 additions & 2 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,18 +231,25 @@ pub struct ExternalFnArg {

#[derive(Debug, Clone, PartialEq)]
pub enum BinOp {
// Boolean logic
And,
Or,

// Equality
Eq,
NotEq,

// Order comparison
LtInt,
LtEqInt,
LtFloat,
LtEqFloat,
Eq,
NotEq,
GtEqInt,
GtInt,
GtEqFloat,
GtFloat,

// Maths
AddInt,
AddFloat,
SubInt,
Expand All @@ -254,6 +261,32 @@ pub enum BinOp {
ModuloInt,
}

impl BinOp {
pub fn precedence(&self) -> u8 {
match self {
Self::Or => 1,

Self::And => 2,

Self::Eq | Self::NotEq => 3,

Self::LtInt
| Self::LtEqInt
| Self::LtFloat
| Self::LtEqFloat
| Self::GtEqInt
| Self::GtInt
| Self::GtEqFloat
| Self::GtFloat => 4,

// Pipe is 5
Self::AddInt | Self::AddFloat | Self::SubInt | Self::SubFloat => 6,

Self::MultInt | Self::MultFloat | Self::DivInt | Self::DivFloat | Self::ModuloInt => 7,
}
}
}

#[derive(Debug, PartialEq, Clone)]
pub struct CallArg<A> {
pub label: Option<String>,
Expand Down
8 changes: 8 additions & 0 deletions src/ast/untyped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,12 @@ impl UntypedExpr {
_ => self.location().start,
}
}

pub fn binop_precedence(&self) -> u8 {
match self {
Self::BinOp { name, .. } => name.precedence(),
Self::Pipe { .. } => 5,
_ => std::u8::MAX,
}
}
}
35 changes: 29 additions & 6 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,7 @@ impl<'a> Formatter<'a> {

UntypedExpr::BinOp {
name, left, right, ..
} => self
.expr(left)
.append(name)
.append(self.expr(right.as_ref())),
} => self.bin_op(name, left, right),

UntypedExpr::Let {
value,
Expand Down Expand Up @@ -515,7 +512,33 @@ impl<'a> Formatter<'a> {
commented(document, comments)
}

pub fn bin_op(&mut self, name: &BinOp, left: &UntypedExpr, right: &UntypedExpr) -> Document {
let precedence = name.precedence();
let left_precedence = left.binop_precedence();
let right_precedence = right.binop_precedence();
let left = self.expr(left);
let right = self.expr(right);
self.operator_side(left, precedence, left_precedence)
.append(name)
.append(self.operator_side(right, precedence, right_precedence))
}

pub fn operator_side(&mut self, doc: Document, op: u8, side: u8) -> Document {
if op > side {
delim("{")
.append(doc)
.nest(INDENT)
.append(break_("", " "))
.append("}")
.group()
} else {
doc
}
}

fn pipe(&mut self, left: &UntypedExpr, right: &UntypedExpr) -> Document {
let left_precedence = left.binop_precedence();
let right_precedence = right.binop_precedence();
let left = self.expr(left);
let right = match right {
UntypedExpr::Fn {
Expand All @@ -527,10 +550,10 @@ impl<'a> Formatter<'a> {
_ => self.expr(right),
};
force_break()
.append(left)
.append(self.operator_side(left, 4, left_precedence))
.append(line())
.append("|> ")
.append(right)
.append(self.operator_side(right, 4, right_precedence))
}

fn pipe_capture_right_hand_side(&mut self, fun: &UntypedExpr) -> Document {
Expand Down
54 changes: 54 additions & 0 deletions src/format/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2380,6 +2380,60 @@ type X {
X
}
// Hello
"
);

//
// Binary operator precedence
//

assert_format!(
"fn main() {
{ 1 + 2 } * 3
}
"
);

assert_format!(
"fn main() {
3 * { 1 + 2 }
}
"
);

assert_format!(
"fn main() {
3 * {
1
|> inc
}
}
"
);

assert_format!(
"fn main() {
{
1
|> inc
} * 3
}
"
);

assert_format!(
"fn main() {
1
|> { a || b }
}
"
);

assert_format!(
"fn main() {
{ a || b }
|> go
}
"
);
}
Expand Down
12 changes: 6 additions & 6 deletions test/core_language/test/binary_operators_test.gleam
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import should

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

0 comments on commit 6ba760b

Please sign in to comment.