Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 377 lines (324 sloc) 9.444 kB
f00763b @Constellation RegisterVM
authored
1 #ifndef IV_LV5_RAILGUN_ANALYZER_H_
2 #define IV_LV5_RAILGUN_ANALYZER_H_
3 #include <iv/lv5/specialized_ast.h>
4 #include <iv/lv5/railgun/fwd.h>
5 namespace iv {
6 namespace lv5 {
7 namespace railgun {
8
9 class Analyzer {
10 public:
0e53e44 @Constellation initial CONCAT opcode implementation
authored
11 // Assignment
f00763b @Constellation RegisterVM
authored
12 class AssignmentVisitor : public ExpressionVisitor {
13 public:
14 AssignmentVisitor() : found_(false) { }
2126181 @Constellation fix lint warning in railgun
authored
15
16 ~AssignmentVisitor() { }
f00763b @Constellation RegisterVM
authored
17
18 void Visit(const Assignment* assign) {
19 if (assign->left()->AsIdentifier()) {
20 found_ = true;
21 return;
22 }
23 assign->left()->AcceptExpressionVisitor(this);
24 if (found()) {
25 return;
26 }
27 assign->right()->AcceptExpressionVisitor(this);
28 }
29
30 void Visit(const BinaryOperation* binary) {
31 binary->left()->AcceptExpressionVisitor(this);
32 if (found()) {
33 return;
34 }
35 binary->right()->AcceptExpressionVisitor(this);
36 }
37
38 void Visit(const ConditionalExpression* cond) {
39 cond->cond()->AcceptExpressionVisitor(this);
40 if (found()) {
41 return;
42 }
43 cond->left()->AcceptExpressionVisitor(this);
44 if (found()) {
45 return;
46 }
47 cond->right()->AcceptExpressionVisitor(this);
48 }
49
50 void Visit(const UnaryOperation* unary) {
51 unary->expr()->AcceptExpressionVisitor(this);
52 }
53
54 void Visit(const PostfixExpression* postfix) {
55 if (postfix->expr()->AsIdentifier()) {
56 found_ = true;
57 return;
58 }
59 postfix->expr()->AcceptExpressionVisitor(this);
60 }
61
62 void Visit(const Assigned* assigned) { }
63 void Visit(const StringLiteral* literal) { }
64 void Visit(const NumberLiteral* literal) { }
65 void Visit(const Identifier* literal) { }
66 void Visit(const ThisLiteral* literal) { }
67 void Visit(const NullLiteral* literal) { }
68 void Visit(const TrueLiteral* literal) { }
69 void Visit(const FalseLiteral* literal) { }
70 void Visit(const RegExpLiteral* literal) { }
71
72 void Visit(const ArrayLiteral* literal) {
73 for (MaybeExpressions::const_iterator it = literal->items().begin(),
74 last = literal->items().end(); it != last; ++it) {
75 if (*it) {
76 (*it).Address()->AcceptExpressionVisitor(this);
77 if (found()) {
78 return;
79 }
80 }
81 }
82 }
83
84 void Visit(const ObjectLiteral* literal) {
2126181 @Constellation fix lint warning in railgun
authored
85 for (ObjectLiteral::Properties::const_iterator
86 it = literal->properties().begin(),
87 last = literal->properties().end();
88 it != last; ++it) {
f00763b @Constellation RegisterVM
authored
89 std::get<2>(*it)->AcceptExpressionVisitor(this);
90 if (found()) {
91 return;
92 }
93 }
94 }
95
96 void Visit(const FunctionLiteral* literal) { }
97
98 void Visit(const IdentifierAccess* prop) {
99 prop->target()->AcceptExpressionVisitor(this);
100 }
101
102 void Visit(const IndexAccess* prop) {
103 prop->target()->AcceptExpressionVisitor(this);
104 if (found()) {
105 return;
106 }
107 prop->key()->AcceptExpressionVisitor(this);
108 }
109
110 void Visit(const FunctionCall* call) {
111 call->target()->AcceptExpressionVisitor(this);
112 if (found()) {
113 return;
114 }
115 for (Expressions::const_iterator it = call->args().begin(),
116 last = call->args().end(); it != last; ++it) {
117 (*it)->AcceptExpressionVisitor(this);
118 if (found()) {
119 return;
120 }
121 }
122 }
123
124 void Visit(const ConstructorCall* call) {
125 call->target()->AcceptExpressionVisitor(this);
126 if (found()) {
127 return;
128 }
129 for (Expressions::const_iterator it = call->args().begin(),
130 last = call->args().end(); it != last; ++it) {
131 (*it)->AcceptExpressionVisitor(this);
132 if (found()) {
133 return;
134 }
135 }
136 }
137
138 bool found() const { return found_; }
139 private:
140 bool found_;
141 };
142
143 static bool ExpressionHasAssignment(const Expression* expr) {
144 AssignmentVisitor visitor;
145 expr->AcceptExpressionVisitor(&visitor);
146 return visitor.found();
147 }
0e53e44 @Constellation initial CONCAT opcode implementation
authored
148
149 // TODO(Constellation) calculate it in parser phase
150 // IsString
151 class IsStringVisitor : public ExpressionVisitor {
152 public:
153 typedef core::Token Token;
154 enum Type {
155 TYPE_STRING,
156 TYPE_NUMBER,
157 TYPE_NULL,
158 TYPE_UNDEFINED,
159 TYPE_BOOL,
160 TYPE_OTHER
161 };
162
163 Type Evaluate(const Expression* expr) {
164 expr->AcceptExpressionVisitor(this);
165 return type_;
166 }
167
168 IsStringVisitor() : type_() { }
169
170 void Visit(const Assignment* assign) {
171 // LHS type
172 if (assign->op() == Token::TK_ASSIGN) {
173 type_ = Evaluate(assign->right());
174 } else {
175 type_ = BinaryEvaluate(assign);
176 }
177 }
178
179 template<typename T>
180 Type BinaryEvaluate(const T* binary) {
181 switch (binary->op()) {
182 case Token::TK_ASSIGN_ADD:
183 case Token::TK_ADD: {
184 const Type type1 = Evaluate(binary->left());
185 const Type type2 = Evaluate(binary->left());
186 if (type1 == TYPE_STRING || type2 == TYPE_STRING) {
187 type_ = TYPE_STRING;
188 } else if (type1 == TYPE_NUMBER || type2 == TYPE_NUMBER) {
189 type_ = TYPE_NUMBER;
190 } else {
191 type_ = TYPE_OTHER; // String or Number anyway
192 }
193 break;
194 }
195
196 case Token::TK_ASSIGN_SUB:
197 case Token::TK_SUB:
198 case Token::TK_ASSIGN_SHR:
199 case Token::TK_SHR:
200 case Token::TK_ASSIGN_SAR:
201 case Token::TK_SAR:
202 case Token::TK_ASSIGN_SHL:
203 case Token::TK_SHL:
204 case Token::TK_ASSIGN_MUL:
205 case Token::TK_MUL:
206 case Token::TK_ASSIGN_DIV:
207 case Token::TK_DIV:
208 case Token::TK_ASSIGN_MOD:
209 case Token::TK_MOD:
210 case Token::TK_ASSIGN_BIT_AND:
211 case Token::TK_BIT_AND:
212 case Token::TK_ASSIGN_BIT_XOR:
213 case Token::TK_BIT_XOR:
214 case Token::TK_ASSIGN_BIT_OR:
215 case Token::TK_BIT_OR:
216 type_ = TYPE_NUMBER;
217 break;
218
219 case Token::TK_LT:
220 case Token::TK_LTE:
221 case Token::TK_GT:
222 case Token::TK_GTE:
223 case Token::TK_INSTANCEOF:
224 case Token::TK_IN:
225 case Token::TK_EQ:
226 case Token::TK_NE:
227 case Token::TK_EQ_STRICT:
228 case Token::TK_NE_STRICT:
229 type_ = TYPE_BOOL;
230 break;
231
232 case Token::TK_COMMA:
233 type_ = Evaluate(binary->right());
234 break;
235
236 case Token::TK_LOGICAL_AND:
237 case Token::TK_LOGICAL_OR: {
238 const Type type1 = Evaluate(binary->left());
239 const Type type2 = Evaluate(binary->right());
240 if (type1 == type2) {
241 type_ = type1;
242 } else {
243 // TODO(Constellation) we can calculate falsy or truly
244 type_ = TYPE_OTHER;
245 }
246 break;
247 }
248
249 default:
250 UNREACHABLE();
251 }
252 return type_;
253 }
254
255 void Visit(const BinaryOperation* binary) {
256 type_ = BinaryEvaluate(binary);
257 }
258
259 void Visit(const ConditionalExpression* cond) {
260 const Type type1 = Evaluate(cond->left());
261 const Type type2 = Evaluate(cond->right());
262 if (type1 == type2) {
263 type_ = type1;
264 } else {
265 type_ = TYPE_OTHER;
266 }
267 }
268
269 void Visit(const UnaryOperation* unary) {
270 switch (unary->op()) {
271 case Token::TK_ADD:
272 case Token::TK_SUB:
273 case Token::TK_INC:
274 case Token::TK_DEC:
275 case Token::TK_BIT_NOT:
276 type_ = TYPE_NUMBER;
277 break;
278 case Token::TK_NOT:
279 case Token::TK_DELETE:
280 type_ = TYPE_BOOL;
281 break;
282 case Token::TK_VOID:
283 type_ = TYPE_UNDEFINED;
284 break;
285 case Token::TK_TYPEOF:
286 type_ = TYPE_STRING;
287 break;
288 default:
289 UNREACHABLE();
290 }
291 }
292
293 void Visit(const PostfixExpression* postfix) {
294 type_ = TYPE_NUMBER;
295 }
296
297 void Visit(const Assigned* assigned) {
298 UNREACHABLE();
299 }
300
301 void Visit(const StringLiteral* literal) {
302 type_ = TYPE_STRING;
303 }
304
305 void Visit(const NumberLiteral* literal) {
306 type_ = TYPE_NUMBER;
307 }
308
309 void Visit(const Identifier* literal) {
310 type_ = TYPE_OTHER;
311 }
312
313 void Visit(const ThisLiteral* literal) {
314 type_ = TYPE_OTHER;
315 }
316
317 void Visit(const NullLiteral* literal) {
318 type_ = TYPE_NULL;
319 }
320
321 void Visit(const TrueLiteral* literal) {
322 type_ = TYPE_BOOL;
323 }
324
325 void Visit(const FalseLiteral* literal) {
326 type_ = TYPE_BOOL;
327 }
328
329 void Visit(const RegExpLiteral* literal) {
330 type_ = TYPE_OTHER;
331 }
332
333 void Visit(const ArrayLiteral* literal) {
334 type_ = TYPE_OTHER;
335 }
336
337 void Visit(const ObjectLiteral* literal) {
338 type_ = TYPE_OTHER;
339 }
340
341 void Visit(const FunctionLiteral* literal) {
342 type_ = TYPE_OTHER;
343 }
344
345 void Visit(const IdentifierAccess* prop) {
346 type_ = TYPE_OTHER;
347 }
348
349 void Visit(const IndexAccess* prop) {
350 type_ = TYPE_OTHER;
351 }
352
353 void Visit(const FunctionCall* call) {
354 type_ = TYPE_OTHER;
355 }
356
357 void Visit(const ConstructorCall* call) {
358 type_ = TYPE_OTHER;
359 }
360
361 bool IsString() const { return type_ == TYPE_STRING; }
362
363 private:
364 Type type_;
365 };
366
367 static bool IsString(const Expression* expr) {
368 IsStringVisitor visitor;
369 expr->AcceptExpressionVisitor(&visitor);
370 return visitor.IsString();
371 }
f00763b @Constellation RegisterVM
authored
372 };
373
374
375 } } } // namespace iv::lv5::railgun
376 #endif // IV_LV5_RAILGUN_ANALYZER_H_
Something went wrong with that request. Please try again.