Skip to content

Commit

Permalink
remove separation between statement_let and statement_let_no_type
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusarich committed Jun 11, 2024
1 parent 07cdc25 commit 713da44
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 101 deletions.
30 changes: 5 additions & 25 deletions src/generator/writers/writeFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ export function writeStatement(
return;
} else if (f.kind === "statement_let") {
// Contract/struct case
const t = resolveTypeRef(ctx.ctx, f.type);
const t =
f.type === null
? getExpType(ctx.ctx, f.expression)
: resolveTypeRef(ctx.ctx, f.type);

if (t.kind === "ref") {
const tt = getType(ctx.ctx, t.name);
if (tt.kind === "contract" || tt.kind === "struct") {
Expand All @@ -112,30 +116,6 @@ export function writeStatement(
`${resolveFuncType(t, ctx)} ${id(f.name)} = ${writeCastedExpression(f.expression, t, ctx)};`,
);
return;
} else if (f.kind === "statement_let_no_type") {
const varType = getExpType(ctx.ctx, f.expression);

// Contract/struct case
if (varType.kind === "ref") {
const tt = getType(ctx.ctx, varType.name);
if (tt.kind === "contract" || tt.kind === "struct") {
if (varType.optional) {
ctx.append(
`tuple ${id(f.name)} = ${writeCastedExpression(f.expression, varType, ctx)};`,
);
} else {
ctx.append(
`var ${resolveFuncTypeUnpack(varType, id(f.name), ctx)} = ${writeCastedExpression(f.expression, varType, ctx)};`,
);
}
return;
}
}

ctx.append(
`${resolveFuncType(varType, ctx)} ${id(f.name)} = ${writeCastedExpression(f.expression, varType, ctx)};`,
);
return;
} else if (f.kind === "statement_assign") {
// Prepare lvalue
const path = f.path
Expand Down
16 changes: 1 addition & 15 deletions src/grammar/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,7 @@ export type ASTStatementLet = {
kind: "statement_let";
id: number;
name: string;
type: ASTTypeRef;
expression: ASTExpression;
ref: ASTRef;
};

export type ASTStatementLetNoType = {
kind: "statement_let_no_type";
id: number;
name: string;
type: ASTTypeRef | null;
expression: ASTExpression;
ref: ASTRef;
};
Expand Down Expand Up @@ -538,7 +530,6 @@ export type ASTStatementForEach = {

export type ASTStatement =
| ASTStatementLet
| ASTStatementLetNoType
| ASTStatementReturn
| ASTStatementExpression
| ASTStatementAssign
Expand All @@ -559,7 +550,6 @@ export type ASTNode =
| ASTFunction
| ASTOpCall
| ASTStatementLet
| ASTStatementLetNoType
| ASTStatementReturn
| ASTProgram
| ASTPrimitive
Expand Down Expand Up @@ -739,10 +729,6 @@ export function traverse(node: ASTNode, callback: (node: ASTNode) => void) {
//

if (node.kind === "statement_let") {
traverse(node.type, callback);
traverse(node.expression, callback);
}
if (node.kind === "statement_let_no_type") {
traverse(node.expression, callback);
}
if (node.kind === "statement_return") {
Expand Down
6 changes: 0 additions & 6 deletions src/grammar/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ export function cloneNode<T extends ASTNode>(src: T): T {
expression: cloneNode(src.expression),
});
} else if (src.kind === "statement_let") {
return cloneASTNode({
...src,
type: cloneASTNode(src.type),
expression: cloneNode(src.expression),
});
} else if (src.kind === "statement_let_no_type") {
return cloneASTNode({
...src,
expression: cloneNode(src.expression),
Expand Down
3 changes: 1 addition & 2 deletions src/grammar/grammar.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ Tact {

StatementBlock = "{" Statement* "}"

StatementLet = let id ":" Type "=" Expression ";" --withType
| let id "=" Expression ";" --withoutType
StatementLet = let id (":" Type)? "=" Expression ";"

StatementReturn = return Expression? ";"

Expand Down
22 changes: 2 additions & 20 deletions src/grammar/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,35 +571,17 @@ semantics.addOperation<ASTNode>("astOfDeclaration", {
semantics.addOperation<ASTNode>("astOfStatement", {
// TODO: process StatementBlock

StatementLet_withType(
_letKwd,
id,
_colon,
type,
_equals,
expression,
_semicolon,
) {
StatementLet(_letKwd, id, _colon, type, _equals, expression, _semicolon) {
checkVariableName(id.sourceString, createRef(id));

return createNode({
kind: "statement_let",
name: id.sourceString,
type: type.astOfType(),
type: unwrapOptNode(type, (t) => t.astOfType()),
expression: expression.astOfExpression(),
ref: createRef(this),
});
},
StatementLet_withoutType(_arg0, arg1, _arg2, arg3, _arg4) {
checkVariableName(arg1.sourceString, createRef(arg1));

return createNode({
kind: "statement_let_no_type",
name: arg1.sourceString,
expression: arg3.astOfExpression(),
ref: createRef(this),
});
},
StatementReturn(_returnKwd, optExpression, _semicolon) {
return createNode({
kind: "statement_return",
Expand Down
33 changes: 20 additions & 13 deletions src/test/feature-local-type-inference.spec.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
import { toNano } from '@ton/core';
import { ContractSystem } from '@tact-lang/emulator';
import { __DANGER_resetNodeId } from '../grammar/ast';
import { LocalTypeInferenceTester } from './features/output/local-type-inference_LocalTypeInferenceTester';
import { toNano } from "@ton/core";
import { ContractSystem } from "@tact-lang/emulator";
import { __DANGER_resetNodeId } from "../grammar/ast";
import { LocalTypeInferenceTester } from "./features/output/local-type-inference_LocalTypeInferenceTester";

describe('feature-local-type-inference', () => {
describe("feature-local-type-inference", () => {
beforeEach(() => {
__DANGER_resetNodeId();
});
it('should automatically set types for let statements', async () => {

it("should automatically set types for let statements", async () => {
// Init
const system = await ContractSystem.create();
const treasure = system.treasure('treasure');
const treasure = system.treasure("treasure");
const contract = system.open(await LocalTypeInferenceTester.fromInit());
await contract.send(treasure, { value: toNano('10') }, { $$type: 'Deploy', queryId: 0n });
await contract.send(
treasure,
{ value: toNano("10") },
{ $$type: "Deploy", queryId: 0n },
);
await system.run();

expect(contract.abi).toMatchSnapshot();
expect(await contract.getTest1()).toStrictEqual(1n);
expect(await contract.getTest2()).toStrictEqual(2n);
expect((await contract.getTest3()).toRawString()).toBe(contract.address.toRawString());
expect((await contract.getTest4()).toRawString()).toBe(contract.address.toRawString());
expect((await contract.getTest3()).toRawString()).toBe(
contract.address.toRawString(),
);
expect((await contract.getTest4()).toRawString()).toBe(
contract.address.toRawString(),
);
expect(await contract.getTest5()).toStrictEqual(true);
});
});
});
32 changes: 12 additions & 20 deletions src/types/resolveStatements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,33 +170,25 @@ function processStatements(
// Process expression
ctx = resolveExpression(s.expression, sctx, ctx);

// Check type
const expressionType = getExpType(ctx, s.expression);
const variableType = resolveTypeRef(ctx, s.type);
if (!isAssignable(expressionType, variableType)) {
throwError(
`Type mismatch: "${printTypeRef(expressionType)}" is not assignable to "${printTypeRef(variableType)}"`,
s.ref,
);
}

// Add variable to statement context
// Check variable name
if (sctx.vars.has(s.name)) {
throwError(`Variable "${s.name}" already exists`, s.ref);
}
sctx = addVariable(s.name, variableType, sctx);
} else if (s.kind === "statement_let_no_type") {
// Process expression
ctx = resolveExpression(s.expression, sctx, ctx);

// Check type
const expressionType = getExpType(ctx, s.expression);

// Add variable to statement context
if (sctx.vars.has(s.name)) {
throwError(`Variable already exists: ${s.name}`, s.ref);
if (s.type !== null) {
const variableType = resolveTypeRef(ctx, s.type);
if (!isAssignable(expressionType, variableType)) {
throwError(
`Type mismatch: "${printTypeRef(expressionType)}" is not assignable to "${printTypeRef(variableType)}"`,
s.ref,
);
}
sctx = addVariable(s.name, variableType, sctx);
} else {
sctx = addVariable(s.name, expressionType, sctx);
}
sctx = addVariable(s.name, expressionType, sctx);
} else if (s.kind === "statement_assign") {
// Process lvalue
ctx = resolveLValueRef(s.path, sctx, ctx);
Expand Down

0 comments on commit 713da44

Please sign in to comment.