diff options
Diffstat (limited to 'Source/JavaScriptCore/parser/Nodes.h')
-rw-r--r-- | Source/JavaScriptCore/parser/Nodes.h | 1617 |
1 files changed, 1617 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h new file mode 100644 index 0000000..b8e9cdf --- /dev/null +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -0,0 +1,1617 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * Copyright (C) 2007 Maks Orlovich + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 "Error.h" +#include "JITCode.h" +#include "Opcode.h" +#include "ParserArena.h" +#include "ResultType.h" +#include "SourceCode.h" +#include "SymbolTable.h" +#include <wtf/MathExtras.h> + +namespace JSC { + + class ArgumentListNode; + class BytecodeGenerator; + class FunctionBodyNode; + class Label; + class PropertyListNode; + class ReadModifyResolveNode; + class RegisterID; + class ScopeChainNode; + class ScopeNode; + + typedef unsigned CodeFeatures; + + const CodeFeatures NoFeatures = 0; + const CodeFeatures EvalFeature = 1 << 0; + const CodeFeatures ClosureFeature = 1 << 1; + const CodeFeatures AssignFeature = 1 << 2; + const CodeFeatures ArgumentsFeature = 1 << 3; + const CodeFeatures WithFeature = 1 << 4; + const CodeFeatures CatchFeature = 1 << 5; + const CodeFeatures ThisFeature = 1 << 6; + const CodeFeatures StrictModeFeature = 1 << 7; + const CodeFeatures ShadowsArgumentsFeature = 1 << 8; + + + const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; + + enum Operator { + OpEqual, + OpPlusEq, + OpMinusEq, + OpMultEq, + OpDivEq, + OpPlusPlus, + OpMinusMinus, + OpAndEq, + OpXOrEq, + OpOrEq, + OpModEq, + OpLShift, + OpRShift, + OpURShift + }; + + enum LogicalOperator { + OpLogicalAnd, + OpLogicalOr + }; + + typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet; + + namespace DeclarationStacks { + enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; + typedef Vector<std::pair<const Identifier*, unsigned> > VarStack; + typedef Vector<FunctionBodyNode*> FunctionStack; + } + + struct SwitchInfo { + enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString }; + uint32_t bytecodeOffset; + SwitchType switchType; + }; + + class ParserArenaFreeable { + public: + // ParserArenaFreeable objects are are freed when the arena is deleted. + // Destructors are not called. Clients must not call delete on such objects. + void* operator new(size_t, JSGlobalData*); + }; + + class ParserArenaDeletable { + public: + virtual ~ParserArenaDeletable() { } + + // ParserArenaDeletable objects are deleted when the arena is deleted. + // Clients must not call delete directly on such objects. + void* operator new(size_t, JSGlobalData*); + }; + + class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> { + protected: + ParserArenaRefCounted(JSGlobalData*); + + public: + virtual ~ParserArenaRefCounted() + { + ASSERT(deletionHasBegun()); + } + }; + + class Node : public ParserArenaFreeable { + protected: + Node(JSGlobalData*); + + public: + virtual ~Node() { } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; + + int lineNo() const { return m_line; } + + protected: + int m_line; + }; + + class ExpressionNode : public Node { + protected: + ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType()); + + public: + virtual bool isNumber() const { return false; } + virtual bool isString() const { return false; } + virtual bool isNull() const { return false; } + virtual bool isPure(BytecodeGenerator&) const { return false; } + virtual bool isLocation() const { return false; } + virtual bool isResolveNode() const { return false; } + virtual bool isBracketAccessorNode() const { return false; } + virtual bool isDotAccessorNode() const { return false; } + virtual bool isFuncExprNode() const { return false; } + virtual bool isCommaNode() const { return false; } + virtual bool isSimpleArray() const { return false; } + virtual bool isAdd() const { return false; } + virtual bool isSubtract() const { return false; } + virtual bool hasConditionContextCodegen() const { return false; } + + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } + + virtual ExpressionNode* stripUnaryPlus() { return this; } + + ResultType resultDescriptor() const { return m_resultType; } + + private: + ResultType m_resultType; + }; + + class StatementNode : public Node { + protected: + StatementNode(JSGlobalData*); + + public: + void setLoc(int firstLine, int lastLine); + int firstLine() const { return lineNo(); } + int lastLine() const { return m_lastLine; } + + virtual bool isEmptyStatement() const { return false; } + virtual bool isReturnNode() const { return false; } + virtual bool isExprStatement() const { return false; } + + virtual bool isBlock() const { return false; } + + private: + int m_lastLine; + }; + + class NullNode : public ExpressionNode { + public: + NullNode(JSGlobalData*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isNull() const { return true; } + }; + + class BooleanNode : public ExpressionNode { + public: + BooleanNode(JSGlobalData*, bool value); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isPure(BytecodeGenerator&) const { return true; } + + bool m_value; + }; + + class NumberNode : public ExpressionNode { + public: + NumberNode(JSGlobalData*, double value); + + double value() const { return m_value; } + void setValue(double value) { m_value = value; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isNumber() const { return true; } + virtual bool isPure(BytecodeGenerator&) const { return true; } + + double m_value; + }; + + class StringNode : public ExpressionNode { + public: + StringNode(JSGlobalData*, const Identifier&); + + const Identifier& value() { return m_value; } + + private: + virtual bool isPure(BytecodeGenerator&) const { return true; } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isString() const { return true; } + + const Identifier& m_value; + }; + + class ThrowableExpressionData { + public: + ThrowableExpressionData() + : m_divot(static_cast<uint32_t>(-1)) + , m_startOffset(static_cast<uint16_t>(-1)) + , m_endOffset(static_cast<uint16_t>(-1)) + { + } + + ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + : m_divot(divot) + , m_startOffset(startOffset) + , m_endOffset(endOffset) + { + } + + void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset) + { + m_divot = divot; + m_startOffset = startOffset; + m_endOffset = endOffset; + } + + uint32_t divot() const { return m_divot; } + uint16_t startOffset() const { return m_startOffset; } + uint16_t endOffset() const { return m_endOffset; } + + protected: + RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message); + RegisterID* emitThrowSyntaxError(BytecodeGenerator&, const UString& message); + + private: + uint32_t m_divot; + uint16_t m_startOffset; + uint16_t m_endOffset; + }; + + class ThrowableSubExpressionData : public ThrowableExpressionData { + public: + ThrowableSubExpressionData() + : m_subexpressionDivotOffset(0) + , m_subexpressionEndOffset(0) + { + } + + ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + : ThrowableExpressionData(divot, startOffset, endOffset) + , m_subexpressionDivotOffset(0) + , m_subexpressionEndOffset(0) + { + } + + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + { + ASSERT(subexpressionDivot <= divot()); + if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + return; + m_subexpressionDivotOffset = divot() - subexpressionDivot; + m_subexpressionEndOffset = subexpressionOffset; + } + + protected: + uint16_t m_subexpressionDivotOffset; + uint16_t m_subexpressionEndOffset; + }; + + class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData { + public: + ThrowablePrefixedSubExpressionData() + : m_subexpressionDivotOffset(0) + , m_subexpressionStartOffset(0) + { + } + + ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + : ThrowableExpressionData(divot, startOffset, endOffset) + , m_subexpressionDivotOffset(0) + , m_subexpressionStartOffset(0) + { + } + + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + { + ASSERT(subexpressionDivot >= divot()); + if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + return; + m_subexpressionDivotOffset = subexpressionDivot - divot(); + m_subexpressionStartOffset = subexpressionOffset; + } + + protected: + uint16_t m_subexpressionDivotOffset; + uint16_t m_subexpressionStartOffset; + }; + + class RegExpNode : public ExpressionNode, public ThrowableExpressionData { + public: + RegExpNode(JSGlobalData*, const Identifier& pattern, const Identifier& flags); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_pattern; + const Identifier& m_flags; + }; + + class ThisNode : public ExpressionNode { + public: + ThisNode(JSGlobalData*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ResolveNode : public ExpressionNode { + public: + ResolveNode(JSGlobalData*, const Identifier&, int startOffset); + + const Identifier& identifier() const { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isPure(BytecodeGenerator&) const ; + virtual bool isLocation() const { return true; } + virtual bool isResolveNode() const { return true; } + + const Identifier& m_ident; + int32_t m_startOffset; + }; + + class ElementNode : public ParserArenaFreeable { + public: + ElementNode(JSGlobalData*, int elision, ExpressionNode*); + ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*); + + int elision() const { return m_elision; } + ExpressionNode* value() { return m_node; } + ElementNode* next() { return m_next; } + + private: + ElementNode* m_next; + int m_elision; + ExpressionNode* m_node; + }; + + class ArrayNode : public ExpressionNode { + public: + ArrayNode(JSGlobalData*, int elision); + ArrayNode(JSGlobalData*, ElementNode*); + ArrayNode(JSGlobalData*, int elision, ElementNode*); + + ArgumentListNode* toArgumentList(JSGlobalData*) const; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isSimpleArray() const ; + + ElementNode* m_element; + int m_elision; + bool m_optional; + }; + + class PropertyNode : public ParserArenaFreeable { + public: + enum Type { Constant = 1, Getter = 2, Setter = 4 }; + + PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type); + PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type); + + const Identifier& name() const { return m_name; } + Type type() const { return m_type; } + + private: + friend class PropertyListNode; + const Identifier& m_name; + ExpressionNode* m_assign; + Type m_type; + }; + + class PropertyListNode : public Node { + public: + PropertyListNode(JSGlobalData*, PropertyNode*); + PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + private: + PropertyNode* m_node; + PropertyListNode* m_next; + }; + + class ObjectLiteralNode : public ExpressionNode { + public: + ObjectLiteralNode(JSGlobalData*); + ObjectLiteralNode(JSGlobalData*, PropertyListNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + PropertyListNode* m_list; + }; + + class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { + public: + BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); + + ExpressionNode* base() const { return m_base; } + ExpressionNode* subscript() const { return m_subscript; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isLocation() const { return true; } + virtual bool isBracketAccessorNode() const { return true; } + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + bool m_subscriptHasAssignments; + }; + + class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { + public: + DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&); + + ExpressionNode* base() const { return m_base; } + const Identifier& identifier() const { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isLocation() const { return true; } + virtual bool isDotAccessorNode() const { return true; } + + ExpressionNode* m_base; + const Identifier& m_ident; + }; + + class ArgumentListNode : public Node { + public: + ArgumentListNode(JSGlobalData*, ExpressionNode*); + ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*); + + ArgumentListNode* m_next; + ExpressionNode* m_expr; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ArgumentsNode : public ParserArenaFreeable { + public: + ArgumentsNode(JSGlobalData*); + ArgumentsNode(JSGlobalData*, ArgumentListNode*); + + ArgumentListNode* m_listNode; + }; + + class NewExprNode : public ExpressionNode, public ThrowableExpressionData { + public: + NewExprNode(JSGlobalData*, ExpressionNode*); + NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + ArgumentsNode* m_args; + }; + + class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { + public: + EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ArgumentsNode* m_args; + }; + + class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { + public: + FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + ArgumentsNode* m_args; + }; + + class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ArgumentsNode* m_args; + size_t m_index; // Used by LocalVarFunctionCallNode. + size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode + }; + + class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ArgumentsNode* m_args; + }; + + class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + protected: + ExpressionNode* m_base; + const Identifier& m_ident; + ArgumentsNode* m_args; + }; + + class CallFunctionCallDotNode : public FunctionCallDotNode { + public: + CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ApplyFunctionCallDotNode : public FunctionCallDotNode { + public: + ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + + protected: + const Identifier& m_ident; + }; + + class PostfixResolveNode : public PrePostResolveNode { + public: + PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + Operator m_operator; + }; + + class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + Operator m_operator; + }; + + class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + Operator m_operator; + }; + + class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + Operator m_operator; + }; + + class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { + public: + DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + }; + + class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { + public: + DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + }; + + class DeleteValueNode : public ExpressionNode { + public: + DeleteValueNode(JSGlobalData*, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class VoidNode : public ExpressionNode { + public: + VoidNode(JSGlobalData*, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class TypeOfResolveNode : public ExpressionNode { + public: + TypeOfResolveNode(JSGlobalData*, const Identifier&); + + const Identifier& identifier() const { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class TypeOfValueNode : public ExpressionNode { + public: + TypeOfValueNode(JSGlobalData*, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class PrefixResolveNode : public PrePostResolveNode { + public: + PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + Operator m_operator; + }; + + class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { + public: + PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + Operator m_operator; + }; + + class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { + public: + PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + Operator m_operator; + }; + + class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { + public: + PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + Operator m_operator; + }; + + class UnaryOpNode : public ExpressionNode { + public: + UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID); + + protected: + ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + OpcodeID opcodeID() const { return m_opcodeID; } + + ExpressionNode* m_expr; + OpcodeID m_opcodeID; + }; + + class UnaryPlusNode : public UnaryOpNode { + public: + UnaryPlusNode(JSGlobalData*, ExpressionNode*); + + private: + virtual ExpressionNode* stripUnaryPlus() { return expr(); } + }; + + class NegateNode : public UnaryOpNode { + public: + NegateNode(JSGlobalData*, ExpressionNode*); + }; + + class BitwiseNotNode : public UnaryOpNode { + public: + BitwiseNotNode(JSGlobalData*, ExpressionNode*); + }; + + class LogicalNotNode : public UnaryOpNode { + public: + LogicalNotNode(JSGlobalData*, ExpressionNode*); + private: + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); + virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } + }; + + class BinaryOpNode : public ExpressionNode { + public: + BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + + RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + + ExpressionNode* lhs() { return m_expr1; }; + ExpressionNode* rhs() { return m_expr2; }; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + protected: + OpcodeID opcodeID() const { return m_opcodeID; } + + protected: + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + private: + OpcodeID m_opcodeID; + protected: + bool m_rightHasAssignments; + }; + + class ReverseBinaryOpNode : public BinaryOpNode { + public: + ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class MultNode : public BinaryOpNode { + public: + MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class DivNode : public BinaryOpNode { + public: + DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class ModNode : public BinaryOpNode { + public: + ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class AddNode : public BinaryOpNode { + public: + AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + virtual bool isAdd() const { return true; } + }; + + class SubNode : public BinaryOpNode { + public: + SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + virtual bool isSubtract() const { return true; } + }; + + class LeftShiftNode : public BinaryOpNode { + public: + LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class RightShiftNode : public BinaryOpNode { + public: + RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class UnsignedRightShiftNode : public BinaryOpNode { + public: + UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class LessNode : public BinaryOpNode { + public: + LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class GreaterNode : public ReverseBinaryOpNode { + public: + GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class LessEqNode : public BinaryOpNode { + public: + LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class GreaterEqNode : public ReverseBinaryOpNode { + public: + GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { + public: + ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class InstanceOfNode : public ThrowableBinaryOpNode { + public: + InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class InNode : public ThrowableBinaryOpNode { + public: + InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class EqualNode : public BinaryOpNode { + public: + EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class NotEqualNode : public BinaryOpNode { + public: + NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class StrictEqualNode : public BinaryOpNode { + public: + StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class NotStrictEqualNode : public BinaryOpNode { + public: + NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class BitAndNode : public BinaryOpNode { + public: + BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class BitOrNode : public BinaryOpNode { + public: + BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class BitXOrNode : public BinaryOpNode { + public: + BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + // m_expr1 && m_expr2, m_expr1 || m_expr2 + class LogicalOpNode : public ExpressionNode { + public: + LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); + virtual bool hasConditionContextCodegen() const { return true; } + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + LogicalOperator m_operator; + }; + + // The ternary operator, "m_logical ? m_expr1 : m_expr2" + class ConditionalNode : public ExpressionNode { + public: + ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_logical; + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + }; + + class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ExpressionNode* m_right; + size_t m_index; // Used by ReadModifyLocalVarNode. + Operator m_operator; + bool m_rightHasAssignments; + }; + + class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ExpressionNode* m_right; + size_t m_index; // Used by ReadModifyLocalVarNode. + bool m_rightHasAssignments; + }; + + class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; + Operator m_operator : 30; + bool m_subscriptHasAssignments : 1; + bool m_rightHasAssignments : 1; + }; + + class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; + bool m_subscriptHasAssignments : 1; + bool m_rightHasAssignments : 1; + }; + + class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + ExpressionNode* m_right; + bool m_rightHasAssignments; + }; + + class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + ExpressionNode* m_right; + Operator m_operator : 31; + bool m_rightHasAssignments : 1; + }; + + class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_left; + Operator m_operator; + ExpressionNode* m_right; + }; + + typedef Vector<ExpressionNode*, 8> ExpressionVector; + + class CommaNode : public ExpressionNode, public ParserArenaDeletable { + public: + CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2); + + using ParserArenaDeletable::operator new; + + void append(ExpressionNode* expr) { m_expressions.append(expr); } + + private: + virtual bool isCommaNode() const { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionVector m_expressions; + }; + + class ConstDeclNode : public ExpressionNode { + public: + ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*); + + bool hasInitializer() const { return m_init; } + const Identifier& ident() { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitCodeSingle(BytecodeGenerator&); + + const Identifier& m_ident; + + public: + ConstDeclNode* m_next; + + private: + ExpressionNode* m_init; + }; + + class ConstStatementNode : public StatementNode { + public: + ConstStatementNode(JSGlobalData*, ConstDeclNode* next); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ConstDeclNode* m_next; + }; + + class SourceElements : public ParserArenaDeletable { + public: + SourceElements(JSGlobalData*); + + void append(StatementNode*); + + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); + + private: + Vector<StatementNode*> m_statements; + }; + + class BlockNode : public StatementNode { + public: + BlockNode(JSGlobalData*, SourceElements* = 0); + + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isBlock() const { return true; } + + SourceElements* m_statements; + }; + + class EmptyStatementNode : public StatementNode { + public: + EmptyStatementNode(JSGlobalData*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isEmptyStatement() const { return true; } + }; + + class DebuggerStatementNode : public StatementNode { + public: + DebuggerStatementNode(JSGlobalData*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ExprStatementNode : public StatementNode { + public: + ExprStatementNode(JSGlobalData*, ExpressionNode*); + + ExpressionNode* expr() const { return m_expr; } + + private: + virtual bool isExprStatement() const { return true; } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class VarStatementNode : public StatementNode { + public: + VarStatementNode(JSGlobalData*, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class IfNode : public StatementNode { + public: + IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock); + + protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_condition; + StatementNode* m_ifBlock; + }; + + class IfElseNode : public IfNode { + public: + IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_elseBlock; + }; + + class DoWhileNode : public StatementNode { + public: + DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_statement; + ExpressionNode* m_expr; + }; + + class WhileNode : public StatementNode { + public: + WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + StatementNode* m_statement; + }; + + class ForNode : public StatementNode { + public: + ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + ExpressionNode* m_expr3; + StatementNode* m_statement; + bool m_expr1WasVarDecl; + }; + + class ForInNode : public StatementNode, public ThrowableExpressionData { + public: + ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*); + ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ExpressionNode* m_init; + ExpressionNode* m_lexpr; + ExpressionNode* m_expr; + StatementNode* m_statement; + bool m_identIsVarDecl; + }; + + class ContinueNode : public StatementNode, public ThrowableExpressionData { + public: + ContinueNode(JSGlobalData*); + ContinueNode(JSGlobalData*, const Identifier&); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class BreakNode : public StatementNode, public ThrowableExpressionData { + public: + BreakNode(JSGlobalData*); + BreakNode(JSGlobalData*, const Identifier&); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class ReturnNode : public StatementNode, public ThrowableExpressionData { + public: + ReturnNode(JSGlobalData*, ExpressionNode* value); + + ExpressionNode* value() { return m_value; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isReturnNode() const { return true; } + + ExpressionNode* m_value; + }; + + class WithNode : public StatementNode { + public: + WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + StatementNode* m_statement; + uint32_t m_divot; + uint32_t m_expressionLength; + }; + + class LabelNode : public StatementNode, public ThrowableExpressionData { + public: + LabelNode(JSGlobalData*, const Identifier& name, StatementNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_name; + StatementNode* m_statement; + }; + + class ThrowNode : public StatementNode, public ThrowableExpressionData { + public: + ThrowNode(JSGlobalData*, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class TryNode : public StatementNode { + public: + TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_tryBlock; + const Identifier& m_exceptionIdent; + StatementNode* m_catchBlock; + StatementNode* m_finallyBlock; + bool m_catchHasEval; + }; + + class ParameterNode : public ParserArenaFreeable { + public: + ParameterNode(JSGlobalData*, const Identifier&); + ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&); + + const Identifier& ident() const { return m_ident; } + ParameterNode* nextParam() const { return m_next; } + + private: + const Identifier& m_ident; + ParameterNode* m_next; + }; + + struct ScopeNodeData : FastAllocBase { + typedef DeclarationStacks::VarStack VarStack; + typedef DeclarationStacks::FunctionStack FunctionStack; + + ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants); + + ParserArena m_arena; + VarStack m_varStack; + FunctionStack m_functionStack; + int m_numConstants; + SourceElements* m_statements; + IdentifierSet m_capturedVariables; + }; + + class ScopeNode : public StatementNode, public ParserArenaRefCounted { + public: + typedef DeclarationStacks::VarStack VarStack; + typedef DeclarationStacks::FunctionStack FunctionStack; + + ScopeNode(JSGlobalData*, bool inStrictContext); + ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + + using ParserArenaRefCounted::operator new; + + ScopeNodeData* data() const { return m_data.get(); } + void destroyData() { m_data.clear(); } + + const SourceCode& source() const { return m_source; } + const UString& sourceURL() const { return m_source.provider()->url(); } + intptr_t sourceID() const { return m_source.provider()->asID(); } + + void setFeatures(CodeFeatures features) { m_features = features; } + CodeFeatures features() { return m_features; } + + bool usesEval() const { return m_features & EvalFeature; } + bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } + bool isStrictMode() const { return m_features & StrictModeFeature; } + void setUsesArguments() { m_features |= ArgumentsFeature; } + bool usesThis() const { return m_features & ThisFeature; } + bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); } + bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } + bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); } + size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); } + bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); } + + VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } + FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } + + int neededConstants() + { + ASSERT(m_data); + // We may need 2 more constants than the count given by the parser, + // because of the various uses of jsUndefined() and jsNull(). + return m_data->m_numConstants + 2; + } + + StatementNode* singleStatement() const; + + void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); + + protected: + void setSource(const SourceCode& source) { m_source = source; } + + private: + OwnPtr<ScopeNodeData> m_data; + CodeFeatures m_features; + SourceCode m_source; + }; + + class ProgramNode : public ScopeNode { + public: + static const bool isFunctionNode = false; + static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + static const bool scopeIsFunction = false; + + private: + ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class EvalNode : public ScopeNode { + public: + static const bool isFunctionNode = false; + static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + static const bool scopeIsFunction = false; + + private: + EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> { + public: + static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); } + + private: + FunctionParameters(ParameterNode*); + }; + + class FunctionBodyNode : public ScopeNode { + public: + static const bool isFunctionNode = true; + static FunctionBodyNode* create(JSGlobalData*, bool isStrictMode); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + FunctionParameters* parameters() const { return m_parameters.get(); } + size_t parameterCount() const { return m_parameters->size(); } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + void finishParsing(const SourceCode&, ParameterNode*, const Identifier&); + void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&); + + const Identifier& ident() { return m_ident; } + + static const bool scopeIsFunction = true; + + private: + FunctionBodyNode(JSGlobalData*, bool inStrictContext); + FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + Identifier m_ident; + RefPtr<FunctionParameters> m_parameters; + }; + + class FuncExprNode : public ExpressionNode { + public: + FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0); + + FunctionBodyNode* body() { return m_body; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isFuncExprNode() const { return true; } + + FunctionBodyNode* m_body; + }; + + class FuncDeclNode : public StatementNode { + public: + FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + + FunctionBodyNode* body() { return m_body; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + FunctionBodyNode* m_body; + }; + + class CaseClauseNode : public ParserArenaFreeable { + public: + CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements* = 0); + + ExpressionNode* expr() const { return m_expr; } + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); + + private: + ExpressionNode* m_expr; + SourceElements* m_statements; + }; + + class ClauseListNode : public ParserArenaFreeable { + public: + ClauseListNode(JSGlobalData*, CaseClauseNode*); + ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*); + + CaseClauseNode* getClause() const { return m_clause; } + ClauseListNode* getNext() const { return m_next; } + + private: + CaseClauseNode* m_clause; + ClauseListNode* m_next; + }; + + class CaseBlockNode : public ParserArenaFreeable { + public: + CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); + + RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); + + private: + SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); + ClauseListNode* m_list1; + CaseClauseNode* m_defaultClause; + ClauseListNode* m_list2; + }; + + class SwitchNode : public StatementNode { + public: + SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + CaseBlockNode* m_block; + }; + + struct ElementList { + ElementNode* head; + ElementNode* tail; + }; + + struct PropertyList { + PropertyListNode* head; + PropertyListNode* tail; + }; + + struct ArgumentList { + ArgumentListNode* head; + ArgumentListNode* tail; + }; + + struct ConstDeclList { + ConstDeclNode* head; + ConstDeclNode* tail; + }; + + struct ParameterList { + ParameterNode* head; + ParameterNode* tail; + }; + + struct ClauseList { + ClauseListNode* head; + ClauseListNode* tail; + }; + +} // namespace JSC + +#endif // Nodes_h |