root/trunk/rphp/include/rphp/analysis/pAST.h @ 1049

Revision 1049, 64.0 KB (checked in by corni, 6 months ago)

Silence a clang warning about an unused parameter and add some const keywords to methods.

Line 
1/* ***** BEGIN LICENSE BLOCK *****
2;; Roadsend PHP Compiler
3;;
4;; Copyright (c) 2008-2010 Shannon Weyrick <weyrick@roadsend.com>
5;; Copyright (c) 2010 Cornelius Riemenschneider <c.r1@gmx.de>
6;;
7;; This program is free software; you can redistribute it and/or
8;; modify it under the terms of the GNU General Public License
9;; as published by the Free Software Foundation; either version 2
10;; of the License, or (at your option) any later version.
11;;
12;; This program is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public License for more details.
16;;
17;; You should have received a copy of the GNU General Public License
18;; along with this program; if not, write to the Free Software
19;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
20   ***** END LICENSE BLOCK *****
21
22 The layout of this AST has taken much inspiration from clang,
23 llvm, and kdevelop-pg, among others. Particularly, the base stmt
24 class using the bump ptr and iterators are based on the ones in the
25 AST library in clang.
26
27 http://clang.llvm.org
28 http://kdevelop.org
29
30*/
31
32#ifndef RPHP_PAST_H_
33#define RPHP_PAST_H_
34
35#include "rphp/pSourceTypes.h"
36#include "rphp/pTypes.h"
37#include "rphp/analysis/pParseContext.h"
38#include "rphp/runtime/pFunction.h"
39
40#include <vector>
41#include <iterator>
42#include <boost/range/iterator_range.hpp>
43
44#include <llvm/Support/StringPool.h>
45#include <llvm/Support/Casting.h>
46#include <llvm/ADT/SmallVector.h>
47
48namespace rphp {
49
50using llvm::isa;
51using llvm::dyn_cast;
52using llvm::cast;
53
54class pSourceModule;
55
56namespace AST {
57
58// These define how big our SmallVectors are, which means
59// this should be a good average length we expect to parse
60const int RPHP_IDLIST_SIZE = 5; // list of ids, used by extends, implements
61const int RPHP_FORMAL_PARAM_VECTOR_SIZE = 5; // formal parameters in function/method decl
62
63// a list of symbols, used for extends, implements
64typedef llvm::SmallVector<llvm::PooledStringPtr,RPHP_IDLIST_SIZE> idList;
65typedef std::vector<const pSourceRange*> sourceRangeList;
66
67enum nodeKind {
68#define STMT(CLASS, PARENT) CLASS##Kind,
69#include "rphp/analysis/astNodes.def"
70};
71
72class stmt;
73
74/* statement iterators */
75class stmtIteratorBase {
76protected:
77
78  stmt** ptr;
79  stmtIteratorBase(stmt** s) : ptr(s) {}
80  stmtIteratorBase() : ptr(NULL) {}
81
82};
83
84
85template <typename DERIVED, typename REFERENCE>
86class stmtIteratorImpl : public stmtIteratorBase,
87                         public std::iterator<std::forward_iterator_tag,
88                                              REFERENCE, ptrdiff_t,
89                                              REFERENCE, REFERENCE> {
90protected:
91  stmtIteratorImpl(const stmtIteratorBase& RHS) : stmtIteratorBase(RHS) {}
92public:
93  stmtIteratorImpl() {}
94  stmtIteratorImpl(stmt** s) : stmtIteratorBase(s) {}
95
96  DERIVED& operator++() {
97      ++ptr;
98      return static_cast<DERIVED&>(*this);
99  }
100
101  DERIVED operator++(int) {
102    DERIVED tmp = static_cast<DERIVED&>(*this);
103    operator++();
104    return tmp;
105  }
106
107  bool operator==(const DERIVED& RHS) const { return ptr == RHS.ptr; }
108  bool operator!=(const DERIVED& RHS) const { return ptr != RHS.ptr; }
109  REFERENCE operator*() const { return (REFERENCE) *ptr; }
110  REFERENCE operator->() const { return operator*(); }
111
112};
113
114struct stmtIterator : public stmtIteratorImpl<stmtIterator,stmt*&> {
115  explicit stmtIterator() : stmtIteratorImpl<stmtIterator,stmt*&>() {}
116
117  stmtIterator(stmt** S) : stmtIteratorImpl<stmtIterator,stmt*&>(S) {}
118};
119
120struct constStmtIterator : public stmtIteratorImpl<constStmtIterator,
121                                                   const stmt*> {
122  explicit constStmtIterator() :
123    stmtIteratorImpl<constStmtIterator,const stmt*>() {}
124
125  constStmtIterator(const stmtIterator& RHS) :
126    stmtIteratorImpl<constStmtIterator,const stmt*>(RHS) {}
127};
128
129// This macro implements the clone method and llvm::cast<> support (classof methods)
130// for leaf nodes.
131#define IMPLEMENT_SUPPORT_MEMBERS(CLASS)      virtual CLASS * clone(pParseContext& C) const {\
132                                                 return new (C) CLASS(*this, C);\
133                                              }\
134                                              static bool classof(const CLASS *) const { return true; }\
135                                              static bool classof(const stmt* s) const { return s->kind() == CLASS##Kind; }\
136                                              CLASS * retain() { stmt::retain(); return this; }
137
138// statement base class
139class stmt {
140
141    nodeKind kind_;
142
143    pUInt refCount_;
144
145    pUInt startLineNum_;
146    pUInt endLineNum_;
147   
148protected:
149  void* operator new(size_t bytes) throw() {
150    assert(0 && "stmt cannot be allocated with regular 'new'.");
151    return 0;
152  }
153  void operator delete(void* data) throw() {
154    assert(0 && "stmt cannot be released with regular 'delete'.");
155  }
156  void* operator new[](size_t bytes) throw() {
157    assert(0 && "stmt cannot be allocated with regular 'new[]'.");
158    return 0;
159  }
160  void operator delete[](void* data) throw() {
161    assert(0 && "stmt cannot be released with regular 'delete[]'.");
162  }
163
164  // overridden by extending classes to perform class specific destruction
165  // note you should still always call Stmt::doDestroy
166  virtual void doDestroy(pParseContext& C);
167
168  void destroyChildren(pParseContext& C);
169 
170  stmt(const stmt& other): kind_(other.kind_), refCount_(1),
171          startLineNum_(other.startLineNum_), endLineNum_(other.endLineNum_) {}
172   
173  // This method assists in deep-copys of stmt**'s which are present for example in block nodes.
174  void deepCopyChildren(stmt**& newChildren, stmt** const& oldChildren, pUInt numChildren, pParseContext& C) {
175      if(numChildren) {
176          newChildren = new (C) stmt*[numChildren];
177          for(pUInt i = 0; i < numChildren; ++i) {
178              if(oldChildren[i])
179                  newChildren[i] = oldChildren[i]->clone(C);
180              else
181                  newChildren[i] = 0;
182          }
183      }
184  }
185public:
186    stmt(nodeKind k): kind_(k), refCount_(1), startLineNum_(0), endLineNum_(0) { }
187
188    void destroy(pParseContext& C) {
189        assert(refCount_ >= 1);
190        if (--refCount_ == 0)
191            doDestroy(C);
192    }
193
194    stmt* retain() {
195      assert(refCount_ >= 1);
196      ++refCount_;
197      return this;
198    }
199   
200    pUInt getRefCount() const {
201        return refCount_;
202    }
203
204    virtual ~stmt(void) { }
205
206    inline void* operator new(size_t bytes, pParseContext& C, size_t align=8) throw() {
207        return C.allocate(bytes, align);
208    }
209    inline void* operator new(size_t bytes, void* mem) throw() {
210      return mem;
211    }
212    void operator delete(void*, pParseContext&, unsigned) throw() { }
213    void operator delete(void*, std::size_t) throw() { }
214    void operator delete(void*, void*) throw() { }
215
216    typedef stmtIterator       child_iterator;
217    typedef constStmtIterator  const_child_iterator;
218    typedef boost::iterator_range<child_iterator> child_range;
219    typedef boost::iterator_range<const_child_iterator> const_child_range;
220
221
222    virtual child_iterator child_begin() = 0;
223    virtual child_iterator child_end()   = 0;
224
225    const_child_iterator child_begin() const {
226      return const_child_iterator(const_cast<stmt*>(this)->child_begin());
227    }
228
229    const_child_iterator child_end() const {
230      return const_child_iterator(const_cast<stmt*>(this)->child_end());
231    }
232    child_range children() {
233        return child_range(child_begin(), child_end());
234    }
235    const_child_range children() const {
236        return const_child_range(child_begin(), child_end());
237    }
238
239    nodeKind kind(void) const { return kind_; }
240
241    void setLine(pUInt start) { startLineNum_ = start; endLineNum_ = start; }
242    void setLine(pUInt start, pUInt end) { startLineNum_ = start; endLineNum_ = end; }
243
244    pUInt startLineNum(void) const { return startLineNum_; }
245    pUInt endLineNum(void) const { return endLineNum_; }
246   
247    // Polymorphic deep copying.
248    virtual stmt* clone(pParseContext& C) const = 0;
249
250    // LLVM isa<T> and casting support
251    static bool classof(const stmt* s) { return true; }
252
253};
254
255typedef std::vector<stmt*> statementList;
256
257// expression base class
258class expr: public stmt {
259
260public:
261    // see astNodes.def
262    static const nodeKind firstExprKind = exprReduceKind;
263    static const nodeKind lastExprKind = unaryOpKind;
264
265    expr(nodeKind k): stmt(k) { }
266
267    static bool classof(const expr* s) { return true; }
268    static bool classof(const stmt* s) {
269        return s->kind() >= firstExprKind &&
270               s->kind() <= lastExprKind;
271    }
272   
273    // We include that clone here so we get a clone which returns expr*.
274    virtual expr* clone(pParseContext& C) const = 0;
275    expr* retain() { stmt::retain(); return this; }
276   
277protected:
278    expr(const expr& other): stmt(other) {}
279};
280
281typedef std::vector<expr*> expressionList;
282
283// a block of statements
284class block: public stmt {
285    stmt** block_;
286    pUInt numStmts_;
287   
288protected:
289    block(const block& other, pParseContext& C): stmt(other), block_(0), 
290            numStmts_(other.numStmts_)
291    {
292        deepCopyChildren(block_, other.block_, numStmts_, C);
293    }
294public:
295
296    // build a block with a single expression
297    block(pParseContext& C, stmt* s): stmt(blockKind), block_(0), numStmts_(1) {
298        block_ = new (C) stmt*[numStmts_];
299        block_[0] = s;
300    }
301
302    block(pParseContext& C, const statementList* s): stmt(blockKind), block_(0), numStmts_(s->size()) {
303        if (numStmts_) {
304            block_ = new (C) stmt*[numStmts_];
305            memcpy(block_, &(s->front()), numStmts_ * sizeof(*block_));
306        }
307    }
308
309    block(pParseContext& C, const expressionList* s): stmt(blockKind), block_(0), numStmts_(s->size()) {
310        if (numStmts_) {
311            block_ = new (C) stmt*[numStmts_];
312            memcpy(block_, &(s->front()), numStmts_ * sizeof(*block_));
313        }
314    }
315
316    stmt::child_iterator child_begin() { return &block_[0]; }
317    stmt::child_iterator child_end() { return &block_[0]+numStmts_; }
318
319    IMPLEMENT_SUPPORT_MEMBERS(block);
320
321};
322
323// declaration base class
324class decl: public stmt {
325   
326protected:
327    decl(const decl& other, pParseContext& C): stmt(other) {}
328   
329public:
330    // see astNodes.def
331    static const nodeKind firstDeclKind = formalParamKind;
332    static const nodeKind lastDeclKind = functionDeclKind;
333
334    decl(nodeKind k): stmt(k) { }
335
336    static bool classof(const decl* s) { return true; }
337    static bool classof(const stmt* s) {
338        return s->kind() >= firstDeclKind &&
339               s->kind() <= lastDeclKind;
340    }
341
342    // We do not implement clone here because decl is an abstract base.
343};
344
345
346// global
347class globalDecl: public stmt {
348
349    stmt** children_;
350    pUInt numChildren_;
351
352protected:
353    globalDecl(const globalDecl& other, pParseContext& C): stmt(other), children_(0),
354        numChildren_(other.numChildren_)
355    {
356        deepCopyChildren(children_, other.children_, numChildren_, C);
357    }
358public:
359
360    globalDecl(const expressionList* varList,
361               pParseContext& C):
362            stmt(globalDeclKind),
363            children_(0),
364            numChildren_(varList->size())
365    {
366        children_ = new (C) stmt*[numChildren_];
367        memcpy(children_, &(varList->front()), (numChildren_) * sizeof(stmt*));
368    }
369
370    stmt::child_iterator child_begin() { return &children_[0]; }
371    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
372
373    IMPLEMENT_SUPPORT_MEMBERS(globalDecl);
374
375};
376
377class staticDecl: public decl {
378
379    enum { DEFAULT=0, VARS=1 };
380
381    stmt** children_;
382    pUInt numChildren_;
383
384protected:
385    staticDecl(const staticDecl& other, pParseContext& C): decl(other), children_(0),
386        numChildren_(other.numChildren_)
387    {
388        deepCopyChildren(children_, other.children_, numChildren_, C);
389    }
390   
391public:
392    staticDecl(const expressionList* varList,
393               pParseContext& C,
394               expr* def=NULL):
395        decl(staticDeclKind),
396        children_(0),
397        numChildren_(1+varList->size())
398    {
399        children_ = new (C) stmt*[numChildren_];
400        children_[DEFAULT] = def;
401        if (numChildren_ > 1) {
402            memcpy(children_+1, &(varList->front()), (numChildren_-1) * sizeof(stmt*));
403        }
404    }
405
406    expr* defaultExpr(void) {
407        return static_cast<expr*>(children_[DEFAULT]);
408    }
409
410    stmt::child_iterator child_begin() { return &children_[DEFAULT]; }
411    stmt::child_iterator child_end() { return &children_[DEFAULT]+numChildren_; }
412
413    stmt::child_iterator var_begin() { return &children_[VARS]; }
414    stmt::child_iterator var_end() { return &children_[VARS]+(numChildren_-1); }
415
416    IMPLEMENT_SUPPORT_MEMBERS(staticDecl);
417
418};
419
420
421class formalParam: public decl {
422
423    enum { byRefBit=1, arrayHintBit=2 };
424
425    llvm::PooledStringPtr name_;
426    llvm::PooledStringPtr classHint_;
427    pUInt flags_;
428    stmt* default_;
429
430    formalParam(const formalParam& other, pParseContext& C): decl(other),
431            name_(other.name_), classHint_(other.classHint_), flags_(other.flags_)
432    {
433        if(other.default_)
434            default_ = other.default_->clone(C);
435    }
436public:
437    formalParam(const pSourceRange& name, pParseContext& C, bool ref, expr* def=NULL):
438        decl(formalParamKind),
439        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
440        classHint_(),
441        flags_(0),
442        default_(def)
443    {
444        if (ref) {
445            flags_ ^= byRefBit;
446        }
447    }
448
449    expr* defaultExpr(void) {
450        return static_cast<expr*>(default_);
451    }
452
453    bool byRef(void) const { return flags_ & byRefBit; }
454
455    bool arrayHint(void) const { return flags_ & arrayHintBit; }
456
457    bool optional(void) const {  return default_ != NULL; }
458
459    void setArrayHint(void) { flags_ ^= arrayHintBit; }
460
461    void setClassHint(const pSourceRange& name, pParseContext& C) {
462        classHint_ = C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())));
463    }
464
465    pIdentString name(void) const {
466        assert(name_);
467        return *name_;
468    }
469
470    pIdentString classHint(void) const {
471        if (classHint_)
472            return *classHint_;
473        else
474            return "";
475    }
476
477    stmt::child_iterator child_begin() { return &default_; }
478    stmt::child_iterator child_end() { return &default_+1; }
479
480    IMPLEMENT_SUPPORT_MEMBERS(formalParam);
481
482};
483
484typedef llvm::SmallVector<formalParam*,RPHP_FORMAL_PARAM_VECTOR_SIZE> formalParamList;
485
486class signature: public decl {
487
488    llvm::PooledStringPtr name_;
489    stmt** formalParamList_;
490    pUInt numParams_;
491    bool returnByRef_;
492
493protected:
494    signature(const signature& other, pParseContext& C): decl(other), name_(other.name_),
495        formalParamList_(0), numParams_(other.numParams_), returnByRef_(other.returnByRef_)
496    {
497        deepCopyChildren(formalParamList_, other.formalParamList_, numParams_, C);
498    }
499   
500public:
501    signature(const pSourceRange& name,
502              pParseContext& C,
503              const formalParamList* s,
504              bool returnByRef=false):
505            decl(signatureKind),
506            name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
507            formalParamList_(0),
508            numParams_(s->size()),
509            returnByRef_(returnByRef)
510    {
511        if (numParams_) {
512            formalParamList_ = new (C) stmt*[numParams_];
513            memcpy(formalParamList_, &(s->front()), numParams_ * sizeof(*formalParamList_));
514        }
515    }
516
517    pIdentString name(void) const {
518        assert(name_);
519        return *name_;
520    }
521
522    bool returnByRef(void) const { return returnByRef_; }
523
524    pUInt numParams(void) const { return numParams_; }
525
526    stmt::child_iterator child_begin() { return &formalParamList_[0]; }
527    stmt::child_iterator child_end() { return &formalParamList_[0]+numParams_; }
528
529    IMPLEMENT_SUPPORT_MEMBERS(signature);
530};
531
532// function declaration
533class functionDecl: public decl {
534
535    enum { SIG, BODY, END_EXPR };
536    stmt* children_[END_EXPR];
537   
538protected:
539    functionDecl(const functionDecl& other, pParseContext& C): decl(other)
540    {
541        memset(children_, 0, sizeof(children_));
542        if(other.children_[SIG])
543            children_[SIG] = other.children_[SIG]->clone(C);
544        if(other.children_[BODY])
545            children_[BODY] = other.children_[BODY]->clone(C);
546    }
547
548public:
549    functionDecl(signature* sig, block* body):
550        decl(functionDeclKind),
551        children_()
552    {
553        children_[SIG] = sig;
554        children_[BODY] = body;
555    }
556
557    signature* sig(void) { return static_cast<signature*>(children_[SIG]); }
558    block* body(void) { return static_cast<block*>(children_[BODY]); }
559
560    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
561    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
562
563    IMPLEMENT_SUPPORT_MEMBERS(functionDecl);
564
565};
566
567struct memberFlags {
568    // these are taken by address during parse
569    static const pUInt PUBLIC;
570    static const pUInt PROTECTED;
571    static const pUInt PRIVATE;
572    static const pUInt STATIC;
573    static const pUInt ABSTRACT;
574    static const pUInt FINAL;
575    static const pUInt CONST;
576};
577
578// method declaration
579class methodDecl: public decl {
580
581    enum { SIG, BODY, END_EXPR };
582    pUInt flags_;
583    stmt* children_[END_EXPR];
584
585protected:
586    methodDecl(const methodDecl& other, pParseContext& C): decl(other),
587        flags_(other.flags_)
588    {
589        memset(children_, 0, sizeof(children_));
590        if(other.children_[SIG])
591            children_[SIG] = other.children_[SIG]->clone(C);
592        if(other.children_[BODY])
593            children_[BODY] = other.children_[BODY]->clone(C);
594    }
595   
596public:
597    methodDecl(signature* sig, pUInt flags, block* body):
598        decl(methodDeclKind),
599        flags_(flags),
600        children_()
601    {
602        children_[SIG] = sig;
603        children_[BODY] = body; // body may be null for abstract method
604        if (body == NULL)
605            flags_ |= memberFlags::ABSTRACT;
606    }
607
608    signature* sig(void) { return static_cast<signature*>(children_[SIG]); }
609    block* body(void) { return static_cast<block*>(children_[BODY]); }
610    pUInt flags(void) const { return flags_; }
611
612    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
613    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
614
615    IMPLEMENT_SUPPORT_MEMBERS(methodDecl);
616
617};
618
619// property declaration
620class propertyDecl: public decl {
621
622    pUInt flags_;
623    llvm::PooledStringPtr name_;
624    expr* default_;
625   
626protected:
627    propertyDecl(const propertyDecl& other, pParseContext& C): decl(other),
628        flags_(other.flags_), name_(other.name_), default_(0)
629    {
630        if(other.default_)
631            default_ = other.default_->clone(C);
632    }
633   
634public:
635    propertyDecl(pParseContext& C,
636                 const pSourceRange& name,
637                 expr* def
638                 ):
639        decl(propertyDeclKind),
640        flags_(0),
641        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
642        default_(def)
643    {
644    }
645
646    void setFlags(pUInt f) { flags_ = f; }
647    pUInt flags(void) const { return flags_; }
648    pIdentString name(void) const {
649        assert(name_);
650        return *name_;
651    }
652
653    stmt::child_iterator child_begin() { return (stmt**)&default_; }
654    stmt::child_iterator child_end() { return (stmt**)&default_+1; }
655
656    IMPLEMENT_SUPPORT_MEMBERS(propertyDecl);
657};
658
659
660
661// class/interface declaration
662class classDecl: public decl {
663public:
664
665    enum classTypes { NORMAL,
666                      IFACE, // "INTERFACE" is keyword? throws error
667                      FINAL,
668                      ABSTRACT };
669
670private:
671    llvm::PooledStringPtr name_;
672    idList extends_;
673    idList implements_;
674    classTypes classType_;
675    block* members_;
676   
677protected:
678    // We copy the SmallVectors here, this works for PooledStringPtrs but wouldn't for
679    // stmt*s!
680    classDecl(const classDecl& other, pParseContext& C): decl(other),
681        name_(other.name_), extends_(other.extends_), implements_(other.implements_),
682        classType_(other.classType_), members_(0)
683    {
684        if(other.members_)
685            members_ = other.members_->clone(C);
686    }
687   
688public:
689    classDecl(pParseContext& C,
690              const pSourceRange& name,
691              classTypes type,
692              const sourceRangeList* extends, // may be null
693              const sourceRangeList* implements, // may be null
694              block* members
695              ):
696        decl(classDeclKind),
697        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
698        extends_(),
699        implements_(),
700        classType_(type),
701        members_(members)
702    {
703        // intern list of extends (if any)
704        if (extends) {
705            for (sourceRangeList::const_iterator i=extends->begin();
706            i != extends->end();
707            ++i) {
708                extends_.push_back(C.idPool().intern(
709                        pStringRef(
710                                (*i)->begin().base(), ((*i)->end() - (*i)->begin()))
711                        ));
712            }
713        }
714        // intern list of implements (if any)
715        if (implements) {
716            for (sourceRangeList::const_iterator i=implements->begin();
717            i != implements->end();
718            ++i) {
719                implements_.push_back(C.idPool().intern(
720                        pStringRef(
721                                (*i)->begin().base(), ((*i)->end() - (*i)->begin()))
722                        ));
723            }
724        }
725    }
726
727    pIdentString name(void) const {
728        assert(name_);
729        return *name_;
730    }
731
732    block* members(void) { return members_; }
733
734    classTypes classType(void) const { return classType_; }
735
736    pUInt implementsCount(void) const { return implements_.size(); }
737    pUInt extendsCount(void) const { return extends_.size(); }
738
739    stmt::child_iterator child_begin() { return (stmt**)&members_; }
740    stmt::child_iterator child_end() { return (stmt**)&members_+1; }
741
742    idList::iterator extends_begin() { return extends_.begin(); }
743    idList::iterator extends_end() { return extends_.end(); }
744
745    idList::iterator implements_begin() { return implements_.begin(); }
746    idList::iterator implements_end() { return implements_.end(); }
747
748    IMPLEMENT_SUPPORT_MEMBERS(classDecl);
749
750};
751
752// if statement
753class ifStmt: public stmt {
754
755    enum { CONDITION, TRUEBLOCK, FALSEBLOCK, END_EXPR };
756    stmt* children_[END_EXPR];
757
758protected:
759    ifStmt(const ifStmt& other, pParseContext& C): stmt(other)
760    {
761        memset(children_, 0, sizeof(children_));
762        children_[CONDITION] = other.children_[CONDITION]->clone(C);
763        if(other.children_[TRUEBLOCK])
764            children_[TRUEBLOCK] = other.children_[TRUEBLOCK]->clone(C);
765        if(other.children_[FALSEBLOCK])
766            children_[FALSEBLOCK] = other.children_[FALSEBLOCK]->clone(C);
767    }
768   
769public:
770    ifStmt(pParseContext& C,
771           expr* cond,
772           stmt* trueBlock,
773           stmt* falseBlock):
774               stmt(ifStmtKind),
775               children_() {
776
777        // enforce blocks to ease later traversal
778        if (trueBlock && !isa<block>(trueBlock))
779            trueBlock = new (C) block(C, trueBlock);
780
781        if (falseBlock && !isa<block>(falseBlock))
782            falseBlock = new (C) block(C, falseBlock);
783
784        children_[CONDITION] = static_cast<stmt*>(cond);
785        children_[TRUEBLOCK] = trueBlock;
786        children_[FALSEBLOCK] = falseBlock;
787
788    }
789
790    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
791    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
792
793    expr* condition(void) { return static_cast<expr*>(children_[CONDITION]); }
794    stmt* trueBlock(void) { return children_[TRUEBLOCK]; }
795    stmt* falseBlock(void) { return children_[FALSEBLOCK]; }
796
797    IMPLEMENT_SUPPORT_MEMBERS(ifStmt);
798
799};
800
801// switch case
802class switchCase: public stmt {
803
804    enum { COND, BODY, END_EXPR };
805    stmt* children_[END_EXPR];
806
807protected:
808    switchCase(const switchCase& other, pParseContext& C): stmt(other)
809    {
810        memset(children_, 0, sizeof(children_));
811        if(other.children_[COND])
812            children_[COND] = other.children_[COND]->clone(C);
813        if(other.children_[BODY])
814            children_[BODY] = other.children_[BODY]->clone(C);
815    }
816   
817public:
818    switchCase(expr* cond,
819               block* body):
820    stmt(switchCaseKind),
821    children_()
822    {
823
824        children_[COND] = static_cast<stmt*>(cond);
825        children_[BODY] = static_cast<stmt*>(body);
826
827    }
828
829    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
830    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
831
832    // note if condition is null, this is a default: case
833    expr* condition(void) { return static_cast<expr*>(children_[COND]); }
834    block* body(void) { return static_cast<block*>(children_[BODY]); }
835
836    IMPLEMENT_SUPPORT_MEMBERS(switchCase);
837
838};
839
840// switch statement
841class switchStmt: public stmt {
842
843    enum { RVAL, CASEBLOCK, END_EXPR };
844    stmt* children_[END_EXPR];
845
846protected:
847    switchStmt(const switchStmt& other, pParseContext& C): stmt(other)
848    {
849        memset(children_, 0, sizeof(children_));
850        if(other.children_[RVAL])
851            children_[RVAL] = other.children_[RVAL]->clone(C);
852        if(other.children_[CASEBLOCK])
853            children_[CASEBLOCK] = other.children_[CASEBLOCK]->clone(C);
854    }
855   
856public:
857    switchStmt(expr* rVal,
858               block* caseBlock):
859    stmt(switchStmtKind),
860    children_() {
861
862        children_[RVAL] = static_cast<stmt*>(rVal);
863        children_[CASEBLOCK] = caseBlock;
864
865    }
866
867    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
868    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
869
870    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
871    block* caseBlock(void) { return static_cast<block*>(children_[CASEBLOCK]); }
872
873    IMPLEMENT_SUPPORT_MEMBERS(switchStmt);
874
875};
876
877// foreach statement
878class forEach: public stmt {
879
880    enum { RVAL, KEY, VAL, BODY, END_EXPR };
881    stmt* children_[END_EXPR];
882    bool byRef_; // value
883
884protected:
885    forEach(const forEach& other, pParseContext& C): stmt(other), byRef_(other.byRef_)
886    {
887        memset(children_, 0, sizeof(children_));
888        if(other.children_[RVAL])
889            children_[RVAL] = other.children_[RVAL]->clone(C);
890        if(other.children_[KEY])
891            children_[KEY] = other.children_[KEY]->clone(C);
892        if(other.children_[VAL])
893            children_[VAL] = other.children_[VAL]->clone(C);
894        if(other.children_[BODY])
895            children_[BODY] = other.children_[BODY]->clone(C);
896    }
897   
898public:
899    forEach(expr* rVal,
900            stmt* body,
901            pParseContext& C,
902            expr* val,
903            bool byRef,
904            expr* key=NULL):
905    stmt(forEachKind),
906    children_(),
907    byRef_(byRef)
908    {
909
910        // enfore a block for body to ease later traversal
911        if (!isa<block>(body)) {
912            body = new (C) block(C, body);
913        }
914
915        children_[RVAL] = static_cast<stmt*>(rVal);
916        children_[KEY] = static_cast<stmt*>(key);
917        children_[VAL] = static_cast<stmt*>(val);
918        children_[BODY] = static_cast<stmt*>(body);
919
920    }
921
922    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
923    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
924
925    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
926    expr* key(void) { return static_cast<expr*>(children_[KEY]); }
927    expr* val(void) { return static_cast<expr*>(children_[VAL]); }
928    block* body(void) { return static_cast<block*>(children_[BODY]); }
929
930    bool hasKey(void) const { return (bool)children_[KEY]; }
931
932    IMPLEMENT_SUPPORT_MEMBERS(forEach);
933
934};
935
936// for statement
937class forStmt: public stmt {
938
939    enum { INIT, COND, INC, BODY, END_EXPR };
940    stmt* children_[END_EXPR];
941
942protected:
943    forStmt(const forStmt& other, pParseContext& C): stmt(other)
944    {
945        memset(children_, 0, sizeof(children_));
946        if(other.children_[INIT])
947            children_[INIT] = other.children_[INIT]->clone(C);
948        if(other.children_[COND])
949            children_[COND] = other.children_[COND]->clone(C);
950        if(other.children_[INC])
951            children_[INC] = other.children_[INC]->clone(C);
952        if(other.children_[BODY])
953            children_[BODY] = other.children_[BODY]->clone(C);
954    }
955
956public:
957    forStmt(pParseContext& C,
958            stmt* init,
959            stmt* cond,
960            stmt* inc,
961            stmt* body):
962    stmt(forStmtKind),
963    children_()
964    {
965
966        // enfore a block for body to ease later traversal
967        if (!isa<block>(body)) {
968            body = new (C) block(C, body);
969        }
970
971        children_[INIT] = init; // may be block or expr
972        children_[COND] = cond; // may be block or expr
973        children_[INC] = inc; // may be block or expr
974        children_[BODY] = static_cast<stmt*>(body);
975
976    }
977
978    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
979    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
980
981    stmt* init(void) const { return children_[INIT]; }
982    stmt* condition(void) const { return children_[COND]; }
983    stmt* increment(void) const { return children_[INC]; }
984    block* body(void) const { return static_cast<block*>(children_[BODY]); }
985
986    IMPLEMENT_SUPPORT_MEMBERS(forStmt);
987};
988
989// do statement
990class doStmt: public stmt {
991
992    enum { COND, BODY, END_EXPR };
993    stmt* children_[END_EXPR];
994
995protected:
996    doStmt(const doStmt& other, pParseContext& C): stmt(other)
997    {
998        memset(children_, 0, sizeof(children_));
999        if(other.children_[COND])
1000            children_[COND] = other.children_[COND]->clone(C);
1001        if(other.children_[BODY])
1002            children_[BODY] = other.children_[BODY]->clone(C);
1003    }
1004
1005public:
1006    doStmt(pParseContext& C,
1007           expr* cond,
1008           stmt* body):
1009    stmt(doStmtKind),
1010    children_()
1011    {
1012
1013        // enfore a block for body to ease later traversal
1014        if (!isa<block>(body)) {
1015            body = new (C) block(C, body);
1016        }
1017
1018        children_[COND] = static_cast<stmt*>(cond);
1019        children_[BODY] = static_cast<stmt*>(body);
1020
1021    }
1022
1023    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1024    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1025
1026    expr* condition(void) { return static_cast<expr*>(children_[COND]); }
1027    block* body(void) { return static_cast<block*>(children_[BODY]); }
1028
1029    IMPLEMENT_SUPPORT_MEMBERS(doStmt);
1030
1031};
1032
1033// while statement
1034class whileStmt: public stmt {
1035
1036    enum { COND, BODY, END_EXPR };
1037    stmt* children_[END_EXPR];
1038
1039protected:
1040    whileStmt(const whileStmt& other, pParseContext& C): stmt(other)
1041    {
1042        memset(children_, 0, sizeof(children_));
1043        if(other.children_[COND])
1044            children_[COND] = other.children_[COND]->clone(C);
1045        if(other.children_[BODY])
1046            children_[BODY] = other.children_[BODY]->clone(C);
1047    }
1048
1049public:
1050    whileStmt(pParseContext& C,
1051              expr* cond,
1052              stmt* body):
1053    stmt(whileStmtKind),
1054    children_()
1055    {
1056
1057        // enfore a block for body to ease later traversal
1058        if (!isa<block>(body)) {
1059            body = new (C) block(C, body);
1060        }
1061
1062        children_[COND] = static_cast<stmt*>(cond);
1063        children_[BODY] = static_cast<stmt*>(body);
1064
1065    }
1066
1067    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1068    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1069
1070    expr* condition(void) { return static_cast<expr*>(children_[COND]); }
1071    block* body(void) { return static_cast<block*>(children_[BODY]); }
1072
1073    IMPLEMENT_SUPPORT_MEMBERS(whileStmt);
1074
1075};
1076
1077
1078
1079// type cast
1080class typeCast: public expr {
1081public:
1082    enum castKindType { STRING, BINARY, UNICODE, INT, REAL, BOOL, UNSET, ARRAY, OBJECT };
1083
1084private:
1085    expr* rVal_;
1086    castKindType castKind_;
1087
1088protected:
1089    typeCast(const typeCast& other, pParseContext& C): expr(other),
1090            rVal_(0), castKind_(other.castKind_)
1091    {
1092        if(other.rVal_)
1093            rVal_ = other.rVal_->clone(C);
1094    }
1095
1096public:
1097    typeCast(castKindType kind, expr* rVal): expr(typeCastKind), rVal_(rVal), castKind_(kind)
1098    {
1099
1100    }
1101
1102    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1103    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1104
1105    expr* rVal(void) { return rVal_; }
1106    castKindType castKind(void) const { return castKind_; }
1107
1108    IMPLEMENT_SUPPORT_MEMBERS(typeCast);
1109
1110};
1111
1112// return statement
1113class returnStmt: public stmt {
1114   
1115    expr* rVal_;
1116   
1117protected:
1118    returnStmt(const returnStmt& other, pParseContext& C): stmt(other), rVal_(0)
1119    {
1120        if(other.rVal_)
1121            rVal_ = other.rVal_->clone(C);
1122    }
1123
1124public:
1125    returnStmt(expr* rVal): stmt(returnStmtKind), rVal_(rVal)
1126    {
1127
1128    }
1129
1130    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1131    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1132
1133    expr* rVal(void) { return rVal_; }
1134    void setRVal(pParseContext& C, expr* r) { if(rVal_) rVal_->destroy(C); rVal_= r; }
1135
1136    IMPLEMENT_SUPPORT_MEMBERS(returnStmt);
1137
1138};
1139
1140// break statement
1141class breakStmt: public stmt {
1142   
1143    expr* rVal_;
1144   
1145protected:
1146    breakStmt(const breakStmt& other, pParseContext& C): stmt(other), rVal_(0)
1147    {
1148        if(other.rVal_)
1149            rVal_ = other.rVal_->clone(C);
1150    }
1151
1152public:
1153    breakStmt(expr* rVal): stmt(breakStmtKind), rVal_(rVal)
1154    {
1155
1156    }
1157
1158    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1159    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1160
1161    expr* rVal(void) { return rVal_; }
1162
1163    IMPLEMENT_SUPPORT_MEMBERS(breakStmt);
1164
1165};
1166
1167// continue statement
1168class continueStmt: public stmt {
1169   
1170    expr* rVal_;
1171   
1172protected:
1173    continueStmt(const continueStmt& other, pParseContext& C): stmt(other), rVal_(0)
1174    {
1175        if(other.rVal_)
1176            rVal_ = other.rVal_->clone(C);
1177    }
1178
1179public:
1180    continueStmt(expr* rVal): stmt(continueStmtKind), rVal_(rVal)
1181    {
1182
1183    }
1184
1185    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1186    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1187
1188    expr* rVal(void) { return rVal_; }
1189
1190    IMPLEMENT_SUPPORT_MEMBERS(continueStmt);
1191
1192};
1193
1194// catch
1195class catchStmt: public stmt {
1196
1197    llvm::PooledStringPtr className_;
1198    llvm::PooledStringPtr varName_;
1199    block* body_;
1200   
1201protected:
1202    catchStmt(const catchStmt& other, pParseContext& C): stmt(other),
1203        className_(other.className_), varName_(other.varName_), body_(0)
1204    {
1205        if(other.body_)
1206            body_ = other.body_->clone(C);
1207    }
1208
1209public:
1210    catchStmt(const pSourceRange& className,
1211              const pSourceRange& varName,
1212              pParseContext& C,
1213              block* body):
1214    stmt(catchStmtKind),
1215    className_(C.idPool().intern(pStringRef(className.begin().base(), (className.end()-className.begin())))),
1216    varName_(C.idPool().intern(pStringRef(varName.begin().base(), (varName.end()-varName.begin())))),
1217    body_(body)
1218    {
1219    }
1220
1221    pIdentString className(void) const {
1222        assert(className_);
1223        return *className_;
1224    }
1225
1226    pIdentString varName(void) const {
1227        assert(varName_);
1228        return *varName_;
1229    }
1230
1231    stmt::child_iterator child_begin() { return (stmt**)&body_; }
1232    stmt::child_iterator child_end() { return (stmt**)&body_+1; }
1233
1234    IMPLEMENT_SUPPORT_MEMBERS(catchStmt);
1235
1236};
1237
1238
1239// try
1240class tryStmt: public stmt {
1241
1242    enum { BODY=0, CATCHLIST=1 };
1243
1244    // children_[0] is always body. the rest are catch blocks
1245    // numChildren_ is always 1 + number of catch blocks
1246    stmt** children_;
1247    pUInt numChildren_;
1248
1249protected:
1250    tryStmt(const tryStmt& other, pParseContext& C): stmt(other), children_(0),
1251        numChildren_(other.numChildren_)
1252    {
1253        deepCopyChildren(children_, other.children_, numChildren_, C);
1254    }
1255   
1256public:
1257    tryStmt(pParseContext& C, block* body, statementList* catchList):
1258        stmt(tryStmtKind),
1259        children_(NULL),
1260        numChildren_(1+catchList->size())
1261    {
1262        children_ = new (C) stmt*[numChildren_];
1263        children_[BODY] = body;
1264        if (numChildren_ > 1) {
1265            memcpy(children_+1, &(catchList->front()), (numChildren_-1) * sizeof(stmt*));
1266        }
1267    }
1268
1269    block* body(void) {
1270        return static_cast<block*>(children_[BODY]);
1271    }
1272
1273    stmt::child_iterator child_begin() { return &children_[0]; }
1274    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
1275
1276    pUInt numCatches(void) const { return numChildren_-1; }
1277
1278    stmt::child_iterator catches_begin() { return &children_[CATCHLIST]; }
1279    stmt::child_iterator catches_end() { return &children_[CATCHLIST]+(numChildren_-1); }
1280
1281    IMPLEMENT_SUPPORT_MEMBERS(tryStmt);
1282
1283};
1284
1285
1286// builtins: language constructs that seem like function calls, but aren't.
1287// exit, isset, unset, empty, echo, print, include, require, clone, throw, @
1288class builtin: public expr {
1289public:
1290    enum opKind {
1291                  EXIT, // start expr
1292                  ISSET,
1293                  UNSET,
1294                  EMPTY,
1295                  CLONE,
1296                  INCLUDE,
1297                  INCLUDE_ONCE,
1298                  REQUIRE,
1299                  REQUIRE_ONCE,
1300                  PRINT, // end expr
1301                  ECHO,   // start statements
1302                  IGNORE_WARNING,
1303                  THROW   // end statements
1304                };
1305
1306private:
1307    stmt** children_;
1308    pUInt numChildren_;
1309    opKind opKind_;
1310
1311protected:
1312    builtin(const builtin& other, pParseContext& C): expr(other), children_(0),
1313        numChildren_(other.numChildren_), opKind_(other.opKind_)
1314    {
1315        deepCopyChildren(children_, other.children_, numChildren_, C);
1316    }
1317   
1318public:
1319
1320    builtin(pParseContext& C, opKind op, const expressionList* s=NULL):
1321            expr(builtinKind),
1322            children_(0),
1323            numChildren_(0),
1324            opKind_(op)
1325    {
1326        if (s) {
1327            numChildren_ = s->size();
1328            children_ = new (C) stmt*[numChildren_];
1329            memcpy(children_, &(s->front()), numChildren_ * sizeof(*children_));
1330        }
1331    }
1332
1333    opKind opKind() const { return opKind_; }
1334    pUInt numArgs() const { return numChildren_; }
1335
1336    stmt::child_iterator child_begin() { return &children_[0]; }
1337    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
1338
1339    IMPLEMENT_SUPPORT_MEMBERS(builtin);
1340
1341};
1342
1343// literal expression base class
1344//TODO: do we want literalExpr to be abstract?
1345class literalExpr: public expr {
1346
1347protected:
1348    pSourceString stringVal_;
1349    literalExpr(const literalExpr& other, pParseContext& C): expr(other),
1350            stringVal_(other.stringVal_) {}
1351   
1352public:
1353
1354    // see astNodes.def
1355    static const nodeKind firstLiteralKind = literalStringKind;
1356    static const nodeKind lastLiteralKind = inlineHtmlKind;
1357
1358    literalExpr(nodeKind k): expr(k), stringVal_() { }
1359    literalExpr(nodeKind k, const pSourceRange& v): expr(k), stringVal_(v.begin(), v.end()) { }
1360
1361    virtual const pSourceString& getStringVal(void) const {
1362        return stringVal_;
1363    }
1364
1365    stmt::child_iterator child_begin() { return child_iterator(); }
1366    stmt::child_iterator child_end() { return child_iterator(); }
1367
1368    static bool classof(const literalExpr* s) { return true; }
1369    static bool classof(const stmt* s) {
1370        return s->kind() >= firstLiteralKind &&
1371               s->kind() <= lastLiteralKind;
1372    }
1373   
1374    virtual literalExpr* clone(pParseContext& C) const {
1375        return new (C) literalExpr(*this, C);
1376    }
1377   
1378    literalExpr* retain() { stmt::retain(); return this; }
1379
1380};
1381
1382// NODE: literal bstring
1383class literalString: public literalExpr {
1384
1385    bool isBinary_;
1386    bool isSimple_; // i.e., single quoted
1387
1388    // this is storage for a string that was artificially created
1389    // during a pass and therefore doesn't exist in the original source
1390    pSourceString* artificial_;
1391
1392protected:
1393    literalString(const literalString& other, pParseContext& C): literalExpr(other),
1394            isBinary_(other.isBinary_), isSimple_(other.isSimple_), artificial_(0)
1395    {
1396        if(other.artificial_)
1397            artificial_ = new pSourceString(*other.artificial_);
1398    }
1399   
1400public:
1401
1402    // empty source string
1403    literalString(bool isBinary):
1404            literalExpr(literalStringKind),
1405            isBinary_(isBinary),
1406            isSimple_(true),
1407            artificial_(0) { }
1408
1409    // normal source string
1410    literalString(const pSourceRange& v, bool isBinary):
1411            literalExpr(literalStringKind, v),
1412            isBinary_(isBinary),
1413            isSimple_(true),
1414            artificial_(0) { }
1415
1416    // extending string (inline html)
1417    literalString(const pSourceRange& v, nodeKind k):
1418            literalExpr(k, v),
1419            isBinary_(false),
1420            isSimple_(true),
1421            artificial_(0) { }
1422
1423    // artificial constructor (creates storage space)
1424    literalString(pStringRef r):
1425            literalExpr(literalStringKind),
1426            isBinary_(true),
1427            isSimple_(true),
1428            artificial_(new pSourceString(r)) { }
1429
1430    ~literalString(void) {
1431        if (artificial_)
1432            delete artificial_;
1433    }
1434
1435    bool isBinary(void) const { return isBinary_; }
1436
1437    void setIsSimple(bool s)  {
1438        isSimple_ = s;
1439    }
1440
1441    void setStringVal(pStringRef s) {
1442        if (artificial_)
1443            delete artificial_;
1444        artificial_ = new pSourceString(s);
1445    }
1446
1447    const pSourceString& getStringVal(void) const {
1448        if (artificial_)
1449            return *artificial_;
1450        else
1451            return stringVal_;
1452    }
1453
1454    bool isSimple(void) const { return isSimple_; }
1455
1456    stmt::child_iterator child_begin() { return child_iterator(); }
1457    stmt::child_iterator child_end() { return child_iterator(); }
1458
1459    IMPLEMENT_SUPPORT_MEMBERS(literalString);
1460
1461};
1462
1463// NODE: literal int
1464class literalInt: public literalExpr {
1465
1466    bool negative_;
1467
1468protected:
1469    literalInt(const literalInt& other, pParseContext& C): literalExpr(other),
1470            negative_(other.negative_) {}
1471   
1472public:
1473    literalInt(const pSourceRange& v): literalExpr(literalIntKind, v), negative_(false) { }
1474
1475    bool negative(void) const { return negative_; }
1476    void setNegative(bool n) { negative_ = n; }
1477
1478    stmt::child_iterator child_begin() { return child_iterator(); }
1479    stmt::child_iterator child_end() { return child_iterator(); }
1480
1481    IMPLEMENT_SUPPORT_MEMBERS(literalInt);
1482
1483};
1484
1485// NODE: literal float
1486class literalFloat: public literalExpr {
1487
1488protected:
1489    literalFloat(const literalFloat& other, pParseContext& C): literalExpr(other) {}
1490   
1491public:
1492    literalFloat(const pSourceRange& v): literalExpr(literalFloatKind, v) { }
1493
1494    stmt::child_iterator child_begin() { return child_iterator(); }
1495    stmt::child_iterator child_end() { return child_iterator(); }
1496
1497    IMPLEMENT_SUPPORT_MEMBERS(literalFloat);
1498
1499};
1500
1501// NODE: literal bool
1502class literalBool: public literalExpr {
1503
1504    bool boolVal_;
1505
1506protected:
1507    literalBool(const literalBool& other, pParseContext& C): literalExpr(other),
1508            boolVal_(other.boolVal_) {}
1509   
1510public:
1511    literalBool(bool v): literalExpr(literalBoolKind), boolVal_(v) { }
1512
1513    bool getBoolVal(void) const { return boolVal_; }
1514
1515    stmt::child_iterator child_begin() { return child_iterator(); }
1516    stmt::child_iterator child_end() { return child_iterator(); }
1517
1518    IMPLEMENT_SUPPORT_MEMBERS(literalBool);
1519
1520};
1521
1522// array items
1523struct arrayItem {
1524    expr* key;
1525    expr* val;
1526    bool isRef;
1527    arrayItem(expr* k, expr* v, bool r):
1528     key(k),
1529     val(v),
1530     isRef(r)
1531     { }
1532};
1533
1534typedef std::vector<arrayItem> arrayList;
1535
1536// NODE: literal array
1537class literalArray: public literalExpr {
1538
1539    arrayList itemList_;
1540
1541protected:
1542    literalArray(const literalArray& other, pParseContext& C): literalExpr(other),
1543            itemList_(other.itemList_)
1544    {
1545        // We have copied all array items by value, now we have to deep-copy the
1546        // expressions in the array items.
1547        foreach(arrayItem& item, itemList_) {
1548            if(item.key)
1549                item.key = item.key->clone(C);
1550            if(item.val)
1551                item.val = item.val->clone(C);
1552        }
1553    }
1554public:
1555    literalArray(arrayList* items):
1556        literalExpr(literalArrayKind),
1557        itemList_(*items) // copy
1558        { }
1559
1560    virtual void doDestroy(pParseContext& C) {
1561        for (arrayList::iterator i = itemList_.begin(); i != itemList_.end(); ++i) {
1562            if (i->key) {
1563                i->key->destroy(C);
1564            }
1565            i->val->destroy(C);
1566        }
1567        stmt::doDestroy(C);
1568    }
1569
1570    arrayList& itemList(void) { return itemList_; }
1571    const arrayList& itemList(void) const { return itemList_; }
1572
1573    IMPLEMENT_SUPPORT_MEMBERS(literalArray);
1574
1575};
1576
1577
1578// NODE: inline html
1579class inlineHtml: public literalString {
1580
1581protected:
1582    inlineHtml(const inlineHtml& other, pParseContext& C): literalString(other) {}
1583   
1584public:
1585    inlineHtml(const pSourceRange& v): literalString(v, inlineHtmlKind) { }
1586
1587    stmt::child_iterator child_begin() { return child_iterator(); }
1588    stmt::child_iterator child_end() { return child_iterator(); }
1589
1590    IMPLEMENT_SUPPORT_MEMBERS(inlineHtml);
1591
1592};
1593
1594
1595// NODE: literal null
1596class literalNull: public literalExpr {
1597
1598protected:
1599    literalNull(const literalNull& other, pParseContext& C): literalExpr(other) {}
1600   
1601public:
1602    literalNull(void): literalExpr(literalNullKind) { }
1603
1604    stmt::child_iterator child_begin() { return child_iterator(); }
1605    stmt::child_iterator child_end() { return child_iterator(); }
1606
1607    IMPLEMENT_SUPPORT_MEMBERS(literalNull);
1608
1609};
1610
1611// literal ID (always represents a class or function symbol name)
1612//TODO: doesn't inherit by literalExpr?
1613class literalID: public expr {
1614
1615    llvm::PooledStringPtr name_;
1616
1617protected:
1618    literalID(const literalID& other, pParseContext& C): expr(other), name_(other.name_) {}
1619   
1620public:
1621    literalID(const pSourceRange& name, pParseContext& C):
1622        expr(literalIDKind),
1623        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin()))))
1624    {
1625    }
1626
1627    pIdentString name(void) const {
1628        assert(name_);
1629        return *name_;
1630    }
1631
1632    static literalID* create(pStringRef name, pParseContext& C) {
1633        return new (C) literalID(pSourceRange(name.begin(),name.end()), C);
1634    }
1635
1636    stmt::child_iterator child_begin() { return child_iterator(); }
1637    stmt::child_iterator child_end() { return child_iterator(); }
1638
1639    IMPLEMENT_SUPPORT_MEMBERS(literalID);
1640
1641};
1642
1643// literal constant (always represents a runtime value symbol. optional target for static class)
1644class literalConstant: public literalExpr {
1645
1646    llvm::PooledStringPtr name_;
1647    expr* target_;
1648
1649protected:
1650    literalConstant(const literalConstant& other, pParseContext& C): literalExpr(other),
1651            name_(other.name_), target_(0)
1652    {
1653        if(other.target_)
1654            target_ = other.target_->clone(C);
1655    }
1656   
1657public:
1658    literalConstant(const pSourceRange& name, pParseContext& C, expr* target = NULL):
1659        literalExpr(literalConstantKind),
1660        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
1661        target_(target)
1662    {
1663    }
1664
1665    pIdentString name(void) const {
1666        assert(name_);
1667        return *name_;
1668    }
1669
1670    expr* target(void) const { return target_; }
1671
1672    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&target_); }
1673    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&target_+1); }
1674
1675    IMPLEMENT_SUPPORT_MEMBERS(literalConstant);
1676
1677};
1678
1679// dynamic ID, i.e. variable variable, or runtime class/method/function name
1680// Reflection in phc
1681class dynamicID: public expr {
1682   
1683    expr* val_;
1684
1685protected:
1686    dynamicID(const dynamicID& other, pParseContext& C): expr(other), val_(0)
1687    {
1688        if(other.val_)
1689            val_ = other.val_->clone(C);
1690    }
1691   
1692public:
1693    dynamicID(expr* val): expr (dynamicIDKind), val_(val)
1694    {
1695
1696    }
1697
1698    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&val_); }
1699    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&val_+1); }
1700
1701    expr* val(void) { return val_; }
1702
1703    IMPLEMENT_SUPPORT_MEMBERS(dynamicID);
1704
1705};
1706
1707
1708// NODE: var
1709class var: public expr {
1710
1711    enum { TARGET=0, INDICES=1 };
1712
1713    llvm::PooledStringPtr name_;
1714    pUInt indirectionCount_; // layers of indirection, i.e. variable variables
1715
1716    // children_[0] is always target, which may be null. the rest will be array indices
1717    // numChildren_ is always 1 + number of indices
1718    stmt** children_;
1719    pUInt numChildren_;
1720
1721protected:
1722    var(const var& other, pParseContext& C): expr(other), name_(other.name_),
1723            indirectionCount_(other.indirectionCount_), children_(other.children_),
1724            numChildren_(other.numChildren_)
1725    {
1726        deepCopyChildren(children_, other.children_, numChildren_, C);
1727    }
1728   
1729public:
1730    var(const pSourceRange& name, pParseContext& C, expr* target = NULL):
1731        expr(varKind),
1732        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
1733        indirectionCount_(0),
1734        children_(NULL),
1735        numChildren_(1)
1736    {
1737        children_ = new (C) stmt*[1];
1738        children_[TARGET] = target;
1739    }
1740
1741    var(const pSourceRange& name, pParseContext& C, expressionList* indices, expr* target = NULL):
1742        expr(varKind),
1743        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
1744        indirectionCount_(0),
1745        children_(NULL),
1746        numChildren_(1+indices->size())
1747    {
1748        children_ = new (C) stmt*[numChildren_];
1749        children_[TARGET] = target;
1750        if (numChildren_ > 1) {
1751            memcpy(children_+1, &(indices->front()), (numChildren_-1) * sizeof(stmt*));
1752        }
1753    }
1754
1755    pIdentString name(void) const {
1756        assert(name_);
1757        return *name_;
1758    }
1759
1760    void setTarget(expr *t) {
1761        children_[TARGET] = t;
1762    }
1763
1764    void setIndirectionCount(pUInt c) { indirectionCount_ = c; }
1765
1766    expr* target(void) const {
1767        assert((children_[TARGET] == NULL || isa<expr>(children_[TARGET])) && "unknown object in target");
1768        return static_cast<expr*>(children_[TARGET]);
1769    }
1770   
1771    /**
1772     * Whether a variable is simple (just $x) or complex, like $x["a"] or ${"xxx"}
1773     */
1774    bool isSimpleVar() const {
1775        if(indirectionCount() == 0 && numIndices() == 0 && target() == NULL)
1776            return true;
1777        return false;
1778    }
1779
1780    pUInt indirectionCount(void) const { return indirectionCount_; }
1781
1782    stmt::child_iterator child_begin() { return &children_[TARGET]; }
1783    stmt::child_iterator child_end() { return &children_[TARGET]+numChildren_; }
1784
1785    pUInt numIndices(void) const { return numChildren_-1; }
1786
1787    stmt::child_iterator indices_begin() { return &children_[INDICES]; }
1788    stmt::child_iterator indices_end() { return &children_[INDICES]+(numChildren_-1); }
1789
1790    IMPLEMENT_SUPPORT_MEMBERS(var);
1791
1792};
1793
1794// NODE: assignment
1795class assignment: public expr {
1796
1797    enum { LVAL, RVAL, END_EXPR };
1798    stmt* children_[END_EXPR];
1799    bool byRef_;
1800
1801protected:
1802    assignment(const assignment& other, pParseContext& C): expr(other),
1803            byRef_(other.byRef_)
1804    {
1805        memset(children_, 0, sizeof(children_));
1806        if(other.children_[LVAL])
1807            children_[LVAL] = other.children_[LVAL]->clone(C);
1808        if(other.children_[RVAL])
1809            children_[RVAL] = other.children_[RVAL]->clone(C);    }
1810   
1811public:
1812    assignment(expr* lVal, expr* rVal, bool r): expr(assignmentKind), children_(), byRef_(r)
1813    {
1814        children_[LVAL] = static_cast<stmt*>(lVal);
1815        children_[RVAL] = static_cast<stmt*>(rVal);
1816    }
1817
1818    expr* lVal(void) { return static_cast<expr*>(children_[LVAL]); }
1819    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1820
1821    bool byRef(void) const { return byRef_; }
1822
1823    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1824    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1825
1826    IMPLEMENT_SUPPORT_MEMBERS(assignment);
1827
1828};
1829
1830// NODE: list assignment
1831class listAssignment: public expr {
1832
1833    enum { VARLIST, RVAL, END_EXPR };
1834    stmt* children_[END_EXPR];
1835
1836protected:
1837    listAssignment(const listAssignment& other, pParseContext& C): expr(other)
1838    {
1839        memset(children_, 0, sizeof(children_));
1840        if(other.children_[VARLIST])
1841            children_[VARLIST] = other.children_[VARLIST]->clone(C);
1842        if(other.children_[RVAL])
1843            children_[RVAL] = other.children_[RVAL]->clone(C);
1844    }
1845   
1846public:
1847    listAssignment(block* varList, expr* rVal):
1848            expr(listAssignmentKind),
1849            children_()
1850    {
1851        children_[VARLIST] = static_cast<stmt*>(varList);
1852        children_[RVAL] = static_cast<stmt*>(rVal);
1853    }
1854
1855    expr* varList(void) { return static_cast<expr*>(children_[VARLIST]); }
1856    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1857
1858    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1859    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1860
1861    IMPLEMENT_SUPPORT_MEMBERS(listAssignment);
1862
1863};
1864
1865// NODE: op assignment
1866class opAssignment: public expr {
1867
1868public:
1869    enum opKind { CONCAT,
1870                  DIV,
1871                  MOD,
1872                  MULT,
1873                  ADD,
1874                  SUB,
1875                  OR,
1876                  XOR,
1877                  AND,
1878                  SHIFT_LEFT,
1879                  SHIFT_RIGHT
1880                };
1881
1882private:
1883    enum { LVAL, RVAL, END_EXPR };
1884    stmt* children_[END_EXPR];
1885    opKind opKind_;
1886
1887protected:
1888    opAssignment(const opAssignment& other, pParseContext& C): expr(other),
1889            opKind_(other.opKind_)
1890    {
1891        memset(children_, 0, sizeof(children_));
1892        if(other.children_[LVAL])
1893            children_[LVAL] = other.children_[LVAL]->clone(C);
1894        if(other.children_[RVAL])
1895            children_[RVAL] = other.children_[RVAL]->clone(C);
1896    }
1897   
1898public:
1899    opAssignment(expr* lVal, expr* rVal, opKind op): expr(assignmentKind), children_(), opKind_(op)
1900    {
1901        children_[LVAL] = static_cast<stmt*>(lVal);
1902        children_[RVAL] = static_cast<stmt*>(rVal);
1903    }
1904
1905    expr* lVal(void) { return static_cast<expr*>(children_[LVAL]); }
1906    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1907
1908    opKind opKind(void) const { return opKind_; }
1909
1910    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1911    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1912
1913    IMPLEMENT_SUPPORT_MEMBERS(opAssignment);
1914
1915};
1916
1917// NODE: function/method invoke
1918class functionInvoke: public expr {
1919
1920    enum { NAME=0, TARGET=1, INDICES=2 };
1921
1922    // children_[0] is always expr for name, which may be literalID or dynamicID
1923    // children_[1] is always target, which may be null. the rest will be array indices
1924    // numChildren_ is always 1 + number of indices
1925    stmt** children_;
1926    pUInt numChildren_;
1927
1928protected:
1929    functionInvoke(const functionInvoke& other, pParseContext& C): expr(other),
1930            children_(0), numChildren_(other.numChildren_)
1931    {
1932        deepCopyChildren(children_, other.children_, numChildren_, C);
1933    }
1934   
1935public:
1936    functionInvoke(expr* name, pParseContext& C):
1937        expr(functionInvokeKind),
1938        children_(NULL),
1939        numChildren_(2)
1940    {
1941        children_ = new (C) stmt*[numChildren_];
1942        children_[NAME] = name;
1943        children_[TARGET] = NULL;
1944    }
1945    functionInvoke(expr* name, pParseContext& C, expressionList* argList, expr* target = NULL):
1946        expr(functionInvokeKind),
1947        children_(NULL),
1948        numChildren_(2+argList->size())
1949    {
1950        children_ = new (C) stmt*[numChildren_];
1951        children_[NAME] = name;
1952        children_[TARGET] = target;
1953        if (numChildren_ > 2) {
1954            memcpy(children_+2, &(argList->front()), (numChildren_-2) * sizeof(stmt*));
1955        }
1956    }
1957    functionInvoke(expr* name, pParseContext& C, expr* arg1, expr* target = NULL):
1958        expr(functionInvokeKind),
1959        children_(NULL),
1960        numChildren_(3)
1961    {
1962        children_ = new (C) stmt*[numChildren_];
1963        children_[NAME] = name;
1964        children_[TARGET] = target;
1965        memcpy(children_+2, &arg1, sizeof(stmt*));
1966    }
1967
1968    bool isDynamic(void) const { return isa<dynamicID>(children_[NAME]); }
1969
1970    void setTarget(expr *t) {
1971        children_[TARGET] = t;
1972    }
1973
1974    expr* name(void) {
1975        assert(isa<literalID>(children_[NAME]) || isa<dynamicID>(children_[NAME]));
1976        return static_cast<expr*>(children_[NAME]);
1977    }
1978
1979    expr* target(void) {
1980        assert((children_[TARGET] == NULL || isa<expr>(children_[TARGET])) && "unknown object in target");
1981        return static_cast<expr*>(children_[TARGET]);
1982    }
1983
1984    pUInt numArgs(void) const { return numChildren_-1; }
1985
1986    stmt::child_iterator child_begin() { return &children_[0]; }
1987    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
1988
1989    stmt::child_iterator args_begin() { return &children_[INDICES]; }
1990    stmt::child_iterator args_end() { return &children_[INDICES]+(numChildren_-INDICES); }
1991
1992    stmt::child_range args() { return stmt::child_range(args_begin(), args_end()); }
1993
1994    IMPLEMENT_SUPPORT_MEMBERS(functionInvoke);
1995
1996};
1997
1998// NOP statement such as ;;
1999class emptyStmt: public stmt {
2000
2001protected:
2002    emptyStmt(const emptyStmt& other, pParseContext& C): stmt(other) {}
2003   
2004public:
2005        emptyStmt() : stmt(emptyStmtKind) {}
2006
2007
2008    stmt::child_iterator child_begin() { return child_iterator(); }
2009    stmt::child_iterator child_end() { return child_iterator(); }
2010
2011    IMPLEMENT_SUPPORT_MEMBERS(emptyStmt);
2012
2013};
2014
2015// NODE: unary operator
2016class unaryOp: public expr {
2017
2018public:
2019    enum opKind { NEGATIVE, POSITIVE, LOGICALNOT, BITWISENOT };
2020
2021private:
2022    expr* rVal_;
2023    opKind opKind_;
2024
2025protected:
2026    unaryOp(const unaryOp& other, pParseContext& C): expr(other), rVal_(0),
2027            opKind_(other.opKind_)
2028    {
2029        if(other.rVal_)
2030            rVal_ = other.rVal_->clone(C);
2031    }
2032   
2033public:
2034
2035    unaryOp(expr* rVal, opKind k): expr(unaryOpKind), rVal_(rVal), opKind_(k) {
2036        if (opKind_ == NEGATIVE) {
2037            // if our expression is a simple literal int, flag its sign
2038            if (literalInt* i = dyn_cast<literalInt>(rVal))
2039                i->setNegative(true);
2040        }
2041    }
2042
2043    expr* rVal(void) { return rVal_; }
2044
2045    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
2046    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
2047
2048    opKind opKind(void) const { return opKind_; }
2049
2050    IMPLEMENT_SUPPORT_MEMBERS(unaryOp);
2051
2052};
2053
2054// NODE: pre operator
2055class preOp: public expr {
2056
2057public:
2058    enum opKind { INC, DEC };
2059
2060private:
2061    expr* rVal_;
2062    opKind opKind_;
2063
2064protected:
2065    preOp(const preOp& other, pParseContext& C): expr(other), rVal_(0),
2066            opKind_(other.opKind_)
2067    {
2068        if(other.rVal_)
2069            rVal_ = other.rVal_->clone(C);
2070    }
2071   
2072public:
2073
2074    preOp(expr* rVal, opKind k): expr(preOpKind), rVal_(rVal), opKind_(k)
2075    {
2076    }
2077
2078    expr* rVal(void) { return rVal_; }
2079
2080    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
2081    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
2082
2083    opKind opKind(void) const { return opKind_; }
2084
2085    IMPLEMENT_SUPPORT_MEMBERS(preOp);
2086
2087};
2088
2089// NODE: post operator
2090class postOp: public expr {
2091
2092public:
2093    enum opKind { INC, DEC };
2094
2095private:
2096    expr* rVal_;
2097    opKind opKind_;
2098
2099protected:
2100    postOp(const postOp& other, pParseContext& C): expr(other), rVal_(0),
2101            opKind_(other.opKind_)
2102    {
2103        if(other.rVal_)
2104            rVal_ = other.rVal_->clone(C);
2105    }
2106   
2107public:
2108
2109    postOp(expr* rVal, opKind k): expr(postOpKind), rVal_(rVal), opKind_(k)
2110    {
2111    }
2112
2113    expr* rVal(void) { return rVal_; }
2114
2115    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
2116    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
2117
2118    opKind opKind(void) const { return opKind_; }
2119
2120    IMPLEMENT_SUPPORT_MEMBERS(postOp);
2121
2122};
2123
2124
2125// NODE: binary operator
2126class binaryOp: public expr {
2127
2128public:
2129    enum opKind { CONCAT,
2130                  BOOLEAN_AND,
2131                  BOOLEAN_OR,
2132                  BOOLEAN_XOR,
2133                  DIV,
2134                  MOD,
2135                  MULT,
2136                  ADD,
2137                  SUB,
2138                  GREATER_THAN,
2139                  LESS_THAN,
2140                  GREATER_OR_EQUAL,
2141                  LESS_OR_EQUAL,
2142                  EQUAL,
2143                  NOT_EQUAL,
2144                  IDENTICAL,
2145                  NOT_IDENTICAL,
2146                  BIT_OR,
2147                  BIT_AND,
2148                  BIT_XOR,
2149                  INSTANCEOF,
2150                  SHIFT_LEFT,
2151                  SHIFT_RIGHT
2152              };
2153
2154private:
2155    enum { LVAL, RVAL, END_EXPR };
2156    stmt* children_[END_EXPR];
2157    opKind opKind_;
2158
2159protected:
2160    binaryOp(const binaryOp& other, pParseContext& C): expr(other), opKind_(other.opKind_)
2161    {
2162        memset(children_, 0, sizeof(children_));
2163        if(other.children_[LVAL])
2164            children_[LVAL] = other.children_[LVAL]->clone(C);
2165        if(other.children_[RVAL])
2166            children_[RVAL] = other.children_[RVAL]->clone(C);
2167    }
2168   
2169public:
2170
2171    binaryOp(expr* lVal, expr* rVal, opKind k): expr(binaryOpKind), children_(), opKind_(k)
2172    {
2173        children_[LVAL] = static_cast<stmt*>(lVal);
2174        children_[RVAL] = static_cast<stmt*>(rVal);
2175    }
2176
2177    expr* lVal(void) { return static_cast<expr*>(children_[LVAL]); }
2178    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
2179
2180    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
2181    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
2182
2183    IMPLEMENT_SUPPORT_MEMBERS(binaryOp);
2184
2185    opKind opKind(void) const { return opKind_; }
2186
2187};
2188
2189// ternary shorthand for ifs ?:
2190class conditionalExpr: public expr {
2191
2192private:
2193    enum { COND, TRUEEXPR, FALSEEXPR, END_EXPR };
2194    stmt* children_[END_EXPR];
2195
2196protected:
2197    conditionalExpr(const conditionalExpr& other, pParseContext& C): expr(other)
2198    {
2199        memset(children_, 0, sizeof(children_));
2200        if(other.children_[COND])
2201            children_[COND] = other.children_[COND]->clone(C);
2202        if(other.children_[TRUEEXPR])
2203            children_[TRUEEXPR] = other.children_[TRUEEXPR]->clone(C);
2204        if(other.children_[FALSEEXPR])
2205            children_[FALSEEXPR] = other.children_[FALSEEXPR]->clone(C);
2206    }
2207   
2208public:
2209
2210    conditionalExpr(expr* condition, expr* trueexpr, expr* falseexpr): expr(conditionalExprKind), children_()
2211    {
2212        children_[COND] = static_cast<stmt*>(condition);
2213        children_[TRUEEXPR] = static_cast<stmt*>(trueexpr);
2214        children_[FALSEEXPR] = static_cast<stmt*>(falseexpr);
2215    }
2216
2217    expr* condition(void) const{ return static_cast<expr*>(children_[COND]); }
2218    expr* trueExpr(void) const{ return static_cast<expr*>(children_[TRUEEXPR]); }
2219    expr* falseExpr(void) const{ return static_cast<expr*>(children_[FALSEEXPR]); }
2220
2221    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
2222    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
2223
2224    IMPLEMENT_SUPPORT_MEMBERS(conditionalExpr);
2225
2226};
2227
2228// This class is needed for some transforms. It represents a block of statements of which the last one needs to be an
2229// expression. This class is used when lowering some expressions into some statements, which still have to evaluate to
2230// _something_. This can even be used to evaluate to a variable (which is then the last instruction in the statementList).
2231// !!!This class is not intended for use by the parser!!!
2232class exprReduce: public expr {
2233   
2234    block* statements_;
2235
2236protected:
2237    exprReduce(const exprReduce& other, pParseContext& C): expr(other), statements_(0)
2238    {
2239        statements_ = other.statements_->clone(C);
2240    }
2241   
2242public:
2243
2244    exprReduce(pParseContext& C, statementList* ptStatements): expr(exprReduceKind), statements_(NULL)
2245    {
2246        assert(!ptStatements->empty());
2247        assert(isa<expr>(ptStatements->back()) && "The last statement of a list of statements for an evalExpr needs to be an expression!");
2248        statements_ = new (C) block(C, ptStatements);
2249    }
2250    exprReduce(pParseContext& C, const expressionList* ptExpressions): expr(exprReduceKind), statements_(NULL)
2251    {
2252        assert(!ptExpressions->empty());
2253        statements_ = new (C) block(C, ptExpressions);
2254    }
2255    block* statements(void) const { return statements_; }
2256
2257    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&statements_); }
2258    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&statements_+1); }
2259
2260    IMPLEMENT_SUPPORT_MEMBERS(exprReduce);
2261
2262};
2263
2264} } // namespace
2265
2266#endif /* RPHP_PAST_H_ */
Note: See TracBrowser for help on using the browser.