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 2 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 @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `@stdlib/stoppable` now imports `@stdlib/ownable` so the programmer does not have to do it separately: PR [#193](https://github.com/tact-lang/tact/pull/193)
- Support escape sequences for strings (`\\`, `\"`, `\n`, `\r`, `\t`, `\v`, `\b`, `\f`, `\u{0}` through `\u{FFFFFF}`, `\u0000` through `\uFFFF`, `\x00` through `\xFF`): PR [#192](https://github.com/tact-lang/tact/pull/192)
- `newAddress` function now evaluates to a constant value if possible: PR [#237](https://github.com/tact-lang/tact/pull/237)
- Operation precendence now matches with JavaScript rules: PR [#265](https://github.com/tact-lang/tact/pull/265)
Gusarich marked this conversation as resolved.
Show resolved Hide resolved
Gusarich marked this conversation as resolved.
Show resolved Hide resolved

### Fixed

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
28 changes: 28 additions & 0 deletions src/test/feature-precendence.spec.ts
Gusarich marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { toNano } from "@ton/core";
import { ContractSystem } from "@tact-lang/emulator";
import { __DANGER_resetNodeId } from "../grammar/ast";
import { PrecendenceTester } from "./features/output/precendence_PrecendenceTester";

describe("feature-precendence", () => {
beforeEach(() => {
__DANGER_resetNodeId();
});
it("should implement precendence of operations correctly", async () => {
// Init
const system = await ContractSystem.create();
const treasure = system.treasure("treasure");
const contract = system.open(await PrecendenceTester.fromInit());
await contract.send(
treasure,
{ value: toNano("10") },
{ $$type: "Deploy", queryId: 0n },
);
await system.run();

// Check methods
expect(await contract.getTest1()).toEqual(12n);
expect(await contract.getTest2()).toEqual(4n);
expect(await contract.getTest3()).toEqual(12n);
expect(await contract.getTest4()).toEqual(12n);
});
});
23 changes: 23 additions & 0 deletions src/test/features/precendence.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import "@stdlib/deploy";

contract PrecendenceTester with Deployable {
init() {

}

get fun test1(): Int {
return 5 & 6 | 1 << 5 + 11 * 3 % 12 >> 11;
Gusarich marked this conversation as resolved.
Show resolved Hide resolved
}

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

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

get fun test4(): Int {
return 5 & 6 | 1 << 5 + (11 * 3) % 12 >> 11;
}
}
8 changes: 8 additions & 0 deletions tact.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,14 @@
"debug": true
}
},
{
"name": "precendence",
"path": "./src/test/features/precendence.tact",
"output": "./src/test/features/output",
"options": {
"debug": true
}
},
{
"name": "ternary",
"path": "./src/test/features/ternary.tact",
Expand Down
Loading