Skip to content

Commit

Permalink
feat: block statements (#1334)
Browse files Browse the repository at this point in the history
  • Loading branch information
i582 authored Jan 14, 2025
1 parent 86995ce commit 90b1f35
Show file tree
Hide file tree
Showing 30 changed files with 838 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `VarInt16`, `VarInt32`, `VarUint16`, `VarUint32` integer serialization types: PR [#1186](https://github.com/tact-lang/tact/pull/1186)
- `unboc`: a standalone CLI utility to expose Tact's TVM disassembler: PR [#1259](https://github.com/tact-lang/tact/pull/1259)
- Added alternative parser: PR [#1258](https://github.com/tact-lang/tact/pull/1258)
- Support for block statements: PR [#1334](https://github.com/tact-lang/tact/pull/1334)

### Changed

Expand Down
10 changes: 9 additions & 1 deletion src/ast/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ export type AstStatement =
| AstStatementTry
| AstStatementTryCatch
| AstStatementForEach
| AstStatementDestruct;
| AstStatementDestruct
| AstStatementBlock;

export type AstStatementLet = {
kind: "statement_let";
Expand Down Expand Up @@ -334,6 +335,13 @@ export type AstStatementDestruct = {
loc: SrcInfo;
};

export type AstStatementBlock = {
kind: "statement_block";
statements: AstStatement[];
id: number;
loc: SrcInfo;
};

//
// Types
//
Expand Down
5 changes: 5 additions & 0 deletions src/ast/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export function cloneNode<T extends AstNode>(
: null,
elseif: src.elseif ? recurse(src.elseif) : null,
});
} else if (src.kind === "statement_block") {
return cloneNode({
...src,
statements: src.statements.map(recurse),
});
} else if (src.kind === "struct_field_initializer") {
return cloneNode({
...src,
Expand Down
7 changes: 7 additions & 0 deletions src/ast/compare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
AstAsmInstruction,
AstDestructMapping,
AstStatementDestruct,
AstStatementBlock,
} from "./ast";
import { AstRenamer } from "./rename";
import { throwInternalCompilerError } from "../error/errors";
Expand Down Expand Up @@ -611,6 +612,12 @@ export class AstComparator {
);
}

case "statement_block": {
const { statements: statements1 } = node1 as AstStatementBlock;
const { statements: statements2 } = node2 as AstStatementBlock;
return this.compareArray(statements1, statements2);
}

case "type_id": {
const { text: typeIdText1 } = node1 as AstTypeId;
const { text: typeIdText2 } = node2 as AstTypeId;
Expand Down
9 changes: 9 additions & 0 deletions src/ast/getAstSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,15 @@ export const getAstSchema = (
statements,
loc: toSrcInfo(loc),
}),
StatementBlock: (
statements: A.AstStatement[],
loc: Loc,
): A.AstStatementBlock =>
createNode<A.AstStatementBlock>({
kind: "statement_block",
statements,
loc: toSrcInfo(loc),
}),
TypeId: (text: string, loc: Loc): A.AstTypeId =>
createNode<A.AstTypeId>({
kind: "type_id",
Expand Down
4 changes: 4 additions & 0 deletions src/ast/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ export class AstHasher {
return `${node.kind}|${this.hash(node.map)}|${this.hashStatements(node.statements)}`;
case "statement_destruct":
return `${node.kind}|${this.hash(node.type)}|${this.hashDestructIdentifiers(Array.from(node.identifiers.values()))}|${this.hash(node.expression)}`;
case "statement_block": {
const statementsHash = this.hashStatements(node.statements);
return `${node.kind}|${statementsHash}`;
}
// Expressions
case "op_binary":
return `${node.kind}|${node.op}|${this.hash(node.left)}|${this.hash(node.right)}`;
Expand Down
5 changes: 5 additions & 0 deletions src/ast/iterators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ export function traverse(node: AstNode, callback: (node: AstNode) => void) {
traverse(e, callback);
});
break;
case "statement_block":
node.statements.forEach((e) => {
traverse(e, callback);
});
break;
case "destruct_mapping":
traverse(node.field, callback);
traverse(node.name, callback);
Expand Down
6 changes: 6 additions & 0 deletions src/generator/writers/writeFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,12 @@ export function writeStatement(
);
return;
}
case "statement_block": {
for (const s of f.statements) {
writeStatement(s, self, returns, ctx);
}
return;
}
}

throw Error("Unknown statement kind");
Expand Down
201 changes: 201 additions & 0 deletions src/grammar/next/__snapshots__/grammar.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,84 @@ exports[`grammar should parse abstract-const 1`] = `
}
`;
exports[`grammar should parse block-statements 1`] = `
{
"id": 10,
"imports": [],
"items": [
{
"attributes": [],
"id": 9,
"kind": "function_def",
"loc": fun foo() {
let x = 100;
{
let y = 200;
}
},
"name": {
"id": 1,
"kind": "id",
"loc": foo,
"text": "foo",
},
"params": [],
"return": null,
"statements": [
{
"expression": {
"base": 10,
"id": 3,
"kind": "number",
"loc": 100,
"value": 100n,
},
"id": 4,
"kind": "statement_let",
"loc": let x = 100;,
"name": {
"id": 2,
"kind": "id",
"loc": x,
"text": "x",
},
"type": null,
},
{
"id": 8,
"kind": "statement_block",
"loc": {
let y = 200;
},
"statements": [
{
"expression": {
"base": 10,
"id": 6,
"kind": "number",
"loc": 200,
"value": 200n,
},
"id": 7,
"kind": "statement_let",
"loc": let y = 200;,
"name": {
"id": 5,
"kind": "id",
"loc": y,
"text": "y",
},
"type": null,
},
],
},
],
},
],
"kind": "module",
}
`;
exports[`grammar should parse case-35 1`] = `
{
"id": 7,
Expand Down Expand Up @@ -6782,6 +6860,129 @@ exports[`grammar should parse literals-int-underscores-bin-dec-hex-oct 1`] = `
}
`;
exports[`grammar should parse nested-block-statements 1`] = `
{
"id": 13,
"imports": [],
"items": [
{
"attributes": [],
"id": 12,
"kind": "function_def",
"loc": fun foo() {
let x = 100;
{
{
{
{
let y = 200;
}
}
}
}
},
"name": {
"id": 1,
"kind": "id",
"loc": foo,
"text": "foo",
},
"params": [],
"return": null,
"statements": [
{
"expression": {
"base": 10,
"id": 3,
"kind": "number",
"loc": 100,
"value": 100n,
},
"id": 4,
"kind": "statement_let",
"loc": let x = 100;,
"name": {
"id": 2,
"kind": "id",
"loc": x,
"text": "x",
},
"type": null,
},
{
"id": 11,
"kind": "statement_block",
"loc": {
{
{
{
let y = 200;
}
}
}
},
"statements": [
{
"id": 10,
"kind": "statement_block",
"loc": {
{
{
let y = 200;
}
}
},
"statements": [
{
"id": 9,
"kind": "statement_block",
"loc": {
{
let y = 200;
}
},
"statements": [
{
"id": 8,
"kind": "statement_block",
"loc": {
let y = 200;
},
"statements": [
{
"expression": {
"base": 10,
"id": 6,
"kind": "number",
"loc": 200,
"value": 200n,
},
"id": 7,
"kind": "statement_let",
"loc": let y = 200;,
"name": {
"id": 5,
"kind": "id",
"loc": y,
"text": "y",
},
"type": null,
},
],
},
],
},
],
},
],
},
],
},
],
"kind": "module",
}
`;
exports[`grammar should parse stmt-augmented-assign-arith 1`] = `
{
"id": 94,
Expand Down
14 changes: 5 additions & 9 deletions src/grammar/next/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import * as $ from "@tonstudio/parser-runtime";
import * as A from "../../ast/ast";
import * as G from "./grammar";
import type { $ast } from "./grammar";
import {
TactCompilationError,
throwInternalCompilerError,
} from "../../error/errors";
import { $ast } from "./grammar";
import { TactCompilationError } from "../../error/errors";
import { SyntaxErrors, syntaxErrorSchema } from "../parser-error";
import { AstSchema, getAstSchema } from "../../ast/getAstSchema";
import { getSrcInfo, ItemOrigin } from "../src-info";
Expand Down Expand Up @@ -475,10 +472,9 @@ const parseStatementDestruct =
};

const parseStatementBlock =
(_node: $ast.StatementBlock): Handler<never> =>
() => {
// TODO: process StatementBlock
throwInternalCompilerError("Block statements are not supported");
({ body, loc }: $ast.StatementBlock): Handler<A.AstStatementBlock> =>
(ctx) => {
return ctx.ast.StatementBlock(parseStatements(body)(ctx), loc);
};

const parseStatementReturn =
Expand Down
Loading

0 comments on commit 90b1f35

Please sign in to comment.