blob: a301ab7e9e354ce07972dd53e1c187234f8b82ef [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_AST_H_
29#define V8_AST_H_
30
31#include "execution.h"
32#include "factory.h"
33#include "runtime.h"
34#include "token.h"
35#include "variables.h"
36#include "macro-assembler.h"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000037#include "jsregexp.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
39namespace v8 { namespace internal {
40
41// The abstract syntax tree is an intermediate, light-weight
42// representation of the parsed JavaScript code suitable for
43// compilation to native code.
44
45// Nodes are allocated in a separate zone, which allows faster
46// allocation and constant-time deallocation of the entire syntax
47// tree.
48
49
50// ----------------------------------------------------------------------------
51// Nodes of the abstract syntax tree. Only concrete classes are
52// enumerated here.
53
54#define NODE_LIST(V) \
55 V(Block) \
56 V(Declaration) \
57 V(ExpressionStatement) \
58 V(EmptyStatement) \
59 V(IfStatement) \
60 V(ContinueStatement) \
61 V(BreakStatement) \
62 V(ReturnStatement) \
63 V(WithEnterStatement) \
64 V(WithExitStatement) \
65 V(SwitchStatement) \
66 V(LoopStatement) \
67 V(ForInStatement) \
68 V(TryCatch) \
69 V(TryFinally) \
70 V(DebuggerStatement) \
71 V(FunctionLiteral) \
72 V(FunctionBoilerplateLiteral) \
73 V(Conditional) \
74 V(Slot) \
75 V(VariableProxy) \
76 V(Literal) \
77 V(RegExpLiteral) \
78 V(ObjectLiteral) \
79 V(ArrayLiteral) \
80 V(Assignment) \
81 V(Throw) \
82 V(Property) \
83 V(Call) \
ager@chromium.orga74f0da2008-12-03 16:05:52 +000084 V(CallEval) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000085 V(CallNew) \
86 V(CallRuntime) \
87 V(UnaryOperation) \
88 V(CountOperation) \
89 V(BinaryOperation) \
90 V(CompareOperation) \
91 V(ThisFunction)
92
93
94#define DEF_FORWARD_DECLARATION(type) class type;
95NODE_LIST(DEF_FORWARD_DECLARATION)
96#undef DEF_FORWARD_DECLARATION
97
98
99// Typedef only introduced to avoid unreadable code.
100// Please do appreciate the required space in "> >".
101typedef ZoneList<Handle<String> > ZoneStringList;
102
103
104class Node: public ZoneObject {
105 public:
ager@chromium.org236ad962008-09-25 09:45:57 +0000106 Node(): statement_pos_(RelocInfo::kNoPosition) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107 virtual ~Node() { }
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000108 virtual void Accept(AstVisitor* v) = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109
110 // Type testing & conversion.
111 virtual Statement* AsStatement() { return NULL; }
112 virtual ExpressionStatement* AsExpressionStatement() { return NULL; }
113 virtual EmptyStatement* AsEmptyStatement() { return NULL; }
114 virtual Expression* AsExpression() { return NULL; }
115 virtual Literal* AsLiteral() { return NULL; }
116 virtual Slot* AsSlot() { return NULL; }
117 virtual VariableProxy* AsVariableProxy() { return NULL; }
118 virtual Property* AsProperty() { return NULL; }
119 virtual Call* AsCall() { return NULL; }
120 virtual LabelCollector* AsLabelCollector() { return NULL; }
121 virtual BreakableStatement* AsBreakableStatement() { return NULL; }
122 virtual IterationStatement* AsIterationStatement() { return NULL; }
123 virtual UnaryOperation* AsUnaryOperation() { return NULL; }
124 virtual BinaryOperation* AsBinaryOperation() { return NULL; }
125 virtual Assignment* AsAssignment() { return NULL; }
126 virtual FunctionLiteral* AsFunctionLiteral() { return NULL; }
127
128 void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
129 int statement_pos() const { return statement_pos_; }
130
131 private:
132 int statement_pos_;
133};
134
135
136class Statement: public Node {
137 public:
138 virtual Statement* AsStatement() { return this; }
139 virtual ReturnStatement* AsReturnStatement() { return NULL; }
140
141 bool IsEmpty() { return AsEmptyStatement() != NULL; }
142};
143
144
145class Expression: public Node {
146 public:
147 virtual Expression* AsExpression() { return this; }
148
149 virtual bool IsValidLeftHandSide() { return false; }
150
151 // Mark the expression as being compiled as an expression
152 // statement. This is used to transform postfix increments to
153 // (faster) prefix increments.
154 virtual void MarkAsStatement() { /* do nothing */ }
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000155
156 // Static type information for this expression.
157 StaticType* type() { return &type_; }
158
159 private:
160 StaticType type_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161};
162
163
164/**
165 * A sentinel used during pre parsing that represents some expression
166 * that is a valid left hand side without having to actually build
167 * the expression.
168 */
169class ValidLeftHandSideSentinel: public Expression {
170 public:
171 virtual bool IsValidLeftHandSide() { return true; }
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000172 virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173 static ValidLeftHandSideSentinel* instance() { return &instance_; }
174 private:
175 static ValidLeftHandSideSentinel instance_;
176};
177
178
179class BreakableStatement: public Statement {
180 public:
181 enum Type {
182 TARGET_FOR_ANONYMOUS,
183 TARGET_FOR_NAMED_ONLY
184 };
185
186 // The labels associated with this statement. May be NULL;
187 // if it is != NULL, guaranteed to contain at least one entry.
188 ZoneStringList* labels() const { return labels_; }
189
190 // Type testing & conversion.
191 virtual BreakableStatement* AsBreakableStatement() { return this; }
192
193 // Code generation
194 Label* break_target() { return &break_target_; }
195
196 // Used during code generation for restoring the stack when a
197 // break/continue crosses a statement that keeps stuff on the stack.
198 int break_stack_height() { return break_stack_height_; }
199 void set_break_stack_height(int height) { break_stack_height_ = height; }
200
201 // Testers.
202 bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; }
203
204 protected:
205 BreakableStatement(ZoneStringList* labels, Type type)
206 : labels_(labels), type_(type) {
207 ASSERT(labels == NULL || labels->length() > 0);
208 }
209
210 private:
211 ZoneStringList* labels_;
212 Type type_;
213 Label break_target_;
214 int break_stack_height_;
215};
216
217
218class Block: public BreakableStatement {
219 public:
220 Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
221 : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
222 statements_(capacity),
223 is_initializer_block_(is_initializer_block) { }
224
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000225 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226
227 void AddStatement(Statement* statement) { statements_.Add(statement); }
228
229 ZoneList<Statement*>* statements() { return &statements_; }
230 bool is_initializer_block() const { return is_initializer_block_; }
231
232 private:
233 ZoneList<Statement*> statements_;
234 bool is_initializer_block_;
235};
236
237
238class Declaration: public Node {
239 public:
240 Declaration(VariableProxy* proxy, Variable::Mode mode, FunctionLiteral* fun)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000241 : proxy_(proxy),
242 mode_(mode),
243 fun_(fun) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244 ASSERT(mode == Variable::VAR || mode == Variable::CONST);
245 // At the moment there are no "const functions"'s in JavaScript...
246 ASSERT(fun == NULL || mode == Variable::VAR);
247 }
248
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000249 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250
251 VariableProxy* proxy() const { return proxy_; }
252 Variable::Mode mode() const { return mode_; }
253 FunctionLiteral* fun() const { return fun_; } // may be NULL
254
255 private:
256 VariableProxy* proxy_;
257 Variable::Mode mode_;
258 FunctionLiteral* fun_;
259};
260
261
262class IterationStatement: public BreakableStatement {
263 public:
264 // Type testing & conversion.
265 virtual IterationStatement* AsIterationStatement() { return this; }
266
267 Statement* body() const { return body_; }
268
269 // Code generation
270 Label* continue_target() { return &continue_target_; }
271
272 protected:
273 explicit IterationStatement(ZoneStringList* labels)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000274 : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275
276 void Initialize(Statement* body) {
277 body_ = body;
278 }
279
280 private:
281 Statement* body_;
282 Label continue_target_;
283};
284
285
286class LoopStatement: public IterationStatement {
287 public:
288 enum Type { DO_LOOP, FOR_LOOP, WHILE_LOOP };
289
290 LoopStatement(ZoneStringList* labels, Type type)
291 : IterationStatement(labels), type_(type), init_(NULL),
292 cond_(NULL), next_(NULL) { }
293
294 void Initialize(Statement* init,
295 Expression* cond,
296 Statement* next,
297 Statement* body) {
298 ASSERT(init == NULL || type_ == FOR_LOOP);
299 ASSERT(next == NULL || type_ == FOR_LOOP);
300 IterationStatement::Initialize(body);
301 init_ = init;
302 cond_ = cond;
303 next_ = next;
304 }
305
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000306 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000307
308 Type type() const { return type_; }
309 Statement* init() const { return init_; }
310 Expression* cond() const { return cond_; }
311 Statement* next() const { return next_; }
312
313#ifdef DEBUG
314 const char* OperatorString() const;
315#endif
316
317 private:
318 Type type_;
319 Statement* init_;
320 Expression* cond_;
321 Statement* next_;
322};
323
324
325class ForInStatement: public IterationStatement {
326 public:
327 explicit ForInStatement(ZoneStringList* labels)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000328 : IterationStatement(labels), each_(NULL), enumerable_(NULL) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000329
330 void Initialize(Expression* each, Expression* enumerable, Statement* body) {
331 IterationStatement::Initialize(body);
332 each_ = each;
333 enumerable_ = enumerable;
334 }
335
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000336 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337
338 Expression* each() const { return each_; }
339 Expression* enumerable() const { return enumerable_; }
340
341 private:
342 Expression* each_;
343 Expression* enumerable_;
344};
345
346
347class ExpressionStatement: public Statement {
348 public:
349 explicit ExpressionStatement(Expression* expression)
350 : expression_(expression) { }
351
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000352 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353
354 // Type testing & conversion.
355 virtual ExpressionStatement* AsExpressionStatement() { return this; }
356
357 void set_expression(Expression* e) { expression_ = e; }
358 Expression* expression() { return expression_; }
359
360 private:
361 Expression* expression_;
362};
363
364
365class ContinueStatement: public Statement {
366 public:
367 explicit ContinueStatement(IterationStatement* target)
368 : target_(target) { }
369
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000370 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371
372 IterationStatement* target() const { return target_; }
373
374 private:
375 IterationStatement* target_;
376};
377
378
379class BreakStatement: public Statement {
380 public:
381 explicit BreakStatement(BreakableStatement* target)
382 : target_(target) { }
383
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000384 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000385
386 BreakableStatement* target() const { return target_; }
387
388 private:
389 BreakableStatement* target_;
390};
391
392
393class ReturnStatement: public Statement {
394 public:
395 explicit ReturnStatement(Expression* expression)
396 : expression_(expression) { }
397
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000398 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399
400 // Type testing & conversion.
401 virtual ReturnStatement* AsReturnStatement() { return this; }
402
403 Expression* expression() { return expression_; }
404
405 private:
406 Expression* expression_;
407};
408
409
410class WithEnterStatement: public Statement {
411 public:
412 explicit WithEnterStatement(Expression* expression)
413 : expression_(expression) { }
414
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000415 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416
417 Expression* expression() const { return expression_; }
418
419 private:
420 Expression* expression_;
421};
422
423
424class WithExitStatement: public Statement {
425 public:
426 WithExitStatement() { }
427
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000428 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429};
430
431
432class CaseClause: public ZoneObject {
433 public:
434 CaseClause(Expression* label, ZoneList<Statement*>* statements)
435 : label_(label), statements_(statements) { }
436
437 bool is_default() const { return label_ == NULL; }
438 Expression* label() const {
439 CHECK(!is_default());
440 return label_;
441 }
442 ZoneList<Statement*>* statements() const { return statements_; }
443
444 private:
445 Expression* label_;
446 ZoneList<Statement*>* statements_;
447};
448
449
450class SwitchStatement: public BreakableStatement {
451 public:
452 explicit SwitchStatement(ZoneStringList* labels)
453 : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
454 tag_(NULL), cases_(NULL) { }
455
456 void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
457 tag_ = tag;
458 cases_ = cases;
459 }
460
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000461 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462
463 Expression* tag() const { return tag_; }
464 ZoneList<CaseClause*>* cases() const { return cases_; }
465
466 private:
467 Expression* tag_;
468 ZoneList<CaseClause*>* cases_;
469};
470
471
472// If-statements always have non-null references to their then- and
473// else-parts. When parsing if-statements with no explicit else-part,
474// the parser implicitly creates an empty statement. Use the
475// HasThenStatement() and HasElseStatement() functions to check if a
476// given if-statement has a then- or an else-part containing code.
477class IfStatement: public Statement {
478 public:
479 IfStatement(Expression* condition,
480 Statement* then_statement,
481 Statement* else_statement)
482 : condition_(condition),
483 then_statement_(then_statement),
484 else_statement_(else_statement) { }
485
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000486 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487
488 bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
489 bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
490
491 Expression* condition() const { return condition_; }
492 Statement* then_statement() const { return then_statement_; }
493 Statement* else_statement() const { return else_statement_; }
494
495 private:
496 Expression* condition_;
497 Statement* then_statement_;
498 Statement* else_statement_;
499};
500
501
502// NOTE: LabelCollectors are represented as nodes to fit in the target
503// stack in the compiler; this should probably be reworked.
504class LabelCollector: public Node {
505 public:
506 explicit LabelCollector(ZoneList<Label*>* labels) : labels_(labels) { }
507
508 // Adds a label to the collector. The collector stores a pointer not
509 // a copy of the label to make binding work, so make sure not to
510 // pass in references to something on the stack.
511 void AddLabel(Label* label);
512
513 // Virtual behaviour. LabelCollectors are never part of the AST.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000514 virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515 virtual LabelCollector* AsLabelCollector() { return this; }
516
517 ZoneList<Label*>* labels() { return labels_; }
518
519 private:
520 ZoneList<Label*>* labels_;
521};
522
523
524class TryStatement: public Statement {
525 public:
526 explicit TryStatement(Block* try_block)
527 : try_block_(try_block), escaping_labels_(NULL) { }
528
529 void set_escaping_labels(ZoneList<Label*>* labels) {
530 escaping_labels_ = labels;
531 }
532
533 Block* try_block() const { return try_block_; }
534 ZoneList<Label*>* escaping_labels() const { return escaping_labels_; }
535
536 private:
537 Block* try_block_;
538 ZoneList<Label*>* escaping_labels_;
539};
540
541
542class TryCatch: public TryStatement {
543 public:
544 TryCatch(Block* try_block, Expression* catch_var, Block* catch_block)
545 : TryStatement(try_block),
546 catch_var_(catch_var),
547 catch_block_(catch_block) {
548 ASSERT(catch_var->AsVariableProxy() != NULL);
549 }
550
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000551 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552
553 Expression* catch_var() const { return catch_var_; }
554 Block* catch_block() const { return catch_block_; }
555
556 private:
557 Expression* catch_var_;
558 Block* catch_block_;
559};
560
561
562class TryFinally: public TryStatement {
563 public:
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000564 TryFinally(Block* try_block, Block* finally_block)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000565 : TryStatement(try_block),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566 finally_block_(finally_block) { }
567
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000568 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000569
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000570 Block* finally_block() const { return finally_block_; }
571
572 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573 Block* finally_block_;
574};
575
576
577class DebuggerStatement: public Statement {
578 public:
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000579 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580};
581
582
583class EmptyStatement: public Statement {
584 public:
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000585 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586
587 // Type testing & conversion.
588 virtual EmptyStatement* AsEmptyStatement() { return this; }
589};
590
591
592class Literal: public Expression {
593 public:
594 explicit Literal(Handle<Object> handle) : handle_(handle) { }
595
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000596 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000597
598 // Type testing & conversion.
599 virtual Literal* AsLiteral() { return this; }
600
601 // Check if this literal is identical to the other literal.
602 bool IsIdenticalTo(const Literal* other) const {
603 return handle_.is_identical_to(other->handle_);
604 }
605
606 // Identity testers.
607 bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
608 bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
609 bool IsFalse() const {
610 return handle_.is_identical_to(Factory::false_value());
611 }
612
613 Handle<Object> handle() const { return handle_; }
614
615 private:
616 Handle<Object> handle_;
617};
618
619
620// Base class for literals that needs space in the corresponding JSFunction.
621class MaterializedLiteral: public Expression {
622 public:
623 explicit MaterializedLiteral(int literal_index)
624 : literal_index_(literal_index) {}
625 int literal_index() { return literal_index_; }
626 private:
627 int literal_index_;
628};
629
630
631// An object literal has a boilerplate object that is used
632// for minimizing the work when constructing it at runtime.
633class ObjectLiteral: public MaterializedLiteral {
634 public:
635 // Property is used for passing information
636 // about an object literal's properties from the parser
637 // to the code generator.
638 class Property: public ZoneObject {
639 public:
640
641 enum Kind {
642 CONSTANT, // Property with constant value (at compile time).
643 COMPUTED, // Property with computed value (at execution time).
644 GETTER, SETTER, // Property is an accessor function.
645 PROTOTYPE // Property is __proto__.
646 };
647
648 Property(Literal* key, Expression* value);
649 Property(bool is_getter, FunctionLiteral* value);
650
651 Literal* key() { return key_; }
652 Expression* value() { return value_; }
653 Kind kind() { return kind_; }
654
655 private:
656 Literal* key_;
657 Expression* value_;
658 Kind kind_;
659 };
660
661 ObjectLiteral(Handle<FixedArray> constant_properties,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662 ZoneList<Property*>* properties,
663 int literal_index)
664 : MaterializedLiteral(literal_index),
665 constant_properties_(constant_properties),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000666 properties_(properties) {
667 }
668
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000669 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670
671 Handle<FixedArray> constant_properties() const {
672 return constant_properties_;
673 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 ZoneList<Property*>* properties() const { return properties_; }
675
676 private:
677 Handle<FixedArray> constant_properties_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000678 ZoneList<Property*>* properties_;
679};
680
681
682// Node for capturing a regexp literal.
683class RegExpLiteral: public MaterializedLiteral {
684 public:
685 RegExpLiteral(Handle<String> pattern,
686 Handle<String> flags,
687 int literal_index)
688 : MaterializedLiteral(literal_index),
689 pattern_(pattern),
690 flags_(flags) {}
691
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000692 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000693
694 Handle<String> pattern() const { return pattern_; }
695 Handle<String> flags() const { return flags_; }
696
697 private:
698 Handle<String> pattern_;
699 Handle<String> flags_;
700};
701
702// An array literal has a literals object that is used
703// used for minimizing the work when contructing it at runtime.
704class ArrayLiteral: public Expression {
705 public:
706 ArrayLiteral(Handle<FixedArray> literals,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707 ZoneList<Expression*>* values)
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000708 : literals_(literals), values_(values) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709 }
710
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000711 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712
713 Handle<FixedArray> literals() const { return literals_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000714 ZoneList<Expression*>* values() const { return values_; }
715
716 private:
717 Handle<FixedArray> literals_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718 ZoneList<Expression*>* values_;
719};
720
721
722class VariableProxy: public Expression {
723 public:
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000724 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000725
726 // Type testing & conversion
727 virtual Property* AsProperty() {
728 return var_ == NULL ? NULL : var_->AsProperty();
729 }
730 virtual VariableProxy* AsVariableProxy() { return this; }
731
732 Variable* AsVariable() {
733 return this == NULL || var_ == NULL ? NULL : var_->AsVariable();
734 }
735 virtual bool IsValidLeftHandSide() {
736 return var_ == NULL ? true : var_->IsValidLeftHandSide();
737 }
738 bool IsVariable(Handle<String> n) {
739 return !is_this() && name().is_identical_to(n);
740 }
741
742 // If this assertion fails it means that some code has tried to
743 // treat the special "this" variable as an ordinary variable with
744 // the name "this".
745 Handle<String> name() const { return name_; }
746 Variable* var() const { return var_; }
747 UseCount* var_uses() { return &var_uses_; }
748 UseCount* obj_uses() { return &obj_uses_; }
749 bool is_this() const { return is_this_; }
750 bool inside_with() const { return inside_with_; }
751
752 // Bind this proxy to the variable var.
753 void BindTo(Variable* var);
754
755 protected:
756 Handle<String> name_;
757 Variable* var_; // resolved variable, or NULL
758 bool is_this_;
759 bool inside_with_;
760
761 // VariableProxy usage info.
762 UseCount var_uses_; // uses of the variable value
763 UseCount obj_uses_; // uses of the object the variable points to
764
765 VariableProxy(Handle<String> name, bool is_this, bool inside_with);
766 explicit VariableProxy(bool is_this);
767
768 friend class Scope;
769};
770
771
772class VariableProxySentinel: public VariableProxy {
773 public:
774 virtual bool IsValidLeftHandSide() { return !is_this(); }
775 static VariableProxySentinel* this_proxy() { return &this_proxy_; }
776 static VariableProxySentinel* identifier_proxy() {
777 return &identifier_proxy_;
778 }
779
780 private:
781 explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
782 static VariableProxySentinel this_proxy_;
783 static VariableProxySentinel identifier_proxy_;
784};
785
786
787class Slot: public Expression {
788 public:
789 enum Type {
790 // A slot in the parameter section on the stack. index() is
791 // the parameter index, counting left-to-right, starting at 0.
792 PARAMETER,
793
794 // A slot in the local section on the stack. index() is
795 // the variable index in the stack frame, starting at 0.
796 LOCAL,
797
798 // An indexed slot in a heap context. index() is the
799 // variable index in the context object on the heap,
800 // starting at 0. var()->scope() is the corresponding
801 // scope.
802 CONTEXT,
803
804 // A named slot in a heap context. var()->name() is the
805 // variable name in the context object on the heap,
806 // with lookup starting at the current context. index()
807 // is invalid.
808 LOOKUP,
809
810 // A property in the global object. var()->name() is
811 // the property name.
812 GLOBAL
813 };
814
815 Slot(Variable* var, Type type, int index)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000816 : var_(var), type_(type), index_(index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000817 ASSERT(var != NULL);
818 }
819
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000820 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000821
822 // Type testing & conversion
823 virtual Slot* AsSlot() { return this; }
824
825 // Accessors
826 Variable* var() const { return var_; }
827 Type type() const { return type_; }
828 int index() const { return index_; }
829
830 private:
831 Variable* var_;
832 Type type_;
833 int index_;
834};
835
836
837class Property: public Expression {
838 public:
839 Property(Expression* obj, Expression* key, int pos)
840 : obj_(obj), key_(key), pos_(pos) { }
841
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000842 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843
844 // Type testing & conversion
845 virtual Property* AsProperty() { return this; }
846
847 virtual bool IsValidLeftHandSide() { return true; }
848
849 Expression* obj() const { return obj_; }
850 Expression* key() const { return key_; }
851 int position() const { return pos_; }
852
853 // Returns a property singleton property access on 'this'. Used
854 // during preparsing.
855 static Property* this_property() { return &this_property_; }
856
857 private:
858 Expression* obj_;
859 Expression* key_;
860 int pos_;
861
862 // Dummy property used during preparsing
863 static Property this_property_;
864};
865
866
867class Call: public Expression {
868 public:
869 Call(Expression* expression,
870 ZoneList<Expression*>* arguments,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871 int pos)
872 : expression_(expression),
873 arguments_(arguments),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874 pos_(pos) { }
875
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000876 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877
878 // Type testing and conversion.
879 virtual Call* AsCall() { return this; }
880
881 Expression* expression() const { return expression_; }
882 ZoneList<Expression*>* arguments() const { return arguments_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000883 int position() { return pos_; }
884
885 static Call* sentinel() { return &sentinel_; }
886
887 private:
888 Expression* expression_;
889 ZoneList<Expression*>* arguments_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890 int pos_;
891
892 static Call sentinel_;
893};
894
895
896class CallNew: public Call {
897 public:
898 CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000899 : Call(expression, arguments, pos) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000901 virtual void Accept(AstVisitor* v);
902};
903
904
905// The CallEval class represents a call of the form 'eval(...)' where eval
906// cannot be seen to be overwritten at compile time. It is potentially a
907// direct (i.e. not aliased) eval call. The real nature of the call is
908// determined at runtime.
909class CallEval: public Call {
910 public:
911 CallEval(Expression* expression, ZoneList<Expression*>* arguments, int pos)
912 : Call(expression, arguments, pos) { }
913
914 virtual void Accept(AstVisitor* v);
915
916 static CallEval* sentinel() { return &sentinel_; }
917
918 private:
919 static CallEval sentinel_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000920};
921
922
923// The CallRuntime class does not represent any official JavaScript
924// language construct. Instead it is used to call a C or JS function
925// with a set of arguments. This is used from the builtins that are
926// implemented in JavaScript (see "v8natives.js").
927class CallRuntime: public Expression {
928 public:
929 CallRuntime(Handle<String> name,
930 Runtime::Function* function,
931 ZoneList<Expression*>* arguments)
932 : name_(name), function_(function), arguments_(arguments) { }
933
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000934 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000935
936 Handle<String> name() const { return name_; }
937 Runtime::Function* function() const { return function_; }
938 ZoneList<Expression*>* arguments() const { return arguments_; }
939
940 private:
941 Handle<String> name_;
942 Runtime::Function* function_;
943 ZoneList<Expression*>* arguments_;
944};
945
946
947class UnaryOperation: public Expression {
948 public:
949 UnaryOperation(Token::Value op, Expression* expression)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000950 : op_(op), expression_(expression) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000951 ASSERT(Token::IsUnaryOp(op));
952 }
953
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000954 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000955
956 // Type testing & conversion
957 virtual UnaryOperation* AsUnaryOperation() { return this; }
958
959 Token::Value op() const { return op_; }
960 Expression* expression() const { return expression_; }
961
962 private:
963 Token::Value op_;
964 Expression* expression_;
965};
966
967
968class BinaryOperation: public Expression {
969 public:
970 BinaryOperation(Token::Value op, Expression* left, Expression* right)
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000971 : op_(op), left_(left), right_(right) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000972 ASSERT(Token::IsBinaryOp(op));
973 }
974
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000975 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000976
977 // Type testing & conversion
978 virtual BinaryOperation* AsBinaryOperation() { return this; }
979
980 // True iff the result can be safely overwritten (to avoid allocation).
981 // False for operations that can return one of their operands.
982 bool ResultOverwriteAllowed() {
983 switch (op_) {
984 case Token::COMMA:
985 case Token::OR:
986 case Token::AND:
987 return false;
988 case Token::BIT_OR:
989 case Token::BIT_XOR:
990 case Token::BIT_AND:
991 case Token::SHL:
992 case Token::SAR:
993 case Token::SHR:
994 case Token::ADD:
995 case Token::SUB:
996 case Token::MUL:
997 case Token::DIV:
998 case Token::MOD:
999 return true;
1000 default:
1001 UNREACHABLE();
1002 }
1003 return false;
1004 }
1005
1006 Token::Value op() const { return op_; }
1007 Expression* left() const { return left_; }
1008 Expression* right() const { return right_; }
1009
1010 private:
1011 Token::Value op_;
1012 Expression* left_;
1013 Expression* right_;
1014};
1015
1016
1017class CountOperation: public Expression {
1018 public:
1019 CountOperation(bool is_prefix, Token::Value op, Expression* expression)
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001020 : is_prefix_(is_prefix), op_(op), expression_(expression) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001021 ASSERT(Token::IsCountOp(op));
1022 }
1023
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001024 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001025
1026 bool is_prefix() const { return is_prefix_; }
1027 bool is_postfix() const { return !is_prefix_; }
1028 Token::Value op() const { return op_; }
1029 Expression* expression() const { return expression_; }
1030
1031 virtual void MarkAsStatement() { is_prefix_ = true; }
1032
1033 private:
1034 bool is_prefix_;
1035 Token::Value op_;
1036 Expression* expression_;
1037};
1038
1039
1040class CompareOperation: public Expression {
1041 public:
1042 CompareOperation(Token::Value op, Expression* left, Expression* right)
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001043 : op_(op), left_(left), right_(right) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001044 ASSERT(Token::IsCompareOp(op));
1045 }
1046
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001047 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001048
1049 Token::Value op() const { return op_; }
1050 Expression* left() const { return left_; }
1051 Expression* right() const { return right_; }
1052
1053 private:
1054 Token::Value op_;
1055 Expression* left_;
1056 Expression* right_;
1057};
1058
1059
1060class Conditional: public Expression {
1061 public:
1062 Conditional(Expression* condition,
1063 Expression* then_expression,
1064 Expression* else_expression)
1065 : condition_(condition),
1066 then_expression_(then_expression),
1067 else_expression_(else_expression) { }
1068
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001069 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001070
1071 Expression* condition() const { return condition_; }
1072 Expression* then_expression() const { return then_expression_; }
1073 Expression* else_expression() const { return else_expression_; }
1074
1075 private:
1076 Expression* condition_;
1077 Expression* then_expression_;
1078 Expression* else_expression_;
1079};
1080
1081
1082class Assignment: public Expression {
1083 public:
1084 Assignment(Token::Value op, Expression* target, Expression* value, int pos)
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001085 : op_(op), target_(target), value_(value), pos_(pos) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086 ASSERT(Token::IsAssignmentOp(op));
1087 }
1088
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001089 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001090 virtual Assignment* AsAssignment() { return this; }
1091
1092 Token::Value binary_op() const;
1093
1094 Token::Value op() const { return op_; }
1095 Expression* target() const { return target_; }
1096 Expression* value() const { return value_; }
1097 int position() { return pos_; }
1098
1099 private:
1100 Token::Value op_;
1101 Expression* target_;
1102 Expression* value_;
1103 int pos_;
1104};
1105
1106
1107class Throw: public Expression {
1108 public:
1109 Throw(Expression* exception, int pos)
1110 : exception_(exception), pos_(pos) {}
1111
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001112 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001113 Expression* exception() const { return exception_; }
1114 int position() const { return pos_; }
1115
1116 private:
1117 Expression* exception_;
1118 int pos_;
1119};
1120
1121
1122class FunctionLiteral: public Expression {
1123 public:
1124 FunctionLiteral(Handle<String> name,
1125 Scope* scope,
1126 ZoneList<Statement*>* body,
1127 int materialized_literal_count,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001128 bool contains_array_literal,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001129 int expected_property_count,
1130 int num_parameters,
1131 int start_position,
1132 int end_position,
1133 bool is_expression)
1134 : name_(name),
1135 scope_(scope),
1136 body_(body),
1137 materialized_literal_count_(materialized_literal_count),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001138 contains_array_literal_(contains_array_literal),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001139 expected_property_count_(expected_property_count),
1140 num_parameters_(num_parameters),
1141 start_position_(start_position),
1142 end_position_(end_position),
1143 is_expression_(is_expression),
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001144 loop_nesting_(0),
ager@chromium.org236ad962008-09-25 09:45:57 +00001145 function_token_position_(RelocInfo::kNoPosition) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146 }
1147
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001148 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001149
1150 // Type testing & conversion
1151 virtual FunctionLiteral* AsFunctionLiteral() { return this; }
1152
1153 Handle<String> name() const { return name_; }
1154 Scope* scope() const { return scope_; }
1155 ZoneList<Statement*>* body() const { return body_; }
1156 void set_function_token_position(int pos) { function_token_position_ = pos; }
1157 int function_token_position() const { return function_token_position_; }
1158 int start_position() const { return start_position_; }
1159 int end_position() const { return end_position_; }
1160 bool is_expression() const { return is_expression_; }
1161
1162 int materialized_literal_count() { return materialized_literal_count_; }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001163 bool contains_array_literal() { return contains_array_literal_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001164 int expected_property_count() { return expected_property_count_; }
1165 int num_parameters() { return num_parameters_; }
1166
1167 bool AllowsLazyCompilation();
1168
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001169 bool loop_nesting() const { return loop_nesting_; }
1170 void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
1171
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172 private:
1173 Handle<String> name_;
1174 Scope* scope_;
1175 ZoneList<Statement*>* body_;
1176 int materialized_literal_count_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001177 bool contains_array_literal_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001178 int expected_property_count_;
1179 int num_parameters_;
1180 int start_position_;
1181 int end_position_;
1182 bool is_expression_;
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001183 int loop_nesting_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001184 int function_token_position_;
1185};
1186
1187
1188class FunctionBoilerplateLiteral: public Expression {
1189 public:
1190 explicit FunctionBoilerplateLiteral(Handle<JSFunction> boilerplate)
1191 : boilerplate_(boilerplate) {
1192 ASSERT(boilerplate->IsBoilerplate());
1193 }
1194
1195 Handle<JSFunction> boilerplate() const { return boilerplate_; }
1196
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001197 virtual void Accept(AstVisitor* v);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001198
1199 private:
1200 Handle<JSFunction> boilerplate_;
1201};
1202
1203
1204class ThisFunction: public Expression {
1205 public:
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001206 virtual void Accept(AstVisitor* v);
1207};
1208
1209
1210// ----------------------------------------------------------------------------
1211// Regular expressions
1212
1213
1214class RegExpTree: public ZoneObject {
1215 public:
1216 virtual ~RegExpTree() { }
1217 virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
1218 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1219 RegExpNode* on_success,
1220 RegExpNode* on_failure) = 0;
1221 virtual bool IsTextElement() { return false; }
1222 virtual void AppendToText(RegExpText* text);
1223 SmartPointer<const char> ToString();
1224#define MAKE_ASTYPE(Name) \
1225 virtual RegExp##Name* As##Name(); \
1226 virtual bool Is##Name();
1227 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE)
1228#undef MAKE_ASTYPE
1229};
1230
1231
1232class RegExpDisjunction: public RegExpTree {
1233 public:
1234 explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
1235 : alternatives_(alternatives) { }
1236 virtual void* Accept(RegExpVisitor* visitor, void* data);
1237 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1238 RegExpNode* on_success,
1239 RegExpNode* on_failure);
1240 virtual RegExpDisjunction* AsDisjunction();
1241 virtual bool IsDisjunction();
1242 ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
1243 private:
1244 ZoneList<RegExpTree*>* alternatives_;
1245};
1246
1247
1248class RegExpAlternative: public RegExpTree {
1249 public:
1250 explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes) : nodes_(nodes) { }
1251 virtual void* Accept(RegExpVisitor* visitor, void* data);
1252 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1253 RegExpNode* on_success,
1254 RegExpNode* on_failure);
1255 virtual RegExpAlternative* AsAlternative();
1256 virtual bool IsAlternative();
1257 ZoneList<RegExpTree*>* nodes() { return nodes_; }
1258 private:
1259 ZoneList<RegExpTree*>* nodes_;
1260};
1261
1262
1263class RegExpText: public RegExpTree {
1264 public:
1265 RegExpText() : elements_(2) { }
1266 virtual void* Accept(RegExpVisitor* visitor, void* data);
1267 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1268 RegExpNode* on_success,
1269 RegExpNode* on_failure);
1270 virtual RegExpText* AsText();
1271 virtual bool IsText();
1272 virtual bool IsTextElement() { return true; }
1273 virtual void AppendToText(RegExpText* text);
1274 void AddElement(TextElement elm) { elements_.Add(elm); }
1275 ZoneList<TextElement>* elements() { return &elements_; }
1276 private:
1277 ZoneList<TextElement> elements_;
1278};
1279
1280
1281class RegExpAssertion: public RegExpTree {
1282 public:
1283 enum Type {
1284 START_OF_LINE,
1285 START_OF_INPUT,
1286 END_OF_LINE,
1287 END_OF_INPUT,
1288 BOUNDARY,
1289 NON_BOUNDARY
1290 };
1291 explicit RegExpAssertion(Type type) : type_(type) { }
1292 virtual void* Accept(RegExpVisitor* visitor, void* data);
1293 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1294 RegExpNode* on_success,
1295 RegExpNode* on_failure);
1296 virtual RegExpAssertion* AsAssertion();
1297 virtual bool IsAssertion();
1298 Type type() { return type_; }
1299 private:
1300 Type type_;
1301};
1302
1303
1304class RegExpCharacterClass: public RegExpTree {
1305 public:
1306 RegExpCharacterClass(ZoneList<CharacterRange>* ranges, bool is_negated)
1307 : ranges_(ranges),
1308 is_negated_(is_negated) { }
1309 explicit RegExpCharacterClass(uc16 type)
1310 : ranges_(new ZoneList<CharacterRange>(2)),
1311 is_negated_(false) {
1312 CharacterRange::AddClassEscape(type, ranges_);
1313 }
1314 virtual void* Accept(RegExpVisitor* visitor, void* data);
1315 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1316 RegExpNode* on_success,
1317 RegExpNode* on_failure);
1318 virtual RegExpCharacterClass* AsCharacterClass();
1319 virtual bool IsCharacterClass();
1320 virtual bool IsTextElement() { return true; }
1321 virtual void AppendToText(RegExpText* text);
1322 ZoneList<CharacterRange>* ranges() { return ranges_; }
1323 bool is_negated() { return is_negated_; }
1324 private:
1325 ZoneList<CharacterRange>* ranges_;
1326 bool is_negated_;
1327};
1328
1329
1330class RegExpAtom: public RegExpTree {
1331 public:
1332 explicit RegExpAtom(Vector<const uc16> data) : data_(data) { }
1333 virtual void* Accept(RegExpVisitor* visitor, void* data);
1334 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1335 RegExpNode* on_success,
1336 RegExpNode* on_failure);
1337 virtual RegExpAtom* AsAtom();
1338 virtual bool IsAtom();
1339 virtual bool IsTextElement() { return true; }
1340 virtual void AppendToText(RegExpText* text);
1341 Vector<const uc16> data() { return data_; }
1342 private:
1343 Vector<const uc16> data_;
1344};
1345
1346
1347class RegExpQuantifier: public RegExpTree {
1348 public:
1349 RegExpQuantifier(int min, int max, bool is_greedy, RegExpTree* body)
1350 : min_(min),
1351 max_(max),
1352 is_greedy_(is_greedy),
1353 body_(body) { }
1354 virtual void* Accept(RegExpVisitor* visitor, void* data);
1355 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1356 RegExpNode* on_success,
1357 RegExpNode* on_failure);
1358 static RegExpNode* ToNode(int min,
1359 int max,
1360 bool is_greedy,
1361 RegExpTree* body,
1362 RegExpCompiler* compiler,
1363 RegExpNode* on_success,
1364 RegExpNode* on_failure);
1365 virtual RegExpQuantifier* AsQuantifier();
1366 virtual bool IsQuantifier();
1367 int min() { return min_; }
1368 int max() { return max_; }
1369 bool is_greedy() { return is_greedy_; }
1370 RegExpTree* body() { return body_; }
1371 // We just use a very large integer value as infinity because 2^30
1372 // is infinite in practice.
1373 static const int kInfinity = (1 << 30);
1374 private:
1375 int min_;
1376 int max_;
1377 bool is_greedy_;
1378 RegExpTree* body_;
1379};
1380
1381
1382enum CaptureAvailability {
1383 CAPTURE_AVAILABLE,
1384 CAPTURE_UNREACHABLE,
1385 CAPTURE_PERMANENTLY_UNREACHABLE
1386};
1387
1388class RegExpCapture: public RegExpTree {
1389 public:
1390 explicit RegExpCapture(RegExpTree* body, int index)
1391 : body_(body), index_(index), available_(CAPTURE_AVAILABLE) { }
1392 virtual void* Accept(RegExpVisitor* visitor, void* data);
1393 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1394 RegExpNode* on_success,
1395 RegExpNode* on_failure);
1396 static RegExpNode* ToNode(RegExpTree* body,
1397 int index,
1398 RegExpCompiler* compiler,
1399 RegExpNode* on_success,
1400 RegExpNode* on_failure);
1401 virtual RegExpCapture* AsCapture();
1402 virtual bool IsCapture();
1403 RegExpTree* body() { return body_; }
1404 int index() { return index_; }
1405 inline CaptureAvailability available() { return available_; }
1406 inline void set_available(CaptureAvailability availability) {
1407 available_ = availability;
1408 }
1409 static int StartRegister(int index) { return index * 2; }
1410 static int EndRegister(int index) { return index * 2 + 1; }
1411 private:
1412 RegExpTree* body_;
1413 int index_;
1414 CaptureAvailability available_;
1415};
1416
1417
1418class RegExpLookahead: public RegExpTree {
1419 public:
1420 RegExpLookahead(RegExpTree* body, bool is_positive)
1421 : body_(body),
1422 is_positive_(is_positive) { }
1423 virtual void* Accept(RegExpVisitor* visitor, void* data);
1424 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1425 RegExpNode* on_success,
1426 RegExpNode* on_failure);
1427 virtual RegExpLookahead* AsLookahead();
1428 virtual bool IsLookahead();
1429 RegExpTree* body() { return body_; }
1430 bool is_positive() { return is_positive_; }
1431 private:
1432 RegExpTree* body_;
1433 bool is_positive_;
1434};
1435
1436
1437class RegExpBackReference: public RegExpTree {
1438 public:
1439 explicit RegExpBackReference(RegExpCapture* capture)
1440 : capture_(capture) { }
1441 virtual void* Accept(RegExpVisitor* visitor, void* data);
1442 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1443 RegExpNode* on_success,
1444 RegExpNode* on_failure);
1445 virtual RegExpBackReference* AsBackReference();
1446 virtual bool IsBackReference();
1447 int index() { return capture_->index(); }
1448 RegExpCapture* capture() { return capture_; }
1449 private:
1450 RegExpCapture* capture_;
1451};
1452
1453
1454class RegExpEmpty: public RegExpTree {
1455 public:
1456 RegExpEmpty() { }
1457 virtual void* Accept(RegExpVisitor* visitor, void* data);
1458 virtual RegExpNode* ToNode(RegExpCompiler* compiler,
1459 RegExpNode* on_success,
1460 RegExpNode* on_failure);
1461 virtual RegExpEmpty* AsEmpty();
1462 virtual bool IsEmpty();
1463 static RegExpEmpty* GetInstance() { return &kInstance; }
1464 private:
1465 static RegExpEmpty kInstance;
1466};
1467
1468
1469class RegExpVisitor BASE_EMBEDDED {
1470 public:
1471 virtual ~RegExpVisitor() { }
1472#define MAKE_CASE(Name) \
1473 virtual void* Visit##Name(RegExp##Name*, void* data) = 0;
1474 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
1475#undef MAKE_CASE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476};
1477
1478
1479// ----------------------------------------------------------------------------
1480// Basic visitor
1481// - leaf node visitors are abstract.
1482
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001483class AstVisitor BASE_EMBEDDED {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001484 public:
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001485 AstVisitor() : stack_overflow_(false) { }
1486 virtual ~AstVisitor() { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001487
1488 // Dispatch
1489 void Visit(Node* node) { node->Accept(this); }
1490
1491 // Iteration
1492 virtual void VisitStatements(ZoneList<Statement*>* statements);
1493 virtual void VisitExpressions(ZoneList<Expression*>* expressions);
1494
1495 // Stack overflow tracking support.
1496 bool HasStackOverflow() const { return stack_overflow_; }
1497 bool CheckStackOverflow() {
1498 if (stack_overflow_) return true;
1499 StackLimitCheck check;
1500 if (!check.HasOverflowed()) return false;
1501 return (stack_overflow_ = true);
1502 }
1503
kasper.lund212ac232008-07-16 07:07:30 +00001504 // If a stack-overflow exception is encountered when visiting a
1505 // node, calling SetStackOverflow will make sure that the visitor
1506 // bails out without visiting more nodes.
1507 void SetStackOverflow() { stack_overflow_ = true; }
1508
1509
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 // Individual nodes
1511#define DEF_VISIT(type) \
1512 virtual void Visit##type(type* node) = 0;
1513 NODE_LIST(DEF_VISIT)
1514#undef DEF_VISIT
1515
1516 private:
1517 bool stack_overflow_;
1518};
1519
1520
1521} } // namespace v8::internal
1522
1523#endif // V8_AST_H_