Skip to content

Commit

Permalink
feat(irBuilder): Support try and try-catch statements
Browse files Browse the repository at this point in the history
Closes #40
  • Loading branch information
byakuren-hijiri committed Jul 29, 2024
1 parent 9385648 commit 94aa43a
Show file tree
Hide file tree
Showing 19 changed files with 305 additions and 19 deletions.
42 changes: 42 additions & 0 deletions src/internals/tactIRBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,13 @@ export class AstMapper {
case "statement_foreach":
stmt.statements.forEach((s) => this.processStmt(s));
break;
case "statement_try":
stmt.statements.forEach((s) => this.processStmt(s));
break;
case "statement_try_catch":
stmt.statements.forEach((s) => this.processStmt(s));
stmt.catchStatements.forEach((s) => this.processStmt(s));
break;
default:
throw InternalException.make("Unsupported statement", { node: stmt });
}
Expand Down Expand Up @@ -649,6 +656,41 @@ export class TactIRBuilder {
}
// Connect condition with the statement after loop.
lastNodeIdxes = [newNode.idx];
} else if (
stmt.kind === "statement_try" ||
stmt.kind === "statement_try_catch"
) {
// Process the try branch.
const [tryNodes, tryEdges] = this.processStatements(
stmt.statements,
nodes,
edges,
[newNode.idx],
);
nodes = tryNodes;
edges = tryEdges;
// Connect the last try block with statements after this `try` block or
// with `try` itself if it is empty.
lastNodeIdxes =
tryNodes.length > 0
? [tryNodes[tryNodes.length - 1].idx]
: [newNode.idx];

// Handle the `catch` clause.
if (stmt.kind === "statement_try_catch") {
const [catchNodes, catchEdges] = this.processStatements(
stmt.catchStatements,
nodes,
edges,
[newNode.idx],
);
nodes = catchNodes;
edges = catchEdges;
// Catch block always terminates execution.
if (catchNodes.length > 0) {
tryNodes[tryNodes.length - 1].kind = { kind: "return" };
}
}
} else if (stmt.kind === "statement_return") {
// No need to connect return statements to subsequent nodes
lastNodeIdxes = [];
Expand Down
13 changes: 13 additions & 0 deletions test/contracts/try-1.cfg.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
digraph "try-1" {
node [shape=box];
subgraph "cluster_test" {
label="test";
"test_141" [label="let a: Int = 42"];
"test_142" [label="try"];
"test_144" [label="a += 1"];
"test_146" [label="return 42",style=filled,fillcolor="#66A7DB"];
"test_141" -> "test_142";
"test_142" -> "test_144";
"test_144" -> "test_146";
}
}
66 changes: 66 additions & 0 deletions test/contracts/try-1.cfg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"projectName": "try-1",
"functions": [
{
"name": "test",
"cfg": {
"nodes": [
{
"id": 141,
"stmtID": 58765,
"srcEdges": [],
"dstEdges": [
143
]
},
{
"id": 142,
"stmtID": 58769,
"srcEdges": [
143
],
"dstEdges": [
145
]
},
{
"id": 144,
"stmtID": 58768,
"srcEdges": [
145
],
"dstEdges": [
147
]
},
{
"id": 146,
"stmtID": 58771,
"srcEdges": [
147
],
"dstEdges": []
}
],
"edges": [
{
"id": 143,
"src": 141,
"dst": 142
},
{
"id": 145,
"src": 142,
"dst": 144
},
{
"id": 147,
"src": 144,
"dst": 146
}
]
}
}
],
"contracts": []
}
1 change: 1 addition & 0 deletions test/contracts/try-1.expected.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

