-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhoist.js
88 lines (73 loc) · 1.77 KB
/
hoist.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
var morphic = require("morphic");
var either = require("./matchers.js").either;
var matchArray = require("./matchers.js").matchArray;
var flatten = require("./utils.js").flatten;
function hoistNode(a, b) {
if (a == undefined || b == undefined) {
throw new Error("tried to create a hoisting flow between undefined points");
}
return {
"type": "hoist",
"start": a,
"end": b
};
}
var dispatcher = new morphic();
var enumerate = new morphic();
dispatcher.with(
morphic.Object("list"),
morphic.number("nodeId")
).then(r => enumerate(r.list, r.nodeId, r.list.get(r.nodeId)));
dispatcher.with(
morphic.Object("list"),
matchArray("nodes")
).then(r => flatten(r.nodes.map(id => enumerate(r.list, id, r.list.get(id)))));
enumerate.with(
morphic.Object("list"),
morphic.Number("id"),
{
"type": "Program",
"body": morphic.Object("elements")
}
).then(
(r, list, id, input) => dispatcher(r.list, r.elements)
);
enumerate.with(
morphic.Object("list"),
morphic.Number("id"),
{
"type": "VariableDeclaration",
"declarations": morphic.Object("elements")
}
).then(
(r, list, id, input) => dispatcher(r.list, r.elements)
);
enumerate.with(
morphic.Object("list"),
morphic.Number("id"),
{
"type": either([
"FunctionDeclaration",
"VariableDeclarator"
])
}
).then((r, list, id, obj) => [id]);
enumerate.otherwise().return([]);
module.exports = function hoist(nodeList) {
var flows = [];
var declarations = dispatcher(nodeList, 0);
var end = {
node: 0,
type: "hoist"
};
declarations.forEach(declaration => {
var node = {node: declaration, type: "hoist"}
flows.push(hoistNode(end, node));
end = node;
});
flows.push(hoistNode(end, {
node: 0,
type: "start"
}));
return flows;
}