diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/JavaScriptCore/kjs/nodes.h --- /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 +#include + +#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 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class ArrayNode; + ListRefPtr next; + int elision; + RefPtr 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 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 name; + RefPtr 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class ObjectLiteralNode; + RefPtr node; + ListRefPtr 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 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 expr1; + RefPtr 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 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class ArgumentsNode; + ListRefPtr next; + RefPtr 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 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 expr; + RefPtr 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 expr; + RefPtr 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 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 base; + RefPtr subscript; + RefPtr 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 base; + Identifier ident; + RefPtr 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 m_base; + RefPtr 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 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 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 m_base; + RefPtr 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 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 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 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 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 m_base; + RefPtr 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 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 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 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 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 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 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 term1; + RefPtr 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 term1; + RefPtr 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 term1; + RefPtr 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 expr1; + RefPtr 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 expr1; + RefPtr 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 expr1; + RefPtr 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 expr1; + RefPtr 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 logical; + RefPtr expr1; + RefPtr 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 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 m_base; + RefPtr m_subscript; + Operator m_oper; + RefPtr 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 m_base; + Identifier m_ident; + Operator m_oper; + RefPtr 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 m_left; + Operator m_oper; + RefPtr 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 expr1; + RefPtr 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 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 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class ForNode; + friend class VarStatementNode; + ListRefPtr next; + RefPtr 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 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 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 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 expr; + RefPtr statement1; + RefPtr 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 statement; + RefPtr 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 expr; + RefPtr 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 expr1; + RefPtr expr2; + RefPtr expr3; + RefPtr 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 init; + RefPtr lexpr; + RefPtr expr; + RefPtr varDecl; + RefPtr 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 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 expr; + RefPtr 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 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 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 tryBlock; + Identifier exceptionIdent; + RefPtr catchBlock; + RefPtr 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class FuncDeclNode; + friend class FuncExprNode; + Identifier id; + ListRefPtr 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& parameters() KJS_FAST_CALL { return m_parameters; } + private: + UString m_sourceURL; + int m_sourceId; + Vector 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 param; + RefPtr 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 param; + RefPtr 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class BlockNode; + friend class CaseClauseNode; + RefPtr node; + ListRefPtr 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 expr; + RefPtr 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 releaseNext() KJS_FAST_CALL { return next.release(); } + virtual void breakCycle() KJS_FAST_CALL; + private: + friend class CaseBlockNode; + RefPtr clause; + ListRefPtr 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 list1; + RefPtr def; + RefPtr 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 expr; + RefPtr block; + }; + + class ProgramNode : public FunctionBodyNode { + public: + ProgramNode(SourceElementsNode *s) KJS_FAST_CALL; + }; + +} // namespace + +#endif