blob: 1a5e0e0486aa3ad0231f5e741de19caf2f8fbb49 [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// Copyright 2006-2008 Google Inc. All Rights Reserved.
2// 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"
37
38namespace v8 { namespace internal {
39
40// The abstract syntax tree is an intermediate, light-weight
41// representation of the parsed JavaScript code suitable for
42// compilation to native code.
43
44// Nodes are allocated in a separate zone, which allows faster
45// allocation and constant-time deallocation of the entire syntax
46// tree.
47
48
49// ----------------------------------------------------------------------------
50// Nodes of the abstract syntax tree. Only concrete classes are
51// enumerated here.
52
53#define NODE_LIST(V) \
54 V(Block) \
55 V(Declaration) \
56 V(ExpressionStatement) \
57 V(EmptyStatement) \
58 V(IfStatement) \
59 V(ContinueStatement) \
60 V(BreakStatement) \
61 V(ReturnStatement) \
62 V(WithEnterStatement) \
63 V(WithExitStatement) \
64 V(SwitchStatement) \
65 V(LoopStatement) \
66 V(ForInStatement) \
67 V(TryCatch) \
68 V(TryFinally) \
69 V(DebuggerStatement) \
70 V(FunctionLiteral) \
71 V(FunctionBoilerplateLiteral) \
72 V(Conditional) \
73 V(Slot) \
74 V(VariableProxy) \
75 V(Literal) \
76 V(RegExpLiteral) \
77 V(ObjectLiteral) \
78 V(ArrayLiteral) \
79 V(Assignment) \
80 V(Throw) \
81 V(Property) \
82 V(Call) \
83 V(CallNew) \
84 V(CallRuntime) \
85 V(UnaryOperation) \
86 V(CountOperation) \
87 V(BinaryOperation) \
88 V(CompareOperation) \
89 V(ThisFunction)
90
91
92#define DEF_FORWARD_DECLARATION(type) class type;
93NODE_LIST(DEF_FORWARD_DECLARATION)
94#undef DEF_FORWARD_DECLARATION
95
96
97// Typedef only introduced to avoid unreadable code.
98// Please do appreciate the required space in "> >".
99typedef ZoneList<Handle<String> > ZoneStringList;
100
101
102class Node: public ZoneObject {
103 public:
104 Node(): statement_pos_(kNoPosition) { }
105 virtual ~Node() { }
106 virtual void Accept(Visitor* v) = 0;
107
108 // Type testing & conversion.
109 virtual Statement* AsStatement() { return NULL; }
110 virtual ExpressionStatement* AsExpressionStatement() { return NULL; }
111 virtual EmptyStatement* AsEmptyStatement() { return NULL; }
112 virtual Expression* AsExpression() { return NULL; }
113 virtual Literal* AsLiteral() { return NULL; }
114 virtual Slot* AsSlot() { return NULL; }
115 virtual VariableProxy* AsVariableProxy() { return NULL; }
116 virtual Property* AsProperty() { return NULL; }
117 virtual Call* AsCall() { return NULL; }
118 virtual LabelCollector* AsLabelCollector() { return NULL; }
119 virtual BreakableStatement* AsBreakableStatement() { return NULL; }
120 virtual IterationStatement* AsIterationStatement() { return NULL; }
121 virtual UnaryOperation* AsUnaryOperation() { return NULL; }
122 virtual BinaryOperation* AsBinaryOperation() { return NULL; }
123 virtual Assignment* AsAssignment() { return NULL; }
124 virtual FunctionLiteral* AsFunctionLiteral() { return NULL; }
125
126 void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
127 int statement_pos() const { return statement_pos_; }
128
129 private:
130 int statement_pos_;
131};
132
133
134class Statement: public Node {
135 public:
136 virtual Statement* AsStatement() { return this; }
137 virtual ReturnStatement* AsReturnStatement() { return NULL; }
138
139 bool IsEmpty() { return AsEmptyStatement() != NULL; }
140};
141
142
143class Expression: public Node {
144 public:
145 virtual Expression* AsExpression() { return this; }
146
147 virtual bool IsValidLeftHandSide() { return false; }
148
149 // Mark the expression as being compiled as an expression
150 // statement. This is used to transform postfix increments to
151 // (faster) prefix increments.
152 virtual void MarkAsStatement() { /* do nothing */ }
153};
154
155
156/**
157 * A sentinel used during pre parsing that represents some expression
158 * that is a valid left hand side without having to actually build
159 * the expression.
160 */
161class ValidLeftHandSideSentinel: public Expression {
162 public:
163 virtual bool IsValidLeftHandSide() { return true; }
164 virtual void Accept(Visitor* v) { UNREACHABLE(); }
165 static ValidLeftHandSideSentinel* instance() { return &instance_; }
166 private:
167 static ValidLeftHandSideSentinel instance_;
168};
169
170
171class BreakableStatement: public Statement {
172 public:
173 enum Type {
174 TARGET_FOR_ANONYMOUS,
175 TARGET_FOR_NAMED_ONLY
176 };
177
178 // The labels associated with this statement. May be NULL;
179 // if it is != NULL, guaranteed to contain at least one entry.
180 ZoneStringList* labels() const { return labels_; }
181
182 // Type testing & conversion.
183 virtual BreakableStatement* AsBreakableStatement() { return this; }
184
185 // Code generation
186 Label* break_target() { return &break_target_; }
187
188 // Used during code generation for restoring the stack when a
189 // break/continue crosses a statement that keeps stuff on the stack.
190 int break_stack_height() { return break_stack_height_; }
191 void set_break_stack_height(int height) { break_stack_height_ = height; }
192
193 // Testers.
194 bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; }
195
196 protected:
197 BreakableStatement(ZoneStringList* labels, Type type)
198 : labels_(labels), type_(type) {
199 ASSERT(labels == NULL || labels->length() > 0);
200 }
201
202 private:
203 ZoneStringList* labels_;
204 Type type_;
205 Label break_target_;
206 int break_stack_height_;
207};
208
209
210class Block: public BreakableStatement {
211 public:
212 Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
213 : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
214 statements_(capacity),
215 is_initializer_block_(is_initializer_block) { }
216
217 virtual void Accept(Visitor* v);
218
219 void AddStatement(Statement* statement) { statements_.Add(statement); }
220
221 ZoneList<Statement*>* statements() { return &statements_; }
222 bool is_initializer_block() const { return is_initializer_block_; }
223
224 private:
225 ZoneList<Statement*> statements_;
226 bool is_initializer_block_;
227};
228
229
230class Declaration: public Node {
231 public:
232 Declaration(VariableProxy* proxy, Variable::Mode mode, FunctionLiteral* fun)
233 : proxy_(proxy),
234 mode_(mode),
235 fun_(fun) {
236 ASSERT(mode == Variable::VAR || mode == Variable::CONST);
237 // At the moment there are no "const functions"'s in JavaScript...
238 ASSERT(fun == NULL || mode == Variable::VAR);
239 }
240
241 virtual void Accept(Visitor* v);
242
243 VariableProxy* proxy() const { return proxy_; }
244 Variable::Mode mode() const { return mode_; }
245 FunctionLiteral* fun() const { return fun_; } // may be NULL
246
247 private:
248 VariableProxy* proxy_;
249 Variable::Mode mode_;
250 FunctionLiteral* fun_;
251};
252
253
254class IterationStatement: public BreakableStatement {
255 public:
256 // Type testing & conversion.
257 virtual IterationStatement* AsIterationStatement() { return this; }
258
259 Statement* body() const { return body_; }
260
261 // Code generation
262 Label* continue_target() { return &continue_target_; }
263
264 protected:
265 explicit IterationStatement(ZoneStringList* labels)
266 : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { }
267
268 void Initialize(Statement* body) {
269 body_ = body;
270 }
271
272 private:
273 Statement* body_;
274 Label continue_target_;
275};
276
277
278class LoopStatement: public IterationStatement {
279 public:
280 enum Type { DO_LOOP, FOR_LOOP, WHILE_LOOP };
281
282 LoopStatement(ZoneStringList* labels, Type type)
283 : IterationStatement(labels), type_(type), init_(NULL),
284 cond_(NULL), next_(NULL) { }
285
286 void Initialize(Statement* init,
287 Expression* cond,
288 Statement* next,
289 Statement* body) {
290 ASSERT(init == NULL || type_ == FOR_LOOP);
291 ASSERT(next == NULL || type_ == FOR_LOOP);
292 IterationStatement::Initialize(body);
293 init_ = init;
294 cond_ = cond;
295 next_ = next;
296 }
297
298 virtual void Accept(Visitor* v);
299
300 Type type() const { return type_; }
301 Statement* init() const { return init_; }
302 Expression* cond() const { return cond_; }
303 Statement* next() const { return next_; }
304
305#ifdef DEBUG
306 const char* OperatorString() const;
307#endif
308
309 private:
310 Type type_;
311 Statement* init_;
312 Expression* cond_;
313 Statement* next_;
314};
315
316
317class ForInStatement: public IterationStatement {
318 public:
319 explicit ForInStatement(ZoneStringList* labels)
320 : IterationStatement(labels), each_(NULL), enumerable_(NULL) { }
321
322 void Initialize(Expression* each, Expression* enumerable, Statement* body) {
323 IterationStatement::Initialize(body);
324 each_ = each;
325 enumerable_ = enumerable;
326 }
327
328 virtual void Accept(Visitor* v);
329
330 Expression* each() const { return each_; }
331 Expression* enumerable() const { return enumerable_; }
332
333 private:
334 Expression* each_;
335 Expression* enumerable_;
336};
337
338
339class ExpressionStatement: public Statement {
340 public:
341 explicit ExpressionStatement(Expression* expression)
342 : expression_(expression) { }
343
344 virtual void Accept(Visitor* v);
345
346 // Type testing & conversion.
347 virtual ExpressionStatement* AsExpressionStatement() { return this; }
348
349 void set_expression(Expression* e) { expression_ = e; }
350 Expression* expression() { return expression_; }
351
352 private:
353 Expression* expression_;
354};
355
356
357class ContinueStatement: public Statement {
358 public:
359 explicit ContinueStatement(IterationStatement* target)
360 : target_(target) { }
361
362 virtual void Accept(Visitor* v);
363
364 IterationStatement* target() const { return target_; }
365
366 private:
367 IterationStatement* target_;
368};
369
370
371class BreakStatement: public Statement {
372 public:
373 explicit BreakStatement(BreakableStatement* target)
374 : target_(target) { }
375
376 virtual void Accept(Visitor* v);
377
378 BreakableStatement* target() const { return target_; }
379
380 private:
381 BreakableStatement* target_;
382};
383
384
385class ReturnStatement: public Statement {
386 public:
387 explicit ReturnStatement(Expression* expression)
388 : expression_(expression) { }
389
390 virtual void Accept(Visitor* v);
391
392 // Type testing & conversion.
393 virtual ReturnStatement* AsReturnStatement() { return this; }
394
395 Expression* expression() { return expression_; }
396
397 private:
398 Expression* expression_;
399};
400
401
402class WithEnterStatement: public Statement {
403 public:
404 explicit WithEnterStatement(Expression* expression)
405 : expression_(expression) { }
406
407 virtual void Accept(Visitor* v);
408
409 Expression* expression() const { return expression_; }
410
411 private:
412 Expression* expression_;
413};
414
415
416class WithExitStatement: public Statement {
417 public:
418 WithExitStatement() { }
419
420 virtual void Accept(Visitor* v);
421};
422
423
424class CaseClause: public ZoneObject {
425 public:
426 CaseClause(Expression* label, ZoneList<Statement*>* statements)
427 : label_(label), statements_(statements) { }
428
429 bool is_default() const { return label_ == NULL; }
430 Expression* label() const {
431 CHECK(!is_default());
432 return label_;
433 }
434 ZoneList<Statement*>* statements() const { return statements_; }
435
436 private:
437 Expression* label_;
438 ZoneList<Statement*>* statements_;
439};
440
441
442class SwitchStatement: public BreakableStatement {
443 public:
444 explicit SwitchStatement(ZoneStringList* labels)
445 : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
446 tag_(NULL), cases_(NULL) { }
447
448 void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
449 tag_ = tag;
450 cases_ = cases;
451 }
452
453 virtual void Accept(Visitor* v);
454
455 Expression* tag() const { return tag_; }
456 ZoneList<CaseClause*>* cases() const { return cases_; }
457
458 private:
459 Expression* tag_;
460 ZoneList<CaseClause*>* cases_;
461};
462
463
464// If-statements always have non-null references to their then- and
465// else-parts. When parsing if-statements with no explicit else-part,
466// the parser implicitly creates an empty statement. Use the
467// HasThenStatement() and HasElseStatement() functions to check if a
468// given if-statement has a then- or an else-part containing code.
469class IfStatement: public Statement {
470 public:
471 IfStatement(Expression* condition,
472 Statement* then_statement,
473 Statement* else_statement)
474 : condition_(condition),
475 then_statement_(then_statement),
476 else_statement_(else_statement) { }
477
478 virtual void Accept(Visitor* v);
479
480 bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
481 bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
482
483 Expression* condition() const { return condition_; }
484 Statement* then_statement() const { return then_statement_; }
485 Statement* else_statement() const { return else_statement_; }
486
487 private:
488 Expression* condition_;
489 Statement* then_statement_;
490 Statement* else_statement_;
491};
492
493
494// NOTE: LabelCollectors are represented as nodes to fit in the target
495// stack in the compiler; this should probably be reworked.
496class LabelCollector: public Node {
497 public:
498 explicit LabelCollector(ZoneList<Label*>* labels) : labels_(labels) { }
499
500 // Adds a label to the collector. The collector stores a pointer not
501 // a copy of the label to make binding work, so make sure not to
502 // pass in references to something on the stack.
503 void AddLabel(Label* label);
504
505 // Virtual behaviour. LabelCollectors are never part of the AST.
506 virtual void Accept(Visitor* v) { UNREACHABLE(); }
507 virtual LabelCollector* AsLabelCollector() { return this; }
508
509 ZoneList<Label*>* labels() { return labels_; }
510
511 private:
512 ZoneList<Label*>* labels_;
513};
514
515
516class TryStatement: public Statement {
517 public:
518 explicit TryStatement(Block* try_block)
519 : try_block_(try_block), escaping_labels_(NULL) { }
520
521 void set_escaping_labels(ZoneList<Label*>* labels) {
522 escaping_labels_ = labels;
523 }
524
525 Block* try_block() const { return try_block_; }
526 ZoneList<Label*>* escaping_labels() const { return escaping_labels_; }
527
528 private:
529 Block* try_block_;
530 ZoneList<Label*>* escaping_labels_;
531};
532
533
534class TryCatch: public TryStatement {
535 public:
536 TryCatch(Block* try_block, Expression* catch_var, Block* catch_block)
537 : TryStatement(try_block),
538 catch_var_(catch_var),
539 catch_block_(catch_block) {
540 ASSERT(catch_var->AsVariableProxy() != NULL);
541 }
542
543 virtual void Accept(Visitor* v);
544
545 Expression* catch_var() const { return catch_var_; }
546 Block* catch_block() const { return catch_block_; }
547
548 private:
549 Expression* catch_var_;
550 Block* catch_block_;
551};
552
553
554class TryFinally: public TryStatement {
555 public:
556 TryFinally(Block* try_block, Expression* finally_var, Block* finally_block)
557 : TryStatement(try_block),
558 finally_var_(finally_var),
559 finally_block_(finally_block) { }
560
561 virtual void Accept(Visitor* v);
562
563 // If the finally block is non-trivial it may be problematic to have
564 // extra stuff on the expression stack while evaluating it. The
565 // finally variable is used to hold the state instead of storing it
566 // on the stack. It may be NULL in which case the state is stored on
567 // the stack.
568 Expression* finally_var() const { return finally_var_; }
569
570 Block* finally_block() const { return finally_block_; }
571
572 private:
573 Expression* finally_var_;
574 Block* finally_block_;
575};
576
577
578class DebuggerStatement: public Statement {
579 public:
580 virtual void Accept(Visitor* v);
581};
582
583
584class EmptyStatement: public Statement {
585 public:
586 virtual void Accept(Visitor* v);
587
588 // Type testing & conversion.
589 virtual EmptyStatement* AsEmptyStatement() { return this; }
590};
591
592
593class Literal: public Expression {
594 public:
595 explicit Literal(Handle<Object> handle) : handle_(handle) { }
596
597 virtual void Accept(Visitor* v);
598
599 // Type testing & conversion.
600 virtual Literal* AsLiteral() { return this; }
601
602 // Check if this literal is identical to the other literal.
603 bool IsIdenticalTo(const Literal* other) const {
604 return handle_.is_identical_to(other->handle_);
605 }
606
607 // Identity testers.
608 bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
609 bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
610 bool IsFalse() const {
611 return handle_.is_identical_to(Factory::false_value());
612 }
613
614 Handle<Object> handle() const { return handle_; }
615
616 private:
617 Handle<Object> handle_;
618};
619
620
621// Base class for literals that needs space in the corresponding JSFunction.
622class MaterializedLiteral: public Expression {
623 public:
624 explicit MaterializedLiteral(int literal_index)
625 : literal_index_(literal_index) {}
626 int literal_index() { return literal_index_; }
627 private:
628 int literal_index_;
629};
630
631
632// An object literal has a boilerplate object that is used
633// for minimizing the work when constructing it at runtime.
634class ObjectLiteral: public MaterializedLiteral {
635 public:
636 // Property is used for passing information
637 // about an object literal's properties from the parser
638 // to the code generator.
639 class Property: public ZoneObject {
640 public:
641
642 enum Kind {
643 CONSTANT, // Property with constant value (at compile time).
644 COMPUTED, // Property with computed value (at execution time).
645 GETTER, SETTER, // Property is an accessor function.
646 PROTOTYPE // Property is __proto__.
647 };
648
649 Property(Literal* key, Expression* value);
650 Property(bool is_getter, FunctionLiteral* value);
651
652 Literal* key() { return key_; }
653 Expression* value() { return value_; }
654 Kind kind() { return kind_; }
655
656 private:
657 Literal* key_;
658 Expression* value_;
659 Kind kind_;
660 };
661
662 ObjectLiteral(Handle<FixedArray> constant_properties,
663 Expression* result,
664 ZoneList<Property*>* properties,
665 int literal_index)
666 : MaterializedLiteral(literal_index),
667 constant_properties_(constant_properties),
668 result_(result),
669 properties_(properties) {
670 }
671
672 virtual void Accept(Visitor* v);
673
674 Handle<FixedArray> constant_properties() const {
675 return constant_properties_;
676 }
677 Expression* result() const { return result_; }
678 ZoneList<Property*>* properties() const { return properties_; }
679
680 private:
681 Handle<FixedArray> constant_properties_;
682 Expression* result_;
683 ZoneList<Property*>* properties_;
684};
685
686
687// Node for capturing a regexp literal.
688class RegExpLiteral: public MaterializedLiteral {
689 public:
690 RegExpLiteral(Handle<String> pattern,
691 Handle<String> flags,
692 int literal_index)
693 : MaterializedLiteral(literal_index),
694 pattern_(pattern),
695 flags_(flags) {}
696
697 virtual void Accept(Visitor* v);
698
699 Handle<String> pattern() const { return pattern_; }
700 Handle<String> flags() const { return flags_; }
701
702 private:
703 Handle<String> pattern_;
704 Handle<String> flags_;
705};
706
707// An array literal has a literals object that is used
708// used for minimizing the work when contructing it at runtime.
709class ArrayLiteral: public Expression {
710 public:
711 ArrayLiteral(Handle<FixedArray> literals,
712 Expression* result,
713 ZoneList<Expression*>* values)
714 : literals_(literals), result_(result), values_(values) {
715 }
716
717 virtual void Accept(Visitor* v);
718
719 Handle<FixedArray> literals() const { return literals_; }
720 Expression* result() const { return result_; }
721 ZoneList<Expression*>* values() const { return values_; }
722
723 private:
724 Handle<FixedArray> literals_;
725 Expression* result_;
726 ZoneList<Expression*>* values_;
727};
728
729
730class VariableProxy: public Expression {
731 public:
732 virtual void Accept(Visitor* v);
733
734 // Type testing & conversion
735 virtual Property* AsProperty() {
736 return var_ == NULL ? NULL : var_->AsProperty();
737 }
738 virtual VariableProxy* AsVariableProxy() { return this; }
739
740 Variable* AsVariable() {
741 return this == NULL || var_ == NULL ? NULL : var_->AsVariable();
742 }
743 virtual bool IsValidLeftHandSide() {
744 return var_ == NULL ? true : var_->IsValidLeftHandSide();
745 }
746 bool IsVariable(Handle<String> n) {
747 return !is_this() && name().is_identical_to(n);
748 }
749
750 // If this assertion fails it means that some code has tried to
751 // treat the special "this" variable as an ordinary variable with
752 // the name "this".
753 Handle<String> name() const { return name_; }
754 Variable* var() const { return var_; }
755 UseCount* var_uses() { return &var_uses_; }
756 UseCount* obj_uses() { return &obj_uses_; }
757 bool is_this() const { return is_this_; }
758 bool inside_with() const { return inside_with_; }
759
760 // Bind this proxy to the variable var.
761 void BindTo(Variable* var);
762
763 protected:
764 Handle<String> name_;
765 Variable* var_; // resolved variable, or NULL
766 bool is_this_;
767 bool inside_with_;
768
769 // VariableProxy usage info.
770 UseCount var_uses_; // uses of the variable value
771 UseCount obj_uses_; // uses of the object the variable points to
772
773 VariableProxy(Handle<String> name, bool is_this, bool inside_with);
774 explicit VariableProxy(bool is_this);
775
776 friend class Scope;
777};
778
779
780class VariableProxySentinel: public VariableProxy {
781 public:
782 virtual bool IsValidLeftHandSide() { return !is_this(); }
783 static VariableProxySentinel* this_proxy() { return &this_proxy_; }
784 static VariableProxySentinel* identifier_proxy() {
785 return &identifier_proxy_;
786 }
787
788 private:
789 explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
790 static VariableProxySentinel this_proxy_;
791 static VariableProxySentinel identifier_proxy_;
792};
793
794
795class Slot: public Expression {
796 public:
797 enum Type {
798 // A slot in the parameter section on the stack. index() is
799 // the parameter index, counting left-to-right, starting at 0.
800 PARAMETER,
801
802 // A slot in the local section on the stack. index() is
803 // the variable index in the stack frame, starting at 0.
804 LOCAL,
805
806 // An indexed slot in a heap context. index() is the
807 // variable index in the context object on the heap,
808 // starting at 0. var()->scope() is the corresponding
809 // scope.
810 CONTEXT,
811
812 // A named slot in a heap context. var()->name() is the
813 // variable name in the context object on the heap,
814 // with lookup starting at the current context. index()
815 // is invalid.
816 LOOKUP,
817
818 // A property in the global object. var()->name() is
819 // the property name.
820 GLOBAL
821 };
822
823 Slot(Variable* var, Type type, int index)
824 : var_(var), type_(type), index_(index) {
825 ASSERT(var != NULL);
826 }
827
828 virtual void Accept(Visitor* v);
829
830 // Type testing & conversion
831 virtual Slot* AsSlot() { return this; }
832
833 // Accessors
834 Variable* var() const { return var_; }
835 Type type() const { return type_; }
836 int index() const { return index_; }
837
838 private:
839 Variable* var_;
840 Type type_;
841 int index_;
842};
843
844
845class Property: public Expression {
846 public:
847 Property(Expression* obj, Expression* key, int pos)
848 : obj_(obj), key_(key), pos_(pos) { }
849
850 virtual void Accept(Visitor* v);
851
852 // Type testing & conversion
853 virtual Property* AsProperty() { return this; }
854
855 virtual bool IsValidLeftHandSide() { return true; }
856
857 Expression* obj() const { return obj_; }
858 Expression* key() const { return key_; }
859 int position() const { return pos_; }
860
861 // Returns a property singleton property access on 'this'. Used
862 // during preparsing.
863 static Property* this_property() { return &this_property_; }
864
865 private:
866 Expression* obj_;
867 Expression* key_;
868 int pos_;
869
870 // Dummy property used during preparsing
871 static Property this_property_;
872};
873
874
875class Call: public Expression {
876 public:
877 Call(Expression* expression,
878 ZoneList<Expression*>* arguments,
879 bool is_eval,
880 int pos)
881 : expression_(expression),
882 arguments_(arguments),
883 is_eval_(is_eval),
884 pos_(pos) { }
885
886 virtual void Accept(Visitor* v);
887
888 // Type testing and conversion.
889 virtual Call* AsCall() { return this; }
890
891 Expression* expression() const { return expression_; }
892 ZoneList<Expression*>* arguments() const { return arguments_; }
893 bool is_eval() { return is_eval_; }
894 int position() { return pos_; }
895
896 static Call* sentinel() { return &sentinel_; }
897
898 private:
899 Expression* expression_;
900 ZoneList<Expression*>* arguments_;
901 bool is_eval_;
902 int pos_;
903
904 static Call sentinel_;
905};
906
907
908class CallNew: public Call {
909 public:
910 CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
911 : Call(expression, arguments, false, pos) { }
912
913 virtual void Accept(Visitor* v);
914};
915
916
917// The CallRuntime class does not represent any official JavaScript
918// language construct. Instead it is used to call a C or JS function
919// with a set of arguments. This is used from the builtins that are
920// implemented in JavaScript (see "v8natives.js").
921class CallRuntime: public Expression {
922 public:
923 CallRuntime(Handle<String> name,
924 Runtime::Function* function,
925 ZoneList<Expression*>* arguments)
926 : name_(name), function_(function), arguments_(arguments) { }
927
928 virtual void Accept(Visitor* v);
929
930 Handle<String> name() const { return name_; }
931 Runtime::Function* function() const { return function_; }
932 ZoneList<Expression*>* arguments() const { return arguments_; }
933
934 private:
935 Handle<String> name_;
936 Runtime::Function* function_;
937 ZoneList<Expression*>* arguments_;
938};
939
940
941class UnaryOperation: public Expression {
942 public:
943 UnaryOperation(Token::Value op, Expression* expression)
944 : op_(op), expression_(expression) {
945 ASSERT(Token::IsUnaryOp(op));
946 }
947
948 virtual void Accept(Visitor* v);
949
950 // Type testing & conversion
951 virtual UnaryOperation* AsUnaryOperation() { return this; }
952
953 Token::Value op() const { return op_; }
954 Expression* expression() const { return expression_; }
955
956 private:
957 Token::Value op_;
958 Expression* expression_;
959};
960
961
962class BinaryOperation: public Expression {
963 public:
964 BinaryOperation(Token::Value op, Expression* left, Expression* right)
965 : op_(op), left_(left), right_(right) {
966 ASSERT(Token::IsBinaryOp(op));
967 }
968
969 virtual void Accept(Visitor* v);
970
971 // Type testing & conversion
972 virtual BinaryOperation* AsBinaryOperation() { return this; }
973
974 // True iff the result can be safely overwritten (to avoid allocation).
975 // False for operations that can return one of their operands.
976 bool ResultOverwriteAllowed() {
977 switch (op_) {
978 case Token::COMMA:
979 case Token::OR:
980 case Token::AND:
981 return false;
982 case Token::BIT_OR:
983 case Token::BIT_XOR:
984 case Token::BIT_AND:
985 case Token::SHL:
986 case Token::SAR:
987 case Token::SHR:
988 case Token::ADD:
989 case Token::SUB:
990 case Token::MUL:
991 case Token::DIV:
992 case Token::MOD:
993 return true;
994 default:
995 UNREACHABLE();
996 }
997 return false;
998 }
999
1000 Token::Value op() const { return op_; }
1001 Expression* left() const { return left_; }
1002 Expression* right() const { return right_; }
1003
1004 private:
1005 Token::Value op_;
1006 Expression* left_;
1007 Expression* right_;
1008};
1009
1010
1011class CountOperation: public Expression {
1012 public:
1013 CountOperation(bool is_prefix, Token::Value op, Expression* expression)
1014 : is_prefix_(is_prefix), op_(op), expression_(expression) {
1015 ASSERT(Token::IsCountOp(op));
1016 }
1017
1018 virtual void Accept(Visitor* v);
1019
1020 bool is_prefix() const { return is_prefix_; }
1021 bool is_postfix() const { return !is_prefix_; }
1022 Token::Value op() const { return op_; }
1023 Expression* expression() const { return expression_; }
1024
1025 virtual void MarkAsStatement() { is_prefix_ = true; }
1026
1027 private:
1028 bool is_prefix_;
1029 Token::Value op_;
1030 Expression* expression_;
1031};
1032
1033
1034class CompareOperation: public Expression {
1035 public:
1036 CompareOperation(Token::Value op, Expression* left, Expression* right)
1037 : op_(op), left_(left), right_(right) {
1038 ASSERT(Token::IsCompareOp(op));
1039 }
1040
1041 virtual void Accept(Visitor* v);
1042
1043 Token::Value op() const { return op_; }
1044 Expression* left() const { return left_; }
1045 Expression* right() const { return right_; }
1046
1047 private:
1048 Token::Value op_;
1049 Expression* left_;
1050 Expression* right_;
1051};
1052
1053
1054class Conditional: public Expression {
1055 public:
1056 Conditional(Expression* condition,
1057 Expression* then_expression,
1058 Expression* else_expression)
1059 : condition_(condition),
1060 then_expression_(then_expression),
1061 else_expression_(else_expression) { }
1062
1063 virtual void Accept(Visitor* v);
1064
1065 Expression* condition() const { return condition_; }
1066 Expression* then_expression() const { return then_expression_; }
1067 Expression* else_expression() const { return else_expression_; }
1068
1069 private:
1070 Expression* condition_;
1071 Expression* then_expression_;
1072 Expression* else_expression_;
1073};
1074
1075
1076class Assignment: public Expression {
1077 public:
1078 Assignment(Token::Value op, Expression* target, Expression* value, int pos)
1079 : op_(op), target_(target), value_(value), pos_(pos) {
1080 ASSERT(Token::IsAssignmentOp(op));
1081 }
1082
1083 virtual void Accept(Visitor* v);
1084 virtual Assignment* AsAssignment() { return this; }
1085
1086 Token::Value binary_op() const;
1087
1088 Token::Value op() const { return op_; }
1089 Expression* target() const { return target_; }
1090 Expression* value() const { return value_; }
1091 int position() { return pos_; }
1092
1093 private:
1094 Token::Value op_;
1095 Expression* target_;
1096 Expression* value_;
1097 int pos_;
1098};
1099
1100
1101class Throw: public Expression {
1102 public:
1103 Throw(Expression* exception, int pos)
1104 : exception_(exception), pos_(pos) {}
1105
1106 virtual void Accept(Visitor* v);
1107 Expression* exception() const { return exception_; }
1108 int position() const { return pos_; }
1109
1110 private:
1111 Expression* exception_;
1112 int pos_;
1113};
1114
1115
1116class FunctionLiteral: public Expression {
1117 public:
1118 FunctionLiteral(Handle<String> name,
1119 Scope* scope,
1120 ZoneList<Statement*>* body,
1121 int materialized_literal_count,
1122 int expected_property_count,
1123 int num_parameters,
1124 int start_position,
1125 int end_position,
1126 bool is_expression)
1127 : name_(name),
1128 scope_(scope),
1129 body_(body),
1130 materialized_literal_count_(materialized_literal_count),
1131 expected_property_count_(expected_property_count),
1132 num_parameters_(num_parameters),
1133 start_position_(start_position),
1134 end_position_(end_position),
1135 is_expression_(is_expression),
1136 function_token_position_(kNoPosition) {
1137 }
1138
1139 virtual void Accept(Visitor* v);
1140
1141 // Type testing & conversion
1142 virtual FunctionLiteral* AsFunctionLiteral() { return this; }
1143
1144 Handle<String> name() const { return name_; }
1145 Scope* scope() const { return scope_; }
1146 ZoneList<Statement*>* body() const { return body_; }
1147 void set_function_token_position(int pos) { function_token_position_ = pos; }
1148 int function_token_position() const { return function_token_position_; }
1149 int start_position() const { return start_position_; }
1150 int end_position() const { return end_position_; }
1151 bool is_expression() const { return is_expression_; }
1152
1153 int materialized_literal_count() { return materialized_literal_count_; }
1154 int expected_property_count() { return expected_property_count_; }
1155 int num_parameters() { return num_parameters_; }
1156
1157 bool AllowsLazyCompilation();
1158
1159 private:
1160 Handle<String> name_;
1161 Scope* scope_;
1162 ZoneList<Statement*>* body_;
1163 int materialized_literal_count_;
1164 int expected_property_count_;
1165 int num_parameters_;
1166 int start_position_;
1167 int end_position_;
1168 bool is_expression_;
1169 int function_token_position_;
1170};
1171
1172
1173class FunctionBoilerplateLiteral: public Expression {
1174 public:
1175 explicit FunctionBoilerplateLiteral(Handle<JSFunction> boilerplate)
1176 : boilerplate_(boilerplate) {
1177 ASSERT(boilerplate->IsBoilerplate());
1178 }
1179
1180 Handle<JSFunction> boilerplate() const { return boilerplate_; }
1181
1182 virtual void Accept(Visitor* v);
1183
1184 private:
1185 Handle<JSFunction> boilerplate_;
1186};
1187
1188
1189class ThisFunction: public Expression {
1190 public:
1191 virtual void Accept(Visitor* v);
1192};
1193
1194
1195// ----------------------------------------------------------------------------
1196// Basic visitor
1197// - leaf node visitors are abstract.
1198
1199class Visitor BASE_EMBEDDED {
1200 public:
1201 Visitor() : stack_overflow_(false) { }
1202 virtual ~Visitor() { }
1203
1204 // Dispatch
1205 void Visit(Node* node) { node->Accept(this); }
1206
1207 // Iteration
1208 virtual void VisitStatements(ZoneList<Statement*>* statements);
1209 virtual void VisitExpressions(ZoneList<Expression*>* expressions);
1210
1211 // Stack overflow tracking support.
1212 bool HasStackOverflow() const { return stack_overflow_; }
1213 bool CheckStackOverflow() {
1214 if (stack_overflow_) return true;
1215 StackLimitCheck check;
1216 if (!check.HasOverflowed()) return false;
1217 return (stack_overflow_ = true);
1218 }
1219
kasper.lund212ac232008-07-16 07:07:30 +00001220 // If a stack-overflow exception is encountered when visiting a
1221 // node, calling SetStackOverflow will make sure that the visitor
1222 // bails out without visiting more nodes.
1223 void SetStackOverflow() { stack_overflow_ = true; }
1224
1225
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001226 // Individual nodes
1227#define DEF_VISIT(type) \
1228 virtual void Visit##type(type* node) = 0;
1229 NODE_LIST(DEF_VISIT)
1230#undef DEF_VISIT
1231
1232 private:
1233 bool stack_overflow_;
1234};
1235
1236
1237} } // namespace v8::internal
1238
1239#endif // V8_AST_H_