7 changes: 7 additions & 0 deletions test/contracts/try-1.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fun test(): Int {
let a: Int = 42;
try {
a += 1;
}
return 42;
}
9 changes: 9 additions & 0 deletions test/contracts/try-2.cfg.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
digraph "try-2" {
node [shape=box];
subgraph "cluster_test" {
label="test";
"test_141" [label="try"];
"test_142" [label="return 42",style=filled,fillcolor="#66A7DB"];
"test_141" -> "test_142";
}
}
36 changes: 36 additions & 0 deletions test/contracts/try-2.cfg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"projectName": "try-2",
"functions": [
{
"name": "test",
"cfg": {
"nodes": [
{
"id": 141,
"stmtID": 61840,
"srcEdges": [],
"dstEdges": [
143
]
},
{
"id": 142,
"stmtID": 61842,
"srcEdges": [
143
],
"dstEdges": []
}
],
"edges": [
{
"id": 143,
"src": 141,
"dst": 142
}
]
}
}
],
"contracts": []
}
1 change: 1 addition & 0 deletions test/contracts/try-2.expected.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

5 changes: 5 additions & 0 deletions test/contracts/try-2.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fun test(): Int {
try { /* empty */ }
return 42;
}

15 changes: 15 additions & 0 deletions test/contracts/try-3.cfg.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
digraph "try-3" {
node [shape=box];
subgraph "cluster_test" {
label="test";
"test_141" [label="let a: Int = 0"];
"test_142" [label="try ... catch (err)"];
"test_144" [label="a = 19"];
"test_146" [label="dump(err)",style=filled,fillcolor="#66A7DB"];
"test_148" [label="return a",style=filled,fillcolor="#66A7DB"];
"test_141" -> "test_142";
"test_142" -> "test_144";
"test_142" -> "test_146";
"test_144" -> "test_148";
}
}
80 changes: 80 additions & 0 deletions test/contracts/try-3.cfg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"projectName": "try-3",
"functions": [
{
"name": "test",
"cfg": {
"nodes": [
{
"id": 141,
"stmtID": 64907,
"srcEdges": [],
"dstEdges": [
143
]
},
{
"id": 142,
"stmtID": 64916,
"srcEdges": [
143
],
"dstEdges": [
145,
147
]
},
{
"id": 144,
"stmtID": 64910,
"srcEdges": [
145
],
"dstEdges": [
149
]
},
{
"id": 146,
"stmtID": 64915,
"srcEdges": [
147
],
"dstEdges": []
},
{
"id": 148,
"stmtID": 64918,
"srcEdges": [
149
],
"dstEdges": []
}
],
"edges": [
{
"id": 143,
"src": 141,
"dst": 142
},
{
"id": 145,
"src": 142,
"dst": 144
},
{
"id": 147,
"src": 142,
"dst": 146
},
{
"id": 149,
"src": 144,
"dst": 148
}
]
}
}
],
"contracts": []
}
1 change: 1 addition & 0 deletions test/contracts/try-3.expected.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

10 changes: 10 additions & 0 deletions test/contracts/try-3.tact
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fun test(): Int {
let a: Int = 0;
try {
a = 19;
} catch (err) {
dump(err);
}
return a;
}

6 changes: 3 additions & 3 deletions test/contracts/unbound-loop-1.cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
"nodes": [
{
"id": 141,
"stmtID": 58765,
"stmtID": 67995,
"srcEdges": [],
"dstEdges": [
143
]
},
{
"id": 142,
"stmtID": 58769,
"stmtID": 67999,
"srcEdges": [
143,
144
Expand All @@ -27,7 +27,7 @@
},
{
"id": 145,
"stmtID": 58771,
"stmtID": 68001,
"srcEdges": [
146
],
Expand Down
6 changes: 3 additions & 3 deletions test/contracts/unbound-loop-2.cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
"nodes": [
{
"id": 141,
"stmtID": 61843,
"stmtID": 71073,
"srcEdges": [],
"dstEdges": [
143
]
},
{
"id": 142,
"stmtID": 61847,
"stmtID": 71077,
"srcEdges": [
143,
144
Expand All @@ -27,7 +27,7 @@
},
{
"id": 145,
"stmtID": 61849,
"stmtID": 71079,
"srcEdges": [
146
],
Expand Down
Loading

0 comments on commit 94aa43a

Please sign in to comment.