// -*- 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. * Copyright (C) 2007, 2008 Maksim Orlovich (maksim@kde.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 "Parser.h" #include "internal.h" #include "CompileState.h" #include "operations.h" #include "SymbolTable.h" #include "opcodes.h" #include "bytecode/opargs.h" #include #include namespace KJS { class ProgramNode; class PropertyNameNode; class PropertyListNode; class RegExp; class SourceElementsNode; class SourceStream; class PackageObject; class FuncDeclNode; class FunctionBodyNode; class Node; class VarDeclVisitor; class FuncDeclVisitor; class CompileState; struct CompileReference; class NodeVisitor { public: virtual ~NodeVisitor() {} /** This method should be overridden by subclasses to process nodes, and perhaps return pointers for replacement nodes. If the node should not be changed, return 0. Otherwise, return the replacement node. The default implementation asks the node to visit its kids, and do replacements on them if needed, but does not change anything for this node */ virtual Node* visit(Node* node); }; class Node { public: enum NodeType { UnknownNodeType, NullNodeType, BooleanNodeType, NumberNodeType, StringNodeType, RegExpNodeType, TryNodeType, GroupNodeType, LabelNodeType }; Node(); virtual ~Node(); virtual NodeType type() const { return UnknownNodeType; } UString toString() const; // This updates line numbers to the pretty-printed version, and // returns it out. UString reindent(int baseLine = 0) const; virtual void streamTo(SourceStream&) const = 0; int lineNo() const { return m_line; } void ref(); void deref(); unsigned refcount(); static void clearNewNodes(); virtual Node *nodeInsideAllParens(); virtual bool isLocation() const { return false; } virtual bool isVarAccessNode() const { return false; } bool isNumber() const { return type() == NumberNodeType; } bool isString() const { return type() == StringNodeType; } bool isGroupNode() const { return type() == GroupNodeType; } bool isTryNode() const { return type() == TryNodeType; } bool isLabelNode() const { return type() == LabelNodeType; } virtual bool scanForDeclarations () const { return true; } virtual bool isIterationStatement() const { return false; } virtual void breakCycle() { } // Processes all function and variable declarations below this node, // adding them to symbol table or the current object depending on the // execution context.. void processDecls(ExecState*); /* Implementations of this method should call visitor->visit on all the children nodes, and if they return value is non-0, update the link to the child. The recurseVisitLink helper takes care of this */ virtual void recurseVisit(NodeVisitor * /*visitor*/) {} template static void recurseVisitLink(NodeVisitor* visitor, RefPtr& link) { if (!link) return; T* newLink = static_cast(visitor->visit(link.get())); if (newLink) link = newLink; } template static void recurseVisitLink(NodeVisitor* visitor, ListRefPtr& link) { if (!link) return; T* newLink = static_cast(visitor->visit(link.get())); if (newLink) link = newLink; } JSValue* throwError(ExecState*, ErrorType, const UString& msg); JSValue* throwError(ExecState*, ErrorType, const UString& msg, const Identifier&); JSValue* throwUndefinedVariableError(ExecState*, const Identifier&); virtual OpValue generateEvalCode(CompileState* comp); protected: mutable int m_line; private: virtual void processVarDecl (ExecState* state); virtual void processFuncDecl(ExecState* state); friend class VarDeclVisitor; friend class FuncDeclVisitor; // disallow assignment Node& operator=(const Node&); Node(const Node &other); }; class LocationNode : public Node { public: virtual bool isLocation() const { return true; } // For assignments, we need to conceptually evaluate the LHS to a reference before looking at the RHS // generateRefBind corresponds to that action. It never issues an error. The returned // reference should be passed to generateRefWrite when needed virtual CompileReference* generateRefBind(CompileState*) = 0; // When we are doing a read-modify-write style op, or just plain read, we want to do a read // right after the binding. This does that, and returns a reference for use of follow up // writes. virtual CompileReference* generateRefRead(CompileState*, OpValue* out) = 0; // Writes to a bound reference. virtual void generateRefWrite (CompileState*, CompileReference* ref, OpValue& valToStore) = 0; // The location nodes also handle deletes themselves. Note that this is called // w/o generateRefBegin virtual OpValue generateRefDelete(CompileState*) = 0; // For function calls, we also do a specialized lookup, getting both the valie and the // scope/this, also making sure it's not an activation. virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut) = 0; }; class StatementNode : public Node { public: StatementNode(); void setLoc(int line0, int line1) const; int firstLine() const { return lineNo(); } int lastLine() const { return m_lastLine; } void hitStatement(ExecState*); void generateDebugInfoIfNeeded(CompileState* comp); virtual void generateExecCode(CompileState*); private: void generateDebugInfo(CompileState* comp); mutable int m_lastLine; }; inline void StatementNode::generateDebugInfoIfNeeded(CompileState* comp) { if (comp->compileType() == Debug) generateDebugInfo(comp); } class NullNode : public Node { public: NullNode() {} virtual NodeType type() const { return NullNodeType; } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; }; class BooleanNode : public Node { public: BooleanNode(bool v) : val(v) {} bool value() const { return val; } virtual NodeType type() const { return BooleanNodeType; } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; private: bool val; }; class NumberNode : public Node { public: NumberNode(double v) : val(v) {} double value() const { return val; } void setValue(double v) { val = v; } virtual NodeType type() const { return NumberNodeType; } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; private: double val; }; class StringNode : public Node { public: StringNode(const UString *v) : val(*v), interned(0) { } ~StringNode(); // in nodes2bytecode.cpp UString value() const { return val; } void setValue(const UString& v) { val = v; } virtual NodeType type() const { return StringNodeType; } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; private: UString val; StringImp* interned; }; class RegExpNode : public Node { public: RegExpNode(const UString &p, const UString &f) : pattern(p), flags(f) { } virtual NodeType type() const { return RegExpNodeType; } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; private: UString pattern, flags; }; class ThisNode : public Node { public: ThisNode() {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; }; class VarAccessNode : public LocationNode { public: VarAccessNode(const Identifier& s) : ident(s) {} virtual bool isVarAccessNode() const { return true; } virtual void streamTo(SourceStream&) const; virtual OpValue generateEvalCode(CompileState* comp); virtual CompileReference* generateRefBind(CompileState*); virtual CompileReference* generateRefRead(CompileState*, OpValue* out); virtual void generateRefWrite (CompileState*, CompileReference* ref, OpValue& valToStore); virtual OpValue generateRefDelete(CompileState*); virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut); // This one never fails.. OpValue valueForTypeOf(CompileState* comp); // Returns the ID this variable should be accessed as, or // missingSymbolMarker(), along with the variable's classification enum Classification { Local, // local variable accessed by register # NonLocal, // one scope above, unless local injected Dynamic, // need to do a full lookup Global // in the global object, if anywhere. }; size_t classifyVariable(CompileState*, Classification& classify); protected: Identifier ident; }; class GroupNode : public Node { public: GroupNode(Node *g) : group(g) { } virtual NodeType type() const { return GroupNodeType; } virtual OpValue generateEvalCode(CompileState* comp); virtual Node *nodeInsideAllParens(); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); 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) : next(this), elision(e), node(n) { Parser::noteNodeCycle(this); } ElementNode(ElementNode *l, int e, Node *n) : next(l->next), elision(e), node(n) { l->next = this; } virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class ArrayNode; ListRefPtr next; int elision; RefPtr node; }; class ArrayNode : public Node { public: ArrayNode(int e) : elision(e), opt(true) { } ArrayNode(ElementNode *ele) : element(ele->next.release()), elision(0), opt(false) { Parser::removeNodeCycle(element.get()); } ArrayNode(int eli, ElementNode *ele) : element(ele->next.release()), elision(eli), opt(true) { Parser::removeNodeCycle(element.get()); } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual bool scanForDeclarations() const { return false; } private: RefPtr element; int elision; bool opt; }; class PropertyNameNode : public Node { public: PropertyNameNode(const Identifier &s) : str(s) { } virtual void streamTo(SourceStream&) const; private: friend class ObjectLiteralNode; Identifier str; }; class PropertyNode : public Node { public: enum Type { Constant, Getter, Setter }; PropertyNode(PropertyNameNode *n, Node *a, Type t) : name(n), assign(a), type(t) { } virtual void streamTo(SourceStream&) const; friend class PropertyListNode; virtual void recurseVisit(NodeVisitor *visitor); private: friend class ObjectLiteralNode; 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) : node(n), next(this) { Parser::noteNodeCycle(this); } PropertyListNode(PropertyNode *n, PropertyListNode *l) : node(n), next(l->next) { l->next = this; } virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class ObjectLiteralNode; RefPtr node; ListRefPtr next; }; class ObjectLiteralNode : public Node { public: ObjectLiteralNode() { } ObjectLiteralNode(PropertyListNode *l) : list(l->next.release()) { Parser::removeNodeCycle(list.get()); } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual bool scanForDeclarations() const { return false; } private: RefPtr list; }; class BracketAccessorNode : public LocationNode { public: BracketAccessorNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {} virtual void streamTo(SourceStream&) const; virtual OpValue generateEvalCode(CompileState* comp); virtual CompileReference* generateRefBind(CompileState*); virtual CompileReference* generateRefRead(CompileState*, OpValue* out); virtual void generateRefWrite (CompileState*, CompileReference* ref, OpValue& valToStore); virtual OpValue generateRefDelete(CompileState*); virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut); Node *base() { return expr1.get(); } Node *subscript() { return expr2.get(); } virtual void recurseVisit(NodeVisitor *visitor); protected: RefPtr expr1; RefPtr expr2; }; class DotAccessorNode : public LocationNode { public: DotAccessorNode(Node *e, const Identifier &s) : expr(e), ident(s) { } virtual void streamTo(SourceStream&) const; virtual OpValue generateEvalCode(CompileState* comp); virtual CompileReference* generateRefBind(CompileState*); virtual CompileReference* generateRefRead(CompileState*, OpValue* out); virtual void generateRefWrite (CompileState*, CompileReference* ref, OpValue& valToStore); virtual OpValue generateRefDelete(CompileState*); virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut); Node *base() const { return expr.get(); } const Identifier& identifier() const { return ident; } virtual void recurseVisit(NodeVisitor *visitor); protected: 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) : next(this), expr(e) { Parser::noteNodeCycle(this); } ArgumentListNode(ArgumentListNode *l, Node *e) : next(l->next), expr(e) { l->next = this; } virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class ArgumentsNode; ListRefPtr next; RefPtr expr; }; class ArgumentsNode : public Node { public: ArgumentsNode() { } ArgumentsNode(ArgumentListNode *l) : list(l->next.release()) { Parser::removeNodeCycle(list.get()); } void generateEvalArguments(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr list; }; class NewExprNode : public Node { public: NewExprNode(Node *e) : expr(e) {} NewExprNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; RefPtr args; }; class FunctionCallValueNode : public Node { public: FunctionCallValueNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; RefPtr args; }; class FunctionCallReferenceNode : public Node { public: FunctionCallReferenceNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; RefPtr args; }; class PostfixNode : public Node { public: PostfixNode(Node *l, Operator o) : m_loc(l), m_oper(o) {} void streamTo(SourceStream&) const; void recurseVisit(NodeVisitor * visitor); virtual OpValue generateEvalCode(CompileState* comp); protected: RefPtr m_loc; Operator m_oper; }; class DeleteReferenceNode : public Node { public: DeleteReferenceNode(LocationNode *l) : loc(l) {} void streamTo(SourceStream&) const; void recurseVisit(NodeVisitor * visitor); virtual OpValue generateEvalCode(CompileState* comp); private: RefPtr loc; }; class DeleteValueNode : public Node { public: DeleteValueNode(Node *e) : m_expr(e) {} virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual OpValue generateEvalCode(CompileState* comp); private: RefPtr m_expr; }; class VoidNode : public Node { public: VoidNode(Node *e) : expr(e) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; }; class TypeOfVarNode : public Node { public: TypeOfVarNode(VarAccessNode *l) : loc(l) {} virtual OpValue generateEvalCode(CompileState* comp); void streamTo(SourceStream&) const; void recurseVisit(NodeVisitor * visitor); private: RefPtr loc; }; class TypeOfValueNode : public Node { public: TypeOfValueNode(Node *e) : m_expr(e) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr m_expr; }; class PrefixNode : public Node { public: PrefixNode(Node *l, Operator o) : m_loc(l), m_oper(o) {} virtual OpValue generateEvalCode(CompileState* comp); void streamTo(SourceStream&) const; void recurseVisit(NodeVisitor * visitor); protected: RefPtr m_loc; Operator m_oper; }; class UnaryPlusNode : public Node { public: UnaryPlusNode(Node *e) : expr(e) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; }; class NegateNode : public Node { public: NegateNode(Node *e) : expr(e) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; }; class BitwiseNotNode : public Node { public: BitwiseNotNode(Node *e) : expr(e) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; }; class LogicalNotNode : public Node { public: LogicalNotNode(Node *e) : expr(e) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; }; class BinaryOperatorNode : public Node { public: BinaryOperatorNode(Node* e1, Node* e2, Operator op) : expr1(e1), expr2(e2), oper(op) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor* visitor); private: RefPtr expr1; RefPtr expr2; Operator oper; }; /** * expr1 && expr2, expr1 || expr2 */ class BinaryLogicalNode : public Node { public: BinaryLogicalNode(Node *e1, Operator o, Node *e2) : expr1(e1), expr2(e2), oper(o) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); 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) : logical(l), expr1(e1), expr2(e2) {} virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr logical; RefPtr expr1; RefPtr expr2; }; class AssignNode : public Node { public: AssignNode(Node* loc, Operator oper, Node *right) : m_loc(loc), m_oper(oper), m_right(right) {} void streamTo(SourceStream&) const; virtual OpValue generateEvalCode(CompileState* comp); void recurseVisit(NodeVisitor * visitor); protected: RefPtr m_loc; Operator m_oper; RefPtr m_right; }; class CommaNode : public Node { public: CommaNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {} virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual OpValue generateEvalCode(CompileState* comp); private: RefPtr expr1; RefPtr expr2; }; class AssignExprNode : public Node { public: AssignExprNode(Node *e) : expr(e) {} virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual OpValue generateEvalCode(CompileState* comp); Node* getExpr() { return expr.get(); } private: RefPtr expr; }; class VarDeclNode : public Node { public: enum Type { Variable, Constant }; VarDeclNode(const Identifier &id, AssignExprNode *in, Type t); void generateCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void processVarDecl(ExecState*); private: friend class VarStatementNode; friend class VarDeclListNode; 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) : next(this), var(v) { Parser::noteNodeCycle(this); } VarDeclListNode(VarDeclListNode *l, VarDeclNode *v) : next(l->next), var(v) { l->next = this; } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class ForNode; friend class VarStatementNode; ListRefPtr next; RefPtr var; }; class VarStatementNode : public StatementNode { public: VarStatementNode(VarDeclListNode *l) : next(l->next.release()) { Parser::removeNodeCycle(next.get()); } virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); private: RefPtr next; }; class BlockNode : public StatementNode { public: BlockNode(SourceElementsNode *s); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); protected: RefPtr source; }; class EmptyStatementNode : public StatementNode { public: EmptyStatementNode() { } // debug virtual void streamTo(SourceStream&) const; virtual void generateExecCode(CompileState*); }; class ExprStatementNode : public StatementNode { public: ExprStatementNode(Node *e) : expr(e) { } virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); private: RefPtr expr; }; class IfNode : public StatementNode { public: IfNode(Node *e, StatementNode *s1, StatementNode *s2) : expr(e), statement1(s1), statement2(s2) {} virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); private: RefPtr expr; RefPtr statement1; RefPtr statement2; }; class DoWhileNode : public StatementNode { public: DoWhileNode(StatementNode *s, Node *e) : statement(s), expr(e) {} virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); virtual bool isIterationStatement() const { return true; } private: RefPtr statement; RefPtr expr; }; class WhileNode : public StatementNode { public: WhileNode(Node *e, StatementNode *s) : expr(e), statement(s) {} virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); virtual bool isIterationStatement() const { return true; } private: RefPtr expr; RefPtr statement; }; class ForNode : public StatementNode { public: ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) : expr1(e1), expr2(e2), expr3(e3), statement(s) {} ForNode(VarDeclListNode *e1, Node *e2, Node *e3, StatementNode *s) : expr1(e1->next.release()), expr2(e2), expr3(e3), statement(s) { Parser::removeNodeCycle(expr1.get()); } virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual bool isIterationStatement() const { return true; } private: RefPtr expr1; RefPtr expr2; RefPtr expr3; RefPtr statement; }; class ForInNode : public StatementNode { public: ForInNode(Node *l, Node *e, StatementNode *s); ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s); virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual bool isIterationStatement() const { return true; } private: Identifier ident; RefPtr init; RefPtr lexpr; RefPtr expr; RefPtr varDecl; RefPtr statement; }; class ContinueNode : public StatementNode { public: ContinueNode() : target(0) { } ContinueNode(const Identifier &i) : ident(i), target(0) { } virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; private: Identifier ident; const Node* target; }; class BreakNode : public StatementNode { public: BreakNode() : target(0) { } BreakNode(const Identifier &i) : ident(i), target(0) { } virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; private: Identifier ident; const Node* target; }; class ReturnNode : public StatementNode { public: ReturnNode(Node *v) : value(v) {} virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr value; }; class WithNode : public StatementNode { public: WithNode(Node *e, StatementNode *s) : expr(e), statement(s) {} virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; RefPtr statement; }; class LabelNode : public StatementNode { public: LabelNode(const Identifier &l, StatementNode *s) : label(l), statement(s) { } virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState*); virtual NodeType type() const { return LabelNodeType; } private: Identifier label; RefPtr statement; }; class ThrowNode : public StatementNode { public: ThrowNode(Node *e) : expr(e) {} virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: RefPtr expr; }; class TryNode : public StatementNode { public: TryNode(StatementNode *b, const Identifier &e, StatementNode *c, StatementNode *f) : tryBlock(b), exceptionIdent(e), catchBlock(c), finallyBlock(f) { } virtual NodeType type() const { return TryNodeType; } virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); 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) : id(i), next(this) { Parser::noteNodeCycle(this); } ParameterNode(ParameterNode *next, const Identifier &i) : id(i), next(next->next) { next->next = this; } const Identifier& ident() const { return id; } ParameterNode *nextParam() const { return next.get(); } virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class FuncDeclNode; friend class FuncExprNode; Identifier id; ListRefPtr next; }; // Flags about function bodies we care about for codegen enum FunctionBodyFlags { // note: neither of the two below is set for things created via // top-level, eval, or function ctor FuncFl_Decl = 1, FuncFl_Expr = 2, FuncFl_HasEvalOp = 4 }; /** This AST node corresponds to the function body or top-level code in the AST, but is used to keep track of much of the information relevant to the whole function, such as parameter names and symbol tables. This is because there are both function declarations and expressions, so there is no natural single place to put this stuff above the body inherited by ProgramNode */ class FunctionBodyNode : public BlockNode { public: struct SymbolInfo { SymbolInfo(int _attr, FuncDeclNode* _funcDecl) : funcDecl(_funcDecl), attr(_attr) {} SymbolInfo() {} FuncDeclNode* funcDecl; int attr; }; FunctionBodyNode(SourceElementsNode *); int sourceId() { return m_sourceId; } const UString& sourceURL() { return m_sourceURL; } bool isCompiled() const { return m_compType != NotCompiled; } void compileIfNeeded(CodeType ctype, CompileType compType); void compile(CodeType ctype, CompileType compType); CompileType compileState() const { return m_compType; } virtual void generateExecCode(CompileState*); // Reserves a register for private use, making sure that id is in the right spot.. void reserveSlot(size_t id, bool shouldMark); // Symbol table functions SymbolTable& symbolTable() { return m_symbolTable; } size_t lookupSymbolID(const Identifier& id) const { return m_symbolTable.get(id.ustring().rep()); } int numLocalsAndRegisters() const { return m_symbolList.size(); } SymbolInfo* getLocalInfo() { return m_symbolList.data(); } size_t numFunctionLocals() const { return m_functionLocals.size(); } size_t* getFunctionLocalInfo() { return m_functionLocals.data(); } // Parameter stuff. We only collect the names during the parsing/ // while FunctionImp is responsible for managing the IDs. void addParam(const Identifier& ident); size_t numParams() const { return m_paramList.size(); } const Identifier& paramName(size_t pos) const { return m_paramList[pos]; } void addVarDecl(const Identifier& ident, int attr, ExecState* exec); void addFunDecl(const Identifier& ident, int attr, FuncDeclNode* funcDecl); // Adds a new symbol, killing any previous ID. void addSymbolOverwriteID(size_t id, const Identifier& ident, int attr); // Runs the code, compiling if needed. This should only be used for non-function ExecStates Completion execute(ExecState *exec); bool tearOffAtEnd() const { return m_tearOffAtEnd; } const CodeBlock& code() const { return m_compiledCode; } CodeBlock& code() { return m_compiledCode; } // Collection of FuncFl_* flags describing information collected about this function // during the parsing. unsigned flags() const { return m_flags; } private: size_t addSymbol(const Identifier& ident, int attr, FuncDeclNode* funcDecl = 0); UString m_sourceURL; int m_sourceId : 31; bool m_tearOffAtEnd : 1; CompileType m_compType; // Flags unsigned m_flags; // This maps id -> attributes and function decl info WTF::Vector m_symbolList; // This contains the list of locals which contains function declarations WTF::Vector m_functionLocals; // This maps name -> id SymbolTable m_symbolTable; // The list of parameter names WTF::Vector m_paramList; CodeBlock m_compiledCode; }; inline void FunctionBodyNode::compileIfNeeded(CodeType ctype, CompileType compType) { if (m_compType != compType) compile(ctype, compType); } class FuncExprNode : public Node { public: FuncExprNode(const Identifier &i, FunctionBodyNode *b, ParameterNode *p = 0) : ident(i), param(p ? p->next.release() : PassRefPtr(0)), body(b) { if (p) { Parser::removeNodeCycle(param.get()); } addParams(); } virtual OpValue generateEvalCode(CompileState* comp); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual bool scanForDeclarations() const { return false; } private: void addParams(); // Used for streamTo friend class PropertyNode; Identifier ident; RefPtr param; RefPtr body; }; class FuncDeclNode : public StatementNode { public: FuncDeclNode(const Identifier &i, FunctionBodyNode *b) : ident(i), body(b) { addParams(); } FuncDeclNode(const Identifier &i, ParameterNode *p, FunctionBodyNode *b) : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); addParams(); } virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual bool scanForDeclarations() const { return false; } virtual void processFuncDecl(ExecState*); FunctionImp* makeFunctionObject(ExecState*); private: void addParams(); Identifier ident; RefPtr param; RefPtr body; }; // A linked list of source element nodes class SourceElementsNode : public StatementNode { public: // list pointer is tail of a circular list, cracked in the BlockNode (or subclass) ctor SourceElementsNode(StatementNode*); SourceElementsNode(SourceElementsNode *s1, StatementNode *s2); virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class BlockNode; friend class CaseClauseNode; RefPtr node; ListRefPtr next; }; class CaseClauseNode : public Node { public: CaseClauseNode(Node *e) : expr(e) { } CaseClauseNode(Node *e, SourceElementsNode *s) : expr(e), source(s->next.release()) { Parser::removeNodeCycle(source.get()); } virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: friend class SwitchNode; 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) : clause(c), next(this) { Parser::noteNodeCycle(this); } ClauseListNode(ClauseListNode *n, CaseClauseNode *c) : clause(c), next(n->next) { n->next = this; } CaseClauseNode *getClause() const { return clause.get(); } ClauseListNode *getNext() const { return next.get(); } virtual void streamTo(SourceStream&) const; PassRefPtr releaseNext() { return next.release(); } virtual void breakCycle(); virtual void recurseVisit(NodeVisitor *visitor); private: friend class SwitchNode; friend class CaseBlockNode; RefPtr clause; ListRefPtr next; }; class CaseBlockNode : public Node { public: CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: friend class SwitchNode; RefPtr list1; RefPtr def; RefPtr list2; }; class SwitchNode : public StatementNode { public: SwitchNode(Node *e, CaseBlockNode *b) : expr(e), block(b) { } virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); virtual void generateExecCode(CompileState* comp); private: RefPtr expr; RefPtr block; }; // important: these are also built when compiling things via the Function constructor // (see FunctionObjectImp::construct() and Parser::parseFunctionBody, so the existence // of this class rather than the bare FunctionBodyNode does not care much information. class ProgramNode : public FunctionBodyNode { public: ProgramNode(SourceElementsNode *s); virtual void streamTo(SourceStream&) const; }; class PackageNameNode : public Node { public: PackageNameNode(const Identifier &i) : names(0), id(i) { } PackageNameNode(PackageNameNode *n, const Identifier &i) : names(n), id(i) { } virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); Completion loadSymbol(ExecState* exec, bool wildcard); PackageObject* resolvePackage(ExecState* exec); private: PackageObject* resolvePackage(ExecState* exec, JSObject* baseObject, Package* basePackage); RefPtr names; Identifier id; }; class ImportStatement : public StatementNode { public: ImportStatement(PackageNameNode *n) : name(n), wld(false) {} void enableWildcard() { wld = true; } void setAlias(const Identifier &a) { al = a; } virtual void generateExecCode(CompileState*); virtual void streamTo(SourceStream&) const; virtual void recurseVisit(NodeVisitor *visitor); private: virtual void processVarDecl (ExecState* state); RefPtr name; Identifier al; bool wld; }; } // namespace #endif // kate: indent-width 2; replace-tabs on; tab-width 4; space-indent on;