Skip to content

Commit

Permalink
feat: constant evaluation of newAddress (tact-lang#237)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusarich authored Apr 17, 2024
1 parent fab39a0 commit d73a836
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The implicit empty `init` function is now present by default in the contract if not declared: PR [#167](https://github.com/tact-lang/tact/pull/167)
- `@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)

### Fixed

Expand Down
35 changes: 35 additions & 0 deletions src/test/feature-constants.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { toNano } from "@ton/core";
import { ContractSystem } from "@tact-lang/emulator";
import { __DANGER_resetNodeId } from "../grammar/ast";
import { ConstantTester } from "./features/output/constants_ConstantTester";

describe("feature-constants", () => {
beforeEach(() => {
__DANGER_resetNodeId();
});
it("should implement constants correctly", async () => {
// Init
const system = await ContractSystem.create();
const treasure = system.treasure("treasure");
const contract = system.open(await ConstantTester.fromInit());
await contract.send(treasure, { value: toNano("10") }, null);
await system.run();

// Check methods
expect(await contract.getSomething1()).toEqual(11n);
expect(await contract.getSomething2()).toBeNull();
expect(await contract.getSomething3()).toEqual(toNano("123"));
expect(await contract.getSomething4()).toEqual(toNano("456"));
expect(await contract.getSomething5()).toEqual("Hello world!");
expect(await contract.getSomething6()).toEqual(10n);
expect(await contract.getSomething7()).toEqual(5n);
expect(await contract.getSomething8()).toEqual(4n);
expect((await contract.getSomething9()).toRawString()).toEqual(
"0:4a81708d2cf7b15a1b362fbf64880451d698461f52f05f145b36c08517d76873",
);
expect((await contract.getSomething10()).toRawString()).toEqual(
"0:4a81708d2cf7b15a1b362fbf64880451d698461f52f05f145b36c08517d76873",
);
expect(await contract.getGlobalConst()).toEqual(100n);
});
});
14 changes: 14 additions & 0 deletions src/test/features/constants.tact
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ contract ConstantTester {
const something6: Int = 10 * 1;
const something7: Int = 10 >> 1;
const something8: Int = (2 + 4) & 4;
const something9: Address = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");
const something10: Address = newAddress(0, 0x4a81708d2cf7b15a1b362fbf64880451d698461f52f05f145b36c08517d76873);

init() {

}

receive() {

}

get fun something1(): Int {
return self.something1;
}
Expand Down Expand Up @@ -46,6 +52,14 @@ contract ConstantTester {
return self.something8;
}

get fun something9(): Address {
return self.something9;
}

get fun something10(): Address {
return self.something10;
}

get fun globalConst(): Int {
return someGlobalConst;
}
Expand Down
23 changes: 23 additions & 0 deletions src/types/resolveConstantValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,29 @@ function reduceAddress(ast: ASTExpression, ctx: CompilerContext): Address {
}
return address;
}
} else if (ast.name === "newAddress") {
if (ast.args.length === 2) {
const wc = reduceInt(ast.args[0]);
const addr = Buffer.from(
reduceInt(ast.args[1]).toString(16),
"hex",
);
if (wc !== 0n && wc !== -1n) {
throwError(
`Expected workchain to equal 0 or -1, received: ${wc}`,
ast.ref,
);
}
if (!enabledMasterchain(ctx)) {
if (wc !== 0n) {
throwError(
`Address ${wc}:${addr} from masterchain are not enabled for this contract`,
ast.ref,
);
}
}
return new Address(parseInt(wc.toString()), addr);
}
}
}
throwError("Cannot reduce expression to a constant Address", ast.ref);
Expand Down

0 comments on commit d73a836

Please sign in to comment.