Skip to content

Commit 7949cc6

Browse files
committed
Add temporary(?) patch for yul node IDs.
It is possible to generate IDs during AST processing by performing a deep search for the last ID in all the original source units; however, this breaks the current tests for the copy method in ASTNodeFactory, which expect hard-coded IDs for specific nodes. Since they are created *after* all of the original source units are processed, and those all have independent contexts, this does not seem like an actual issue or breaking change for consumers. Until the tests are updated or a better mechanism is determined, the current workaround is to offset yul AST nodes by 100000.
1 parent ac350d8 commit 7949cc6

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

src/ast/ast_node_factory.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ import {
8585
YulLiteral,
8686
YulIdentifier,
8787
YulFunctionCall,
88-
YulTypedName
88+
YulTypedName,
89+
isYulASTNode
8990
} from "./implementation/yul";
9091

9192
/**
@@ -821,12 +822,14 @@ export class ASTNodeFactory {
821822
postprocessor: ASTPostprocessor;
822823

823824
private lastId: number;
825+
private lastYulId: number;
824826

825827
constructor(context = new ASTContext(), postprocessor = new ASTPostprocessor()) {
826828
this.context = context;
827829
this.postprocessor = postprocessor;
828830

829831
this.lastId = context.lastId;
832+
this.lastYulId = context.lastYulId;
830833
}
831834

832835
makeYulAssignment(
@@ -1288,7 +1291,8 @@ export class ASTNodeFactory {
12881291
type: ASTNodeConstructor<T>,
12891292
...args: Specific<ConstructorParameters<typeof type>>
12901293
): T {
1291-
const node = new type(++this.lastId, "0:0:0", ...args);
1294+
const id = isYulASTNode(type.prototype) ? ++this.lastYulId : ++this.lastId;
1295+
const node = new type(id, "0:0:0", ...args);
12921296

12931297
this.context.register(node);
12941298

src/ast/ast_reader.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
// import { deepFindIn } from "../misc";
12
import { ASTNode, ASTNodeConstructor } from "./ast_node";
23
import { SourceUnit } from "./implementation/meta/source_unit";
4+
import { isYulASTNode } from "./implementation/yul";
35
import { LegacyConfiguration } from "./legacy";
46
import { ModernConfiguration } from "./modern";
57
import { DefaultNodePostprocessorList } from "./postprocessing";
@@ -45,6 +47,12 @@ export class ASTContext {
4547
*/
4648
id = contextIdSequence.next().value;
4749

50+
/**
51+
* Temporary workaround
52+
*/
53+
readonly yulIdStart = 1e5;
54+
lastYulId = this.yulIdStart;
55+
4856
/**
4957
* Map from ID number to the `AST` node with same ID in tree
5058
*/
@@ -61,6 +69,9 @@ export class ASTContext {
6169
let last = 0;
6270

6371
for (const id of this.map.keys()) {
72+
if (id >= this.yulIdStart) {
73+
continue;
74+
}
6475
if (id > last) {
6576
last = id;
6677
}
@@ -75,6 +86,9 @@ export class ASTContext {
7586

7687
register(...nodes: ASTNode[]): void {
7788
for (const node of nodes) {
89+
if (node.id === undefined && isYulASTNode(node)) {
90+
node.id = ++this.lastYulId;
91+
}
7892
if (this.map.has(node.id)) {
7993
throw new Error(`The id ${node.id} is already taken for the context`);
8094
}
@@ -190,6 +204,19 @@ export class ASTReader {
190204
const rootNodeTypeName = "SourceUnit";
191205
const result: SourceUnit[] = [];
192206

207+
// const nodes = entries.map((e) => e[1]);
208+
// const hasAssemblyAST = deepFindIn(
209+
// nodes,
210+
// "nodeType",
211+
// (node: any) => node.nodeType.startsWith("Yul"),
212+
// true
213+
// );
214+
// if (hasAssemblyAST) {
215+
// const ids = deepFindIn(nodes, "id", (id) => typeof id === "number");
216+
// const lastId = Math.max(...ids);
217+
// this.context.lastOriginalId = lastId;
218+
// }
219+
193220
for (const [key, content] of entries) {
194221
let ast;
195222

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import expect from "expect";
2+
import { deepFindIn } from "../../../../src";
3+
4+
const testObject = {
5+
type: "SourceUnit",
6+
id: 0,
7+
children: [
8+
{
9+
id: 2,
10+
type: "FunctionDefinition",
11+
vParameters: {
12+
a: 1,
13+
b: 3,
14+
c: {
15+
id: 1
16+
}
17+
}
18+
},
19+
[[{ id: 5 }], { id: "6" }, { x: 2 }]
20+
]
21+
};
22+
23+
const cases: Array<[string, any, ((obj: any) => any) | undefined, any[], ...([boolean] | [])]> = [
24+
[
25+
"Returns deeply nested obj[matchKey] when no callback is provided",
26+
"id",
27+
undefined,
28+
[0, 2, 1, 5, "6"]
29+
],
30+
[
31+
"Returns deeply nested obj[matchKey] when cb returns true",
32+
"id",
33+
(obj) => typeof obj.id === "number" && obj.id > 1,
34+
[2, 5]
35+
],
36+
[
37+
"Returns cb response when it is not true or falsey",
38+
"0",
39+
(arr) => arr.length === 2 && arr[0]?.type,
40+
["FunctionDefinition"]
41+
],
42+
["Stops at first result if match found", "id", undefined, [0], true]
43+
];
44+
45+
describe("deepFindIn()", () => {
46+
for (const [title, key, cb, expectation, onlyFirst] of cases) {
47+
it(`${title}`, () => {
48+
expect(deepFindIn(testObject, key, cb, onlyFirst)).toMatchObject(expectation);
49+
});
50+
}
51+
});

0 commit comments

Comments
 (0)