1 |
|
2 | (function() {
|
3 | var estools, nodeIsInfinity, nodeIsNumericLiteral, nodeIsUnaryMinus, numberProperty, replaceAllNodes, replaceWithLiteral, reservedWords, tools;
|
4 |
|
5 | tools = require('./tools');
|
6 |
|
7 | estools = require('./estools');
|
8 |
|
9 | reservedWords = ['break', 'case', 'catch', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'false', 'finally', 'for', 'function', 'if', 'in', 'instanceof', 'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'abstract', 'boolean', 'byte', 'char', 'double', 'final', 'float', 'goto', 'implements', 'int', 'interface', 'long', 'native', 'package', 'private', 'protected', 'public', 'short', 'static', 'synchronized', 'throws', 'transient', 'export'];
|
10 |
|
11 | nodeIsInfinity = function(node) {
|
12 | return node.type === 'Literal' && node.value === Infinity;
|
13 | };
|
14 |
|
15 | nodeIsNumericLiteral = function(node) {
|
16 | return node.type === 'Literal' && typeof node.value === 'number';
|
17 | };
|
18 |
|
19 | nodeIsUnaryMinus = function(node) {
|
20 | return node.type === 'UnaryExpression' && node.operator === '-';
|
21 | };
|
22 |
|
23 | numberProperty = function(property) {
|
24 | return {
|
25 | type: 'MemberExpression',
|
26 | computed: false,
|
27 | object: {
|
28 | type: 'Identifier',
|
29 | name: 'Number'
|
30 | },
|
31 | property: {
|
32 | type: 'Identifier',
|
33 | name: property
|
34 | }
|
35 | };
|
36 | };
|
37 |
|
38 | replaceAllNodes = function(_arg) {
|
39 | var ast, predicate, replacement;
|
40 | ast = _arg.ast, predicate = _arg.predicate, replacement = _arg.replacement;
|
41 | return estools.traverse(ast, function(node) {
|
42 | if (predicate(node)) {
|
43 | return tools.replaceProperties(node, replacement(node));
|
44 | }
|
45 | });
|
46 | };
|
47 |
|
48 | replaceWithLiteral = function(node, value) {
|
49 | return tools.replaceProperties(node, estools.createLiteral(value));
|
50 | };
|
51 |
|
52 | exports.isNumericLiteral = function(node) {
|
53 | return nodeIsNumericLiteral(node) || (nodeIsUnaryMinus(node) && nodeIsNumericLiteral(node.argument));
|
54 | };
|
55 |
|
56 | exports.replaceNegativeInfinities = function(ast) {
|
57 | return replaceAllNodes({
|
58 | ast: ast,
|
59 | predicate: function(node) {
|
60 | return nodeIsUnaryMinus(node) && nodeIsInfinity(node.argument);
|
61 | },
|
62 | replacement: function() {
|
63 | return numberProperty('NEGATIVE_INFINITY');
|
64 | }
|
65 | });
|
66 | };
|
67 |
|
68 | exports.replacePositiveInfinities = function(ast) {
|
69 | return replaceAllNodes({
|
70 | ast: ast,
|
71 | predicate: nodeIsInfinity,
|
72 | replacement: function() {
|
73 | return numberProperty('POSITIVE_INFINITY');
|
74 | }
|
75 | });
|
76 | };
|
77 |
|
78 | exports.isReservedWord = (function() {
|
79 | var reservedWordsHash;
|
80 | reservedWordsHash = reservedWords.reduce(function(acc, word) {
|
81 | acc[word] = 1;
|
82 | return acc;
|
83 | }, {});
|
84 | return function(name) {
|
85 | return !!reservedWordsHash.hasOwnProperty(name);
|
86 | };
|
87 | })();
|
88 |
|
89 | exports.isValidIdentifier = function(name) {
|
90 | return (name != null ? name.toString().match(/^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/) : void 0) && !exports.isReservedWord(name);
|
91 | };
|
92 |
|
93 | exports.evalBinaryExpression = (function() {
|
94 | var methods;
|
95 | methods = {
|
96 | '+': function(x, y) {
|
97 | return x + y;
|
98 | },
|
99 | '-': function(x, y) {
|
100 | return x - y;
|
101 | },
|
102 | '*': function(x, y) {
|
103 | return x * y;
|
104 | },
|
105 | '%': function(x, y) {
|
106 | return x % y;
|
107 | },
|
108 | '/': function(x, y) {
|
109 | return x / y;
|
110 | },
|
111 | '<<': function(x, y) {
|
112 | return x << y;
|
113 | },
|
114 | '>>': function(x, y) {
|
115 | return x >> y;
|
116 | },
|
117 | '>>>': function(x, y) {
|
118 | return x >>> y;
|
119 | }
|
120 | };
|
121 | return function(arg1, op, arg2) {
|
122 | var method;
|
123 | method = methods[op];
|
124 | if (method == null) {
|
125 | throw "operator not supported";
|
126 | }
|
127 | return method(arg1, arg2);
|
128 | };
|
129 | })();
|
130 |
|
131 | exports.evalLiterals = function(ast, evals) {
|
132 | var format, _results;
|
133 | format = true;
|
134 | _results = [];
|
135 | while (format) {
|
136 | format = false;
|
137 | _results.push(estools.traverse(ast, function(node) {
|
138 | return evals.forEach(function(n) {
|
139 | var v;
|
140 | if (n.test(node)) {
|
141 | v = n["eval"](node);
|
142 | if (typeof v === 'number' && isNaN(v)) {
|
143 | tools.replaceProperties(node, {
|
144 | type: 'MemberExpression',
|
145 | computed: false,
|
146 | object: {
|
147 | type: 'Identifier',
|
148 | name: 'Number'
|
149 | },
|
150 | property: {
|
151 | type: 'Identifier',
|
152 | name: 'NaN'
|
153 | }
|
154 | });
|
155 | } else {
|
156 | replaceWithLiteral(node, v);
|
157 | }
|
158 | return format = true;
|
159 | }
|
160 | });
|
161 | }));
|
162 | }
|
163 | return _results;
|
164 | };
|
165 |
|
166 | exports.evalLiteral = function(node) {
|
167 | if (nodeIsNumericLiteral(node)) {
|
168 | return node.value;
|
169 | } else if (nodeIsUnaryMinus(node) && nodeIsNumericLiteral(node.argument)) {
|
170 | return -node.argument.value;
|
171 | } else {
|
172 | throw "not a numeric literal";
|
173 | }
|
174 | };
|
175 |
|
176 | }).call(this);
|