Skip to content

Commit

Permalink
unified catchName and catchStatements to single catchBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
i582 committed Jan 20, 2025
1 parent 26cd009 commit bfcddc4
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 85 deletions.
6 changes: 4 additions & 2 deletions src/ast/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,10 @@ export type AstStatementRepeat = {
export type AstStatementTry = {
kind: "statement_try";
statements: AstStatement[];
catchName?: AstId;
catchStatements?: AstStatement[];
catchBlock?: {
catchName: AstId;
catchStatements: AstStatement[];
};
id: number;
loc: SrcInfo;
};
Expand Down
8 changes: 7 additions & 1 deletion src/ast/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,13 @@ export function cloneNode<T extends AstNode>(
return cloneNode({
...src,
statements: src.statements.map(recurse),
catchStatements: (src.catchStatements ?? []).map(recurse),
catchBlock: src.catchBlock
? {
catchName: src.catchBlock.catchName,
catchStatements:
src.catchBlock.catchStatements.map(recurse),
}
: undefined,
});
} else if (src.kind === "statement_foreach") {
return cloneNode({
Expand Down
39 changes: 21 additions & 18 deletions src/ast/compare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,35 +508,38 @@ export class AstComparator {
case "statement_try": {
const {
statements: tryCatchStatements1,
catchName: catchName1,
catchStatements: catchStatements1,
catchBlock: catchBlock1,
} = node1 as AstStatementTry;
const {
statements: tryCatchStatements2,
catchName: catchName2,
catchStatements: catchStatements2,
catchBlock: catchBlock2,
} = node2 as AstStatementTry;

const equal =
this.compareArray(
tryCatchStatements1,
tryCatchStatements2,
) &&
this.compareArray(
catchStatements1 ?? [],
catchStatements2 ?? [],
);

if (!equal) {
if (
!this.compareArray(tryCatchStatements1, tryCatchStatements2)
) {
return false;
}

if (catchName1 === undefined && catchName2 === undefined) {
if (catchBlock1 === undefined && catchBlock2 === undefined) {
return true;
}

if (catchName1 !== undefined && catchName2 !== undefined) {
return this.compare(catchName1, catchName2);
if (catchBlock1 !== undefined && catchBlock2 !== undefined) {
const {
catchName: catchName1,
catchStatements: catchStatements1,
} = catchBlock1;

const {
catchName: catchName2,
catchStatements: catchStatements2,
} = catchBlock2;

return (
this.compare(catchName1, catchName2) &&
this.compareArray(catchStatements1, catchStatements2)
);
}

return false;
Expand Down
9 changes: 7 additions & 2 deletions src/ast/getAstSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,13 @@ export const getAstSchema = (
createNode<A.AstStatementTry>({
kind: "statement_try",
statements,
catchName,
catchStatements,
catchBlock:
catchName !== undefined && catchStatements !== undefined
? {
catchName,
catchStatements,
}
: undefined,
loc: toSrcInfo(loc),
}),
StatementForEach: (
Expand Down
7 changes: 2 additions & 5 deletions src/ast/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,8 @@ export class AstHasher {
case "statement_repeat":
return `${node.kind}|${this.hash(node.iterations)}|${this.hashStatements(node.statements)}`;
case "statement_try":
if (
node.catchName !== undefined &&
node.catchStatements !== undefined
) {
return `${node.kind}|${this.hashStatements(node.statements)}|${this.hash(node.catchName)}|${this.hashStatements(node.catchStatements)}`;
if (node.catchBlock !== undefined) {
return `${node.kind}|${this.hashStatements(node.statements)}|${this.hash(node.catchBlock.catchName)}|${this.hashStatements(node.catchBlock.catchStatements)}`;
}

return `${node.kind}|${this.hashStatements(node.statements)}`;
Expand Down
8 changes: 3 additions & 5 deletions src/ast/iterators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,9 @@ export function traverse(node: AstNode, callback: (node: AstNode) => void) {
node.statements.forEach((e) => {
traverse(e, callback);
});
if (node.catchName !== undefined) {
traverse(node.catchName, callback);
}
if (node.catchStatements !== undefined) {
node.catchStatements.forEach((e) => {
if (node.catchBlock !== undefined) {
traverse(node.catchBlock.catchName, callback);
node.catchBlock.catchStatements.forEach((e) => {
traverse(e, callback);
});
}
Expand Down
11 changes: 8 additions & 3 deletions src/ast/rename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,14 @@ export class AstRenamer {
return {
...stmt,
statements: this.renameStatements(stmt.statements),
catchStatements: this.renameStatements(
stmt.catchStatements ?? [],
),
catchBlock: stmt.catchBlock
? {
catchName: stmt.catchBlock.catchName,
catchStatements: this.renameStatements(
stmt.catchBlock.catchStatements,
),
}
: undefined,
};
case "statement_foreach":
return {
Expand Down
13 changes: 9 additions & 4 deletions src/generator/writers/writeFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,17 +228,22 @@ export function writeStatement(
}
});

if (f.catchName !== undefined && f.catchStatements !== undefined) {
if (isWildcard(f.catchName)) {
const catchBlock = f.catchBlock;
if (catchBlock !== undefined) {
if (isWildcard(catchBlock.catchName)) {
ctx.append(`} catch (_) {`);
} else {
ctx.append(`} catch (_, ${funcIdOf(f.catchName)}) {`);
ctx.append(
`} catch (_, ${funcIdOf(catchBlock.catchName)}) {`,
);
}
ctx.inIndent(() => {
for (const s of f.catchStatements!) {
for (const s of catchBlock.catchStatements!) {
writeStatement(s, self, returns, ctx);
}
});
} else {
ctx.append("} catch (_) { ");
}

ctx.append(`}`);
Expand Down
8 changes: 6 additions & 2 deletions src/grammar/prev/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -989,8 +989,12 @@ semantics.addOperation<AstNode>("astOfStatement", {
return createNode({
kind: "statement_try",
statements: tryBlock.children.map((s) => s.astOfStatement()),
catchName: exitCodeId.astOfExpression(),
catchStatements: catchBlock.children.map((s) => s.astOfStatement()),
catchBlock: {
catchName: exitCodeId.astOfExpression(),
catchStatements: catchBlock.children.map((s) =>
s.astOfStatement(),
),
},
loc: createRef(this),
});
},
Expand Down
12 changes: 6 additions & 6 deletions src/prettyPrinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -790,20 +790,20 @@ export const ppAstStatementForEach: Printer<A.AstStatementForEach> =
]);

export const ppAstStatementTry: Printer<A.AstStatementTry> =
({ statements, catchName, catchStatements }) =>
({ statements, catchBlock }) =>
(c) => {
const catchBlock =
catchStatements !== undefined && catchName !== undefined
const catchBlocks =
catchBlock !== undefined
? [
c.row(` catch (${ppAstId(catchName)}) `),
ppStatementBlock(catchStatements)(c),
c.row(` catch (${ppAstId(catchBlock.catchName)}) `),
ppStatementBlock(catchBlock.catchStatements)(c),
]
: [];

return c.concat([
c.row(`try `),
ppStatementBlock(statements)(c),
...catchBlock,
...catchBlocks,
]);
};

Expand Down
73 changes: 36 additions & 37 deletions src/types/resolveStatements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,48 +581,47 @@ function processStatements(

// try-statement might not return from the current function
// because the control flow can go to the empty catch block
if (s.catchBlock === undefined) {
break;
}

let catchCtx = sctx;
if (s.catchName !== undefined) {
// Process catchName variable for exit code
checkVariableExists(ctx, initialSctx, s.catchName);
catchCtx = addVariable(
s.catchName,
{ kind: "ref", name: "Int", optional: false },
ctx,
initialSctx,
);
}
// Process catchName variable for exit code
checkVariableExists(
ctx,
initialSctx,
s.catchBlock.catchName,
);
catchCtx = addVariable(
s.catchBlock.catchName,
{ kind: "ref", name: "Int", optional: false },
ctx,
initialSctx,
);

if (s.catchStatements !== undefined) {
// Process catch statements
const rCatch = processStatements(
s.catchStatements,
catchCtx,
ctx,
);
ctx = rCatch.ctx;
catchCtx = rCatch.sctx;
// if both catch- and try- blocks always return from the current function
// we mark the whole try-catch statement as always returning
returnAlwaysReachable ||=
r.returnAlwaysReachable &&
rCatch.returnAlwaysReachable;

// Merge statement contexts
const removed: string[] = [];
for (const f of initialSctx.requiredFields) {
if (!catchCtx.requiredFields.find((v) => v === f)) {
removed.push(f);
}
}
for (const r of removed) {
initialSctx = removeRequiredVariable(
r,
initialSctx,
);
// Process catch statements
const rCatch = processStatements(
s.catchBlock.catchStatements,
catchCtx,
ctx,
);
ctx = rCatch.ctx;
catchCtx = rCatch.sctx;
// if both catch- and try- blocks always return from the current function
// we mark the whole try-catch statement as always returning
returnAlwaysReachable ||=
r.returnAlwaysReachable && rCatch.returnAlwaysReachable;

// Merge statement contexts
const removed: string[] = [];
for (const f of initialSctx.requiredFields) {
if (!catchCtx.requiredFields.find((v) => v === f)) {
removed.push(f);
}
}
for (const r of removed) {
initialSctx = removeRequiredVariable(r, initialSctx);
}
}
break;
case "statement_foreach": {
Expand Down

0 comments on commit bfcddc4

Please sign in to comment.