Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix operations precendence #265

Merged
merged 3 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}
Loading