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

Expand reduceBool and add reduceSlice #197

Closed
wants to merge 4 commits into from
Closed
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 @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Update the `dump` function to handle addresses: PR [#175](https://github.com/tact-lang/tact/pull/175)
- 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)
- Improved `Bool` reduction in constant expressions: PR [#195](https://github.com/tact-lang/tact/pull/195)
Gusarich marked this conversation as resolved.
Show resolved Hide resolved

### Fixed

Expand Down
62 changes: 55 additions & 7 deletions src/types/resolveConstantValue.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Address, Cell, toNano } from "@ton/core";
import { Address, Cell, Slice, toNano } from "@ton/core";
import { enabledMasterchain } from "../config/features";
import { CompilerContext } from "../context";
import { ASTExpression, throwError } from "../grammar/ast";
import { printTypeRef, TypeRef } from "./types";
import { sha256_sync } from "@ton/crypto";
import { getExpType } from "./resolveExpression";

function reduceInt(ast: ASTExpression): bigint {
if (ast.kind === 'number') {
Expand Down Expand Up @@ -59,22 +60,51 @@ function reduceInt(ast: ASTExpression): bigint {
throwError('Cannot reduce expression to a constant integer', ast.ref);
}

function reduceBool(ast: ASTExpression): boolean {
function reduceBool(ast: ASTExpression, ctx: CompilerContext): boolean {
if (ast.kind === 'boolean') {
return ast.value;
}
if (ast.kind === 'op_unary') {
if (ast.op === '!') {
return !reduceBool(ast.right);
return !reduceBool(ast.right, ctx);
}
}
if (ast.kind === 'op_binary') {
if (ast.op === '&&') {
return reduceBool(ast.left) && reduceBool(ast.right);
return reduceBool(ast.left, ctx) && reduceBool(ast.right, ctx);
} else if (ast.op === '||') {
return reduceBool(ast.left) || reduceBool(ast.right);
return reduceBool(ast.left, ctx) || reduceBool(ast.right, ctx);
} else {
const leftType = getExpType(ctx, ast.left);
const rightType = getExpType(ctx, ast.right);
if (ast.op === '>') {
return reduceInt(ast.left) > reduceInt(ast.right);
} else if (ast.op === '<') {
return reduceInt(ast.left) < reduceInt(ast.right);
} else if (ast.op === '>=') {
return reduceInt(ast.left) >= reduceInt(ast.right);
} else if (ast.op === '<=') {
return reduceInt(ast.left) <= reduceInt(ast.right);
} else if (ast.op === '==') {
if (leftType.kind === 'ref' && rightType.kind === 'ref') {
Gusarich marked this conversation as resolved.
Show resolved Hide resolved
if (leftType.name === 'Address' && rightType.name === 'Address') {
return reduceAddress(ast.left, ctx).equals(reduceAddress(ast.right, ctx));
} else if (leftType.name === 'Cell' && rightType.name === 'Cell') {
return reduceCell(ast.left).equals(reduceCell(ast.right));
} else if (leftType.name === 'String' && rightType.name === 'String') {
return reduceString(ast.left) === reduceString(ast.right);
} else if (leftType.name === 'Int' && rightType.name === 'Int') {
return reduceInt(ast.left) === reduceInt(ast.right);
} else if (leftType.name === 'Bool' && rightType.name === 'Bool') {
return reduceBool(ast.left, ctx) === reduceBool(ast.right, ctx);
} else if (leftType.name === 'Slice' && rightType.name === 'Slice') {
return reduceSlice(ast.left).asCell().equals(reduceSlice(ast.right).asCell());
}
} else if (leftType.kind === 'null' && rightType.kind === 'null') {
return true;
Gusarich marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
// TODO: More cases
}

throwError('Cannot reduce expression to a constant boolean', ast.ref);
Expand Down Expand Up @@ -126,6 +156,24 @@ function reduceCell(ast: ASTExpression): Cell {
throwError('Cannot reduce expression to a constant Cell', ast.ref);
}

function reduceSlice(ast: ASTExpression): Slice {
if (ast.kind === 'op_static_call') {
if (ast.name === 'slice') {
Gusarich marked this conversation as resolved.
Show resolved Hide resolved
if (ast.args.length === 1) {
const str = reduceString(ast.args[0]);
let c: Cell;
try {
c = Cell.fromBase64(str);
} catch (e) {
throwError(`Invalid cell ${str}`, ast.ref);
}
return c.asSlice();
}
}
}
throwError('Cannot reduce expression to a constant Slice', ast.ref);
}

export function resolveConstantValue(type: TypeRef, ast: ASTExpression | null, ctx: CompilerContext) {
if (ast === null) {
return undefined;
Expand All @@ -149,7 +197,7 @@ export function resolveConstantValue(type: TypeRef, ast: ASTExpression | null, c

// Handle bool
if (type.name === 'Bool') {
return reduceBool(ast);
return reduceBool(ast, ctx);
}

// Handle string
Expand Down
Loading