34
// *******************************************************************************************
35
// *******************************************************************************************
36
37
-const GLOBALS: Map<string, t.Identifier> = new Map([
38
- ["Map", t.identifier("Map")],
39
- ["Set", t.identifier("Set")],
40
- ["Math", t.identifier("Math")],
41
-]);
42
-
43
-// TODO: This will work as a stopgap but it isn't really correct. We need proper handling of globals
44
-// and module-scoped variables, which means understanding module constants and imports.
45
-function getOrAddGlobal(identifierName: string): t.Identifier {
46
- const ident = GLOBALS.get(identifierName);
47
- if (ident != null) {
48
- return ident;
49
- }
50
- const newIdent = t.identifier(identifierName);
51
- GLOBALS.set(identifierName, newIdent);
52
- return newIdent;
53
-}
54
-
37
/**
38
* Lower a function declaration into a control flow graph that models aspects of
39
* control flow that are necessary for memoization. Notably, only control flow
52
const builder = new HIRBuilder(env);
53
54
const id =
73
- func.isFunctionDeclaration() && func.node.id != null
74
- ? builder.resolveIdentifier(func.node.id)
55
+ func.isFunctionDeclaration() && func.get("id").hasNode()
56
+ ? builder.resolveIdentifier(func.get("id") as NodePath<t.Identifier>)
57
: null;
58
59
const params: Array<Place> = [];
78
- for (const param of func.get("params")) {
60
+ func.get("params").forEach((param) => {
61
if (param.isIdentifier()) {
80
- const identifier = builder.resolveIdentifier(param.node);
62
+ const identifier = builder.resolveIdentifier(param);
63
const place: Place = {
64
kind: "Identifier",
65
identifier,
79
source: func.toString(),
80
loc: param.node.loc ?? null,
81
});
100
- continue;
82
}
102
- }
83
+ });
84
85
const body = func.get("body");
86
if (body.isExpression()) {
1341
const exprLoc = exprPath.node.loc ?? GeneratedSource;
1342
const tag: string = exprPath.node.name;
1343
if (tag.match(/^[A-Z]/)) {
1363
- const binding =
1364
- exprPath.scope.getBindingIdentifier(tag) ?? getOrAddGlobal(tag);
1365
- invariant(
1366
- binding != null,
1367
- `Expected to find a binding for variable '%s'`,
1368
- tag
1369
- );
1370
- const identifier = builder.resolveIdentifier(binding);
1344
+ const identifier = builder.resolveIdentifier(exprPath);
1345
const place: Place = {
1346
kind: "Identifier",
1347
identifier: identifier,
1461
): Place {
1462
const exprNode = exprPath.node;
1463
const exprLoc = exprNode.loc ?? GeneratedSource;
1490
- const binding =
1491
- exprPath.scope.getBindingIdentifier(exprNode.name) ??
1492
- getOrAddGlobal(exprNode.name);
1493
- invariant(
1494
- binding != null,
1495
- `Expected to find a binding for variable '%s'`,
1496
- exprNode.name
1497
- );
1498
- const identifier = builder.resolveIdentifier(binding);
1464
+ const identifier = builder.resolveIdentifier(exprPath);
1465
const place: Place = {
1466
kind: "Identifier",
1467
identifier: identifier,
1660
fn.get("body").traverse({
1661
Expression(path) {
1662
// TODO(gsn): Handle member expressions
1697
- if (!path.isIdentifier) {
1663
+ if (!path.isIdentifier()) {
1664
return;
1665
}
1666
1701
- const id = path as NodePath<t.Identifier>;
1702
- const binding = id.scope.getBinding(id.node.name);
1667
+ const binding = path.scope.getBinding(path.node.name);
1668
if (binding === undefined || !pureScopes.has(binding.scope)) {
1669
return;
1670
}
1671
1672
captured.add({
1673
kind: "Identifier",
1709
- identifier: builder.resolveIdentifier(binding.identifier),
1674
+ identifier: builder.resolveIdentifier(path),
1675
effect: Effect.Unknown,
1711
- loc: id.node.loc!,
1676
+ loc: path.node.loc ?? GeneratedSource,
1677
});
1678
},
1679
});