Skip to content

Commit

Permalink
fix: operations precendence levels (tact-lang#265)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusarich authored Apr 19, 2024
1 parent d73a836 commit 88e3c38
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Escape backticks in error messages for generated TypeScript code: PR [#192](https://github.com/tact-lang/tact/pull/192)
- Empty inherited trait lists after `with` keyword are now disallowed: PR [#246](https://github.com/tact-lang/tact/pull/246)
- Allow chaining method calls with `!!`, for instance, `map.asCell()!!.hash()` is grammatically correct now: PR [#257](ttps://github.com/tact-lang/tact/pull/257)
- Operation precendence for bitwise operators, equality and comparisons now matches common languages, like JavaScript: PR [#265](https://github.com/tact-lang/tact/pull/265)

## [1.2.0] - 2024-02-29

Expand Down
43 changes: 29 additions & 14 deletions src/grammar/grammar.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -126,35 +126,50 @@ Tact {

// Expressions
Expression = ExpressionConditional

ExpressionConditional = ExpressionOr "?" ExpressionOr ":" ExpressionConditional --ternary
| ExpressionOr

ExpressionOr = ExpressionOr "||" ExpressionAnd --or
| ExpressionAnd
ExpressionAnd = ExpressionAnd "&&" ExpressionCompare --and
| ExpressionCompare
ExpressionCompare = ExpressionCompare "!=" ExpressionBinary --not
| ExpressionCompare "==" ExpressionBinary --eq
| ExpressionCompare ">" ExpressionBinary --gt
| ExpressionCompare ">=" ExpressionBinary --gte
| ExpressionCompare "<" ExpressionBinary --lt
| ExpressionCompare "<=" ExpressionBinary --lte
| ExpressionBinary
ExpressionBinary = ExpressionBinary ">>" ExpressionAdd --shr
| ExpressionBinary "<<" ExpressionAdd --shl
| ExpressionBinary "&" ExpressionAdd --bin_and
| ExpressionBinary "|" ExpressionAdd --bin_or
| ExpressionAdd

ExpressionAnd = ExpressionAnd "&&" ExpressionBinaryOr --and
| ExpressionBinaryOr

ExpressionBinaryOr = ExpressionBinaryOr "|" ExpressionBinaryAnd --bin_or
| ExpressionBinaryAnd

ExpressionBinaryAnd = ExpressionBinaryAnd "&" ExpressionEquality --bin_and
| ExpressionEquality

ExpressionEquality = ExpressionEquality "!=" ExpressionCompare --not
| ExpressionEquality "==" ExpressionCompare --eq
| ExpressionCompare

ExpressionCompare = ExpressionCompare ">" ExpressionBinaryShift --gt
| ExpressionCompare ">=" ExpressionBinaryShift --gte
| ExpressionCompare "<" ExpressionBinaryShift --lt
| ExpressionCompare "<=" ExpressionBinaryShift --lte
| ExpressionBinaryShift

ExpressionBinaryShift = ExpressionBinaryShift "<<" ExpressionAdd --shl
| ExpressionBinaryShift ">>" ExpressionAdd --shr
| ExpressionAdd

ExpressionAdd = ExpressionAdd "+" ~"+" ExpressionMul --add
| ExpressionAdd "-" ~"-" ExpressionMul --sub
| ExpressionMul

ExpressionMul = ExpressionMul "*" ExpressionUnary --mul
| ExpressionMul "/" ExpressionUnary --div
| ExpressionMul "%" ExpressionUnary --rem
| ExpressionUnary

ExpressionUnary = "-" ExpressionValue --neg
| "+" ExpressionValue --add
| "!" ExpressionValue --not
| ExpressionValue

ExpressionBracket = "(" Expression ")"

// Order is important
Expand Down
12 changes: 6 additions & 6 deletions src/grammar/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ semantics.addOperation<ASTNode>("resolve_expression", {
ref: createRef(this),
});
},
ExpressionCompare_eq(arg0, _arg1, arg2) {
ExpressionEquality_eq(arg0, _arg1, arg2) {
return createNode({
kind: "op_binary",
op: "==",
Expand All @@ -982,7 +982,7 @@ semantics.addOperation<ASTNode>("resolve_expression", {
ref: createRef(this),
});
},
ExpressionCompare_not(arg0, _arg1, arg2) {
ExpressionEquality_not(arg0, _arg1, arg2) {
return createNode({
kind: "op_binary",
op: "!=",
Expand Down Expand Up @@ -1045,7 +1045,7 @@ semantics.addOperation<ASTNode>("resolve_expression", {
ref: createRef(this),
});
},
ExpressionBinary_shr(arg0, _arg1, arg2) {
ExpressionBinaryShift_shr(arg0, _arg1, arg2) {
return createNode({
kind: "op_binary",
op: ">>",
Expand All @@ -1054,7 +1054,7 @@ semantics.addOperation<ASTNode>("resolve_expression", {
ref: createRef(this),
});
},
ExpressionBinary_shl(arg0, _arg1, arg2) {
ExpressionBinaryShift_shl(arg0, _arg1, arg2) {
return createNode({
kind: "op_binary",
op: "<<",
Expand All @@ -1063,7 +1063,7 @@ semantics.addOperation<ASTNode>("resolve_expression", {
ref: createRef(this),
});
},
ExpressionBinary_bin_and(arg0, _arg1, arg2) {
ExpressionBinaryAnd_bin_and(arg0, _arg1, arg2) {
return createNode({
kind: "op_binary",
op: "&",
Expand All @@ -1072,7 +1072,7 @@ semantics.addOperation<ASTNode>("resolve_expression", {
ref: createRef(this),
});
},
ExpressionBinary_bin_or(arg0, _arg1, arg2) {
ExpressionBinaryOr_bin_or(arg0, _arg1, arg2) {
return createNode({
kind: "op_binary",
op: "|",
Expand Down
9 changes: 9 additions & 0 deletions src/test/feature-math.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,5 +388,14 @@ describe("feature-math", () => {
);
}
}

// Test operation precendence

expect(await contract.getPrecendence1()).toBe(12n);
expect(await contract.getPrecendence2()).toBe(4n);
expect(await contract.getPrecendence3()).toBe(12n);
expect(await contract.getPrecendence4()).toBe(12n);
expect(await contract.getPrecendence5()).toBe(5n);
expect(await contract.getPrecendence6()).toBe(0n);
});
});
24 changes: 24 additions & 0 deletions src/test/features/math.tact
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,28 @@ contract MathTester with Deployable {
get fun log(num: Int, base: Int): Int {
return log(num, base);
}

get fun precendence1(): Int {
return 5 & 6 | 1 << 5 + 11 * 3 % 12 >> 11;
}

get fun precendence2(): Int {
return 5 & 6 | 1 << (5 + 11) * 3 % 12 >> 11;
}

get fun precendence3(): Int {
return 5 & 6 | 1 << 5 + 11 * (3 % 12) >> 35;
}

get fun precendence4(): Int {
return 5 & 6 | 1 << 5 + (11 * 3) % 12 >> 11;
}

get fun precendence5(): Int {
return 5 | 6 & 8;
}

get fun precendence6(): Int {
return (5 | 6) & 8;
}
}

0 comments on commit 88e3c38

Please sign in to comment.