-
Notifications
You must be signed in to change notification settings - Fork 4
/
evaluator.js
98 lines (83 loc) · 3.35 KB
/
evaluator.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
89
90
91
92
93
94
95
96
97
98
(function(ns){
var Syntax = require('estraverse').Syntax,
ANNO = require("../../type-system/annotation.js").ANNO,
Shade = require("../../interfaces.js");
var UnaryFunctions = {
"!": function(a) { return !a; },
"-": function(a) { return -a; },
"+": function(a) { return +a; },
"typeof": function(a) { return typeof a; },
"void": function(a) { return void a; },
"delete": function(a) { return true; }
};
var BinaryFunctions = {
"+" : function(a,b) { return a + b; },
"-" : function(a,b) { return a - b; },
"/" : function(a,b) { return a / b; },
"*" : function(a,b) { return a * b; },
"%" : function(a,b) { return a % b; },
"==" : function(a,b) { return a == b; },
"!=" : function(a,b) { return a != b; },
"===" : function(a,b) { return a === b; },
"!==" : function(a,b) { return a !== b; },
"<" : function(a,b) { return a < b; },
"<=" : function(a,b) { return a <= b; },
">" : function(a,b) { return a > b; },
">=" : function(a,b) { return a >= b; }
};
/**
*
* @param node
*/
function getStaticValue(node) {
if (node.type === Syntax.Literal) {
var value = node.raw !== undefined ? node.raw : node.value;
var number = parseFloat(value);
if (!isNaN(number))
return number;
value = node.value;
switch(value) {
case "true": return true;
case "false": return false;
case "null": return null;
default: return value;
}
}
if (node.type == Syntax.MemberExpression || node.type == Syntax.CallExpression || node.type == Syntax.Identifier || node.type == Syntax.NewExpression || node.type == Syntax.LogicalExpression) {
return ANNO(node).getStaticValue();
}
if (node.type === Syntax.UnaryExpression) {
if (node.operator == "typeof") {
return ANNO(node).getStaticValue();
}
if(UnaryFunctions.hasOwnProperty(node.operator)) {
return UnaryFunctions[node.operator](getStaticValue(node.argument));
}
Shade.throwError(node, "Unknown unary operator: " + node.operator);
}
if (node.type === Syntax.BinaryExpression) {
if(BinaryFunctions.hasOwnProperty(node.operator)) {
return BinaryFunctions[node.operator](getStaticValue(node.left), getStaticValue(node.right));
}
Shade.throwError(node, "Unknown binary operator: " + node.operator);
}
Shade.throwError(node, "Evaluating static value for node type: " + node.type);
};
function getStaticTruthValue(node) {
var aNode = ANNO(node);
// !!undefined == false;
if (aNode.isNullOrUndefined())
return false;
// !!{} == true
if (aNode.isObject() || this.isFunction())
return true;
// In all other cases, it depends on the value,
// thus we can only evaluate this for static objects
if (aNode.hasStaticValue()) {
return !!aNode.getStaticValue();
}
return undefined;
}
exports.getStaticValue = getStaticValue;
exports.getStaticTruthValue = getStaticTruthValue;
}(exports));