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

Revision 1024, 53.3 KB (checked in by weyrick, 7 months ago)

magic and ignore

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// statement base class
130class stmt {
131
132    nodeKind kind_;
133
134    pUInt refCount_;
135
136    pUInt startLineNum_;
137    pUInt endLineNum_;
138
139protected:
140  void* operator new(size_t bytes) throw() {
141    assert(0 && "stmt cannot be allocated with regular 'new'.");
142    return 0;
143  }
144  void operator delete(void* data) throw() {
145    assert(0 && "stmt cannot be released with regular 'delete'.");
146  }
147
148  // overridden by extending classes to perform class specific destruction
149  // note you should still always call Stmt::doDestroy
150  virtual void doDestroy(pParseContext& C);
151
152  void destroyChildren(pParseContext& C);
153
154public:
155    stmt(nodeKind k): kind_(k), refCount_(1), startLineNum_(0), endLineNum_(0) { }
156
157    void destroy(pParseContext& C) {
158        assert(refCount_ >= 1);
159        if (--refCount_ == 0)
160            doDestroy(C);
161    }
162
163    stmt* retain() {
164      assert(refCount_ >= 1);
165      ++refCount_;
166      return this;
167    }
168
169    virtual ~stmt(void) { }
170
171    inline void* operator new(size_t bytes, pParseContext& C, size_t align=8) throw() {
172        return C.allocate(bytes, align);
173    }
174    inline void* operator new(size_t bytes, void* mem) throw() {
175      return mem;
176    }
177    void operator delete(void*, pParseContext&, unsigned) throw() { }
178    void operator delete(void*, std::size_t) throw() { }
179    void operator delete(void*, void*) throw() { }
180
181    typedef stmtIterator       child_iterator;
182    typedef constStmtIterator  const_child_iterator;
183    typedef boost::iterator_range<child_iterator> child_range;
184    typedef boost::iterator_range<const_child_iterator> const_child_range;
185
186
187    virtual child_iterator child_begin() = 0;
188    virtual child_iterator child_end()   = 0;
189
190    const_child_iterator child_begin() const {
191      return const_child_iterator(const_cast<stmt*>(this)->child_begin());
192    }
193
194    const_child_iterator child_end() const {
195      return const_child_iterator(const_cast<stmt*>(this)->child_end());
196    }
197    child_range children() {
198        return child_range(child_begin(), child_end());
199    }
200    const_child_range children() const {
201        return const_child_range(child_begin(), child_end());
202    }
203
204    nodeKind kind(void) const { return kind_; }
205
206    void setLine(pUInt start) { startLineNum_ = start; endLineNum_ = start; }
207    void setLine(pUInt start, pUInt end) { startLineNum_ = start; endLineNum_ = end; }
208
209    pUInt startLineNum(void) const { return startLineNum_; }
210    pUInt endLineNum(void) const { return endLineNum_; }
211
212    // LLVM isa<T> and casting support
213    static bool classof(const stmt* s) { return true; }
214
215};
216
217typedef std::vector<stmt*> statementList;
218
219// expression base class
220class expr: public stmt {
221
222public:
223    // see astNodes.def
224    static const nodeKind firstExprKind = exprReduceKind;
225    static const nodeKind lastExprKind = unaryOpKind;
226
227    expr(nodeKind k): stmt(k) { }
228
229    static bool classof(const expr* s) { return true; }
230    static bool classof(const stmt* s) {
231        return s->kind() >= firstExprKind &&
232               s->kind() <= lastExprKind;
233    }
234
235};
236
237typedef std::vector<expr*> expressionList;
238
239// a block of statements
240class block: public stmt {
241    stmt** block_;
242    pUInt numStmts_;
243public:
244
245    // build a block with a single expression
246    block(pParseContext& C, stmt* s): stmt(blockKind), block_(0), numStmts_(1) {
247        block_ = new (C) stmt*[numStmts_];
248        block_[0] = s;
249    }
250
251    block(pParseContext& C, const statementList* s): stmt(blockKind), block_(0), numStmts_(s->size()) {
252        if (numStmts_) {
253            block_ = new (C) stmt*[numStmts_];
254            memcpy(block_, &(s->front()), numStmts_ * sizeof(*block_));
255        }
256    }
257
258    block(pParseContext& C, const expressionList* s): stmt(blockKind), block_(0), numStmts_(s->size()) {
259        if (numStmts_) {
260            block_ = new (C) stmt*[numStmts_];
261            memcpy(block_, &(s->front()), numStmts_ * sizeof(*block_));
262        }
263    }
264
265    stmt::child_iterator child_begin() { return &block_[0]; }
266    stmt::child_iterator child_end() { return &block_[0]+numStmts_; }
267
268    static bool classof(const block* s) { return true; }
269    static bool classof(const stmt* s) { return s->kind() == blockKind; }
270
271};
272
273// declaration base class
274class decl: public stmt {
275
276public:
277    // see astNodes.def
278    static const nodeKind firstDeclKind = formalParamKind;
279    static const nodeKind lastDeclKind = functionDeclKind;
280
281    decl(nodeKind k): stmt(k) { }
282
283    static bool classof(const decl* s) { return true; }
284    static bool classof(const stmt* s) {
285        return s->kind() >= firstDeclKind &&
286               s->kind() <= lastDeclKind;
287    }
288
289};
290
291
292// global
293class globalDecl: public stmt {
294
295    stmt** children_;
296    pUInt numChildren_;
297
298public:
299
300    globalDecl(const expressionList* varList,
301               pParseContext& C):
302            stmt(globalDeclKind),
303            children_(0),
304            numChildren_(varList->size())
305    {
306        children_ = new (C) stmt*[numChildren_];
307        memcpy(children_, &(varList->front()), (numChildren_) * sizeof(stmt*));
308    }
309
310    stmt::child_iterator child_begin() { return &children_[0]; }
311    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
312
313    static bool classof(const globalDecl* s) { return true; }
314    static bool classof(const stmt* s) { return s->kind() == globalDeclKind; }
315
316};
317
318class staticDecl: public decl {
319
320    enum { DEFAULT=0, VARS=1 };
321
322    stmt** children_;
323    pUInt numChildren_;
324
325public:
326    staticDecl(const expressionList* varList,
327               pParseContext& C,
328               expr* def=NULL):
329        decl(staticDeclKind),
330        children_(0),
331        numChildren_(1+varList->size())
332    {
333        children_ = new (C) stmt*[numChildren_];
334        children_[DEFAULT] = def;
335        if (numChildren_ > 1) {
336            memcpy(children_+1, &(varList->front()), (numChildren_-1) * sizeof(stmt*));
337        }
338    }
339
340    expr* defaultExpr(void) {
341        return static_cast<expr*>(children_[DEFAULT]);
342    }
343
344    stmt::child_iterator child_begin() { return &children_[DEFAULT]; }
345    stmt::child_iterator child_end() { return &children_[DEFAULT]+numChildren_; }
346
347    stmt::child_iterator var_begin() { return &children_[VARS]; }
348    stmt::child_iterator var_end() { return &children_[VARS]+(numChildren_-1); }
349
350    static bool classof(const staticDecl* s) { return true; }
351    static bool classof(const stmt* s) { return s->kind() == staticDeclKind; }
352
353};
354
355
356class formalParam: public decl {
357
358    enum { byRefBit=1, arrayHintBit=2 };
359
360    llvm::PooledStringPtr name_;
361    llvm::PooledStringPtr classHint_;
362    pUInt flags_;
363    stmt* default_;
364
365public:
366    formalParam(const pSourceRange& name, pParseContext& C, bool ref, expr* def=NULL):
367        decl(formalParamKind),
368        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
369        classHint_(),
370        flags_(0),
371        default_(def)
372    {
373        if (ref) {
374            flags_ ^= byRefBit;
375        }
376    }
377
378    bool byRef(void) const { return flags_ & byRefBit; }
379
380    bool arrayHint(void) const { return flags_ & arrayHintBit; }
381
382    bool optional(void) const {  return default_ != NULL; }
383
384    void setArrayHint(void) { flags_ ^= arrayHintBit; }
385
386    void setClassHint(const pSourceRange& name, pParseContext& C) {
387        classHint_ = C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())));
388    }
389
390    pIdentString name(void) const {
391        assert(name_);
392        return *name_;
393    }
394
395    pIdentString classHint(void) const {
396        if (classHint_)
397            return *classHint_;
398        else
399            return "";
400    }
401
402    stmt::child_iterator child_begin() { return &default_; }
403    stmt::child_iterator child_end() { return &default_+1; }
404
405    static bool classof(const formalParam* s) { return true; }
406    static bool classof(const stmt* s) { return s->kind() == formalParamKind; }
407
408};
409
410typedef llvm::SmallVector<formalParam*,RPHP_FORMAL_PARAM_VECTOR_SIZE> formalParamList;
411
412class signature: public decl {
413
414    llvm::PooledStringPtr name_;
415    stmt** formalParamList_;
416    pUInt numParams_;
417    bool returnByRef_;
418
419public:
420    signature(const pSourceRange& name,
421              pParseContext& C,
422              const formalParamList* s,
423              bool returnByRef=false):
424            decl(signatureKind),
425            name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
426            formalParamList_(0),
427            numParams_(s->size()),
428            returnByRef_(returnByRef)
429    {
430        if (numParams_) {
431            formalParamList_ = new (C) stmt*[numParams_];
432            memcpy(formalParamList_, &(s->front()), numParams_ * sizeof(*formalParamList_));
433        }
434    }
435
436    pIdentString name(void) const {
437        assert(name_);
438        return *name_;
439    }
440
441    bool returnByRef(void) const { return returnByRef_; }
442
443    stmt::child_iterator child_begin() { return &formalParamList_[0]; }
444    stmt::child_iterator child_end() { return &formalParamList_[0]+numParams_; }
445
446    static bool classof(const signature* s) { return true; }
447    static bool classof(const stmt* s) { return s->kind() == signatureKind; }
448
449};
450
451// function declaration
452class functionDecl: public decl {
453
454    enum { SIG, BODY, END_EXPR };
455    stmt* children_[END_EXPR];
456
457public:
458    functionDecl(signature* sig, block* body):
459        decl(functionDeclKind),
460        children_()
461    {
462        children_[SIG] = sig;
463        children_[BODY] = body;
464    }
465
466    signature* sig(void) { return static_cast<signature*>(children_[SIG]); }
467    block* body(void) { return static_cast<block*>(children_[BODY]); }
468
469    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
470    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
471
472    static bool classof(const functionDecl* s) { return true; }
473    static bool classof(const stmt* s) { return s->kind() == functionDeclKind; }
474
475};
476
477struct memberFlags {
478    // these are taken by address during parse
479    static const pUInt PUBLIC;
480    static const pUInt PROTECTED;
481    static const pUInt PRIVATE;
482    static const pUInt STATIC;
483    static const pUInt ABSTRACT;
484    static const pUInt FINAL;
485    static const pUInt CONST;
486};
487
488// method declaration
489class methodDecl: public decl {
490
491    enum { SIG, BODY, END_EXPR };
492    pUInt flags_;
493    stmt* children_[END_EXPR];
494
495public:
496    methodDecl(signature* sig, pUInt flags, block* body):
497        decl(methodDeclKind),
498        flags_(flags),
499        children_()
500    {
501        children_[SIG] = sig;
502        children_[BODY] = body; // body may be null for abstract method
503        if (body == NULL)
504            flags_ |= memberFlags::ABSTRACT;
505    }
506
507    signature* sig(void) { return static_cast<signature*>(children_[SIG]); }
508    block* body(void) { return static_cast<block*>(children_[BODY]); }
509    pUInt flags(void) const { return flags_; }
510
511    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
512    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
513
514    static bool classof(const methodDecl* s) { return true; }
515    static bool classof(const stmt* s) { return s->kind() == methodDeclKind; }
516
517};
518
519// property declaration
520class propertyDecl: public decl {
521
522    pUInt flags_;
523    llvm::PooledStringPtr name_;
524    expr* default_;
525
526public:
527    propertyDecl(pParseContext& C,
528                 const pSourceRange& name,
529                 expr* def
530                 ):
531        decl(propertyDeclKind),
532        flags_(0),
533        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
534        default_(def)
535    {
536    }
537
538    void setFlags(pUInt f) { flags_ = f; }
539    pUInt flags(void) const { return flags_; }
540    pIdentString name(void) const {
541        assert(name_);
542        return *name_;
543    }
544
545    stmt::child_iterator child_begin() { return (stmt**)&default_; }
546    stmt::child_iterator child_end() { return (stmt**)&default_+1; }
547
548    static bool classof(const propertyDecl* s) { return true; }
549    static bool classof(const stmt* s) { return s->kind() == propertyDeclKind; }
550
551};
552
553
554
555// class/interface declaration
556class classDecl: public decl {
557public:
558
559    enum classType { NORMAL, IFACE, FINAL, ABSTRACT };
560
561private:
562    llvm::PooledStringPtr name_;
563    idList extends_;
564    idList implements_;
565    classType type_;
566    block* members_;
567
568public:
569    classDecl(pParseContext& C,
570              const pSourceRange& name,
571              classType type,
572              const sourceRangeList* extends, // may be null
573              const sourceRangeList* implements, // may be null
574              block* members
575              ):
576        decl(classDeclKind),
577        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
578        extends_(),
579        implements_(),
580        type_(type),
581        members_(members)
582    {
583        // intern list of extends (if any)
584        if (extends) {
585            for (sourceRangeList::const_iterator i=extends->begin();
586            i != extends->end();
587            ++i) {
588                extends_.push_back(C.idPool().intern(
589                        pStringRef(
590                                (*i)->begin().base(), ((*i)->end() - (*i)->begin()))
591                        ));
592            }
593        }
594        // intern list of implements (if any)
595        if (implements) {
596            for (sourceRangeList::const_iterator i=implements->begin();
597            i != implements->end();
598            ++i) {
599                implements_.push_back(C.idPool().intern(
600                        pStringRef(
601                                (*i)->begin().base(), ((*i)->end() - (*i)->begin()))
602                        ));
603            }
604        }
605    }
606
607    pIdentString name(void) const {
608        assert(name_);
609        return *name_;
610    }
611    block* members(void) { return members_; }
612
613    stmt::child_iterator child_begin() { return (stmt**)&members_; }
614    stmt::child_iterator child_end() { return (stmt**)&members_+1; }
615
616    static bool classof(const classDecl* s) { return true; }
617    static bool classof(const stmt* s) { return s->kind() == classDeclKind; }
618
619};
620
621// if statement
622class ifStmt: public stmt {
623
624    enum { CONDITION, TRUEBLOCK, FALSEBLOCK, END_EXPR };
625    stmt* children_[END_EXPR];
626
627public:
628    ifStmt(pParseContext& C,
629           expr* cond,
630           stmt* trueBlock,
631           stmt* falseBlock):
632               stmt(ifStmtKind),
633               children_() {
634
635        // enforce blocks to ease later traversal
636        if (trueBlock && !isa<block>(trueBlock))
637            trueBlock = new (C) block(C, trueBlock);
638
639        if (falseBlock && !isa<block>(falseBlock))
640            falseBlock = new (C) block(C, falseBlock);
641
642        children_[CONDITION] = static_cast<stmt*>(cond);
643        children_[TRUEBLOCK] = trueBlock;
644        children_[FALSEBLOCK] = falseBlock;
645
646    }
647
648    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
649    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
650
651    expr* condition(void) { return static_cast<expr*>(children_[CONDITION]); }
652    stmt* trueBlock(void) { return children_[TRUEBLOCK]; }
653    stmt* falseBlock(void) { return children_[FALSEBLOCK]; }
654
655    static bool classof(const ifStmt* s) { return true; }
656    static bool classof(const stmt* s) { return s->kind() == ifStmtKind; }
657
658};
659
660// switch case
661class switchCase: public stmt {
662
663    enum { COND, BODY, END_EXPR };
664    stmt* children_[END_EXPR];
665
666public:
667    switchCase(expr* cond,
668               block* body):
669    stmt(switchCaseKind),
670    children_()
671    {
672
673        children_[COND] = static_cast<stmt*>(cond);
674        children_[BODY] = static_cast<stmt*>(body);
675
676    }
677
678    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
679    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
680
681    // note if condition is null, this is a default: case
682    expr* condition(void) { return static_cast<expr*>(children_[COND]); }
683    block* body(void) { return static_cast<block*>(children_[BODY]); }
684
685    static bool classof(const switchCase* s) { return true; }
686    static bool classof(const stmt* s) { return s->kind() == switchCaseKind; }
687
688};
689
690// switch statement
691class switchStmt: public stmt {
692
693    enum { RVAL, CASEBLOCK, END_EXPR };
694    stmt* children_[END_EXPR];
695
696public:
697    switchStmt(expr* rVal,
698               block* caseBlock):
699    stmt(switchStmtKind),
700    children_() {
701
702        children_[RVAL] = static_cast<stmt*>(rVal);
703        children_[CASEBLOCK] = caseBlock;
704
705    }
706
707    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
708    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
709
710    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
711    block* caseBlock(void) { return static_cast<block*>(children_[CASEBLOCK]); }
712
713    static bool classof(const switchStmt* s) { return true; }
714    static bool classof(const stmt* s) { return s->kind() == switchStmtKind; }
715
716};
717
718// foreach statement
719class forEach: public stmt {
720
721    enum { RVAL, BODY, END_EXPR };
722    stmt* children_[END_EXPR];
723
724    llvm::PooledStringPtr value_;
725    llvm::PooledStringPtr key_; // may be empty
726    bool byRef_;
727
728public:
729    forEach(expr* rVal,
730            stmt* body,
731            pParseContext& C,
732            const pSourceRange& val,           
733            bool byRef,
734            const pSourceRange* key=NULL):
735    stmt(forEachKind),
736    children_(),
737    value_(C.idPool().intern(pStringRef(val.begin().base(), (val.end()-val.begin())))),
738    key_(),
739    byRef_(byRef)
740    {
741
742        // enfore a block for body to ease later traversal
743        if (!isa<block>(body)) {
744            body = new (C) block(C, body);
745        }
746
747        children_[RVAL] = static_cast<stmt*>(rVal);
748        children_[BODY] = static_cast<stmt*>(body);
749        if (key) {
750            key_ = C.idPool().intern(pStringRef(key->begin().base(), (key->end()-key->begin())));
751        }
752
753    }
754
755    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
756    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
757
758    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
759    block* body(void) { return static_cast<block*>(children_[BODY]); }
760
761    bool hasKey(void) const { return key_; }
762
763    pIdentString key(void) const {
764        if (key_)
765            return *key_;
766        else
767            return pIdentString();
768    }
769
770    pIdentString value(void) const {
771        assert(value_);
772        return *value_;
773    }
774
775    static bool classof(const forEach* s) { return true; }
776    static bool classof(const stmt* s) { return s->kind() == forEachKind; }
777
778};
779
780// for statement
781class forStmt: public stmt {
782
783    enum { INIT, COND, INC, BODY, END_EXPR };
784    stmt* children_[END_EXPR];
785
786public:
787    forStmt(pParseContext& C,
788            stmt* init,
789            stmt* cond,
790            stmt* inc,
791            stmt* body):
792    stmt(forStmtKind),
793    children_()
794    {
795
796        // enfore a block for body to ease later traversal
797        if (!isa<block>(body)) {
798            body = new (C) block(C, body);
799        }
800
801        children_[INIT] = init; // may be block or expr
802        children_[COND] = cond; // may be block or expr
803        children_[INC] = inc; // may be block or expr
804        children_[BODY] = static_cast<stmt*>(body);
805
806    }
807
808    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
809    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
810
811    stmt* init(void) const { return children_[INIT]; }
812    stmt* condition(void) const { return children_[COND]; }
813    stmt* increment(void) const { return children_[INC]; }
814    block* body(void) const { return static_cast<block*>(children_[BODY]); }
815
816    static bool classof(const forStmt* s) { return true; }
817    static bool classof(const stmt* s) { return s->kind() == forStmtKind; }
818
819};
820
821// do statement
822class doStmt: public stmt {
823
824    enum { COND, BODY, END_EXPR };
825    stmt* children_[END_EXPR];
826
827public:
828    doStmt(pParseContext& C,
829           expr* cond,
830           stmt* body):
831    stmt(doStmtKind),
832    children_()
833    {
834
835        // enfore a block for body to ease later traversal
836        if (!isa<block>(body)) {
837            body = new (C) block(C, body);
838        }
839
840        children_[COND] = static_cast<stmt*>(cond);
841        children_[BODY] = static_cast<stmt*>(body);
842
843    }
844
845    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
846    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
847
848    expr* condition(void) { return static_cast<expr*>(children_[COND]); }
849    block* body(void) { return static_cast<block*>(children_[BODY]); }
850
851    static bool classof(const doStmt* s) { return true; }
852    static bool classof(const stmt* s) { return s->kind() == doStmtKind; }
853
854};
855
856// while statement
857class whileStmt: public stmt {
858
859    enum { COND, BODY, END_EXPR };
860    stmt* children_[END_EXPR];
861
862public:
863    whileStmt(pParseContext& C,
864              expr* cond,
865              stmt* body):
866    stmt(whileStmtKind),
867    children_()
868    {
869
870        // enfore a block for body to ease later traversal
871        if (!isa<block>(body)) {
872            body = new (C) block(C, body);
873        }
874
875        children_[COND] = static_cast<stmt*>(cond);
876        children_[BODY] = static_cast<stmt*>(body);
877
878    }
879
880    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
881    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
882
883    expr* condition(void) { return static_cast<expr*>(children_[COND]); }
884    block* body(void) { return static_cast<block*>(children_[BODY]); }
885
886    static bool classof(const whileStmt* s) { return true; }
887    static bool classof(const stmt* s) { return s->kind() == whileStmtKind; }
888
889};
890
891
892
893// type cast
894class typeCast: public expr {
895public:
896    enum castKindType { STRING, BINARY, UNICODE, INT, REAL, BOOL, UNSET, ARRAY, OBJECT };
897
898private:
899    expr* rVal_;
900    castKindType castKind_;
901
902public:
903    typeCast(castKindType kind, expr* rVal): expr(typeCastKind), rVal_(rVal), castKind_(kind)
904    {
905
906    }
907
908    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
909    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
910
911    expr* rVal(void) { return rVal_; }
912    castKindType castKind(void) const { return castKind_; }
913
914    static bool classof(const typeCast* s) { return true; }
915    static bool classof(const stmt* s) { return s->kind() == typeCastKind; }
916
917};
918
919// return statement
920class returnStmt: public stmt {
921    expr* rVal_;
922public:
923    returnStmt(expr* rVal): stmt(returnStmtKind), rVal_(rVal)
924    {
925
926    }
927
928    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
929    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
930
931    expr* rVal(void) { return rVal_; }
932
933    static bool classof(const returnStmt* s) { return true; }
934    static bool classof(const stmt* s) { return s->kind() == returnStmtKind; }
935
936};
937
938// break statement
939class breakStmt: public stmt {
940    expr* rVal_;
941public:
942    breakStmt(expr* rVal): stmt(breakStmtKind), rVal_(rVal)
943    {
944
945    }
946
947    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
948    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
949
950    expr* rVal(void) { return rVal_; }
951
952    static bool classof(const breakStmt* s) { return true; }
953    static bool classof(const stmt* s) { return s->kind() == breakStmtKind; }
954
955};
956
957// continue statement
958class continueStmt: public stmt {
959    expr* rVal_;
960public:
961    continueStmt(expr* rVal): stmt(continueStmtKind), rVal_(rVal)
962    {
963
964    }
965
966    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
967    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
968
969    expr* rVal(void) { return rVal_; }
970
971    static bool classof(const continueStmt* s) { return true; }
972    static bool classof(const stmt* s) { return s->kind() == continueStmtKind; }
973
974};
975
976// catch
977class catchStmt: public stmt {
978
979    llvm::PooledStringPtr className_;
980    llvm::PooledStringPtr varName_;
981    block* body_;
982
983public:
984    catchStmt(const pSourceRange& className,
985              const pSourceRange& varName,
986              pParseContext& C,
987              block* body):
988    stmt(catchStmtKind),
989    className_(C.idPool().intern(pStringRef(className.begin().base(), (className.end()-className.begin())))),
990    varName_(C.idPool().intern(pStringRef(varName.begin().base(), (varName.end()-varName.begin())))),
991    body_(body)
992    {
993    }
994
995    pIdentString className(void) const {
996        assert(className_);
997        return *className_;
998    }
999
1000    pIdentString varName(void) const {
1001        assert(varName_);
1002        return *varName_;
1003    }
1004
1005    stmt::child_iterator child_begin() { return (stmt**)&body_; }
1006    stmt::child_iterator child_end() { return (stmt**)&body_+1; }
1007
1008    static bool classof(const catchStmt* s) { return true; }
1009    static bool classof(const stmt* s) { return s->kind() == catchStmtKind; }
1010
1011};
1012
1013
1014// try
1015class tryStmt: public stmt {
1016
1017    enum { BODY=0, CATCHLIST=1 };
1018
1019    // children_[0] is always body. the rest are catch blocks
1020    // numChildren_ is always 1 + number of catch blocks
1021    stmt** children_;
1022    pUInt numChildren_;
1023
1024public:
1025    tryStmt(pParseContext& C, block* body, statementList* catchList):
1026        stmt(tryStmtKind),
1027        children_(NULL),
1028        numChildren_(1+catchList->size())
1029    {
1030        children_ = new (C) stmt*[numChildren_];
1031        children_[BODY] = body;
1032        if (numChildren_ > 1) {
1033            memcpy(children_+1, &(catchList->front()), (numChildren_-1) * sizeof(stmt*));
1034        }
1035    }
1036
1037    block* body(void) {
1038        return static_cast<block*>(children_[BODY]);
1039    }
1040
1041    stmt::child_iterator child_begin() { return &children_[0]; }
1042    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
1043
1044    pUInt numCatches(void) const { return numChildren_-1; }
1045
1046    stmt::child_iterator catches_begin() { return &children_[CATCHLIST]; }
1047    stmt::child_iterator catches_end() { return &children_[CATCHLIST]+(numChildren_-1); }
1048
1049    static bool classof(const tryStmt* s) { return true; }
1050    static bool classof(const stmt* s) { return s->kind() == tryStmtKind; }
1051
1052};
1053
1054
1055// builtins: language constructs that seem like function calls, but aren't.
1056// exit, isset, unset, empty, echo, print, include, require, clone, throw, @
1057class builtin: public expr {
1058public:
1059    enum opKind {
1060                  EXIT, // start expr
1061                  ISSET,
1062                  UNSET,
1063                  EMPTY,
1064                  CLONE,
1065                  INCLUDE,
1066                  INCLUDE_ONCE,
1067                  REQUIRE,
1068                  REQUIRE_ONCE,
1069                  PRINT, // end expr
1070                  ECHO,   // start statements
1071                  IGNORE_WARNING,
1072                  THROW   // end statements
1073                };
1074
1075private:
1076    stmt** children_;
1077    pUInt numChildren_;
1078    opKind opKind_;
1079
1080public:
1081
1082    builtin(pParseContext& C, opKind op, const expressionList* s=NULL):
1083            expr(builtinKind),
1084            children_(0),
1085            numChildren_(0),
1086            opKind_(op)
1087    {
1088        if (s) {
1089            numChildren_ = s->size();
1090            children_ = new (C) stmt*[numChildren_];
1091            memcpy(children_, &(s->front()), numChildren_ * sizeof(*children_));
1092        }
1093    }
1094
1095    opKind opKind() const { return opKind_; }
1096    pUInt numArgs() const { return numChildren_; }
1097
1098    stmt::child_iterator child_begin() { return &children_[0]; }
1099    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
1100
1101    static bool classof(const builtin* s) { return true; }
1102    static bool classof(const stmt* s) { return s->kind() == builtinKind; }
1103
1104};
1105
1106// literal expression base class
1107class literalExpr: public expr {
1108
1109protected:
1110    pSourceString stringVal_;
1111
1112public:
1113
1114    // see astNodes.def
1115    static const nodeKind firstLiteralKind = literalStringKind;
1116    static const nodeKind lastLiteralKind = inlineHtmlKind;
1117
1118    literalExpr(nodeKind k): expr(k), stringVal_() { }
1119    literalExpr(nodeKind k, const pSourceRange& v): expr(k), stringVal_(v.begin(), v.end()) { }
1120
1121    virtual const pSourceString& getStringVal(void) const {
1122        return stringVal_;
1123    }
1124
1125    stmt::child_iterator child_begin() { return child_iterator(); }
1126    stmt::child_iterator child_end() { return child_iterator(); }
1127
1128    static bool classof(const literalExpr* s) { return true; }
1129    static bool classof(const stmt* s) {
1130        return s->kind() >= firstLiteralKind &&
1131               s->kind() <= lastLiteralKind;
1132    }
1133
1134};
1135
1136// NODE: literal bstring
1137class literalString: public literalExpr {
1138
1139    bool isBinary_;
1140    bool isSimple_; // i.e., single quoted
1141
1142    // this is storage for a string that was artificially created
1143    // during a pass and therefore doesn't exist in the original source
1144    pSourceString* artificial_;
1145
1146public:
1147
1148    // empty source string
1149    literalString(bool isBinary):
1150            literalExpr(literalStringKind),
1151            isBinary_(isBinary),
1152            isSimple_(true),
1153            artificial_(0) { }
1154
1155    // normal source string
1156    literalString(const pSourceRange& v, bool isBinary):
1157            literalExpr(literalStringKind, v),
1158            isBinary_(isBinary),
1159            isSimple_(true),
1160            artificial_(0) { }
1161
1162    // extending string (inline html)
1163    literalString(const pSourceRange& v, nodeKind k):
1164            literalExpr(k, v),
1165            isBinary_(false),
1166            isSimple_(true),
1167            artificial_(0) { }
1168
1169    // artificial constructor (creates storage space)
1170    literalString(pStringRef r):
1171            literalExpr(literalStringKind),
1172            isBinary_(true),
1173            isSimple_(true),
1174            artificial_(new pSourceString(r)) { }
1175
1176    ~literalString(void) {
1177        if (artificial_)
1178            delete artificial_;
1179    }
1180
1181    bool isBinary(void) const { return isBinary_; }
1182
1183    void setIsSimple(bool s)  {
1184        isSimple_ = s;
1185    }
1186
1187    void setStringVal(pStringRef s) {
1188        if (artificial_)
1189            delete artificial_;
1190        artificial_ = new pSourceString(s);
1191    }
1192
1193    const pSourceString& getStringVal(void) const {
1194        if (artificial_)
1195            return *artificial_;
1196        else
1197            return stringVal_;
1198    }
1199
1200    bool isSimple(void) const { return isSimple_; }
1201
1202    stmt::child_iterator child_begin() { return child_iterator(); }
1203    stmt::child_iterator child_end() { return child_iterator(); }
1204
1205    static bool classof(const literalString* s) { return true; }
1206    static bool classof(const stmt* s) { return s->kind() == literalStringKind; }
1207
1208};
1209
1210// NODE: literal int
1211class literalInt: public literalExpr {
1212
1213    bool negative_;
1214
1215public:
1216    literalInt(const pSourceRange& v): literalExpr(literalIntKind, v), negative_(false) { }
1217
1218    bool negative(void) const { return negative_; }
1219    void setNegative(bool n) { negative_ = n; }
1220
1221    stmt::child_iterator child_begin() { return child_iterator(); }
1222    stmt::child_iterator child_end() { return child_iterator(); }
1223
1224    static bool classof(const literalInt* s) { return true; }
1225    static bool classof(const stmt* s) { return s->kind() == literalIntKind; }
1226
1227};
1228
1229// NODE: literal float
1230class literalFloat: public literalExpr {
1231
1232public:
1233    literalFloat(const pSourceRange& v): literalExpr(literalFloatKind, v) { }
1234
1235    stmt::child_iterator child_begin() { return child_iterator(); }
1236    stmt::child_iterator child_end() { return child_iterator(); }
1237
1238    static bool classof(const literalFloat* s) { return true; }
1239    static bool classof(const stmt* s) { return s->kind() == literalFloatKind; }
1240
1241};
1242
1243// NODE: literal bool
1244class literalBool: public literalExpr {
1245
1246    bool boolVal_;
1247
1248public:
1249    literalBool(bool v): literalExpr(literalBoolKind), boolVal_(v) { }
1250
1251    bool getBoolVal(void) const { return boolVal_; }
1252
1253    stmt::child_iterator child_begin() { return child_iterator(); }
1254    stmt::child_iterator child_end() { return child_iterator(); }
1255
1256    static bool classof(const literalBool* s) { return true; }
1257    static bool classof(const stmt* s) { return s->kind() == literalBoolKind; }
1258
1259};
1260
1261// array items
1262struct arrayItem {
1263    expr* key;
1264    expr* val;
1265    bool isRef;
1266    arrayItem(expr* k, expr* v, bool r):
1267     key(k),
1268     val(v),
1269     isRef(r)
1270     { }
1271};
1272
1273typedef std::vector<arrayItem> arrayList;
1274
1275// NODE: literal array
1276class literalArray: public literalExpr {
1277
1278    arrayList itemList_;
1279
1280public:
1281    literalArray(arrayList* items):
1282        literalExpr(literalArrayKind),
1283        itemList_(*items) // copy
1284        { }
1285
1286    virtual void doDestroy(pParseContext& C) {
1287        for (arrayList::iterator i = itemList_.begin(); i != itemList_.end(); ++i) {
1288            if ((*i).key) {
1289                (*i).key->destroy(C);
1290            }
1291            (*i).val->destroy(C);
1292        }
1293        stmt::doDestroy(C);
1294    }
1295
1296    arrayList& itemList(void) { return itemList_; }
1297    const arrayList& itemList(void) const { return itemList_; }
1298
1299    static bool classof(const literalArray* s) { return true; }
1300    static bool classof(const stmt* s) { return s->kind() == literalArrayKind; }
1301
1302};
1303
1304
1305// NODE: inline html
1306class inlineHtml: public literalString {
1307
1308public:
1309    inlineHtml(const pSourceRange& v): literalString(v, inlineHtmlKind) { }
1310
1311    stmt::child_iterator child_begin() { return child_iterator(); }
1312    stmt::child_iterator child_end() { return child_iterator(); }
1313
1314    static bool classof(const inlineHtml* s) { return true; }
1315    static bool classof(const stmt* s) { return s->kind() == inlineHtmlKind; }
1316
1317};
1318
1319
1320// NODE: literal null
1321class literalNull: public literalExpr {
1322
1323public:
1324    literalNull(void): literalExpr(literalNullKind) { }
1325
1326    stmt::child_iterator child_begin() { return child_iterator(); }
1327    stmt::child_iterator child_end() { return child_iterator(); }
1328
1329    static bool classof(const literalNull* s) { return true; }
1330    static bool classof(const stmt* s) { return s->kind() == literalNullKind; }
1331
1332};
1333
1334// literal ID (always represents a class or function symbol name)
1335class literalID: public expr {
1336
1337    llvm::PooledStringPtr name_;
1338
1339public:
1340    literalID(const pSourceRange& name, pParseContext& C):
1341        expr(literalIDKind),
1342        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin()))))
1343    {
1344    }
1345
1346    pIdentString name(void) const {
1347        assert(name_);
1348        return *name_;
1349    }
1350
1351    static literalID* create(pStringRef name, pParseContext& C) {
1352        return new (C) literalID(pSourceRange(name.begin(),name.end()), C);
1353    }
1354
1355    stmt::child_iterator child_begin() { return child_iterator(); }
1356    stmt::child_iterator child_end() { return child_iterator(); }
1357
1358    static bool classof(const literalID* s) { return true; }
1359    static bool classof(const stmt* s) { return s->kind() == literalIDKind; }
1360
1361};
1362
1363// literal constant (always represents a runtime value symbol. optional target for static class)
1364class literalConstant: public literalExpr {
1365
1366    llvm::PooledStringPtr name_;
1367    expr* target_;
1368
1369public:
1370    literalConstant(const pSourceRange& name, pParseContext& C, expr* target = NULL):
1371        literalExpr(literalConstantKind),
1372        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
1373        target_(target)
1374    {
1375    }
1376
1377    pIdentString name(void) const {
1378        assert(name_);
1379        return *name_;
1380    }
1381
1382    expr* target(void) const { return target_; }
1383
1384    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&target_); }
1385    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&target_+1); }
1386
1387    static bool classof(const literalConstant* s) { return true; }
1388    static bool classof(const stmt* s) { return s->kind() == literalConstantKind; }
1389
1390};
1391
1392// dynamic ID, i.e. variable variable, or runtime class/method/function name
1393// Reflection in phc
1394class dynamicID: public expr {
1395    expr* val_;
1396public:
1397    dynamicID(expr* val): expr (dynamicIDKind), val_(val)
1398    {
1399
1400    }
1401
1402    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&val_); }
1403    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&val_+1); }
1404
1405    expr* val(void) { return val_; }
1406
1407    static bool classof(const dynamicID* s) { return true; }
1408    static bool classof(const stmt* s) { return s->kind() == dynamicIDKind; }
1409
1410};
1411
1412
1413// NODE: var
1414class var: public expr {
1415
1416    enum { TARGET=0, INDICES=1 };
1417
1418    llvm::PooledStringPtr name_;
1419    pUInt indirectionCount_; // layers of indirection, i.e. variable variables
1420
1421    // children_[0] is always target, which may be null. the rest will be array indices
1422    // numChildren_ is always 1 + number of indices
1423    stmt** children_;
1424    pUInt numChildren_;
1425
1426public:
1427    var(const pSourceRange& name, pParseContext& C, expr* target = NULL):
1428        expr(varKind),
1429        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
1430        indirectionCount_(0),
1431        children_(NULL),
1432        numChildren_(1)
1433    {
1434        children_ = new (C) stmt*[1];
1435        children_[TARGET] = target;
1436    }
1437
1438    var(const pSourceRange& name, pParseContext& C, expressionList* indices, expr* target = NULL):
1439        expr(varKind),
1440        name_(C.idPool().intern(pStringRef(name.begin().base(), (name.end()-name.begin())))),
1441        indirectionCount_(0),
1442        children_(NULL),
1443        numChildren_(1+indices->size())
1444    {
1445        children_ = new (C) stmt*[numChildren_];
1446        children_[TARGET] = target;
1447        if (numChildren_ > 1) {
1448            memcpy(children_+1, &(indices->front()), (numChildren_-1) * sizeof(stmt*));
1449        }
1450    }
1451
1452    pIdentString name(void) const {
1453        assert(name_);
1454        return *name_;
1455    }
1456
1457    void setTarget(expr *t) {
1458        children_[TARGET] = t;
1459    }
1460
1461    void setIndirectionCount(pUInt c) { indirectionCount_ = c; }
1462
1463    expr* target(void) {
1464        assert((children_[TARGET] == NULL || isa<expr>(children_[TARGET])) && "unknown object in target");
1465        return static_cast<expr*>(children_[TARGET]);
1466    }
1467
1468    pUInt indirectionCount(void) const { return indirectionCount_; }
1469
1470    stmt::child_iterator child_begin() { return &children_[TARGET]; }
1471    stmt::child_iterator child_end() { return &children_[TARGET]+numChildren_; }
1472
1473    pUInt numIndices(void) const { return numChildren_-1; }
1474
1475    stmt::child_iterator indices_begin() { return &children_[INDICES]; }
1476    stmt::child_iterator indices_end() { return &children_[INDICES]+(numChildren_-1); }
1477
1478    static bool classof(const var* s) { return true; }
1479    static bool classof(const stmt* s) { return s->kind() == varKind; }
1480
1481};
1482
1483// NODE: assignment
1484class assignment: public expr {
1485
1486    enum { LVAL, RVAL, END_EXPR };
1487    stmt* children_[END_EXPR];
1488    bool byRef_;
1489
1490public:
1491    assignment(expr* lVal, expr* rVal, bool r): expr(assignmentKind), children_(), byRef_(r)
1492    {
1493        children_[LVAL] = static_cast<stmt*>(lVal);
1494        children_[RVAL] = static_cast<stmt*>(rVal);
1495    }
1496
1497    expr* lVal(void) { return static_cast<expr*>(children_[LVAL]); }
1498    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1499
1500    bool byRef(void) const { return byRef_; }
1501
1502    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1503    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1504
1505    static bool classof(const assignment* s) { return true; }
1506    static bool classof(const stmt* s) { return s->kind() == assignmentKind; }
1507
1508};
1509
1510// NODE: list assignment
1511class listAssignment: public expr {
1512
1513    enum { VARLIST, RVAL, END_EXPR };
1514    stmt* children_[END_EXPR];
1515
1516public:
1517    listAssignment(block* varList, expr* rVal):
1518            expr(listAssignmentKind),
1519            children_()
1520    {
1521        children_[VARLIST] = static_cast<stmt*>(varList);
1522        children_[RVAL] = static_cast<stmt*>(rVal);
1523    }
1524
1525    expr* varList(void) { return static_cast<expr*>(children_[VARLIST]); }
1526    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1527
1528    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1529    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1530
1531    static bool classof(const listAssignment* s) { return true; }
1532    static bool classof(const stmt* s) { return s->kind() == listAssignmentKind; }
1533
1534};
1535
1536// NODE: op assignment
1537class opAssignment: public expr {
1538
1539public:
1540    enum opKind { CONCAT,
1541                  DIV,
1542                  MOD,
1543                  MULT,
1544                  ADD,
1545                  SUB,
1546                  OR,
1547                  XOR,
1548                  AND,
1549                  SHIFT_LEFT,
1550                  SHIFT_RIGHT
1551                };
1552
1553private:
1554    enum { LVAL, RVAL, END_EXPR };
1555    stmt* children_[END_EXPR];
1556    opKind opKind_;
1557
1558public:
1559    opAssignment(expr* lVal, expr* rVal, opKind op): expr(assignmentKind), children_(), opKind_(op)
1560    {
1561        children_[LVAL] = static_cast<stmt*>(lVal);
1562        children_[RVAL] = static_cast<stmt*>(rVal);
1563    }
1564
1565    expr* lVal(void) { return static_cast<expr*>(children_[LVAL]); }
1566    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1567
1568    opKind opKind(void) const { return opKind_; }
1569
1570    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1571    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1572
1573    static bool classof(const opAssignment* s) { return true; }
1574    static bool classof(const stmt* s) { return s->kind() == opAssignmentKind; }
1575
1576};
1577
1578// NODE: function/method invoke
1579class functionInvoke: public expr {
1580
1581    enum { NAME=0, TARGET=1, INDICES=2 };
1582
1583    // children_[0] is always expr for name, which may be literalID or dynamicID
1584    // children_[1] is always target, which may be null. the rest will be array indices
1585    // numChildren_ is always 1 + number of indices
1586    stmt** children_;
1587    pUInt numChildren_;
1588
1589public:
1590    functionInvoke(expr* name, pParseContext& C):
1591        expr(functionInvokeKind),
1592        children_(NULL),
1593        numChildren_(2)
1594    {
1595        children_ = new (C) stmt*[numChildren_];
1596        children_[NAME] = name;
1597        children_[TARGET] = NULL;
1598    }
1599    functionInvoke(expr* name, pParseContext& C, expressionList* argList, expr* target = NULL):
1600        expr(functionInvokeKind),
1601        children_(NULL),
1602        numChildren_(2+argList->size())
1603    {
1604        children_ = new (C) stmt*[numChildren_];
1605        children_[NAME] = name;
1606        children_[TARGET] = target;
1607        if (numChildren_ > 2) {
1608            memcpy(children_+2, &(argList->front()), (numChildren_-2) * sizeof(stmt*));
1609        }
1610    }
1611    functionInvoke(expr* name, pParseContext& C, expr* arg1, expr* target = NULL):
1612        expr(functionInvokeKind),
1613        children_(NULL),
1614        numChildren_(3)
1615    {
1616        children_ = new (C) stmt*[numChildren_];
1617        children_[NAME] = name;
1618        children_[TARGET] = target;
1619        memcpy(children_+2, &arg1, sizeof(stmt*));
1620    }
1621
1622    bool isDynamic(void) const { return isa<dynamicID>(children_[NAME]); }
1623
1624    void setTarget(expr *t) {
1625        children_[TARGET] = t;
1626    }
1627
1628    expr* name(void) {
1629        assert(isa<literalID>(children_[NAME]) || isa<dynamicID>(children_[NAME]));
1630        return static_cast<expr*>(children_[NAME]);
1631    }
1632
1633    expr* target(void) {
1634        assert((children_[TARGET] == NULL || isa<expr>(children_[TARGET])) && "unknown object in target");
1635        return static_cast<expr*>(children_[TARGET]);
1636    }
1637
1638    pUInt numArgs(void) const { return numChildren_-1; }
1639
1640    stmt::child_iterator child_begin() { return &children_[0]; }
1641    stmt::child_iterator child_end() { return &children_[0]+numChildren_; }
1642
1643    stmt::child_iterator args_begin() { return &children_[INDICES]; }
1644    stmt::child_iterator args_end() { return &children_[INDICES]+(numChildren_-INDICES); }
1645
1646    stmt::child_range args() { return stmt::child_range(args_begin(), args_end()); }
1647
1648    static bool classof(const functionInvoke* s) { return true; }
1649    static bool classof(const stmt* s) { return s->kind() == functionInvokeKind; }
1650
1651};
1652
1653// NOP statement such as ;;
1654class emptyStmt: public stmt {
1655
1656public:
1657        emptyStmt() : stmt(emptyStmtKind) {}
1658
1659
1660    stmt::child_iterator child_begin() { return child_iterator(); }
1661    stmt::child_iterator child_end() { return child_iterator(); }
1662
1663    static bool classof(const emptyStmt* s) { return true; }
1664    static bool classof(const stmt* s) { return s->kind() == emptyStmtKind; }
1665
1666};
1667
1668// NODE: unary operator
1669class unaryOp: public expr {
1670
1671public:
1672    enum opKind { NEGATIVE, POSITIVE, LOGICALNOT };
1673
1674private:
1675    expr* rVal_;
1676    opKind opKind_;
1677
1678public:
1679
1680    unaryOp(expr* rVal, opKind k): expr(unaryOpKind), rVal_(rVal), opKind_(k) {
1681        if (opKind_ == NEGATIVE) {
1682            // if our expression is a simple literal int, flag its sign
1683            if (literalInt* i = dyn_cast<literalInt>(rVal))
1684                i->setNegative(true);
1685        }
1686    }
1687
1688    expr* rVal(void) { return rVal_; }
1689
1690    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1691    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1692
1693    opKind opKind(void) const { return opKind_; }
1694
1695    static bool classof(const unaryOp* s) { return true; }
1696    static bool classof(const stmt* s) { return s->kind() == unaryOpKind; }
1697
1698};
1699
1700// NODE: pre operator
1701class preOp: public expr {
1702
1703public:
1704    enum opKind { INC, DEC };
1705
1706private:
1707    expr* rVal_;
1708    opKind opKind_;
1709
1710public:
1711
1712    preOp(expr* rVal, opKind k): expr(preOpKind), rVal_(rVal), opKind_(k)
1713    {
1714    }
1715
1716    expr* rVal(void) { return rVal_; }
1717
1718    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1719    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1720
1721    opKind opKind(void) const { return opKind_; }
1722
1723    static bool classof(const preOp* s) { return true; }
1724    static bool classof(const stmt* s) { return s->kind() == preOpKind; }
1725
1726};
1727
1728// NODE: post operator
1729class postOp: public expr {
1730
1731public:
1732    enum opKind { INC, DEC };
1733
1734private:
1735    expr* rVal_;
1736    opKind opKind_;
1737
1738public:
1739
1740    postOp(expr* rVal, opKind k): expr(postOpKind), rVal_(rVal), opKind_(k)
1741    {
1742    }
1743
1744    expr* rVal(void) { return rVal_; }
1745
1746    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&rVal_); }
1747    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&rVal_+1); }
1748
1749    opKind opKind(void) const { return opKind_; }
1750
1751    static bool classof(const postOp* s) { return true; }
1752    static bool classof(const stmt* s) { return s->kind() == postOpKind; }
1753
1754};
1755
1756
1757// NODE: binary operator
1758class binaryOp: public expr {
1759
1760public:
1761    enum opKind { CONCAT,
1762                  BOOLEAN_AND,
1763                  BOOLEAN_OR,
1764                  BOOLEAN_XOR,
1765                  DIV,
1766                  MOD,
1767                  MULT,
1768                  ADD,
1769                  SUB,
1770                  GREATER_THAN,
1771                  LESS_THAN,
1772                  GREATER_OR_EQUAL,
1773                  LESS_OR_EQUAL,
1774                  EQUAL,
1775                  NOT_EQUAL,
1776                  IDENTICAL,
1777                  NOT_IDENTICAL,
1778                  BIT_OR,
1779                  BIT_AND,
1780                  BIT_XOR,
1781                  INSTANCEOF,
1782                  SHIFT_LEFT,
1783                  SHIFT_RIGHT
1784              };
1785
1786private:
1787    enum { LVAL, RVAL, END_EXPR };
1788    stmt* children_[END_EXPR];
1789    opKind opKind_;
1790
1791public:
1792
1793    binaryOp(expr* lVal, expr* rVal, opKind k): expr(binaryOpKind), children_(), opKind_(k)
1794    {
1795        children_[LVAL] = static_cast<stmt*>(lVal);
1796        children_[RVAL] = static_cast<stmt*>(rVal);
1797    }
1798
1799    expr* lVal(void) { return static_cast<expr*>(children_[LVAL]); }
1800    expr* rVal(void) { return static_cast<expr*>(children_[RVAL]); }
1801
1802    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1803    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1804
1805    static bool classof(const binaryOp* s) { return true; }
1806    static bool classof(const stmt* s) { return s->kind() == binaryOpKind; }
1807
1808    opKind opKind(void) const { return opKind_; }
1809
1810};
1811
1812// ternary shorthand for ifs ?:
1813class conditionalExpr: public expr {
1814
1815private:
1816    enum { COND, TRUEEXPR, FALSEEXPR, END_EXPR };
1817    stmt* children_[END_EXPR];
1818
1819public:
1820
1821    conditionalExpr(expr* condition, expr* trueexpr, expr* falseexpr): expr(conditionalExprKind), children_()
1822    {
1823        children_[COND] = static_cast<stmt*>(condition);
1824        children_[TRUEEXPR] = static_cast<stmt*>(trueexpr);
1825        children_[FALSEEXPR] = static_cast<stmt*>(falseexpr);
1826    }
1827
1828    expr* condition(void) const{ return static_cast<expr*>(children_[COND]); }
1829    expr* trueExpr(void) const{ return static_cast<expr*>(children_[TRUEEXPR]); }
1830    expr* falseExpr(void) const{ return static_cast<expr*>(children_[FALSEEXPR]); }
1831
1832    stmt::child_iterator child_begin() { return (stmt**)&children_[0]; }
1833    stmt::child_iterator child_end() { return (stmt**)&children_[0]+END_EXPR; }
1834
1835    static bool classof(const conditionalExpr* s) { return true; }
1836    static bool classof(const stmt* s) { return s->kind() == conditionalExprKind; }
1837
1838};
1839
1840// This class is needed for some transforms. It represents a block of statements of which the last one needs to be an
1841// expression. This class is used when lowering some expressions into some statements, which still have to evaluate to
1842// _something_. This can even be used to evaluate to a variable (which is then the last instruction in the statementList).
1843// !!!This class is not intended for use by the parser!!!
1844class exprReduce: public expr {
1845private:
1846    block* statements_;
1847public:
1848
1849    exprReduce(pParseContext& C, statementList* ptStatements): expr(exprReduceKind), statements_(NULL)
1850    {
1851        assert(!ptStatements->empty());
1852        assert(isa<expr>(ptStatements->back()) && "The last statement of a list of statements for an evalExpr needs to be an expression!");
1853        statements_ = new (C) block(C, ptStatements);
1854    }
1855    exprReduce(pParseContext& C, const expressionList* ptExpressions): expr(exprReduceKind), statements_(NULL)
1856    {
1857        assert(!ptExpressions->empty());
1858        statements_ = new (C) block(C, ptExpressions);
1859    }
1860    block* statements(void) const { return statements_; }
1861
1862    stmt::child_iterator child_begin() { return reinterpret_cast<stmt**>(&statements_); }
1863    stmt::child_iterator child_end() { return reinterpret_cast<stmt**>(&statements_+1); }
1864
1865    static bool classof(const exprReduce* s) { return true; }
1866    static bool classof(const stmt* s) { return s->kind() == exprReduceKind; }
1867
1868};
1869
1870} } // namespace
1871
1872#endif /* RPHP_PAST_H_ */
Note: See TracBrowser for help on using the browser.