webengine/osswebengine/JavaScriptCore/kjs/nodes.h
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/JavaScriptCore/kjs/nodes.h	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1166 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef NODES_H_
+#define NODES_H_
+
+#include "Parser.h"
+#include "internal.h"
+#include <wtf/ListRefPtr.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(X86) && COMPILER(GCC)
+#define KJS_FAST_CALL __attribute__((regparm(3)))
+#else
+#define KJS_FAST_CALL
+#endif
+
+#if COMPILER(GCC)
+#define KJS_NO_INLINE __attribute__((noinline))
+#else
+#define KJS_NO_INLINE
+#endif
+
+namespace KJS {
+
+  class ProgramNode;
+  class PropertyNameNode;
+  class PropertyListNode;
+  class RegExp;
+  class SourceElementsNode;
+  class SourceStream;
+
+  enum Operator { OpEqual,
+                  OpEqEq,
+                  OpNotEq,
+                  OpStrEq,
+                  OpStrNEq,
+                  OpPlusEq,
+                  OpMinusEq,
+                  OpMultEq,
+                  OpDivEq,
+                  OpPlusPlus,
+                  OpMinusMinus,
+                  OpLess,
+                  OpLessEq,
+                  OpGreater,
+                  OpGreaterEq,
+                  OpAndEq,
+                  OpXOrEq,
+                  OpOrEq,
+                  OpModEq,
+                  OpAnd,
+                  OpOr,
+                  OpBitAnd,
+                  OpBitXOr,
+                  OpBitOr,
+                  OpLShift,
+                  OpRShift,
+                  OpURShift,
+                  OpIn,
+                  OpInstanceOf
+  };
+
+  class Node {
+  public:
+    Node() KJS_FAST_CALL;
+    virtual ~Node();
+
+    virtual JSValue *evaluate(ExecState *exec) KJS_FAST_CALL = 0;
+    UString toString() const KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL = 0;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL {}
+    int lineNo() const KJS_FAST_CALL { return m_line; }
+
+    void ref() KJS_FAST_CALL;
+    void deref() KJS_FAST_CALL;
+    unsigned refcount() KJS_FAST_CALL;
+    static void clearNewNodes() KJS_FAST_CALL;
+
+    virtual Node *nodeInsideAllParens() KJS_FAST_CALL;
+
+    virtual bool isLocation() const KJS_FAST_CALL { return false; }
+    virtual bool isResolveNode() const KJS_FAST_CALL { return false; }
+    virtual bool isBracketAccessorNode() const KJS_FAST_CALL { return false; }
+    virtual bool isDotAccessorNode() const KJS_FAST_CALL { return false; }
+    virtual bool isGroupNode() const KJS_FAST_CALL { return false; }
+
+    virtual void breakCycle() KJS_FAST_CALL { }
+
+  protected:
+    Completion createErrorCompletion(ExecState *, ErrorType, const char *msg) KJS_FAST_CALL;
+    Completion createErrorCompletion(ExecState *, ErrorType, const char *msg, const Identifier &) KJS_FAST_CALL;
+
+    JSValue *throwError(ExecState *, ErrorType, const char *msg) KJS_FAST_CALL;
+    JSValue* throwError(ExecState *, ErrorType, const char* msg, const char*) KJS_FAST_CALL;
+    JSValue *throwError(ExecState *, ErrorType, const char *msg, JSValue *, Node *) KJS_FAST_CALL;
+    JSValue *throwError(ExecState *, ErrorType, const char *msg, const Identifier &) KJS_FAST_CALL;
+    JSValue *throwError(ExecState *, ErrorType, const char *msg, JSValue *, const Identifier &) KJS_FAST_CALL;
+    JSValue *throwError(ExecState *, ErrorType, const char *msg, JSValue *, Node *, Node *) KJS_FAST_CALL;
+    JSValue *throwError(ExecState *, ErrorType, const char *msg, JSValue *, Node *, const Identifier &) KJS_FAST_CALL;
+
+    JSValue *throwUndefinedVariableError(ExecState *, const Identifier &) KJS_FAST_CALL;
+
+    void handleException(ExecState*) KJS_FAST_CALL;
+    void handleException(ExecState*, JSValue*) KJS_FAST_CALL;
+
+    int m_line;
+  private:
+    // disallow assignment
+    Node& operator=(const Node&) KJS_FAST_CALL;
+    Node(const Node &other) KJS_FAST_CALL;
+  };
+
+  class StatementNode : public Node {
+  public:
+    StatementNode() KJS_FAST_CALL;
+    void setLoc(int line0, int line1) KJS_FAST_CALL;
+    int firstLine() const KJS_FAST_CALL { return lineNo(); }
+    int lastLine() const KJS_FAST_CALL { return m_lastLine; }
+    bool hitStatement(ExecState*) KJS_FAST_CALL;
+    virtual Completion execute(ExecState *exec) KJS_FAST_CALL = 0;
+    void pushLabel(const Identifier &id) KJS_FAST_CALL { ls.push(id); }
+    virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
+  protected:
+    LabelStack ls;
+  private:
+    JSValue *evaluate(ExecState*) KJS_FAST_CALL { return jsUndefined(); }
+    int m_lastLine;
+  };
+
+  class NullNode : public Node {
+  public:
+    NullNode() KJS_FAST_CALL {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  };
+
+  class BooleanNode : public Node {
+  public:
+    BooleanNode(bool v) KJS_FAST_CALL : value(v) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    bool value;
+  };
+
+  class NumberNode : public Node {
+  public:
+    NumberNode(double v) KJS_FAST_CALL : value(v) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    double value;
+  };
+
+  class StringNode : public Node {
+  public:
+    StringNode(const UString *v) KJS_FAST_CALL { value = *v; }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    UString value;
+  };
+
+  class RegExpNode : public Node {
+  public:
+    RegExpNode(const UString &p, const UString &f) KJS_FAST_CALL 
+      : pattern(p), flags(f) { }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    UString pattern, flags;
+  };
+
+  class ThisNode : public Node {
+  public:
+    ThisNode() KJS_FAST_CALL {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  };
+
+  class ResolveNode : public Node {
+  public:
+    ResolveNode(const Identifier &s) KJS_FAST_CALL : ident(s) { }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+
+    virtual bool isLocation() const KJS_FAST_CALL { return true; }
+    virtual bool isResolveNode() const KJS_FAST_CALL { return true; }
+    const Identifier& identifier() const KJS_FAST_CALL { return ident; }
+
+  private:
+    Identifier ident;
+  };
+
+  class GroupNode : public Node {
+  public:
+    GroupNode(Node *g) KJS_FAST_CALL : group(g) { }
+    virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual Node *nodeInsideAllParens() KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    virtual bool isGroupNode() const KJS_FAST_CALL { return true; }
+  private:
+    RefPtr<Node> group;
+  };
+
+  class ElementNode : public Node {
+  public:
+    // list pointer is tail of a circular list, cracked in the ArrayNode ctor
+    ElementNode(int e, Node *n) KJS_FAST_CALL : next(this), elision(e), node(n) { Parser::noteNodeCycle(this); }
+    ElementNode(ElementNode *l, int e, Node *n) KJS_FAST_CALL
+      : next(l->next), elision(e), node(n) { l->next = this; }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    PassRefPtr<ElementNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+    virtual void breakCycle() KJS_FAST_CALL;
+  private:
+    friend class ArrayNode;
+    ListRefPtr<ElementNode> next;
+    int elision;
+    RefPtr<Node> node;
+  };
+
+  class ArrayNode : public Node {
+  public:
+    ArrayNode(int e) KJS_FAST_CALL : elision(e), opt(true) { }
+    ArrayNode(ElementNode *ele) KJS_FAST_CALL
+      : element(ele->next.release()), elision(0), opt(false) { Parser::removeNodeCycle(element.get()); }
+    ArrayNode(int eli, ElementNode *ele) KJS_FAST_CALL
+      : element(ele->next.release()), elision(eli), opt(true) { Parser::removeNodeCycle(element.get()); }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<ElementNode> element;
+    int elision;
+    bool opt;
+  };
+
+  class PropertyNameNode : public Node {
+  public:
+    PropertyNameNode(double d) KJS_FAST_CALL : numeric(d) { }
+    PropertyNameNode(const Identifier &s) KJS_FAST_CALL : str(s) { }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    double numeric;
+    Identifier str;
+  };
+  
+  class PropertyNode : public Node {
+  public:
+    enum Type { Constant, Getter, Setter };
+    PropertyNode(PropertyNameNode *n, Node *a, Type t) KJS_FAST_CALL
+      : name(n), assign(a), type(t) { }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    friend class PropertyListNode;
+  private:
+    RefPtr<PropertyNameNode> name;
+    RefPtr<Node> assign;
+    Type type;
+  };
+  
+  class PropertyListNode : public Node {
+  public:
+    // list pointer is tail of a circular list, cracked in the ObjectLiteralNode ctor
+    PropertyListNode(PropertyNode *n) KJS_FAST_CALL
+      : node(n), next(this) { Parser::noteNodeCycle(this); }
+    PropertyListNode(PropertyNode *n, PropertyListNode *l) KJS_FAST_CALL
+      : node(n), next(l->next) { l->next = this; }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    PassRefPtr<PropertyListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+    virtual void breakCycle() KJS_FAST_CALL;
+  private:
+    friend class ObjectLiteralNode;
+    RefPtr<PropertyNode> node;
+    ListRefPtr<PropertyListNode> next;
+  };
+
+  class ObjectLiteralNode : public Node {
+  public:
+    ObjectLiteralNode() KJS_FAST_CALL { }
+    ObjectLiteralNode(PropertyListNode *l) KJS_FAST_CALL : list(l->next.release()) { Parser::removeNodeCycle(list.get()); }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<PropertyListNode> list;
+  };
+
+  class BracketAccessorNode : public Node {
+  public:
+    BracketAccessorNode(Node *e1, Node *e2) KJS_FAST_CALL : expr1(e1), expr2(e2) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+
+    virtual bool isLocation() const KJS_FAST_CALL { return true; }
+    virtual bool isBracketAccessorNode() const KJS_FAST_CALL { return true; }
+    Node *base() KJS_FAST_CALL { return expr1.get(); }
+    Node *subscript() KJS_FAST_CALL { return expr2.get(); }
+
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+  };
+
+  class DotAccessorNode : public Node {
+  public:
+    DotAccessorNode(Node *e, const Identifier &s) KJS_FAST_CALL : expr(e), ident(s) { }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+
+    virtual bool isLocation() const KJS_FAST_CALL { return true; }
+    virtual bool isDotAccessorNode() const KJS_FAST_CALL { return true; }
+    Node *base() const KJS_FAST_CALL { return expr.get(); }
+    const Identifier& identifier() const KJS_FAST_CALL { return ident; }
+
+  private:
+    RefPtr<Node> expr;
+    Identifier ident;
+  };
+
+  class ArgumentListNode : public Node {
+  public:
+    // list pointer is tail of a circular list, cracked in the ArgumentsNode ctor
+    ArgumentListNode(Node *e) KJS_FAST_CALL : next(this), expr(e) { Parser::noteNodeCycle(this); }
+    ArgumentListNode(ArgumentListNode *l, Node *e) KJS_FAST_CALL 
+      : next(l->next), expr(e) { l->next = this; }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    List evaluateList(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    PassRefPtr<ArgumentListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+    virtual void breakCycle() KJS_FAST_CALL;
+  private:
+    friend class ArgumentsNode;
+    ListRefPtr<ArgumentListNode> next;
+    RefPtr<Node> expr;
+  };
+
+  class ArgumentsNode : public Node {
+  public:
+    ArgumentsNode() KJS_FAST_CALL { }
+    ArgumentsNode(ArgumentListNode *l) KJS_FAST_CALL
+      : list(l->next.release()) { Parser::removeNodeCycle(list.get()); }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    List evaluateList(ExecState *exec) KJS_FAST_CALL { return list ? list->evaluateList(exec) : List(); }
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<ArgumentListNode> list;
+  };
+
+  class NewExprNode : public Node {
+  public:
+    NewExprNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    NewExprNode(Node *e, ArgumentsNode *a) KJS_FAST_CALL : expr(e), args(a) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+    RefPtr<ArgumentsNode> args;
+  };
+
+  class FunctionCallValueNode : public Node {
+  public:
+    FunctionCallValueNode(Node *e, ArgumentsNode *a) KJS_FAST_CALL : expr(e), args(a) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+    RefPtr<ArgumentsNode> args;
+  };
+
+  class FunctionCallResolveNode : public Node {
+  public:
+    FunctionCallResolveNode(const Identifier& i, ArgumentsNode *a) KJS_FAST_CALL : ident(i), args(a) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier ident;
+    RefPtr<ArgumentsNode> args;
+  };
+
+  class FunctionCallBracketNode : public Node {
+  public:
+    FunctionCallBracketNode(Node *b, Node *s, ArgumentsNode *a) KJS_FAST_CALL : base(b), subscript(s), args(a) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    RefPtr<Node> base;
+    RefPtr<Node> subscript;
+    RefPtr<ArgumentsNode> args;
+  };
+
+  class FunctionCallParenBracketNode : public FunctionCallBracketNode {
+  public:
+    FunctionCallParenBracketNode(Node *b, Node *s, ArgumentsNode *a) KJS_FAST_CALL : FunctionCallBracketNode(b, s, a) {}
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  };
+
+  class FunctionCallDotNode : public Node {
+  public:
+    FunctionCallDotNode(Node *b, const Identifier &i, ArgumentsNode *a) KJS_FAST_CALL : base(b), ident(i), args(a) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    RefPtr<Node> base;
+    Identifier ident;
+    RefPtr<ArgumentsNode> args;
+  };
+
+  class FunctionCallParenDotNode : public FunctionCallDotNode {
+  public:
+    FunctionCallParenDotNode(Node *b, const Identifier &i, ArgumentsNode *a) KJS_FAST_CALL : FunctionCallDotNode(b, i, a) {}
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  };
+
+  class PostfixResolveNode : public Node {
+  public:
+    PostfixResolveNode(const Identifier& i, Operator o) KJS_FAST_CALL : m_ident(i), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier m_ident;
+    Operator m_oper;
+  };
+
+  class PostfixBracketNode : public Node {
+  public:
+    PostfixBracketNode(Node *b, Node *s, Operator o) KJS_FAST_CALL : m_base(b), m_subscript(s), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_base;
+    RefPtr<Node> m_subscript;
+    Operator m_oper;
+  };
+
+  class PostfixDotNode : public Node {
+  public:
+    PostfixDotNode(Node *b, const Identifier& i, Operator o) KJS_FAST_CALL : m_base(b), m_ident(i), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_base;
+    Identifier m_ident;
+    Operator m_oper;
+  };
+
+  class PostfixErrorNode : public Node {
+  public:
+    PostfixErrorNode(Node* e, Operator o) KJS_FAST_CALL : m_expr(e), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_expr;
+    Operator m_oper;
+  };
+
+  class DeleteResolveNode : public Node {
+  public:
+    DeleteResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier m_ident;
+  };
+
+  class DeleteBracketNode : public Node {
+  public:
+    DeleteBracketNode(Node *base, Node *subscript) KJS_FAST_CALL : m_base(base), m_subscript(subscript) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_base;
+    RefPtr<Node> m_subscript;
+  };
+
+  class DeleteDotNode : public Node {
+  public:
+    DeleteDotNode(Node *base, const Identifier& i) KJS_FAST_CALL : m_base(base), m_ident(i) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_base;
+    Identifier m_ident;
+  };
+
+  class DeleteValueNode : public Node {
+  public:
+    DeleteValueNode(Node *e) KJS_FAST_CALL : m_expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_expr;
+  };
+
+  class VoidNode : public Node {
+  public:
+    VoidNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class TypeOfResolveNode : public Node {
+  public:
+    TypeOfResolveNode(const Identifier& i) KJS_FAST_CALL : m_ident(i) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier m_ident;
+  };
+
+  class TypeOfValueNode : public Node {
+  public:
+    TypeOfValueNode(Node *e) KJS_FAST_CALL : m_expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_expr;
+  };
+
+  class PrefixResolveNode : public Node {
+  public:
+    PrefixResolveNode(const Identifier& i, Operator o) KJS_FAST_CALL : m_ident(i), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier m_ident;
+    Operator m_oper;
+  };
+
+  class PrefixBracketNode : public Node {
+  public:
+    PrefixBracketNode(Node *b, Node *s, Operator o) KJS_FAST_CALL : m_base(b), m_subscript(s), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_base;
+    RefPtr<Node> m_subscript;
+    Operator m_oper;
+  };
+
+  class PrefixDotNode : public Node {
+  public:
+    PrefixDotNode(Node *b, const Identifier& i, Operator o) KJS_FAST_CALL : m_base(b), m_ident(i), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_base;
+    Identifier m_ident;
+    Operator m_oper;
+  };
+
+  class PrefixErrorNode : public Node {
+  public:
+    PrefixErrorNode(Node* e, Operator o) KJS_FAST_CALL : m_expr(e), m_oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> m_expr;
+    Operator m_oper;
+  };
+
+  class UnaryPlusNode : public Node {
+  public:
+    UnaryPlusNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class NegateNode : public Node {
+  public:
+    NegateNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class BitwiseNotNode : public Node {
+  public:
+    BitwiseNotNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class LogicalNotNode : public Node {
+  public:
+    LogicalNotNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class MultNode : public Node {
+  public:
+    MultNode(Node *t1, Node *t2, char op) KJS_FAST_CALL : term1(t1), term2(t2), oper(op) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> term1;
+    RefPtr<Node> term2;
+    char oper;
+  };
+
+  class AddNode : public Node {
+  public:
+    AddNode(Node *t1, Node *t2, char op) KJS_FAST_CALL : term1(t1), term2(t2), oper(op) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> term1;
+    RefPtr<Node> term2;
+    char oper;
+  };
+
+  class ShiftNode : public Node {
+  public:
+    ShiftNode(Node *t1, Operator o, Node *t2) KJS_FAST_CALL
+      : term1(t1), term2(t2), oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> term1;
+    RefPtr<Node> term2;
+    Operator oper;
+  };
+
+  class RelationalNode : public Node {
+  public:
+    RelationalNode(Node *e1, Operator o, Node *e2) KJS_FAST_CALL :
+      expr1(e1), expr2(e2), oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+    Operator oper;
+  };
+
+  class EqualNode : public Node {
+  public:
+    EqualNode(Node *e1, Operator o, Node *e2) KJS_FAST_CALL
+      : expr1(e1), expr2(e2), oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+    Operator oper;
+  };
+
+  class BitOperNode : public Node {
+  public:
+    BitOperNode(Node *e1, Operator o, Node *e2) KJS_FAST_CALL :
+      expr1(e1), expr2(e2), oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+    Operator oper;
+  };
+
+  /**
+   * expr1 && expr2, expr1 || expr2
+   */
+  class BinaryLogicalNode : public Node {
+  public:
+    BinaryLogicalNode(Node *e1, Operator o, Node *e2) KJS_FAST_CALL :
+      expr1(e1), expr2(e2), oper(o) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+    Operator oper;
+  };
+
+  /**
+   * The ternary operator, "logical ? expr1 : expr2"
+   */
+  class ConditionalNode : public Node {
+  public:
+    ConditionalNode(Node *l, Node *e1, Node *e2) KJS_FAST_CALL :
+      logical(l), expr1(e1), expr2(e2) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> logical;
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+  };
+
+  class AssignResolveNode : public Node {
+  public:
+    AssignResolveNode(const Identifier &ident, Operator oper, Node *right) KJS_FAST_CALL
+      : m_ident(ident), m_oper(oper), m_right(right) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    Identifier m_ident;
+    Operator m_oper;
+    RefPtr<Node> m_right;
+  };
+
+  class AssignBracketNode : public Node {
+  public:
+    AssignBracketNode(Node *base, Node *subscript, Operator oper, Node *right) KJS_FAST_CALL
+      : m_base(base), m_subscript(subscript), m_oper(oper), m_right(right) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    RefPtr<Node> m_base;
+    RefPtr<Node> m_subscript;
+    Operator m_oper;
+    RefPtr<Node> m_right;
+  };
+
+  class AssignDotNode : public Node {
+  public:
+    AssignDotNode(Node *base, const Identifier& ident, Operator oper, Node *right) KJS_FAST_CALL
+      : m_base(base), m_ident(ident), m_oper(oper), m_right(right) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    RefPtr<Node> m_base;
+    Identifier m_ident;
+    Operator m_oper;
+    RefPtr<Node> m_right;
+  };
+
+  class AssignErrorNode : public Node {
+  public:
+    AssignErrorNode(Node* left, Operator oper, Node* right) KJS_FAST_CALL
+      : m_left(left), m_oper(oper), m_right(right) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    RefPtr<Node> m_left;
+    Operator m_oper;
+    RefPtr<Node> m_right;
+  };
+
+  class CommaNode : public Node {
+  public:
+    CommaNode(Node *e1, Node *e2) KJS_FAST_CALL : expr1(e1), expr2(e2) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+  };
+
+  class AssignExprNode : public Node {
+  public:
+    AssignExprNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class VarDeclNode: public Node {
+  public:
+    enum Type { Variable, Constant };
+    VarDeclNode(const Identifier &id, AssignExprNode *in, Type t) KJS_FAST_CALL;
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    JSValue* handleSlowCase(ExecState*, const ScopeChain&, JSValue*) KJS_FAST_CALL KJS_NO_INLINE;
+    Type varType;
+    Identifier ident;
+    RefPtr<AssignExprNode> init;
+  };
+
+  class VarDeclListNode : public Node {
+  public:
+    // list pointer is tail of a circular list, cracked in the ForNode/VarStatementNode ctor
+    VarDeclListNode(VarDeclNode *v) KJS_FAST_CALL : next(this), var(v) { Parser::noteNodeCycle(this); }
+    VarDeclListNode(VarDeclListNode *l, VarDeclNode *v) KJS_FAST_CALL
+      : next(l->next), var(v) { l->next = this; }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    PassRefPtr<VarDeclListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+    virtual void breakCycle() KJS_FAST_CALL;
+  private:
+    friend class ForNode;
+    friend class VarStatementNode;
+    ListRefPtr<VarDeclListNode> next;
+    RefPtr<VarDeclNode> var;
+  };
+
+  class VarStatementNode : public StatementNode {
+  public:
+    VarStatementNode(VarDeclListNode *l) KJS_FAST_CALL : next(l->next.release()) { Parser::removeNodeCycle(next.get()); }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<VarDeclListNode> next;
+  };
+
+  class BlockNode : public StatementNode {
+  public:
+    BlockNode(SourceElementsNode *s) KJS_FAST_CALL;
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  protected:
+    RefPtr<SourceElementsNode> source;
+  };
+
+  class EmptyStatementNode : public StatementNode {
+  public:
+    EmptyStatementNode() KJS_FAST_CALL { } // debug
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  };
+
+  class ExprStatementNode : public StatementNode {
+  public:
+    ExprStatementNode(Node *e) KJS_FAST_CALL : expr(e) { }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class IfNode : public StatementNode {
+  public:
+    IfNode(Node *e, StatementNode *s1, StatementNode *s2) KJS_FAST_CALL
+      : expr(e), statement1(s1), statement2(s2) {}
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+    RefPtr<StatementNode> statement1;
+    RefPtr<StatementNode> statement2;
+  };
+
+  class DoWhileNode : public StatementNode {
+  public:
+    DoWhileNode(StatementNode *s, Node *e) KJS_FAST_CALL : statement(s), expr(e) {}
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<StatementNode> statement;
+    RefPtr<Node> expr;
+  };
+
+  class WhileNode : public StatementNode {
+  public:
+    WhileNode(Node *e, StatementNode *s) KJS_FAST_CALL : expr(e), statement(s) {}
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+    RefPtr<StatementNode> statement;
+  };
+
+  class ForNode : public StatementNode {
+  public:
+    ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) KJS_FAST_CALL :
+      expr1(e1), expr2(e2), expr3(e3), statement(s) {}
+    ForNode(VarDeclListNode *e1, Node *e2, Node *e3, StatementNode *s) KJS_FAST_CALL :
+      expr1(e1->next.release()), expr2(e2), expr3(e3), statement(s) { Parser::removeNodeCycle(expr1.get()); }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr1;
+    RefPtr<Node> expr2;
+    RefPtr<Node> expr3;
+    RefPtr<StatementNode> statement;
+  };
+
+  class ForInNode : public StatementNode {
+  public:
+    ForInNode(Node *l, Node *e, StatementNode *s) KJS_FAST_CALL;
+    ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s) KJS_FAST_CALL;
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier ident;
+    RefPtr<AssignExprNode> init;
+    RefPtr<Node> lexpr;
+    RefPtr<Node> expr;
+    RefPtr<VarDeclNode> varDecl;
+    RefPtr<StatementNode> statement;
+  };
+
+  class ContinueNode : public StatementNode {
+  public:
+    ContinueNode() KJS_FAST_CALL { }
+    ContinueNode(const Identifier &i) KJS_FAST_CALL : ident(i) { }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier ident;
+  };
+
+  class BreakNode : public StatementNode {
+  public:
+    BreakNode() KJS_FAST_CALL { }
+    BreakNode(const Identifier &i) KJS_FAST_CALL : ident(i) { }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier ident;
+  };
+
+  class ReturnNode : public StatementNode {
+  public:
+    ReturnNode(Node *v) KJS_FAST_CALL : value(v) {}
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> value;
+  };
+
+  class WithNode : public StatementNode {
+  public:
+    WithNode(Node *e, StatementNode *s) KJS_FAST_CALL : expr(e), statement(s) {}
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+    RefPtr<StatementNode> statement;
+  };
+
+  class LabelNode : public StatementNode {
+  public:
+    LabelNode(const Identifier &l, StatementNode *s) KJS_FAST_CALL : label(l), statement(s) { }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    Identifier label;
+    RefPtr<StatementNode> statement;
+  };
+
+  class ThrowNode : public StatementNode {
+  public:
+    ThrowNode(Node *e) KJS_FAST_CALL : expr(e) {}
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<Node> expr;
+  };
+
+  class TryNode : public StatementNode {
+  public:
+    TryNode(StatementNode *b, const Identifier &e, StatementNode *c, StatementNode *f) KJS_FAST_CALL
+      : tryBlock(b), exceptionIdent(e), catchBlock(c), finallyBlock(f) { }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    RefPtr<StatementNode> tryBlock;
+    Identifier exceptionIdent;
+    RefPtr<StatementNode> catchBlock;
+    RefPtr<StatementNode> finallyBlock;
+  };
+
+  class ParameterNode : public Node {
+  public:
+    // list pointer is tail of a circular list, cracked in the FuncDeclNode/FuncExprNode ctor
+    ParameterNode(const Identifier &i) KJS_FAST_CALL : id(i), next(this) { Parser::noteNodeCycle(this); }
+    ParameterNode(ParameterNode *next, const Identifier &i) KJS_FAST_CALL
+      : id(i), next(next->next) { next->next = this; }
+    JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+    Identifier ident() KJS_FAST_CALL { return id; }
+    ParameterNode *nextParam() KJS_FAST_CALL { return next.get(); }
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    PassRefPtr<ParameterNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+    virtual void breakCycle() KJS_FAST_CALL;
+  private:
+    friend class FuncDeclNode;
+    friend class FuncExprNode;
+    Identifier id;
+    ListRefPtr<ParameterNode> next;
+  };
+
+  class Parameter {
+  public:
+    Parameter() KJS_FAST_CALL { }
+    Parameter(const Identifier& n) KJS_FAST_CALL : name(n) { }
+    Identifier name;
+  };
+
+  // inherited by ProgramNode
+  class FunctionBodyNode : public BlockNode {
+  public:
+    FunctionBodyNode(SourceElementsNode *) KJS_FAST_CALL;
+    virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
+    int sourceId() KJS_FAST_CALL { return m_sourceId; }
+    const UString& sourceURL() KJS_FAST_CALL { return m_sourceURL; }
+
+    void addParam(const Identifier& ident) KJS_FAST_CALL;
+    size_t numParams() const KJS_FAST_CALL { return m_parameters.size(); }
+    Identifier paramName(size_t pos) const KJS_FAST_CALL { return m_parameters[pos].name; }
+    UString paramString() const KJS_FAST_CALL;
+    Vector<Parameter>& parameters() KJS_FAST_CALL { return m_parameters; }
+  private:
+    UString m_sourceURL;
+    int m_sourceId;
+    Vector<Parameter> m_parameters;
+  };
+
+  class FuncExprNode : public Node {
+  public:
+    FuncExprNode(const Identifier &i, FunctionBodyNode *b, ParameterNode *p = 0) KJS_FAST_CALL 
+      : ident(i), param(p ? p->next.release() : 0), body(b) { if (p) { Parser::removeNodeCycle(param.get()); } addParams(); }
+    virtual JSValue *evaluate(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    void addParams() KJS_FAST_CALL;
+    // Used for streamTo
+    friend class PropertyNode;
+    Identifier ident;
+    RefPtr<ParameterNode> param;
+    RefPtr<FunctionBodyNode> body;
+  };
+
+  class FuncDeclNode : public StatementNode {
+  public:
+    FuncDeclNode(const Identifier &i, FunctionBodyNode *b) KJS_FAST_CALL
+      : ident(i), body(b) { addParams(); }
+    FuncDeclNode(const Identifier &i, ParameterNode *p, FunctionBodyNode *b) KJS_FAST_CALL
+      : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); addParams(); }
+    virtual Completion execute(ExecState*) KJS_FAST_CALL;
+    virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+    void addParams() KJS_FAST_CALL;
+    Identifier ident;
+    RefPtr<ParameterNode> param;
+    RefPtr<FunctionBodyNode> body;
+  };
+
+  // A linked list of source element nodes
+  class SourceElementsNode : public StatementNode {
+  public:
+    static int count;
+    // list pointer is tail of a circular list, cracked in the BlockNode (or subclass) ctor
+    SourceElementsNode(StatementNode*) KJS_FAST_CALL;
+    SourceElementsNode(SourceElementsNode *s1, StatementNode *s2) KJS_FAST_CALL;
+    
+    Completion execute(ExecState*) KJS_FAST_CALL;
+    void processFuncDecl(ExecState*) KJS_FAST_CALL;
+    virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+    virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+    PassRefPtr<SourceElementsNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+    virtual void breakCycle() KJS_FAST_CALL;
+  private:
+    friend class BlockNode;
+    friend class CaseClauseNode;
+    RefPtr<StatementNode> node;
+    ListRefPtr<SourceElementsNode> next;
+  };
+
+  class CaseClauseNode : public Node {
+  public:
+      CaseClauseNode(Node *e) KJS_FAST_CALL : expr(e) { }
+      CaseClauseNode(Node *e, SourceElementsNode *s) KJS_FAST_CALL
+      : expr(e), source(s->next.release()) { Parser::removeNodeCycle(source.get()); }
+      JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+      Completion evalStatements(ExecState*) KJS_FAST_CALL;
+      void processFuncDecl(ExecState*) KJS_FAST_CALL;
+      virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+      RefPtr<Node> expr;
+      RefPtr<SourceElementsNode> source;
+  };
+  
+  class ClauseListNode : public Node {
+  public:
+      // list pointer is tail of a circular list, cracked in the CaseBlockNode ctor
+      ClauseListNode(CaseClauseNode *c) KJS_FAST_CALL : clause(c), next(this) { Parser::noteNodeCycle(this); }
+      ClauseListNode(ClauseListNode *n, CaseClauseNode *c) KJS_FAST_CALL
+      : clause(c), next(n->next) { n->next = this; }
+      JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+      CaseClauseNode *getClause() const KJS_FAST_CALL { return clause.get(); }
+      ClauseListNode *getNext() const KJS_FAST_CALL { return next.get(); }
+      virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+      void processFuncDecl(ExecState*) KJS_FAST_CALL;
+      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+      PassRefPtr<ClauseListNode> releaseNext() KJS_FAST_CALL { return next.release(); }
+      virtual void breakCycle() KJS_FAST_CALL;
+  private:
+      friend class CaseBlockNode;
+      RefPtr<CaseClauseNode> clause;
+      ListRefPtr<ClauseListNode> next;
+  };
+  
+  class CaseBlockNode : public Node {
+  public:
+      CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2) KJS_FAST_CALL;
+      JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+      Completion evalBlock(ExecState *exec, JSValue *input) KJS_FAST_CALL;
+      virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+      void processFuncDecl(ExecState*) KJS_FAST_CALL;
+      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+      RefPtr<ClauseListNode> list1;
+      RefPtr<CaseClauseNode> def;
+      RefPtr<ClauseListNode> list2;
+  };
+  
+  class SwitchNode : public StatementNode {
+  public:
+      SwitchNode(Node *e, CaseBlockNode *b) KJS_FAST_CALL : expr(e), block(b) { }
+      virtual Completion execute(ExecState*) KJS_FAST_CALL;
+      virtual void processVarDecls(ExecState*) KJS_FAST_CALL;
+      virtual void processFuncDecl(ExecState*) KJS_FAST_CALL;
+      virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+  private:
+      RefPtr<Node> expr;
+      RefPtr<CaseBlockNode> block;
+  };
+  
+  class ProgramNode : public FunctionBodyNode {
+  public:
+    ProgramNode(SourceElementsNode *s) KJS_FAST_CALL;
+  };
+
+} // namespace
+
+#endif