forked from marijnh/blint
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathloop.js
More file actions
63 lines (61 loc) · 2.06 KB
/
loop.js
File metadata and controls
63 lines (61 loc) · 2.06 KB
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
var walk = require("acorn-walk");
exports.checkReusedIndex = function(node, fail) {
if (!node.init || node.init.type != "VariableDeclaration") return;
var name = node.init.declarations[0].id.name;
walk.recursive(node.body, null, {
Function: function() {},
VariableDeclaration: function(node, st, c) {
for (var i = 0; i < node.declarations.length; i++)
if (node.declarations[i].id.name == name)
fail("Redefined loop variable", node.declarations[i].id.loc);
walk.base.VariableDeclaration(node, st, c);
}
});
};
exports.checkObviousInfiniteLoop = function(test, update, fail) {
var vars = Object.create(null);
function compDir(op) {
if (op == "<" || op == "<=") return 1;
if (op == ">" || op == ">=") return -1;
return 0;
}
function opDir(op) {
if (/\+/.test(op)) return 1;
if (/-/.test(op)) return -1;
return 0;
}
function store(name, dir) {
if (!(name in vars)) vars[name] = {below: false, above: false};
if (dir > 0) vars[name].up = true;
if (dir < 0) vars[name].down = true;
}
function check(node, dir) {
var known = vars[node.name];
if (!known) return;
if (dir > 0 && known.down && !known.up ||
dir < 0 && known.up && !known.down)
fail("Suspiciously infinite-looking loop", node.loc);
}
walk.simple(test, {
BinaryExpression: function(node) {
if (node.left.type == "Identifier")
store(node.left.name, compDir(node.operator));
if (node.right.type == "Identifier")
store(node.right.name, -compDir(node.operator));
}
});
walk.simple(update, {
UpdateExpression: function(node) {
if (node.argument.type == "Identifier")
check(node.argument, opDir(node.operator));
},
AssignmentExpression: function(node) {
if (node.left.type == "Identifier") {
if (node.operator == "=" && node.right.type == "BinaryExpression" && node.right.left.name == node.left.name)
check(node.left, opDir(node.right.operator));
else
check(node.left, opDir(node.operator));
}
}
});
};