summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/JavaScriptCore/parser
diff options
context:
space:
mode:
authorAlexis Menard <alexis.menard@nokia.com>2009-04-17 10:40:52 (GMT)
committerAlexis Menard <alexis.menard@nokia.com>2009-04-17 10:40:52 (GMT)
commitbb2e4df9bee3148e819c98410aa36e22dad95d7a (patch)
treea6e6e8c070a72378d4b2e5f39ad3cc9c368b61ab /src/3rdparty/webkit/JavaScriptCore/parser
downloadQt-bb2e4df9bee3148e819c98410aa36e22dad95d7a.zip
Qt-bb2e4df9bee3148e819c98410aa36e22dad95d7a.tar.gz
Qt-bb2e4df9bee3148e819c98410aa36e22dad95d7a.tar.bz2
Initial import of kinetic-animations branch from the old kinetic
repository to the new repository
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/parser')
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y2084
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Keywords.table72
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp900
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h171
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/NodeInfo.h63
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp2721
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h2418
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Parser.cpp104
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/Parser.h123
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/ResultType.h159
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h91
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/parser/SourceProvider.h79
12 files changed, 8985 insertions, 0 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y b/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y
new file mode 100644
index 0000000..ae787f6
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y
@@ -0,0 +1,2084 @@
+%pure_parser
+
+%{
+
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * 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 Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include "JSValue.h"
+#include "JSObject.h"
+#include "Nodes.h"
+#include "Lexer.h"
+#include "JSString.h"
+#include "JSGlobalData.h"
+#include "CommonIdentifiers.h"
+#include "NodeInfo.h"
+#include "Parser.h"
+#include <wtf/MathExtras.h>
+
+#define YYMAXDEPTH 10000
+#define YYENABLE_NLS 0
+
+/* default values for bison */
+#define YYDEBUG 0 // Set to 1 to debug a parse error.
+#define jscyydebug 0 // Set to 1 to debug a parse error.
+#if !PLATFORM(DARWIN)
+ // avoid triggering warnings in older bison
+#define YYERROR_VERBOSE
+#endif
+
+int jscyylex(void* lvalp, void* llocp, void* globalPtr);
+int jscyyerror(const char*);
+static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
+
+#define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr)
+#define LEXER (GLOBAL_DATA->lexer)
+
+#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0)
+#define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot))
+#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line)
+
+using namespace JSC;
+using namespace std;
+
+static ExpressionNode* makeAssignNode(void*, ExpressionNode* loc, Operator, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end);
+static ExpressionNode* makePrefixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
+static ExpressionNode* makePostfixNode(void*, ExpressionNode* expr, Operator, int start, int divot, int end);
+static PropertyNode* makeGetterOrSetterPropertyNode(void*, const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
+static ExpressionNodeInfo makeFunctionCallNode(void*, ExpressionNodeInfo func, ArgumentsNodeInfo, int start, int divot, int end);
+static ExpressionNode* makeTypeOfNode(void*, ExpressionNode*);
+static ExpressionNode* makeDeleteNode(void*, ExpressionNode*, int start, int divot, int end);
+static ExpressionNode* makeNegateNode(void*, ExpressionNode*);
+static NumberNode* makeNumberNode(void*, double);
+static ExpressionNode* makeBitwiseNotNode(void*, ExpressionNode*);
+static ExpressionNode* makeMultNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeDivNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeAddNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeSubNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeLeftShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static ExpressionNode* makeRightShiftNode(void*, ExpressionNode*, ExpressionNode*, bool rightHasAssignments);
+static StatementNode* makeVarStatementNode(void*, ExpressionNode*);
+static ExpressionNode* combineVarInitializers(void*, ExpressionNode* list, AssignResolveNode* init);
+
+#if COMPILER(MSVC)
+
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4702)
+
+// At least some of the time, the declarations of malloc and free that bison
+// generates are causing warnings. A way to avoid this is to explicitly define
+// the macros so that bison doesn't try to declare malloc and free.
+#define YYMALLOC malloc
+#define YYFREE free
+
+#endif
+
+#define YYPARSE_PARAM globalPtr
+#define YYLEX_PARAM globalPtr
+
+template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls,
+ ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls,
+ CodeFeatures info,
+ int numConstants)
+{
+ ASSERT((info & ~AllFeatures) == 0);
+ NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info, numConstants};
+ return result;
+}
+
+template <typename T> NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants)
+{
+ ASSERT((info & ~AllFeatures) == 0);
+ NodeInfo<T> result = {node, info, numConstants};
+ return result;
+}
+
+template <typename T> T mergeDeclarationLists(T decls1, T decls2)
+{
+ // decls1 or both are null
+ if (!decls1)
+ return decls2;
+ // only decls1 is non-null
+ if (!decls2)
+ return decls1;
+
+ // Both are non-null
+ decls1->data.append(decls2->data);
+
+ // We manually release the declaration lists to avoid accumulating many many
+ // unused heap allocated vectors
+ decls2->ref();
+ decls2->deref();
+ return decls1;
+}
+
+static void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
+{
+ if (!varDecls)
+ varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+
+ varDecls->data.append(make_pair(ident, attrs));
+
+}
+
+static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
+{
+ unsigned attrs = DeclarationStacks::IsConstant;
+ if (decl->m_init)
+ attrs |= DeclarationStacks::HasInitializer;
+ appendToVarDeclarationList(globalPtr, varDecls, decl->m_ident, attrs);
+}
+
+%}
+
+%union {
+ int intValue;
+ double doubleValue;
+ Identifier* ident;
+
+ // expression subtrees
+ ExpressionNodeInfo expressionNode;
+ FuncDeclNodeInfo funcDeclNode;
+ PropertyNodeInfo propertyNode;
+ ArgumentsNodeInfo argumentsNode;
+ ConstDeclNodeInfo constDeclNode;
+ CaseBlockNodeInfo caseBlockNode;
+ CaseClauseNodeInfo caseClauseNode;
+ FuncExprNodeInfo funcExprNode;
+
+ // statement nodes
+ StatementNodeInfo statementNode;
+ FunctionBodyNode* functionBodyNode;
+ ProgramNode* programNode;
+
+ SourceElementsInfo sourceElements;
+ PropertyListInfo propertyList;
+ ArgumentListInfo argumentList;
+ VarDeclListInfo varDeclList;
+ ConstDeclListInfo constDeclList;
+ ClauseListInfo clauseList;
+ ElementListInfo elementList;
+ ParameterListInfo parameterList;
+
+ Operator op;
+}
+
+%start Program
+
+/* literals */
+%token NULLTOKEN TRUETOKEN FALSETOKEN
+
+/* keywords */
+%token BREAK CASE DEFAULT FOR NEW VAR CONSTTOKEN CONTINUE
+%token FUNCTION RETURN VOIDTOKEN DELETETOKEN
+%token IF THISTOKEN DO WHILE INTOKEN INSTANCEOF TYPEOF
+%token SWITCH WITH RESERVED
+%token THROW TRY CATCH FINALLY
+%token DEBUGGER
+
+/* give an if without an else higher precedence than an else to resolve the ambiguity */
+%nonassoc IF_WITHOUT_ELSE
+%nonassoc ELSE
+
+/* punctuators */
+%token EQEQ NE /* == and != */
+%token STREQ STRNEQ /* === and !== */
+%token LE GE /* < and > */
+%token OR AND /* || and && */
+%token PLUSPLUS MINUSMINUS /* ++ and -- */
+%token LSHIFT /* << */
+%token RSHIFT URSHIFT /* >> and >>> */
+%token PLUSEQUAL MINUSEQUAL /* += and -= */
+%token MULTEQUAL DIVEQUAL /* *= and /= */
+%token LSHIFTEQUAL /* <<= */
+%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
+%token ANDEQUAL MODEQUAL /* &= and %= */
+%token XOREQUAL OREQUAL /* ^= and |= */
+%token <intValue> OPENBRACE /* { (with char offset) */
+%token <intValue> CLOSEBRACE /* { (with char offset) */
+
+/* terminal types */
+%token <doubleValue> NUMBER
+%token <ident> IDENT STRING
+
+/* automatically inserted semicolon */
+%token AUTOPLUSPLUS AUTOMINUSMINUS
+
+/* non-terminal types */
+%type <expressionNode> Literal ArrayLiteral
+
+%type <expressionNode> PrimaryExpr PrimaryExprNoBrace
+%type <expressionNode> MemberExpr MemberExprNoBF /* BF => brace or function */
+%type <expressionNode> NewExpr NewExprNoBF
+%type <expressionNode> CallExpr CallExprNoBF
+%type <expressionNode> LeftHandSideExpr LeftHandSideExprNoBF
+%type <expressionNode> PostfixExpr PostfixExprNoBF
+%type <expressionNode> UnaryExpr UnaryExprNoBF UnaryExprCommon
+%type <expressionNode> MultiplicativeExpr MultiplicativeExprNoBF
+%type <expressionNode> AdditiveExpr AdditiveExprNoBF
+%type <expressionNode> ShiftExpr ShiftExprNoBF
+%type <expressionNode> RelationalExpr RelationalExprNoIn RelationalExprNoBF
+%type <expressionNode> EqualityExpr EqualityExprNoIn EqualityExprNoBF
+%type <expressionNode> BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
+%type <expressionNode> BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
+%type <expressionNode> BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
+%type <expressionNode> LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
+%type <expressionNode> LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
+%type <expressionNode> ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
+%type <expressionNode> AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
+%type <expressionNode> Expr ExprNoIn ExprNoBF
+
+%type <expressionNode> ExprOpt ExprNoInOpt
+
+%type <statementNode> Statement Block
+%type <statementNode> VariableStatement ConstStatement EmptyStatement ExprStatement
+%type <statementNode> IfStatement IterationStatement ContinueStatement
+%type <statementNode> BreakStatement ReturnStatement WithStatement
+%type <statementNode> SwitchStatement LabelledStatement
+%type <statementNode> ThrowStatement TryStatement
+%type <statementNode> DebuggerStatement
+
+%type <expressionNode> Initializer InitializerNoIn
+%type <statementNode> FunctionDeclaration
+%type <funcExprNode> FunctionExpr
+%type <functionBodyNode> FunctionBody
+%type <sourceElements> SourceElements
+%type <parameterList> FormalParameterList
+%type <op> AssignmentOperator
+%type <argumentsNode> Arguments
+%type <argumentList> ArgumentList
+%type <varDeclList> VariableDeclarationList VariableDeclarationListNoIn
+%type <constDeclList> ConstDeclarationList
+%type <constDeclNode> ConstDeclaration
+%type <caseBlockNode> CaseBlock
+%type <caseClauseNode> CaseClause DefaultClause
+%type <clauseList> CaseClauses CaseClausesOpt
+%type <intValue> Elision ElisionOpt
+%type <elementList> ElementList
+%type <propertyNode> Property
+%type <propertyList> PropertyList
+%%
+
+// FIXME: There are currently two versions of the grammar in this file, the normal one, and the NoNodes version used for
+// lazy recompilation of FunctionBodyNodes. We should move to generating the two versions from a script to avoid bugs.
+// In the mean time, make sure to make any changes to the grammar in both versions.
+
+Literal:
+ NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new NullNode(GLOBAL_DATA), 0, 1); }
+ | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, true), 0, 1); }
+ | FALSETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, false), 0, 1); }
+ | NUMBER { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); }
+ | STRING { $$ = createNodeInfo<ExpressionNode*>(new StringNode(GLOBAL_DATA, *$1), 0, 1); }
+ | '/' /* regexp */ {
+ Lexer& l = *LEXER;
+ if (!l.scanRegExp())
+ YYABORT;
+ RegExpNode* node = new RegExpNode(GLOBAL_DATA, l.pattern(), l.flags());
+ int size = l.pattern().size() + 2; // + 2 for the two /'s
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
+ $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
+ }
+ | DIVEQUAL /* regexp with /= */ {
+ Lexer& l = *LEXER;
+ if (!l.scanRegExp())
+ YYABORT;
+ RegExpNode* node = new RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags());
+ int size = l.pattern().size() + 2; // + 2 for the two /'s
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size);
+ $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
+ }
+;
+
+Property:
+ IDENT ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | STRING ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | NUMBER ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, Identifier(GLOBAL_DATA, UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
+ | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, 0, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); if (!$$.m_node) YYABORT; }
+ | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, $4.m_node.head, $7, LEXER->sourceCode($6, $8, @6.first_line)), $4.m_features | ClosureFeature, 0);
+ if ($4.m_features & ArgumentsFeature)
+ $7->setUsesArguments();
+ DBG($7, @6, @8);
+ if (!$$.m_node)
+ YYABORT;
+ }
+;
+
+PropertyList:
+ Property { $$.m_node.head = new PropertyListNode(GLOBAL_DATA, $1.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants; }
+ | PropertyList ',' Property { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new PropertyListNode(GLOBAL_DATA, $3.m_node, $1.m_node.tail);
+ $$.m_features = $1.m_features | $3.m_features;
+ $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
+;
+
+PrimaryExpr:
+ PrimaryExprNoBrace
+ | OPENBRACE CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA), 0, 0); }
+ | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+ /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
+ | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+;
+
+PrimaryExprNoBrace:
+ THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new ThisNode(GLOBAL_DATA), ThisFeature, 0); }
+ | Literal
+ | ArrayLiteral
+ | IDENT { $$ = createNodeInfo<ExpressionNode*>(new ResolveNode(GLOBAL_DATA, *$1, @1.first_column), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
+ | '(' Expr ')' { $$ = $2; }
+;
+
+ArrayLiteral:
+ '[' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); }
+ | '[' ElementList ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+ | '[' ElementList ',' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $4, $2.m_node.head), $2.m_features, $4 ? $2.m_numConstants + 1 : $2.m_numConstants); }
+;
+
+ElementList:
+ ElisionOpt AssignmentExpr { $$.m_node.head = new ElementNode(GLOBAL_DATA, $1, $2.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_features = $2.m_features;
+ $$.m_numConstants = $2.m_numConstants; }
+ | ElementList ',' ElisionOpt AssignmentExpr
+ { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new ElementNode(GLOBAL_DATA, $1.m_node.tail, $3, $4.m_node);
+ $$.m_features = $1.m_features | $4.m_features;
+ $$.m_numConstants = $1.m_numConstants + $4.m_numConstants; }
+;
+
+ElisionOpt:
+ /* nothing */ { $$ = 0; }
+ | Elision
+;
+
+Elision:
+ ',' { $$ = 1; }
+ | Elision ',' { $$ = $1 + 1; }
+;
+
+MemberExpr:
+ PrimaryExpr
+ | FunctionExpr { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); }
+ | MemberExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | MemberExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
+ }
+ | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
+ }
+;
+
+MemberExprNoBF:
+ PrimaryExprNoBrace
+ | MemberExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | MemberExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
+ }
+ | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
+ }
+;
+
+NewExpr:
+ MemberExpr
+ | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
+ }
+;
+
+NewExprNoBF:
+ MemberExprNoBF
+ | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
+ }
+;
+
+CallExpr:
+ MemberExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | CallExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); }
+;
+
+CallExprNoBF:
+ MemberExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
+ | CallExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants);
+ }
+ | CallExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
+ }
+;
+
+Arguments:
+ '(' ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA), 0, 0); }
+ | '(' ArgumentList ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
+;
+
+ArgumentList:
+ AssignmentExpr { $$.m_node.head = new ArgumentListNode(GLOBAL_DATA, $1.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants; }
+ | ArgumentList ',' AssignmentExpr { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new ArgumentListNode(GLOBAL_DATA, $1.m_node.tail, $3.m_node);
+ $$.m_features = $1.m_features | $3.m_features;
+ $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
+;
+
+LeftHandSideExpr:
+ NewExpr
+ | CallExpr
+;
+
+LeftHandSideExprNoBF:
+ NewExprNoBF
+ | CallExprNoBF
+;
+
+PostfixExpr:
+ LeftHandSideExpr
+ | LeftHandSideExpr PLUSPLUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+ | LeftHandSideExpr MINUSMINUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+;
+
+PostfixExprNoBF:
+ LeftHandSideExprNoBF
+ | LeftHandSideExprNoBF PLUSPLUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+ | LeftHandSideExprNoBF MINUSMINUS { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
+;
+
+UnaryExprCommon:
+ DELETETOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDeleteNode(GLOBAL_DATA, $2.m_node, @1.first_column, @2.last_column, @2.last_column), $2.m_features, $2.m_numConstants); }
+ | VOIDTOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new VoidNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants + 1); }
+ | TYPEOF UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeTypeOfNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | PLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | AUTOPLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | MINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | AUTOMINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
+ | '+' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new UnaryPlusNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | '-' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeNegateNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | '~' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeBitwiseNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+ | '!' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
+
+UnaryExpr:
+ PostfixExpr
+ | UnaryExprCommon
+;
+
+UnaryExprNoBF:
+ PostfixExprNoBF
+ | UnaryExprCommon
+;
+
+MultiplicativeExpr:
+ UnaryExpr
+ | MultiplicativeExpr '*' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExpr '/' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExpr '%' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+MultiplicativeExprNoBF:
+ UnaryExprNoBF
+ | MultiplicativeExprNoBF '*' UnaryExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExprNoBF '/' UnaryExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | MultiplicativeExprNoBF '%' UnaryExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+AdditiveExpr:
+ MultiplicativeExpr
+ | AdditiveExpr '+' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | AdditiveExpr '-' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+AdditiveExprNoBF:
+ MultiplicativeExprNoBF
+ | AdditiveExprNoBF '+' MultiplicativeExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | AdditiveExprNoBF '-' MultiplicativeExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ShiftExpr:
+ AdditiveExpr
+ | ShiftExpr LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExpr RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExpr URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ShiftExprNoBF:
+ AdditiveExprNoBF
+ | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+RelationalExpr:
+ ShiftExpr
+ | RelationalExpr '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExpr INTOKEN ShiftExpr { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+RelationalExprNoIn:
+ ShiftExpr
+ | RelationalExprNoIn '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoIn INSTANCEOF ShiftExpr
+ { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+RelationalExprNoBF:
+ ShiftExprNoBF
+ | RelationalExprNoBF '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF INSTANCEOF ShiftExpr
+ { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | RelationalExprNoBF INTOKEN ShiftExpr
+ { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column);
+ $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+EqualityExpr:
+ RelationalExpr
+ | EqualityExpr EQEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExpr NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExpr STREQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExpr STRNEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+EqualityExprNoIn:
+ RelationalExprNoIn
+ | EqualityExprNoIn EQEQ RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoIn NE RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoIn STREQ RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoIn STRNEQ RelationalExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+EqualityExprNoBF:
+ RelationalExprNoBF
+ | EqualityExprNoBF EQEQ RelationalExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoBF NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoBF STREQ RelationalExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+ | EqualityExprNoBF STRNEQ RelationalExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseANDExpr:
+ EqualityExpr
+ | BitwiseANDExpr '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseANDExprNoIn:
+ EqualityExprNoIn
+ | BitwiseANDExprNoIn '&' EqualityExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseANDExprNoBF:
+ EqualityExprNoBF
+ | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseXORExpr:
+ BitwiseANDExpr
+ | BitwiseXORExpr '^' BitwiseANDExpr { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseXORExprNoIn:
+ BitwiseANDExprNoIn
+ | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseXORExprNoBF:
+ BitwiseANDExprNoBF
+ | BitwiseXORExprNoBF '^' BitwiseANDExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseORExpr:
+ BitwiseXORExpr
+ | BitwiseORExpr '|' BitwiseXORExpr { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseORExprNoIn:
+ BitwiseXORExprNoIn
+ | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+BitwiseORExprNoBF:
+ BitwiseXORExprNoBF
+ | BitwiseORExprNoBF '|' BitwiseXORExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalANDExpr:
+ BitwiseORExpr
+ | LogicalANDExpr AND BitwiseORExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalANDExprNoIn:
+ BitwiseORExprNoIn
+ | LogicalANDExprNoIn AND BitwiseORExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalANDExprNoBF:
+ BitwiseORExprNoBF
+ | LogicalANDExprNoBF AND BitwiseORExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalORExpr:
+ LogicalANDExpr
+ | LogicalORExpr OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalORExprNoIn:
+ LogicalANDExprNoIn
+ | LogicalORExprNoIn OR LogicalANDExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+LogicalORExprNoBF:
+ LogicalANDExprNoBF
+ | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ConditionalExpr:
+ LogicalORExpr
+ | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
+;
+
+ConditionalExprNoIn:
+ LogicalORExprNoIn
+ | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
+;
+
+ConditionalExprNoBF:
+ LogicalORExprNoBF
+ | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
+;
+
+AssignmentExpr:
+ ConditionalExpr
+ | LeftHandSideExpr AssignmentOperator AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
+ @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
+ }
+;
+
+AssignmentExprNoIn:
+ ConditionalExprNoIn
+ | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
+ { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
+ @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
+ }
+;
+
+AssignmentExprNoBF:
+ ConditionalExprNoBF
+ | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
+ { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
+ @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
+ }
+;
+
+AssignmentOperator:
+ '=' { $$ = OpEqual; }
+ | PLUSEQUAL { $$ = OpPlusEq; }
+ | MINUSEQUAL { $$ = OpMinusEq; }
+ | MULTEQUAL { $$ = OpMultEq; }
+ | DIVEQUAL { $$ = OpDivEq; }
+ | LSHIFTEQUAL { $$ = OpLShift; }
+ | RSHIFTEQUAL { $$ = OpRShift; }
+ | URSHIFTEQUAL { $$ = OpURShift; }
+ | ANDEQUAL { $$ = OpAndEq; }
+ | XOREQUAL { $$ = OpXOrEq; }
+ | OREQUAL { $$ = OpOrEq; }
+ | MODEQUAL { $$ = OpModEq; }
+;
+
+Expr:
+ AssignmentExpr
+ | Expr ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ExprNoIn:
+ AssignmentExprNoIn
+ | ExprNoIn ',' AssignmentExprNoIn { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+ExprNoBF:
+ AssignmentExprNoBF
+ | ExprNoBF ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
+;
+
+Statement:
+ Block
+ | VariableStatement
+ | ConstStatement
+ | FunctionDeclaration
+ | EmptyStatement
+ | ExprStatement
+ | IfStatement
+ | IterationStatement
+ | ContinueStatement
+ | BreakStatement
+ | ReturnStatement
+ | WithStatement
+ | SwitchStatement
+ | LabelledStatement
+ | ThrowStatement
+ | TryStatement
+ | DebuggerStatement
+;
+
+Block:
+ OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); }
+ | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+;
+
+VariableStatement:
+ VAR VariableDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+ | VAR VariableDeclarationList error { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @2);
+ AUTO_SEMICOLON; }
+;
+
+VariableDeclarationList:
+ IDENT { $$.m_node = 0;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
+ $$.m_numConstants = 0;
+ }
+ | IDENT Initializer { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
+ $$.m_node = node;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
+ $$.m_numConstants = $2.m_numConstants;
+ }
+ | VariableDeclarationList ',' IDENT
+ { $$.m_node = $1.m_node;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | VariableDeclarationList ',' IDENT Initializer
+ { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
+ $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node);
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
+ $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
+ }
+;
+
+VariableDeclarationListNoIn:
+ IDENT { $$.m_node = 0;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
+ $$.m_numConstants = 0;
+ }
+ | IDENT InitializerNoIn { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column);
+ $$.m_node = node;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
+ $$.m_numConstants = $2.m_numConstants;
+ }
+ | VariableDeclarationListNoIn ',' IDENT
+ { $$.m_node = $1.m_node;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
+ { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
+ SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column);
+ $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node);
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
+ $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
+ }
+;
+
+ConstStatement:
+ CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+ | CONSTTOKEN ConstDeclarationList error
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
+ DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+ConstDeclarationList:
+ ConstDeclaration { $$.m_node.head = $1.m_node;
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA);
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $1.m_node);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | ConstDeclarationList ',' ConstDeclaration
+ { $$.m_node.head = $1.m_node.head;
+ $1.m_node.tail->m_next = $3.m_node;
+ $$.m_node.tail = $3.m_node;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $3.m_node);
+ $$.m_funcDeclarations = 0;
+ $$.m_features = $1.m_features | $3.m_features;
+ $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
+;
+
+ConstDeclaration:
+ IDENT { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
+ | IDENT Initializer { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); }
+;
+
+Initializer:
+ '=' AssignmentExpr { $$ = $2; }
+;
+
+InitializerNoIn:
+ '=' AssignmentExprNoIn { $$ = $2; }
+;
+
+EmptyStatement:
+ ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); }
+;
+
+ExprStatement:
+ ExprNoBF ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+ | ExprNoBF error { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
+ DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+;
+
+IfStatement:
+ IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+ | IF '(' Expr ')' Statement ELSE Statement
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node),
+ mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations),
+ $3.m_features | $5.m_features | $7.m_features,
+ $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+;
+
+IterationStatement:
+ DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @3); }
+ | DO Statement WHILE '(' Expr ')' error { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
+ | WHILE '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+ | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations,
+ $3.m_features | $5.m_features | $7.m_features | $9.m_features,
+ $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
+ DBG($$.m_node, @1, @8);
+ }
+ | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true),
+ mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations),
+ mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations),
+ $4.m_features | $6.m_features | $8.m_features | $10.m_features,
+ $4.m_numConstants + $6.m_numConstants + $8.m_numConstants + $10.m_numConstants);
+ DBG($$.m_node, @1, @9); }
+ | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
+ {
+ ForInNode* node = new ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node);
+ SET_EXCEPTION_LOCATION(node, @3.first_column, @3.last_column, @5.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations,
+ $3.m_features | $5.m_features | $7.m_features,
+ $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
+ DBG($$.m_node, @1, @6);
+ }
+ | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
+ { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column);
+ SET_EXCEPTION_LOCATION(forIn, @4.first_column, @5.first_column + 1, @6.last_column);
+ appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
+ $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants);
+ DBG($$.m_node, @1, @7); }
+ | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
+ { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column);
+ SET_EXCEPTION_LOCATION(forIn, @4.first_column, @6.first_column + 1, @7.last_column);
+ appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
+ $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations,
+ ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $5.m_features | $7.m_features | $9.m_features,
+ $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
+ DBG($$.m_node, @1, @8); }
+;
+
+ExprOpt:
+ /* nothing */ { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
+ | Expr
+;
+
+ExprNoInOpt:
+ /* nothing */ { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
+ | ExprNoIn
+;
+
+ContinueStatement:
+ CONTINUE ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); }
+ | CONTINUE error { ContinueNode* node = new ContinueNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | CONTINUE IDENT ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @3); }
+ | CONTINUE IDENT error { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+BreakStatement:
+ BREAK ';' { BreakNode* node = new BreakNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
+ | BREAK error { BreakNode* node = new BreakNode(GLOBAL_DATA);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | BREAK IDENT ';' { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @3); }
+ | BREAK IDENT error { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+ReturnStatement:
+ RETURN ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); }
+ | RETURN error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+ | RETURN Expr ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); }
+ | RETURN Expr error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; }
+;
+
+WithStatement:
+ WITH '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column),
+ $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+;
+
+SwitchStatement:
+ SWITCH '(' Expr ')' CaseBlock { $$ = createNodeDeclarationInfo<StatementNode*>(new SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations,
+ $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
+ DBG($$.m_node, @1, @4); }
+;
+
+CaseBlock:
+ OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); }
+ | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE
+ { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, $3.m_node, $4.m_node.head),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations),
+ $2.m_features | $3.m_features | $4.m_features,
+ $2.m_numConstants + $3.m_numConstants + $4.m_numConstants); }
+;
+
+CaseClausesOpt:
+/* nothing */ { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; $$.m_features = 0; $$.m_numConstants = 0; }
+ | CaseClauses
+;
+
+CaseClauses:
+ CaseClause { $$.m_node.head = new ClauseListNode(GLOBAL_DATA, $1.m_node);
+ $$.m_node.tail = $$.m_node.head;
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ $$.m_funcDeclarations = $1.m_funcDeclarations;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants; }
+ | CaseClauses CaseClause { $$.m_node.head = $1.m_node.head;
+ $$.m_node.tail = new ClauseListNode(GLOBAL_DATA, $1.m_node.tail, $2.m_node);
+ $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
+ $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
+ $$.m_features = $1.m_features | $2.m_features;
+ $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
+ }
+;
+
+CaseClause:
+ CASE Expr ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); }
+ | CASE Expr ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations, $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); }
+;
+
+DefaultClause:
+ DEFAULT ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); }
+ | DEFAULT ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
+;
+
+LabelledStatement:
+ IDENT ':' Statement { LabelNode* node = new LabelNode(GLOBAL_DATA, *$1, $3.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
+;
+
+ThrowStatement:
+ THROW Expr ';' { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2);
+ }
+ | THROW Expr error { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node);
+ SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column);
+ $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON;
+ }
+;
+
+TryStatement:
+ TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node),
+ mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations),
+ mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations),
+ $2.m_features | $4.m_features,
+ $2.m_numConstants + $4.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+ | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0),
+ mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
+ mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations),
+ $2.m_features | $7.m_features | CatchFeature,
+ $2.m_numConstants + $7.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+ | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
+ { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
+ mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations),
+ $2.m_features | $7.m_features | $9.m_features | CatchFeature,
+ $2.m_numConstants + $7.m_numConstants + $9.m_numConstants);
+ DBG($$.m_node, @1, @2); }
+;
+
+DebuggerStatement:
+ DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
+ DBG($$.m_node, @1, @2); }
+ | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
+ DBG($$.m_node, @1, @1); AUTO_SEMICOLON; }
+;
+
+FunctionDeclaration:
+ FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); }
+ | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0);
+ if ($4.m_features & ArgumentsFeature)
+ $7->setUsesArguments();
+ DBG($7, @6, @8);
+ $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node));
+ }
+;
+
+FunctionExpr:
+ FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, LEXER->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); DBG($5, @4, @6); }
+ | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, LEXER->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0);
+ if ($3.m_features & ArgumentsFeature)
+ $6->setUsesArguments();
+ DBG($6, @5, @7);
+ }
+ | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ {
+ $$ = createNodeInfo(new FuncExprNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), $4.m_features | ClosureFeature, 0);
+ if ($4.m_features & ArgumentsFeature)
+ $7->setUsesArguments();
+ DBG($7, @6, @8);
+ }
+;
+
+FormalParameterList:
+ IDENT { $$.m_node.head = new ParameterNode(GLOBAL_DATA, *$1);
+ $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
+ $$.m_node.tail = $$.m_node.head; }
+ | FormalParameterList ',' IDENT { $$.m_node.head = $1.m_node.head;
+ $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
+ $$.m_node.tail = new ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3); }
+;
+
+FunctionBody:
+ /* not in spec */ { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
+ | SourceElements_NoNode { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
+;
+
+Program:
+ /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); }
+ | SourceElements { GLOBAL_DATA->parser->didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, $1.m_features,
+ @1.last_line, $1.m_numConstants); }
+;
+
+SourceElements:
+ Statement { $$.m_node = new SourceElements(GLOBAL_DATA);
+ $$.m_node->append($1.m_node);
+ $$.m_varDeclarations = $1.m_varDeclarations;
+ $$.m_funcDeclarations = $1.m_funcDeclarations;
+ $$.m_features = $1.m_features;
+ $$.m_numConstants = $1.m_numConstants;
+ }
+ | SourceElements Statement { $$.m_node->append($2.m_node);
+ $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
+ $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
+ $$.m_features = $1.m_features | $2.m_features;
+ $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
+ }
+;
+
+// Start NoNodes
+
+Literal_NoNode:
+ NULLTOKEN
+ | TRUETOKEN
+ | FALSETOKEN
+ | NUMBER { }
+ | STRING { }
+ | '/' /* regexp */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+ | DIVEQUAL /* regexp with /= */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; }
+;
+
+Property_NoNode:
+ IDENT ':' AssignmentExpr_NoNode { }
+ | STRING ':' AssignmentExpr_NoNode { }
+ | NUMBER ':' AssignmentExpr_NoNode { }
+ | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
+ | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
+;
+
+PropertyList_NoNode:
+ Property_NoNode
+ | PropertyList_NoNode ',' Property_NoNode
+;
+
+PrimaryExpr_NoNode:
+ PrimaryExprNoBrace_NoNode
+ | OPENBRACE CLOSEBRACE { }
+ | OPENBRACE PropertyList_NoNode CLOSEBRACE { }
+ /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
+ | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE { }
+;
+
+PrimaryExprNoBrace_NoNode:
+ THISTOKEN
+ | Literal_NoNode
+ | ArrayLiteral_NoNode
+ | IDENT { }
+ | '(' Expr_NoNode ')'
+;
+
+ArrayLiteral_NoNode:
+ '[' ElisionOpt_NoNode ']'
+ | '[' ElementList_NoNode ']'
+ | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']'
+;
+
+ElementList_NoNode:
+ ElisionOpt_NoNode AssignmentExpr_NoNode
+ | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode
+;
+
+ElisionOpt_NoNode:
+ /* nothing */
+ | Elision_NoNode
+;
+
+Elision_NoNode:
+ ','
+ | Elision_NoNode ','
+;
+
+MemberExpr_NoNode:
+ PrimaryExpr_NoNode
+ | FunctionExpr_NoNode
+ | MemberExpr_NoNode '[' Expr_NoNode ']'
+ | MemberExpr_NoNode '.' IDENT
+ | NEW MemberExpr_NoNode Arguments_NoNode
+;
+
+MemberExprNoBF_NoNode:
+ PrimaryExprNoBrace_NoNode
+ | MemberExprNoBF_NoNode '[' Expr_NoNode ']'
+ | MemberExprNoBF_NoNode '.' IDENT
+ | NEW MemberExpr_NoNode Arguments_NoNode
+;
+
+NewExpr_NoNode:
+ MemberExpr_NoNode
+ | NEW NewExpr_NoNode
+;
+
+NewExprNoBF_NoNode:
+ MemberExprNoBF_NoNode
+ | NEW NewExpr_NoNode
+;
+
+CallExpr_NoNode:
+ MemberExpr_NoNode Arguments_NoNode
+ | CallExpr_NoNode Arguments_NoNode
+ | CallExpr_NoNode '[' Expr_NoNode ']'
+ | CallExpr_NoNode '.' IDENT
+;
+
+CallExprNoBF_NoNode:
+ MemberExprNoBF_NoNode Arguments_NoNode
+ | CallExprNoBF_NoNode Arguments_NoNode
+ | CallExprNoBF_NoNode '[' Expr_NoNode ']'
+ | CallExprNoBF_NoNode '.' IDENT
+;
+
+Arguments_NoNode:
+ '(' ')'
+ | '(' ArgumentList_NoNode ')'
+;
+
+ArgumentList_NoNode:
+ AssignmentExpr_NoNode
+ | ArgumentList_NoNode ',' AssignmentExpr_NoNode
+;
+
+LeftHandSideExpr_NoNode:
+ NewExpr_NoNode
+ | CallExpr_NoNode
+;
+
+LeftHandSideExprNoBF_NoNode:
+ NewExprNoBF_NoNode
+ | CallExprNoBF_NoNode
+;
+
+PostfixExpr_NoNode:
+ LeftHandSideExpr_NoNode
+ | LeftHandSideExpr_NoNode PLUSPLUS
+ | LeftHandSideExpr_NoNode MINUSMINUS
+;
+
+PostfixExprNoBF_NoNode:
+ LeftHandSideExprNoBF_NoNode
+ | LeftHandSideExprNoBF_NoNode PLUSPLUS
+ | LeftHandSideExprNoBF_NoNode MINUSMINUS
+;
+
+UnaryExprCommon_NoNode:
+ DELETETOKEN UnaryExpr_NoNode
+ | VOIDTOKEN UnaryExpr_NoNode
+ | TYPEOF UnaryExpr_NoNode
+ | PLUSPLUS UnaryExpr_NoNode
+ | AUTOPLUSPLUS UnaryExpr_NoNode
+ | MINUSMINUS UnaryExpr_NoNode
+ | AUTOMINUSMINUS UnaryExpr_NoNode
+ | '+' UnaryExpr_NoNode
+ | '-' UnaryExpr_NoNode
+ | '~' UnaryExpr_NoNode
+ | '!' UnaryExpr_NoNode
+
+UnaryExpr_NoNode:
+ PostfixExpr_NoNode
+ | UnaryExprCommon_NoNode
+;
+
+UnaryExprNoBF_NoNode:
+ PostfixExprNoBF_NoNode
+ | UnaryExprCommon_NoNode
+;
+
+MultiplicativeExpr_NoNode:
+ UnaryExpr_NoNode
+ | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode
+ | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode
+ | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode
+;
+
+MultiplicativeExprNoBF_NoNode:
+ UnaryExprNoBF_NoNode
+ | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode
+ | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode
+ | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode
+;
+
+AdditiveExpr_NoNode:
+ MultiplicativeExpr_NoNode
+ | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode
+ | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode
+;
+
+AdditiveExprNoBF_NoNode:
+ MultiplicativeExprNoBF_NoNode
+ | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode
+ | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode
+;
+
+ShiftExpr_NoNode:
+ AdditiveExpr_NoNode
+ | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode
+ | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode
+ | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode
+;
+
+ShiftExprNoBF_NoNode:
+ AdditiveExprNoBF_NoNode
+ | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode
+ | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode
+ | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode
+;
+
+RelationalExpr_NoNode:
+ ShiftExpr_NoNode
+ | RelationalExpr_NoNode '<' ShiftExpr_NoNode
+ | RelationalExpr_NoNode '>' ShiftExpr_NoNode
+ | RelationalExpr_NoNode LE ShiftExpr_NoNode
+ | RelationalExpr_NoNode GE ShiftExpr_NoNode
+ | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode
+ | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode
+;
+
+RelationalExprNoIn_NoNode:
+ ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode '<' ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode '>' ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode
+ | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode
+;
+
+RelationalExprNoBF_NoNode:
+ ShiftExprNoBF_NoNode
+ | RelationalExprNoBF_NoNode '<' ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode '>' ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode
+ | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode
+;
+
+EqualityExpr_NoNode:
+ RelationalExpr_NoNode
+ | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode
+ | EqualityExpr_NoNode NE RelationalExpr_NoNode
+ | EqualityExpr_NoNode STREQ RelationalExpr_NoNode
+ | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode
+;
+
+EqualityExprNoIn_NoNode:
+ RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode
+ | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode
+;
+
+EqualityExprNoBF_NoNode:
+ RelationalExprNoBF_NoNode
+ | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode
+ | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode
+ | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode
+ | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode
+;
+
+BitwiseANDExpr_NoNode:
+ EqualityExpr_NoNode
+ | BitwiseANDExpr_NoNode '&' EqualityExpr_NoNode
+;
+
+BitwiseANDExprNoIn_NoNode:
+ EqualityExprNoIn_NoNode
+ | BitwiseANDExprNoIn_NoNode '&' EqualityExprNoIn_NoNode
+;
+
+BitwiseANDExprNoBF_NoNode:
+ EqualityExprNoBF_NoNode
+ | BitwiseANDExprNoBF_NoNode '&' EqualityExpr_NoNode
+;
+
+BitwiseXORExpr_NoNode:
+ BitwiseANDExpr_NoNode
+ | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode
+;
+
+BitwiseXORExprNoIn_NoNode:
+ BitwiseANDExprNoIn_NoNode
+ | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode
+;
+
+BitwiseXORExprNoBF_NoNode:
+ BitwiseANDExprNoBF_NoNode
+ | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode
+;
+
+BitwiseORExpr_NoNode:
+ BitwiseXORExpr_NoNode
+ | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode
+;
+
+BitwiseORExprNoIn_NoNode:
+ BitwiseXORExprNoIn_NoNode
+ | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode
+;
+
+BitwiseORExprNoBF_NoNode:
+ BitwiseXORExprNoBF_NoNode
+ | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode
+;
+
+LogicalANDExpr_NoNode:
+ BitwiseORExpr_NoNode
+ | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode
+;
+
+LogicalANDExprNoIn_NoNode:
+ BitwiseORExprNoIn_NoNode
+ | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode
+;
+
+LogicalANDExprNoBF_NoNode:
+ BitwiseORExprNoBF_NoNode
+ | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode
+;
+
+LogicalORExpr_NoNode:
+ LogicalANDExpr_NoNode
+ | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode
+;
+
+LogicalORExprNoIn_NoNode:
+ LogicalANDExprNoIn_NoNode
+ | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode
+;
+
+LogicalORExprNoBF_NoNode:
+ LogicalANDExprNoBF_NoNode
+ | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode
+;
+
+ConditionalExpr_NoNode:
+ LogicalORExpr_NoNode
+ | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
+;
+
+ConditionalExprNoIn_NoNode:
+ LogicalORExprNoIn_NoNode
+ | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode
+;
+
+ConditionalExprNoBF_NoNode:
+ LogicalORExprNoBF_NoNode
+ | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
+;
+
+AssignmentExpr_NoNode:
+ ConditionalExpr_NoNode
+ | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
+;
+
+AssignmentExprNoIn_NoNode:
+ ConditionalExprNoIn_NoNode
+ | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode
+;
+
+AssignmentExprNoBF_NoNode:
+ ConditionalExprNoBF_NoNode
+ | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
+;
+
+AssignmentOperator_NoNode:
+ '='
+ | PLUSEQUAL
+ | MINUSEQUAL
+ | MULTEQUAL
+ | DIVEQUAL
+ | LSHIFTEQUAL
+ | RSHIFTEQUAL
+ | URSHIFTEQUAL
+ | ANDEQUAL
+ | XOREQUAL
+ | OREQUAL
+ | MODEQUAL
+;
+
+Expr_NoNode:
+ AssignmentExpr_NoNode
+ | Expr_NoNode ',' AssignmentExpr_NoNode
+;
+
+ExprNoIn_NoNode:
+ AssignmentExprNoIn_NoNode
+ | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode
+;
+
+ExprNoBF_NoNode:
+ AssignmentExprNoBF_NoNode
+ | ExprNoBF_NoNode ',' AssignmentExpr_NoNode
+;
+
+Statement_NoNode:
+ Block_NoNode
+ | VariableStatement_NoNode
+ | ConstStatement_NoNode
+ | FunctionDeclaration_NoNode
+ | EmptyStatement_NoNode
+ | ExprStatement_NoNode
+ | IfStatement_NoNode
+ | IterationStatement_NoNode
+ | ContinueStatement_NoNode
+ | BreakStatement_NoNode
+ | ReturnStatement_NoNode
+ | WithStatement_NoNode
+ | SwitchStatement_NoNode
+ | LabelledStatement_NoNode
+ | ThrowStatement_NoNode
+ | TryStatement_NoNode
+ | DebuggerStatement_NoNode
+;
+
+Block_NoNode:
+ OPENBRACE CLOSEBRACE { }
+ | OPENBRACE SourceElements_NoNode CLOSEBRACE { }
+;
+
+VariableStatement_NoNode:
+ VAR VariableDeclarationList_NoNode ';'
+ | VAR VariableDeclarationList_NoNode error { AUTO_SEMICOLON; }
+;
+
+VariableDeclarationList_NoNode:
+ IDENT { }
+ | IDENT Initializer_NoNode { }
+ | VariableDeclarationList_NoNode ',' IDENT
+ | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode
+;
+
+VariableDeclarationListNoIn_NoNode:
+ IDENT { }
+ | IDENT InitializerNoIn_NoNode { }
+ | VariableDeclarationListNoIn_NoNode ',' IDENT
+ | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode
+;
+
+ConstStatement_NoNode:
+ CONSTTOKEN ConstDeclarationList_NoNode ';'
+ | CONSTTOKEN ConstDeclarationList_NoNode error { AUTO_SEMICOLON; }
+;
+
+ConstDeclarationList_NoNode:
+ ConstDeclaration_NoNode
+ | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode
+;
+
+ConstDeclaration_NoNode:
+ IDENT { }
+ | IDENT Initializer_NoNode { }
+;
+
+Initializer_NoNode:
+ '=' AssignmentExpr_NoNode
+;
+
+InitializerNoIn_NoNode:
+ '=' AssignmentExprNoIn_NoNode
+;
+
+EmptyStatement_NoNode:
+ ';'
+;
+
+ExprStatement_NoNode:
+ ExprNoBF_NoNode ';'
+ | ExprNoBF_NoNode error { AUTO_SEMICOLON; }
+;
+
+IfStatement_NoNode:
+ IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE
+ | IF '(' Expr_NoNode ')' Statement_NoNode ELSE Statement_NoNode
+;
+
+IterationStatement_NoNode:
+ DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';'
+ | DO Statement_NoNode WHILE '(' Expr_NoNode ')' error // Always performs automatic semicolon insertion
+ | WHILE '(' Expr_NoNode ')' Statement_NoNode
+ | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
+ | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
+ | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
+ | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode
+ | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
+;
+
+ExprOpt_NoNode:
+ /* nothing */
+ | Expr_NoNode
+;
+
+ExprNoInOpt_NoNode:
+ /* nothing */
+ | ExprNoIn_NoNode
+;
+
+ContinueStatement_NoNode:
+ CONTINUE ';'
+ | CONTINUE error { AUTO_SEMICOLON; }
+ | CONTINUE IDENT ';'
+ | CONTINUE IDENT error { AUTO_SEMICOLON; }
+;
+
+BreakStatement_NoNode:
+ BREAK ';'
+ | BREAK error { AUTO_SEMICOLON; }
+ | BREAK IDENT ';'
+ | BREAK IDENT error { AUTO_SEMICOLON; }
+;
+
+ReturnStatement_NoNode:
+ RETURN ';'
+ | RETURN error { AUTO_SEMICOLON; }
+ | RETURN Expr_NoNode ';'
+ | RETURN Expr_NoNode error { AUTO_SEMICOLON; }
+;
+
+WithStatement_NoNode:
+ WITH '(' Expr_NoNode ')' Statement_NoNode
+;
+
+SwitchStatement_NoNode:
+ SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode
+;
+
+CaseBlock_NoNode:
+ OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE { }
+ | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE { }
+;
+
+CaseClausesOpt_NoNode:
+ /* nothing */
+ | CaseClauses_NoNode
+;
+
+CaseClauses_NoNode:
+ CaseClause_NoNode
+ | CaseClauses_NoNode CaseClause_NoNode
+;
+
+CaseClause_NoNode:
+ CASE Expr_NoNode ':'
+ | CASE Expr_NoNode ':' SourceElements_NoNode
+;
+
+DefaultClause_NoNode:
+ DEFAULT ':'
+ | DEFAULT ':' SourceElements_NoNode
+;
+
+LabelledStatement_NoNode:
+ IDENT ':' Statement_NoNode { }
+;
+
+ThrowStatement_NoNode:
+ THROW Expr_NoNode ';'
+ | THROW Expr_NoNode error { AUTO_SEMICOLON; }
+;
+
+TryStatement_NoNode:
+ TRY Block_NoNode FINALLY Block_NoNode
+ | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode
+ | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode
+;
+
+DebuggerStatement_NoNode:
+ DEBUGGER ';'
+ | DEBUGGER error { AUTO_SEMICOLON; }
+;
+
+FunctionDeclaration_NoNode:
+ FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+;
+
+FunctionExpr_NoNode:
+ FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+ | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
+;
+
+FormalParameterList_NoNode:
+ IDENT { }
+ | FormalParameterList_NoNode ',' IDENT
+;
+
+FunctionBody_NoNode:
+ /* not in spec */
+ | SourceElements_NoNode
+;
+
+SourceElements_NoNode:
+ Statement_NoNode
+ | SourceElements_NoNode Statement_NoNode
+;
+
+// End NoNodes
+
+%%
+
+static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
+{
+ if (!loc->isLocation())
+ return new AssignErrorNode(GLOBAL_DATA, loc, op, expr, divot, divot - start, end - divot);
+
+ if (loc->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(loc);
+ if (op == OpEqual) {
+ AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, resolve->identifier(), expr, exprHasAssignments);
+ SET_EXCEPTION_LOCATION(node, start, divot, end);
+ return node;
+ } else
+ return new ReadModifyResolveNode(GLOBAL_DATA, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+ }
+ if (loc->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
+ if (op == OpEqual)
+ return new AssignBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
+ else {
+ ReadModifyBracketNode* node = new ReadModifyBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return node;
+ }
+ }
+ ASSERT(loc->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
+ if (op == OpEqual)
+ return new AssignDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+
+ ReadModifyDotNode* node = new ReadModifyDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+static ExpressionNode* makePrefixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new PrefixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
+
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new PrefixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ PrefixBracketNode* node = new PrefixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
+ return node;
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ PrefixDotNode* node = new PrefixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->startOffset());
+ return node;
+}
+
+static ExpressionNode* makePostfixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new PostfixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot);
+
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new PostfixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ PostfixBracketNode* node = new PostfixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return node;
+
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ PostfixDotNode* node = new PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return node;
+}
+
+static ExpressionNodeInfo makeFunctionCallNode(void* globalPtr, ExpressionNodeInfo func, ArgumentsNodeInfo args, int start, int divot, int end)
+{
+ CodeFeatures features = func.m_features | args.m_features;
+ int numConstants = func.m_numConstants + args.m_numConstants;
+ if (!func.m_node->isLocation())
+ return createNodeInfo<ExpressionNode*>(new FunctionCallValueNode(GLOBAL_DATA, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants);
+ if (func.m_node->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node);
+ const Identifier& identifier = resolve->identifier();
+ if (identifier == GLOBAL_DATA->propertyNames->eval)
+ return createNodeInfo<ExpressionNode*>(new EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
+ return createNodeInfo<ExpressionNode*>(new FunctionCallResolveNode(GLOBAL_DATA, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants);
+ }
+ if (func.m_node->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node);
+ FunctionCallBracketNode* node = new FunctionCallBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+ return createNodeInfo<ExpressionNode*>(node, features, numConstants);
+ }
+ ASSERT(func.m_node->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node);
+ FunctionCallDotNode* node = new FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
+ node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+ return createNodeInfo<ExpressionNode*>(node, features, numConstants);
+}
+
+static ExpressionNode* makeTypeOfNode(void* globalPtr, ExpressionNode* expr)
+{
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new TypeOfResolveNode(GLOBAL_DATA, resolve->identifier());
+ }
+ return new TypeOfValueNode(GLOBAL_DATA, expr);
+}
+
+static ExpressionNode* makeDeleteNode(void* globalPtr, ExpressionNode* expr, int start, int divot, int end)
+{
+ if (!expr->isLocation())
+ return new DeleteValueNode(GLOBAL_DATA, expr);
+ if (expr->isResolveNode()) {
+ ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+ return new DeleteResolveNode(GLOBAL_DATA, resolve->identifier(), divot, divot - start, end - divot);
+ }
+ if (expr->isBracketAccessorNode()) {
+ BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+ return new DeleteBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
+ }
+ ASSERT(expr->isDotAccessorNode());
+ DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+ return new DeleteDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), divot, divot - start, end - divot);
+}
+
+static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
+{
+ PropertyNode::Type type;
+ if (getOrSet == "get")
+ type = PropertyNode::Getter;
+ else if (getOrSet == "set")
+ type = PropertyNode::Setter;
+ else
+ return 0;
+ return new PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type);
+}
+
+static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n)
+{
+ if (n->isNumber()) {
+ NumberNode* number = static_cast<NumberNode*>(n);
+
+ if (number->value() > 0.0) {
+ number->setValue(-number->value());
+ return number;
+ }
+ }
+
+ return new NegateNode(GLOBAL_DATA, n);
+}
+
+static NumberNode* makeNumberNode(void* globalPtr, double d)
+{
+ return new NumberNode(GLOBAL_DATA, d);
+}
+
+static ExpressionNode* makeBitwiseNotNode(void* globalPtr, ExpressionNode* expr)
+{
+ if (expr->isNumber())
+ return makeNumberNode(globalPtr, ~toInt32(static_cast<NumberNode*>(expr)->value()));
+ return new BitwiseNotNode(GLOBAL_DATA, expr);
+}
+
+static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
+
+ if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
+ return new UnaryPlusNode(GLOBAL_DATA, expr2);
+
+ if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
+ return new UnaryPlusNode(GLOBAL_DATA, expr1);
+
+ return new MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeDivNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
+ return new DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeAddNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
+ return new AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeSubNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ expr1 = expr1->stripUnaryPlus();
+ expr2 = expr2->stripUnaryPlus();
+
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
+ return new SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeLeftShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+ return new LeftShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+static ExpressionNode* makeRightShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+ if (expr1->isNumber() && expr2->isNumber())
+ return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+ return new RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments);
+}
+
+/* called by yyparse on error */
+int yyerror(const char *)
+{
+ return 1;
+}
+
+/* may we automatically insert a semicolon ? */
+static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
+{
+ return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
+}
+
+static ExpressionNode* combineVarInitializers(void* globalPtr, ExpressionNode* list, AssignResolveNode* init)
+{
+ if (!list)
+ return init;
+ return new VarDeclCommaNode(GLOBAL_DATA, list, init);
+}
+
+// We turn variable declarations into either assignments or empty
+// statements (which later get stripped out), because the actual
+// declaration work is hoisted up to the start of the function body
+static StatementNode* makeVarStatementNode(void* globalPtr, ExpressionNode* expr)
+{
+ if (!expr)
+ return new EmptyStatementNode(GLOBAL_DATA);
+ return new VarStatementNode(GLOBAL_DATA, expr);
+}
+
+#undef GLOBAL_DATA
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Keywords.table b/src/3rdparty/webkit/JavaScriptCore/parser/Keywords.table
new file mode 100644
index 0000000..490c1cc
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Keywords.table
@@ -0,0 +1,72 @@
+# main keywords
+@begin mainTable 41
+
+# types
+null NULLTOKEN
+true TRUETOKEN
+false FALSETOKEN
+
+# keywords
+break BREAK
+case CASE
+catch CATCH
+const CONSTTOKEN
+default DEFAULT
+finally FINALLY
+for FOR
+instanceof INSTANCEOF
+new NEW
+var VAR
+continue CONTINUE
+function FUNCTION
+return RETURN
+void VOIDTOKEN
+delete DELETETOKEN
+if IF
+this THISTOKEN
+do DO
+while WHILE
+else ELSE
+in INTOKEN
+switch SWITCH
+throw THROW
+try TRY
+typeof TYPEOF
+with WITH
+debugger DEBUGGER
+
+# reserved for future use
+class RESERVED
+enum RESERVED
+export RESERVED
+extends RESERVED
+import RESERVED
+super RESERVED
+
+# these words are reserved for future use in the ECMA spec, but not in WinIE
+# (see http://bugs.webkit.org/show_bug.cgi?id=6179)
+# abstract RESERVED
+# boolean RESERVED
+# byte RESERVED
+# char RESERVED
+# double RESERVED
+# final RESERVED
+# float RESERVED
+# goto RESERVED
+# implements RESERVED
+# int RESERVED
+# interface RESERVED
+# long RESERVED
+# native RESERVED
+# package RESERVED
+# private RESERVED
+# protected RESERVED
+# public RESERVED
+# short RESERVED
+# static RESERVED
+# synchronized RESERVED
+# throws RESERVED
+# transient RESERVED
+# volatile RESERVED
+@end
+
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp
new file mode 100644
index 0000000..0bacb22
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp
@@ -0,0 +1,900 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+#include "Lexer.h"
+
+#include "JSFunction.h"
+#include "JSGlobalObjectFunctions.h"
+#include "NodeInfo.h"
+#include "Nodes.h"
+#include "dtoa.h"
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/unicode/Unicode.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+// we can't specify the namespace in yacc's C output, so do it here
+using namespace JSC;
+
+#ifndef KDE_USE_FINAL
+#include "Grammar.h"
+#endif
+
+#include "Lookup.h"
+#include "Lexer.lut.h"
+
+// a bridge for yacc from the C world to C++
+int jscyylex(void* lvalp, void* llocp, void* globalData)
+{
+ return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
+}
+
+namespace JSC {
+
+static bool isDecimalDigit(int);
+
+Lexer::Lexer(JSGlobalData* globalData)
+ : yylineno(1)
+ , m_restrKeyword(false)
+ , m_eatNextIdentifier(false)
+ , m_stackToken(-1)
+ , m_lastToken(-1)
+ , m_position(0)
+ , m_code(0)
+ , m_length(0)
+ , m_isReparsing(false)
+ , m_atLineStart(true)
+ , m_current(0)
+ , m_next1(0)
+ , m_next2(0)
+ , m_next3(0)
+ , m_currentOffset(0)
+ , m_nextOffset1(0)
+ , m_nextOffset2(0)
+ , m_nextOffset3(0)
+ , m_globalData(globalData)
+ , m_mainTable(JSC::mainTable)
+{
+ m_buffer8.reserveCapacity(initialReadBufferCapacity);
+ m_buffer16.reserveCapacity(initialReadBufferCapacity);
+}
+
+Lexer::~Lexer()
+{
+ m_mainTable.deleteTable();
+}
+
+void Lexer::setCode(const SourceCode& source)
+{
+ yylineno = source.firstLine();
+ m_restrKeyword = false;
+ m_delimited = false;
+ m_eatNextIdentifier = false;
+ m_stackToken = -1;
+ m_lastToken = -1;
+
+ m_position = source.startOffset();
+ m_source = &source;
+ m_code = source.provider()->data();
+ m_length = source.endOffset();
+ m_skipLF = false;
+ m_skipCR = false;
+ m_error = false;
+ m_atLineStart = true;
+
+ // read first characters
+ shift(4);
+}
+
+void Lexer::shift(unsigned p)
+{
+ // ECMA-262 calls for stripping Cf characters here, but we only do this for BOM,
+ // see <https://bugs.webkit.org/show_bug.cgi?id=4931>.
+
+ while (p--) {
+ m_current = m_next1;
+ m_next1 = m_next2;
+ m_next2 = m_next3;
+ m_currentOffset = m_nextOffset1;
+ m_nextOffset1 = m_nextOffset2;
+ m_nextOffset2 = m_nextOffset3;
+ do {
+ if (m_position >= m_length) {
+ m_nextOffset3 = m_position;
+ m_position++;
+ m_next3 = -1;
+ break;
+ }
+ m_nextOffset3 = m_position;
+ m_next3 = m_code[m_position++];
+ } while (m_next3 == 0xFEFF);
+ }
+}
+
+// called on each new line
+void Lexer::nextLine()
+{
+ yylineno++;
+ m_atLineStart = true;
+}
+
+void Lexer::setDone(State s)
+{
+ m_state = s;
+ m_done = true;
+}
+
+int Lexer::lex(void* p1, void* p2)
+{
+ YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1);
+ YYLTYPE* llocp = static_cast<YYLTYPE*>(p2);
+ int token = 0;
+ m_state = Start;
+ unsigned short stringType = 0; // either single or double quotes
+ m_buffer8.clear();
+ m_buffer16.clear();
+ m_done = false;
+ m_terminator = false;
+ m_skipLF = false;
+ m_skipCR = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (m_stackToken >= 0) {
+ setDone(Other);
+ token = m_stackToken;
+ m_stackToken = 0;
+ }
+ int startOffset = m_currentOffset;
+ while (!m_done) {
+ if (m_skipLF && m_current != '\n') // found \r but not \n afterwards
+ m_skipLF = false;
+ if (m_skipCR && m_current != '\r') // found \n but not \r afterwards
+ m_skipCR = false;
+ if (m_skipLF || m_skipCR) { // found \r\n or \n\r -> eat the second one
+ m_skipLF = false;
+ m_skipCR = false;
+ shift(1);
+ }
+ switch (m_state) {
+ case Start:
+ startOffset = m_currentOffset;
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (m_current == '/' && m_next1 == '/') {
+ shift(1);
+ m_state = InSingleLineComment;
+ } else if (m_current == '/' && m_next1 == '*') {
+ shift(1);
+ m_state = InMultiLineComment;
+ } else if (m_current == -1) {
+ if (!m_terminator && !m_delimited && !m_isReparsing) {
+ // automatic semicolon insertion if program incomplete
+ token = ';';
+ m_stackToken = 0;
+ setDone(Other);
+ } else
+ setDone(Eof);
+ } else if (isLineTerminator()) {
+ nextLine();
+ m_terminator = true;
+ if (m_restrKeyword) {
+ token = ';';
+ setDone(Other);
+ }
+ } else if (m_current == '"' || m_current == '\'') {
+ m_state = InString;
+ stringType = static_cast<unsigned short>(m_current);
+ } else if (isIdentStart(m_current)) {
+ record16(m_current);
+ m_state = InIdentifierOrKeyword;
+ } else if (m_current == '\\')
+ m_state = InIdentifierStartUnicodeEscapeStart;
+ else if (m_current == '0') {
+ record8(m_current);
+ m_state = InNum0;
+ } else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InNum;
+ } else if (m_current == '.' && isDecimalDigit(m_next1)) {
+ record8(m_current);
+ m_state = InDecimal;
+ // <!-- marks the beginning of a line comment (for www usage)
+ } else if (m_current == '<' && m_next1 == '!' && m_next2 == '-' && m_next3 == '-') {
+ shift(3);
+ m_state = InSingleLineComment;
+ // same for -->
+ } else if (m_atLineStart && m_current == '-' && m_next1 == '-' && m_next2 == '>') {
+ shift(2);
+ m_state = InSingleLineComment;
+ } else {
+ token = matchPunctuator(lvalp->intValue, m_current, m_next1, m_next2, m_next3);
+ if (token != -1)
+ setDone(Other);
+ else
+ setDone(Bad);
+ }
+ break;
+ case InString:
+ if (m_current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (isLineTerminator() || m_current == -1)
+ setDone(Bad);
+ else if (m_current == '\\')
+ m_state = InEscapeSequence;
+ else
+ record16(m_current);
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(m_current)) {
+ if (m_current >= '0' && m_current <= '3' &&
+ isOctalDigit(m_next1) && isOctalDigit(m_next2)) {
+ record16(convertOctal(m_current, m_next1, m_next2));
+ shift(2);
+ m_state = InString;
+ } else if (isOctalDigit(m_current) && isOctalDigit(m_next1)) {
+ record16(convertOctal('0', m_current, m_next1));
+ shift(1);
+ m_state = InString;
+ } else if (isOctalDigit(m_current)) {
+ record16(convertOctal('0', '0', m_current));
+ m_state = InString;
+ } else
+ setDone(Bad);
+ } else if (m_current == 'x')
+ m_state = InHexEscape;
+ else if (m_current == 'u')
+ m_state = InUnicodeEscape;
+ else if (isLineTerminator()) {
+ nextLine();
+ m_state = InString;
+ } else {
+ record16(singleEscape(static_cast<unsigned short>(m_current)));
+ m_state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(m_current) && isHexDigit(m_next1)) {
+ m_state = InString;
+ record16(convertHex(m_current, m_next1));
+ shift(1);
+ } else if (m_current == stringType) {
+ record16('x');
+ shift(1);
+ setDone(String);
+ } else {
+ record16('x');
+ record16(m_current);
+ m_state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(m_current) && isHexDigit(m_next1) && isHexDigit(m_next2) && isHexDigit(m_next3)) {
+ record16(convertUnicode(m_current, m_next1, m_next2, m_next3));
+ shift(3);
+ m_state = InString;
+ } else if (m_current == stringType) {
+ record16('u');
+ shift(1);
+ setDone(String);
+ } else
+ setDone(Bad);
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ nextLine();
+ m_terminator = true;
+ if (m_restrKeyword) {
+ token = ';';
+ setDone(Other);
+ } else
+ m_state = Start;
+ } else if (m_current == -1)
+ setDone(Eof);
+ break;
+ case InMultiLineComment:
+ if (m_current == -1)
+ setDone(Bad);
+ else if (isLineTerminator())
+ nextLine();
+ else if (m_current == '*' && m_next1 == '/') {
+ m_state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifierOrKeyword:
+ case InIdentifier:
+ if (isIdentPart(m_current))
+ record16(m_current);
+ else if (m_current == '\\')
+ m_state = InIdentifierPartUnicodeEscapeStart;
+ else
+ setDone(m_state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier);
+ break;
+ case InNum0:
+ if (m_current == 'x' || m_current == 'X') {
+ record8(m_current);
+ m_state = InHex;
+ } else if (m_current == '.') {
+ record8(m_current);
+ m_state = InDecimal;
+ } else if (m_current == 'e' || m_current == 'E') {
+ record8(m_current);
+ m_state = InExponentIndicator;
+ } else if (isOctalDigit(m_current)) {
+ record8(m_current);
+ m_state = InOctal;
+ } else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InDecimal;
+ } else
+ setDone(Number);
+ break;
+ case InHex:
+ if (isHexDigit(m_current))
+ record8(m_current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(m_current))
+ record8(m_current);
+ else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InDecimal;
+ } else
+ setDone(Octal);
+ break;
+ case InNum:
+ if (isDecimalDigit(m_current))
+ record8(m_current);
+ else if (m_current == '.') {
+ record8(m_current);
+ m_state = InDecimal;
+ } else if (m_current == 'e' || m_current == 'E') {
+ record8(m_current);
+ m_state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InDecimal:
+ if (isDecimalDigit(m_current))
+ record8(m_current);
+ else if (m_current == 'e' || m_current == 'E') {
+ record8(m_current);
+ m_state = InExponentIndicator;
+ } else
+ setDone(Number);
+ break;
+ case InExponentIndicator:
+ if (m_current == '+' || m_current == '-')
+ record8(m_current);
+ else if (isDecimalDigit(m_current)) {
+ record8(m_current);
+ m_state = InExponent;
+ } else
+ setDone(Bad);
+ break;
+ case InExponent:
+ if (isDecimalDigit(m_current))
+ record8(m_current);
+ else
+ setDone(Number);
+ break;
+ case InIdentifierStartUnicodeEscapeStart:
+ if (m_current == 'u')
+ m_state = InIdentifierStartUnicodeEscape;
+ else
+ setDone(Bad);
+ break;
+ case InIdentifierPartUnicodeEscapeStart:
+ if (m_current == 'u')
+ m_state = InIdentifierPartUnicodeEscape;
+ else
+ setDone(Bad);
+ break;
+ case InIdentifierStartUnicodeEscape:
+ if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) {
+ setDone(Bad);
+ break;
+ }
+ token = convertUnicode(m_current, m_next1, m_next2, m_next3);
+ shift(3);
+ if (!isIdentStart(token)) {
+ setDone(Bad);
+ break;
+ }
+ record16(token);
+ m_state = InIdentifier;
+ break;
+ case InIdentifierPartUnicodeEscape:
+ if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) {
+ setDone(Bad);
+ break;
+ }
+ token = convertUnicode(m_current, m_next1, m_next2, m_next3);
+ shift(3);
+ if (!isIdentPart(token)) {
+ setDone(Bad);
+ break;
+ }
+ record16(token);
+ m_state = InIdentifier;
+ break;
+ default:
+ ASSERT(!"Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!m_done)
+ shift(1);
+ if (m_state != Start && m_state != InSingleLineComment)
+ m_atLineStart = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((m_state == Number || m_state == Octal || m_state == Hex) && isIdentStart(m_current))
+ m_state = Bad;
+
+ // terminate string
+ m_buffer8.append('\0');
+
+#ifdef JSC_DEBUG_LEX
+ fprintf(stderr, "line: %d ", lineNo());
+ fprintf(stderr, "yytext (%x): ", m_buffer8[0]);
+ fprintf(stderr, "%s ", m_buffer8.data());
+#endif
+
+ double dval = 0;
+ if (m_state == Number)
+ dval = WTF::strtod(m_buffer8.data(), 0L);
+ else if (m_state == Hex) { // scan hex numbers
+ const char* p = m_buffer8.data() + 2;
+ while (char c = *p++) {
+ dval *= 16;
+ dval += convertHex(c);
+ }
+
+ if (dval >= mantissaOverflowLowerBound)
+ dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16);
+
+ m_state = Number;
+ } else if (m_state == Octal) { // scan octal number
+ const char* p = m_buffer8.data() + 1;
+ while (char c = *p++) {
+ dval *= 8;
+ dval += c - '0';
+ }
+
+ if (dval >= mantissaOverflowLowerBound)
+ dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8);
+
+ m_state = Number;
+ }
+
+#ifdef JSC_DEBUG_LEX
+ switch (m_state) {
+ case Eof:
+ printf("(EOF)\n");
+ break;
+ case Other:
+ printf("(Other)\n");
+ break;
+ case Identifier:
+ printf("(Identifier)/(Keyword)\n");
+ break;
+ case String:
+ printf("(String)\n");
+ break;
+ case Number:
+ printf("(Number)\n");
+ break;
+ default:
+ printf("(unknown)");
+ }
+#endif
+
+ if (m_state != Identifier)
+ m_eatNextIdentifier = false;
+
+ m_restrKeyword = false;
+ m_delimited = false;
+ llocp->first_line = yylineno;
+ llocp->last_line = yylineno;
+ llocp->first_column = startOffset;
+ llocp->last_column = m_currentOffset;
+ switch (m_state) {
+ case Eof:
+ token = 0;
+ break;
+ case Other:
+ if (token == '}' || token == ';')
+ m_delimited = true;
+ break;
+ case Identifier:
+ // Apply anonymous-function hack below (eat the identifier).
+ if (m_eatNextIdentifier) {
+ m_eatNextIdentifier = false;
+ token = lex(lvalp, llocp);
+ break;
+ }
+ lvalp->ident = makeIdentifier(m_buffer16);
+ token = IDENT;
+ break;
+ case IdentifierOrKeyword: {
+ lvalp->ident = makeIdentifier(m_buffer16);
+ const HashEntry* entry = m_mainTable.entry(m_globalData, *lvalp->ident);
+ if (!entry) {
+ // Lookup for keyword failed, means this is an identifier.
+ token = IDENT;
+ break;
+ }
+ token = entry->lexerValue();
+ // Hack for "f = function somename() { ... }"; too hard to get into the grammar.
+ m_eatNextIdentifier = token == FUNCTION && m_lastToken == '=';
+ if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW)
+ m_restrKeyword = true;
+ break;
+ }
+ case String:
+ // Atomize constant strings in case they're later used in property lookup.
+ lvalp->ident = makeIdentifier(m_buffer16);
+ token = STRING;
+ break;
+ case Number:
+ lvalp->doubleValue = dval;
+ token = NUMBER;
+ break;
+ case Bad:
+#ifdef JSC_DEBUG_LEX
+ fprintf(stderr, "yylex: ERROR.\n");
+#endif
+ m_error = true;
+ return -1;
+ default:
+ ASSERT(!"unhandled numeration value in switch");
+ m_error = true;
+ return -1;
+ }
+ m_lastToken = token;
+ return token;
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return m_current == '\t' || m_current == 0x0b || m_current == 0x0c || isSeparatorSpace(m_current);
+}
+
+bool Lexer::isLineTerminator()
+{
+ bool cr = (m_current == '\r');
+ bool lf = (m_current == '\n');
+ if (cr)
+ m_skipLF = true;
+ else if (lf)
+ m_skipCR = true;
+ return cr || lf || m_current == 0x2028 || m_current == 0x2029;
+}
+
+bool Lexer::isIdentStart(int c)
+{
+ return isASCIIAlpha(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other)));
+}
+
+bool Lexer::isIdentPart(int c)
+{
+ return isASCIIAlphanumeric(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
+ | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)));
+}
+
+static bool isDecimalDigit(int c)
+{
+ return isASCIIDigit(c);
+}
+
+bool Lexer::isHexDigit(int c)
+{
+ return isASCIIHexDigit(c);
+}
+
+bool Lexer::isOctalDigit(int c)
+{
+ return isASCIIOctalDigit(c);
+}
+
+int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return URSHIFTEQUAL;
+ }
+ if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STREQ;
+ }
+ if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return STRNEQ;
+ }
+ if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return URSHIFT;
+ }
+ if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return LSHIFTEQUAL;
+ }
+ if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return RSHIFTEQUAL;
+ }
+ if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return LE;
+ }
+ if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return GE;
+ }
+ if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return NE;
+ }
+ if (c1 == '+' && c2 == '+') {
+ shift(2);
+ if (m_terminator)
+ return AUTOPLUSPLUS;
+ return PLUSPLUS;
+ }
+ if (c1 == '-' && c2 == '-') {
+ shift(2);
+ if (m_terminator)
+ return AUTOMINUSMINUS;
+ return MINUSMINUS;
+ }
+ if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return EQEQ;
+ }
+ if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return PLUSEQUAL;
+ }
+ if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return MINUSEQUAL;
+ }
+ if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return MULTEQUAL;
+ }
+ if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return DIVEQUAL;
+ }
+ if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return ANDEQUAL;
+ }
+ if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return XOREQUAL;
+ }
+ if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return MODEQUAL;
+ }
+ if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return OREQUAL;
+ }
+ if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return LSHIFT;
+ }
+ if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return RSHIFT;
+ }
+ if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return AND;
+ }
+ if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return OR;
+ }
+
+ switch (c1) {
+ case '=':
+ case '>':
+ case '<':
+ case ',':
+ case '!':
+ case '~':
+ case '?':
+ case ':':
+ case '.':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '&':
+ case '|':
+ case '^':
+ case '%':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case ';':
+ shift(1);
+ return static_cast<int>(c1);
+ case '{':
+ charPos = m_position - 4;
+ shift(1);
+ return OPENBRACE;
+ case '}':
+ charPos = m_position - 4;
+ shift(1);
+ return CLOSEBRACE;
+ default:
+ return -1;
+ }
+}
+
+unsigned short Lexer::singleEscape(unsigned short c)
+{
+ switch (c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+unsigned short Lexer::convertOctal(int c1, int c2, int c3)
+{
+ return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(int c)
+{
+ if (c >= '0' && c <= '9')
+ return static_cast<unsigned char>(c - '0');
+ if (c >= 'a' && c <= 'f')
+ return static_cast<unsigned char>(c - 'a' + 10);
+ return static_cast<unsigned char>(c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(int c1, int c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4)
+{
+ unsigned char highByte = (convertHex(c1) << 4) + convertHex(c2);
+ unsigned char lowByte = (convertHex(c3) << 4) + convertHex(c4);
+ return (highByte << 8 | lowByte);
+}
+
+void Lexer::record8(int c)
+{
+ ASSERT(c >= 0);
+ ASSERT(c <= 0xff);
+ m_buffer8.append(static_cast<char>(c));
+}
+
+void Lexer::record16(int c)
+{
+ ASSERT(c >= 0);
+ ASSERT(c <= USHRT_MAX);
+ record16(UChar(static_cast<unsigned short>(c)));
+}
+
+void Lexer::record16(UChar c)
+{
+ m_buffer16.append(c);
+}
+
+bool Lexer::scanRegExp()
+{
+ m_buffer16.clear();
+ bool lastWasEscape = false;
+ bool inBrackets = false;
+
+ while (1) {
+ if (isLineTerminator() || m_current == -1)
+ return false;
+ else if (m_current != '/' || lastWasEscape == true || inBrackets == true) {
+ // keep track of '[' and ']'
+ if (!lastWasEscape) {
+ if ( m_current == '[' && !inBrackets )
+ inBrackets = true;
+ if ( m_current == ']' && inBrackets )
+ inBrackets = false;
+ }
+ record16(m_current);
+ lastWasEscape =
+ !lastWasEscape && (m_current == '\\');
+ } else { // end of regexp
+ m_pattern = UString(m_buffer16);
+ m_buffer16.clear();
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ while (isIdentPart(m_current)) {
+ record16(m_current);
+ shift(1);
+ }
+ m_flags = UString(m_buffer16);
+
+ return true;
+}
+
+void Lexer::clear()
+{
+ m_identifiers.clear();
+
+ Vector<char> newBuffer8;
+ newBuffer8.reserveCapacity(initialReadBufferCapacity);
+ m_buffer8.swap(newBuffer8);
+
+ Vector<UChar> newBuffer16;
+ newBuffer16.reserveCapacity(initialReadBufferCapacity);
+ m_buffer16.swap(newBuffer16);
+
+ m_isReparsing = false;
+
+ m_pattern = 0;
+ m_flags = 0;
+}
+
+} // namespace JSC
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h
new file mode 100644
index 0000000..cb553af
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 Lexer_h
+#define Lexer_h
+
+#include "Identifier.h"
+#include "Lookup.h"
+#include "SegmentedVector.h"
+#include "SourceCode.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class RegExp;
+
+ class Lexer : Noncopyable {
+ public:
+ void setCode(const SourceCode&);
+ void setIsReparsing() { m_isReparsing = true; }
+ int lex(void* lvalp, void* llocp);
+
+ int lineNo() const { return yylineno; }
+
+ bool prevTerminator() const { return m_terminator; }
+
+ enum State {
+ Start,
+ IdentifierOrKeyword,
+ Identifier,
+ InIdentifierOrKeyword,
+ InIdentifier,
+ InIdentifierStartUnicodeEscapeStart,
+ InIdentifierStartUnicodeEscape,
+ InIdentifierPartUnicodeEscapeStart,
+ InIdentifierPartUnicodeEscape,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad
+ };
+
+ bool scanRegExp();
+ const UString& pattern() const { return m_pattern; }
+ const UString& flags() const { return m_flags; }
+
+ static unsigned char convertHex(int);
+ static unsigned char convertHex(int c1, int c2);
+ static UChar convertUnicode(int c1, int c2, int c3, int c4);
+ static bool isIdentStart(int);
+ static bool isIdentPart(int);
+ static bool isHexDigit(int);
+
+ bool sawError() const { return m_error; }
+
+ void clear();
+ SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source->provider(), openBrace + 1, closeBrace, firstLine); }
+
+ private:
+ friend class JSGlobalData;
+ Lexer(JSGlobalData*);
+ ~Lexer();
+
+ void setDone(State);
+ void shift(unsigned int p);
+ void nextLine();
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator();
+ static bool isOctalDigit(int);
+
+ int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4);
+ static unsigned short singleEscape(unsigned short);
+ static unsigned short convertOctal(int c1, int c2, int c3);
+
+ void record8(int);
+ void record16(int);
+ void record16(UChar);
+
+ JSC::Identifier* makeIdentifier(const Vector<UChar>& buffer)
+ {
+ m_identifiers.append(JSC::Identifier(m_globalData, buffer.data(), buffer.size()));
+ return &m_identifiers.last();
+ }
+
+ static const size_t initialReadBufferCapacity = 32;
+ static const size_t initialIdentifierTableCapacity = 64;
+
+ int yylineno;
+ int yycolumn;
+
+ bool m_done;
+ Vector<char> m_buffer8;
+ Vector<UChar> m_buffer16;
+ bool m_terminator;
+ bool m_restrKeyword;
+ bool m_delimited; // encountered delimiter like "'" and "}" on last run
+ bool m_skipLF;
+ bool m_skipCR;
+ bool m_eatNextIdentifier;
+ int m_stackToken;
+ int m_lastToken;
+
+ State m_state;
+ unsigned int m_position;
+ const SourceCode* m_source;
+ const UChar* m_code;
+ unsigned int m_length;
+ bool m_isReparsing;
+ int m_atLineStart;
+ bool m_error;
+
+ // current and following unicode characters (int to allow for -1 for end-of-file marker)
+ int m_current;
+ int m_next1;
+ int m_next2;
+ int m_next3;
+
+ int m_currentOffset;
+ int m_nextOffset1;
+ int m_nextOffset2;
+ int m_nextOffset3;
+
+ SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers;
+
+ JSGlobalData* m_globalData;
+
+ UString m_pattern;
+ UString m_flags;
+
+ const HashTable m_mainTable;
+ };
+
+} // namespace JSC
+
+#endif // Lexer_h
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/NodeInfo.h b/src/3rdparty/webkit/JavaScriptCore/parser/NodeInfo.h
new file mode 100644
index 0000000..a518b23
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/NodeInfo.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 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 Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NodeInfo_h
+#define NodeInfo_h
+
+#include "Nodes.h"
+#include "Parser.h"
+
+namespace JSC {
+
+ template <typename T> struct NodeInfo {
+ T m_node;
+ CodeFeatures m_features;
+ int m_numConstants;
+ };
+
+ typedef NodeInfo<FuncDeclNode*> FuncDeclNodeInfo;
+ typedef NodeInfo<FuncExprNode*> FuncExprNodeInfo;
+ typedef NodeInfo<ExpressionNode*> ExpressionNodeInfo;
+ typedef NodeInfo<ArgumentsNode*> ArgumentsNodeInfo;
+ typedef NodeInfo<ConstDeclNode*> ConstDeclNodeInfo;
+ typedef NodeInfo<PropertyNode*> PropertyNodeInfo;
+ typedef NodeInfo<PropertyList> PropertyListInfo;
+ typedef NodeInfo<ElementList> ElementListInfo;
+ typedef NodeInfo<ArgumentList> ArgumentListInfo;
+
+ template <typename T> struct NodeDeclarationInfo {
+ T m_node;
+ ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations;
+ ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+ CodeFeatures m_features;
+ int m_numConstants;
+ };
+
+ typedef NodeDeclarationInfo<StatementNode*> StatementNodeInfo;
+ typedef NodeDeclarationInfo<CaseBlockNode*> CaseBlockNodeInfo;
+ typedef NodeDeclarationInfo<CaseClauseNode*> CaseClauseNodeInfo;
+ typedef NodeDeclarationInfo<SourceElements*> SourceElementsInfo;
+ typedef NodeDeclarationInfo<ClauseList> ClauseListInfo;
+ typedef NodeDeclarationInfo<ExpressionNode*> VarDeclListInfo;
+ typedef NodeDeclarationInfo<ConstDeclList> ConstDeclListInfo;
+ typedef NodeDeclarationInfo<ParameterList> ParameterListInfo;
+
+} // namespace JSC
+
+#endif // NodeInfo_h
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp
new file mode 100644
index 0000000..bdc5d2f
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp
@@ -0,0 +1,2721 @@
+/*
+* Copyright (C) 1999-2002 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.
+*
+*/
+
+#include "config.h"
+#include "Nodes.h"
+
+#include "BytecodeGenerator.h"
+#include "CallFrame.h"
+#include "JSGlobalObject.h"
+#include "JSStaticScopeObject.h"
+#include "LabelScope.h"
+#include "Parser.h"
+#include "PropertyNameArray.h"
+#include "RegExpObject.h"
+#include "SamplingTool.h"
+#include "Debugger.h"
+#include "Lexer.h"
+#include "Operations.h"
+#include <math.h>
+#include <wtf/Assertions.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+#include <wtf/MathExtras.h>
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/Threading.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
+
+// ------------------------------ NodeReleaser --------------------------------
+
+class NodeReleaser : Noncopyable {
+public:
+ // Call this function inside the destructor of a class derived from Node.
+ // This will traverse the tree below this node, destroying all of those nodes,
+ // but without relying on recursion.
+ static void releaseAllNodes(ParserRefCounted* root);
+
+ // Call this on each node in a the releaseNodes virtual function.
+ // It gives the node to the NodeReleaser, which will then release the
+ // node later at the end of the releaseAllNodes process.
+ template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); }
+ void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); }
+
+private:
+ NodeReleaser() { }
+ ~NodeReleaser() { }
+
+ void adopt(PassRefPtr<ParserRefCounted>);
+ void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&);
+
+ typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector;
+ OwnPtr<NodeReleaseVector> m_vector;
+};
+
+void NodeReleaser::releaseAllNodes(ParserRefCounted* root)
+{
+ ASSERT(root);
+ NodeReleaser releaser;
+ root->releaseNodes(releaser);
+ if (!releaser.m_vector)
+ return;
+ // Note: The call to release.m_vector->size() is intentionally inside
+ // the loop, since calls to releaseNodes are expected to increase the size.
+ for (size_t i = 0; i < releaser.m_vector->size(); ++i) {
+ ParserRefCounted* node = (*releaser.m_vector)[i].get();
+ if (node->hasOneRef())
+ node->releaseNodes(releaser);
+ }
+}
+
+void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node)
+{
+ ASSERT(node);
+ if (!node->hasOneRef())
+ return;
+ if (!m_vector)
+ m_vector.set(new NodeReleaseVector);
+ m_vector->append(node);
+}
+
+void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode)
+{
+ // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode>
+ // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode
+ // and ParserRefCounted) unbalanced. It would be nice to fix this problem in
+ // a cleaner way -- perhaps we could remove the FunctionBodyNode reference
+ // count at some point.
+ RefPtr<Node> node = functionBodyNode;
+ functionBodyNode = 0;
+ adopt(node.release());
+}
+
+// ------------------------------ ParserRefCounted -----------------------------------------
+
+#ifndef NDEBUG
+static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
+#endif
+
+ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
+ : m_globalData(globalData)
+{
+#ifndef NDEBUG
+ parserRefCountedCounter.increment();
+#endif
+ if (!m_globalData->newParserObjects)
+ m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
+ m_globalData->newParserObjects->add(this);
+ ASSERT(m_globalData->newParserObjects->contains(this));
+}
+
+ParserRefCounted::~ParserRefCounted()
+{
+#ifndef NDEBUG
+ parserRefCountedCounter.decrement();
+#endif
+}
+
+void ParserRefCounted::releaseNodes(NodeReleaser&)
+{
+}
+
+void ParserRefCounted::ref()
+{
+ // bumping from 0 to 1 is just removing from the new nodes set
+ if (m_globalData->newParserObjects) {
+ HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
+ if (it != m_globalData->newParserObjects->end()) {
+ m_globalData->newParserObjects->remove(it);
+ ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
+ return;
+ }
+ }
+
+ ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
+
+ if (!m_globalData->parserObjectExtraRefCounts)
+ m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
+ m_globalData->parserObjectExtraRefCounts->add(this);
+}
+
+void ParserRefCounted::deref()
+{
+ ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
+
+ if (!m_globalData->parserObjectExtraRefCounts) {
+ delete this;
+ return;
+ }
+
+ HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
+ if (it == m_globalData->parserObjectExtraRefCounts->end())
+ delete this;
+ else
+ m_globalData->parserObjectExtraRefCounts->remove(it);
+}
+
+bool ParserRefCounted::hasOneRef()
+{
+ if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
+ ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
+ return false;
+ }
+
+ ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
+
+ if (!m_globalData->parserObjectExtraRefCounts)
+ return true;
+
+ return !m_globalData->parserObjectExtraRefCounts->contains(this);
+}
+
+void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
+{
+ if (!globalData->newParserObjects)
+ return;
+
+#ifndef NDEBUG
+ HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
+ for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
+ ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
+#endif
+ deleteAllValues(*globalData->newParserObjects);
+ delete globalData->newParserObjects;
+ globalData->newParserObjects = 0;
+}
+
+// ------------------------------ Node --------------------------------
+
+Node::Node(JSGlobalData* globalData)
+ : ParserRefCounted(globalData)
+{
+ m_line = globalData->lexer->lineNo();
+}
+
+// ------------------------------ ThrowableExpressionData --------------------------------
+
+static void substitute(UString& string, const UString& substring)
+{
+ int position = string.find("%s");
+ ASSERT(position != -1);
+ UString newString = string.substr(0, position);
+ newString.append(substring);
+ newString.append(string.substr(position + 2));
+ string = newString;
+}
+
+RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg)
+{
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
+ generator.emitThrow(exception);
+ return exception;
+}
+
+RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
+{
+ UString message = msg;
+ substitute(message, label.ustring());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
+ generator.emitThrow(exception);
+ return exception;
+}
+
+// ------------------------------ StatementNode --------------------------------
+
+StatementNode::StatementNode(JSGlobalData* globalData)
+ : Node(globalData)
+ , m_lastLine(-1)
+{
+}
+
+void StatementNode::setLoc(int firstLine, int lastLine)
+{
+ m_line = firstLine;
+ m_lastLine = lastLine;
+}
+
+// ------------------------------ SourceElements --------------------------------
+
+void SourceElements::append(PassRefPtr<StatementNode> statement)
+{
+ if (statement->isEmptyStatement())
+ return;
+
+ m_statements.append(statement);
+}
+
+// ------------------------------ NullNode -------------------------------------
+
+RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, jsNull());
+}
+
+// ------------------------------ BooleanNode ----------------------------------
+
+RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ NumberNode -----------------------------------
+
+RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, m_double);
+}
+
+// ------------------------------ StringNode -----------------------------------
+
+RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitLoad(dst, m_value);
+}
+
+// ------------------------------ RegExpNode -----------------------------------
+
+RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
+ if (!regExp->isValid())
+ return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
+}
+
+// ------------------------------ ThisNode -------------------------------------
+
+RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
+}
+
+// ------------------------------ ResolveNode ----------------------------------
+
+bool ResolveNode::isPure(BytecodeGenerator& generator) const
+{
+ return generator.isLocal(m_ident);
+}
+
+RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.moveToDestinationIfNeeded(dst, local);
+ }
+
+ generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
+ return generator.emitResolve(generator.finalDestination(dst), m_ident);
+}
+
+// ------------------------------ ElementNode ------------------------------------
+
+ElementNode::~ElementNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ElementNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+ releaser.release(m_node);
+}
+
+// ------------------------------ ArrayNode ------------------------------------
+
+ArrayNode::~ArrayNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ArrayNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_element);
+}
+
+RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ // FIXME: Should we put all of this code into emitNewArray?
+
+ unsigned length = 0;
+ ElementNode* firstPutElement;
+ for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) {
+ if (firstPutElement->elision())
+ break;
+ ++length;
+ }
+
+ if (!firstPutElement && !m_elision)
+ return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
+
+ RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
+
+ for (ElementNode* n = firstPutElement; n; n = n->next()) {
+ RegisterID* value = generator.emitNode(n->value());
+ length += n->elision();
+ generator.emitPutByIndex(array.get(), length++, value);
+ }
+
+ if (m_elision) {
+ RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
+ generator.emitPutById(array.get(), generator.propertyNames().length, value);
+ }
+
+ return generator.moveToDestinationIfNeeded(dst, array.get());
+}
+
+// ------------------------------ PropertyNode ----------------------------
+
+PropertyNode::~PropertyNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PropertyNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_assign);
+}
+
+// ------------------------------ ObjectLiteralNode ----------------------------
+
+ObjectLiteralNode::~ObjectLiteralNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_list);
+}
+
+RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (!m_list) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitNewObject(generator.finalDestination(dst));
+ }
+ return generator.emitNode(dst, m_list.get());
+}
+
+// ------------------------------ PropertyListNode -----------------------------
+
+PropertyListNode::~PropertyListNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PropertyListNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_node);
+ releaser.release(m_next);
+}
+
+RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newObj = generator.tempDestination(dst);
+
+ generator.emitNewObject(newObj.get());
+
+ for (PropertyListNode* p = this; p; p = p->m_next.get()) {
+ RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
+
+ switch (p->m_node->m_type) {
+ case PropertyNode::Constant: {
+ generator.emitPutById(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ case PropertyNode::Getter: {
+ generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ case PropertyNode::Setter: {
+ generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ return generator.moveToDestinationIfNeeded(dst, newObj.get());
+}
+
+// ------------------------------ BracketAccessorNode --------------------------------
+
+BracketAccessorNode::~BracketAccessorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void BracketAccessorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
+ RegisterID* property = generator.emitNode(m_subscript.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
+}
+
+// ------------------------------ DotAccessorNode --------------------------------
+
+DotAccessorNode::~DotAccessorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DotAccessorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* base = generator.emitNode(m_base.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
+}
+
+// ------------------------------ ArgumentListNode -----------------------------
+
+ArgumentListNode::~ArgumentListNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ArgumentListNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+ releaser.release(m_expr);
+}
+
+RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(dst, m_expr.get());
+}
+
+// ------------------------------ ArgumentsNode -----------------------------
+
+ArgumentsNode::~ArgumentsNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ArgumentsNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_listNode);
+}
+
+// ------------------------------ NewExprNode ----------------------------------
+
+NewExprNode::~NewExprNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void NewExprNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_args);
+}
+
+RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
+ return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ EvalFunctionCallNode ----------------------------------
+
+EvalFunctionCallNode::~EvalFunctionCallNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_args);
+}
+
+RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> func = generator.tempDestination(dst);
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
+ generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
+ return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallValueNode ----------------------------------
+
+FunctionCallValueNode::~FunctionCallValueNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallResolveNode ----------------------------------
+
+FunctionCallResolveNode::~FunctionCallResolveNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
+ RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+ return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+ }
+
+ RefPtr<RegisterID> func = generator.tempDestination(dst);
+ RefPtr<RegisterID> thisRegister = generator.newTemporary();
+ int identifierStart = divot() - startOffset();
+ generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
+ generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallBracketNode ----------------------------------
+
+FunctionCallBracketNode::~FunctionCallBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RegisterID* property = generator.emitNode(m_subscript.get());
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
+ RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+ return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ FunctionCallDotNode ----------------------------------
+
+FunctionCallDotNode::~FunctionCallDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_args);
+}
+
+RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+ RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
+ return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
+}
+
+// ------------------------------ PostfixResolveNode ----------------------------------
+
+static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
+{
+ return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
+}
+
+static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
+{
+ return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
+}
+
+RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitToJSNumber(generator.finalDestination(dst), local);
+ }
+
+ if (dst == generator.ignoredResult())
+ return emitPreIncOrDec(generator, local, m_operator);
+ return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ emitPreIncOrDec(generator, value.get(), m_operator);
+ } else {
+ oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
+ }
+ generator.emitPutScopedVar(depth, index, value.get(), globalObject);
+ return oldValue;
+ }
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RefPtr<RegisterID> value = generator.newTemporary();
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ emitPreIncOrDec(generator, value.get(), m_operator);
+ } else {
+ oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
+ }
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+// ------------------------------ PostfixBracketNode ----------------------------------
+
+PostfixBracketNode::~PostfixBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PostfixBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value.get());
+ else
+ generator.emitPreDec(value.get());
+ } else {
+ oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
+ }
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), value.get());
+ return oldValue;
+}
+
+// ------------------------------ PostfixDotNode ----------------------------------
+
+PostfixDotNode::~PostfixDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PostfixDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+ RegisterID* oldValue;
+ if (dst == generator.ignoredResult()) {
+ oldValue = 0;
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value.get());
+ else
+ generator.emitPreDec(value.get());
+ } else {
+ oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
+ }
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+// ------------------------------ PostfixErrorNode -----------------------------------
+
+PostfixErrorNode::~PostfixErrorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PostfixErrorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
+}
+
+// ------------------------------ DeleteResolveNode -----------------------------------
+
+RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.registerFor(m_ident))
+ return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
+}
+
+// ------------------------------ DeleteBracketNode -----------------------------------
+
+DeleteBracketNode::~DeleteBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DeleteBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
+ RegisterID* r1 = generator.emitNode(m_subscript.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
+}
+
+// ------------------------------ DeleteDotNode -----------------------------------
+
+DeleteDotNode::~DeleteDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DeleteDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* r0 = generator.emitNode(m_base.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
+}
+
+// ------------------------------ DeleteValueNode -----------------------------------
+
+DeleteValueNode::~DeleteValueNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DeleteValueNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(generator.ignoredResult(), m_expr.get());
+
+ // delete on a non-location expression ignores the value and returns true
+ return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
+}
+
+// ------------------------------ VoidNode -------------------------------------
+
+VoidNode::~VoidNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void VoidNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult()) {
+ generator.emitNode(generator.ignoredResult(), m_expr.get());
+ return 0;
+ }
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ return generator.emitLoad(dst, jsUndefined());
+}
+
+// ------------------------------ TypeOfValueNode -----------------------------------
+
+RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitTypeOf(generator.finalDestination(dst), local);
+ }
+
+ RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ generator.emitGetById(scratch.get(), scratch.get(), m_ident);
+ if (dst == generator.ignoredResult())
+ return 0;
+ return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
+}
+
+// ------------------------------ TypeOfValueNode -----------------------------------
+
+TypeOfValueNode::~TypeOfValueNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void TypeOfValueNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult()) {
+ generator.emitNode(generator.ignoredResult(), m_expr.get());
+ return 0;
+ }
+ RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
+ return generator.emitTypeOf(generator.finalDestination(dst), src.get());
+}
+
+// ------------------------------ PrefixResolveNode ----------------------------------
+
+RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ if (dst == generator.ignoredResult())
+ return 0;
+ RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
+ return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
+ }
+
+ emitPreIncOrDec(generator, local, m_operator);
+ return generator.moveToDestinationIfNeeded(dst, local);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+ emitPreIncOrDec(generator, propDst.get(), m_operator);
+ generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+ }
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
+ emitPreIncOrDec(generator, propDst.get(), m_operator);
+ generator.emitPutById(base.get(), m_ident, propDst.get());
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixBracketNode ----------------------------------
+
+PrefixBracketNode::~PrefixBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PrefixBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+}
+
+RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+
+ generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
+ RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value);
+ else
+ generator.emitPreDec(value);
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixDotNode ----------------------------------
+
+PrefixDotNode::~PrefixDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PrefixDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+}
+
+RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+
+ generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
+ RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
+ if (m_operator == OpPlusPlus)
+ generator.emitPreInc(value);
+ else
+ generator.emitPreDec(value);
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base.get(), m_ident, value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+// ------------------------------ PrefixErrorNode -----------------------------------
+
+PrefixErrorNode::~PrefixErrorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void PrefixErrorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
+}
+
+// ------------------------------ Unary Operation Nodes -----------------------------------
+
+UnaryOpNode::~UnaryOpNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void UnaryOpNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* src = generator.emitNode(m_expr.get());
+ return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
+}
+
+// ------------------------------ Binary Operation Nodes -----------------------------------
+
+BinaryOpNode::~BinaryOpNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void BinaryOpNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ OpcodeID opcodeID = this->opcodeID();
+ if (opcodeID == op_neq) {
+ if (m_expr1->isNull() || m_expr2->isNull()) {
+ RefPtr<RegisterID> src = generator.tempDestination(dst);
+ generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
+ return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
+ }
+ }
+
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
+}
+
+RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (m_expr1->isNull() || m_expr2->isNull()) {
+ RefPtr<RegisterID> src = generator.tempDestination(dst);
+ generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
+ return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
+ }
+
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
+}
+
+RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
+}
+
+RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
+ RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitGetByIdExceptionInfo(op_instanceof);
+ RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
+}
+
+// ------------------------------ LogicalOpNode ----------------------------
+
+LogicalOpNode::~LogicalOpNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void LogicalOpNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> temp = generator.tempDestination(dst);
+ RefPtr<Label> target = generator.newLabel();
+
+ generator.emitNode(temp.get(), m_expr1.get());
+ if (m_operator == OpLogicalAnd)
+ generator.emitJumpIfFalse(temp.get(), target.get());
+ else
+ generator.emitJumpIfTrue(temp.get(), target.get());
+ generator.emitNode(temp.get(), m_expr2.get());
+ generator.emitLabel(target.get());
+
+ return generator.moveToDestinationIfNeeded(dst, temp.get());
+}
+
+// ------------------------------ ConditionalNode ------------------------------
+
+ConditionalNode::~ConditionalNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ConditionalNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_logical);
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newDst = generator.finalDestination(dst);
+ RefPtr<Label> beforeElse = generator.newLabel();
+ RefPtr<Label> afterElse = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_logical.get());
+ generator.emitJumpIfFalse(cond, beforeElse.get());
+
+ generator.emitNode(newDst.get(), m_expr1.get());
+ generator.emitJump(afterElse.get());
+
+ generator.emitLabel(beforeElse.get());
+ generator.emitNode(newDst.get(), m_expr2.get());
+
+ generator.emitLabel(afterElse.get());
+
+ return newDst.get();
+}
+
+// ------------------------------ ReadModifyResolveNode -----------------------------------
+
+ReadModifyResolveNode::~ReadModifyResolveNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_right);
+}
+
+// FIXME: should this be moved to be a method on BytecodeGenerator?
+static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
+{
+ OpcodeID opcodeID;
+ switch (oper) {
+ case OpMultEq:
+ opcodeID = op_mul;
+ break;
+ case OpDivEq:
+ opcodeID = op_div;
+ break;
+ case OpPlusEq:
+ opcodeID = op_add;
+ break;
+ case OpMinusEq:
+ opcodeID = op_sub;
+ break;
+ case OpLShift:
+ opcodeID = op_lshift;
+ break;
+ case OpRShift:
+ opcodeID = op_rshift;
+ break;
+ case OpURShift:
+ opcodeID = op_urshift;
+ break;
+ case OpAndEq:
+ opcodeID = op_bitand;
+ break;
+ case OpXOrEq:
+ opcodeID = op_bitxor;
+ break;
+ case OpOrEq:
+ opcodeID = op_bitor;
+ break;
+ case OpModEq:
+ opcodeID = op_mod;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return dst;
+ }
+
+ return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
+}
+
+RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+ }
+
+ if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
+ RefPtr<RegisterID> result = generator.newTemporary();
+ generator.emitMove(result.get(), local);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+ generator.emitMove(local, result.get());
+ return generator.moveToDestinationIfNeeded(dst, result.get());
+ }
+
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+ return generator.moveToDestinationIfNeeded(dst, result);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+ RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+ generator.emitPutScopedVar(depth, index, result, globalObject);
+ return result;
+ }
+
+ RefPtr<RegisterID> src1 = generator.tempDestination(dst);
+ generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+ return generator.emitPutById(base.get(), m_ident, result);
+}
+
+// ------------------------------ AssignResolveNode -----------------------------------
+
+AssignResolveNode::~AssignResolveNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignResolveNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_right);
+}
+
+RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerFor(m_ident)) {
+ if (generator.isLocalConstant(m_ident))
+ return generator.emitNode(dst, m_right.get());
+
+ RegisterID* result = generator.emitNode(local, m_right.get());
+ return generator.moveToDestinationIfNeeded(dst, result);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ JSObject* globalObject = 0;
+ if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RegisterID* value = generator.emitNode(dst, m_right.get());
+ generator.emitPutScopedVar(depth, index, value, globalObject);
+ return value;
+ }
+
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RegisterID* value = generator.emitNode(dst, m_right.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitPutById(base.get(), m_ident, value);
+}
+
+// ------------------------------ AssignDotNode -----------------------------------
+
+AssignDotNode::~AssignDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_right);
+}
+
+RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
+ RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+ RegisterID* result = generator.emitNode(value.get(), m_right.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base.get(), m_ident, result);
+ return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+// ------------------------------ ReadModifyDotNode -----------------------------------
+
+ReadModifyDotNode::~ReadModifyDotNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_right);
+}
+
+RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+ RegisterID* change = generator.emitNode(m_right.get());
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ return generator.emitPutById(base.get(), m_ident, updatedValue);
+}
+
+// ------------------------------ AssignErrorNode -----------------------------------
+
+AssignErrorNode::~AssignErrorNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignErrorNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_left);
+ releaser.release(m_right);
+}
+
+RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
+}
+
+// ------------------------------ AssignBracketNode -----------------------------------
+
+AssignBracketNode::~AssignBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void AssignBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+ releaser.release(m_right);
+}
+
+RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
+ RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+ RegisterID* result = generator.emitNode(value.get(), m_right.get());
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), result);
+ return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+// ------------------------------ ReadModifyBracketNode -----------------------------------
+
+ReadModifyBracketNode::~ReadModifyBracketNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_base);
+ releaser.release(m_subscript);
+ releaser.release(m_right);
+}
+
+RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
+
+ generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
+ RegisterID* change = generator.emitNode(m_right.get());
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutByVal(base.get(), property.get(), updatedValue);
+
+ return updatedValue;
+}
+
+// ------------------------------ CommaNode ------------------------------------
+
+CommaNode::~CommaNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void CommaNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+}
+
+RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(generator.ignoredResult(), m_expr1.get());
+ return generator.emitNode(dst, m_expr2.get());
+}
+
+// ------------------------------ ConstDeclNode ------------------------------------
+
+ConstDeclNode::~ConstDeclNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ConstDeclNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+ releaser.release(m_init);
+}
+
+ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_init(init)
+{
+}
+
+RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
+{
+ if (RegisterID* local = generator.constRegisterFor(m_ident)) {
+ if (!m_init)
+ return local;
+
+ return generator.emitNode(local, m_init.get());
+ }
+
+ // FIXME: While this code should only be hit in eval code, it will potentially
+ // assign to the wrong base if m_ident exists in an intervening dynamic scope.
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
+ return generator.emitPutById(base.get(), m_ident, value);
+}
+
+RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ RegisterID* result = 0;
+ for (ConstDeclNode* n = this; n; n = n->m_next.get())
+ result = n->emitCodeSingle(generator);
+
+ return result;
+}
+
+// ------------------------------ ConstStatementNode -----------------------------
+
+ConstStatementNode::~ConstStatementNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ConstStatementNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+}
+
+RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ return generator.emitNode(m_next.get());
+}
+
+// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
+
+static inline RegisterID* statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst)
+{
+ StatementVector::const_iterator end = statements.end();
+ for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) {
+ StatementNode* n = it->get();
+ if (!n->isLoop())
+ generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
+ generator.emitNode(dst, n);
+ }
+ return 0;
+}
+
+// ------------------------------ BlockNode ------------------------------------
+
+BlockNode::~BlockNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void BlockNode::releaseNodes(NodeReleaser& releaser)
+{
+ size_t size = m_children.size();
+ for (size_t i = 0; i < size; ++i)
+ releaser.release(m_children[i]);
+}
+
+BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
+ : StatementNode(globalData)
+{
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+}
+
+RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ return statementListEmitCode(m_children, generator, dst);
+}
+
+// ------------------------------ EmptyStatementNode ---------------------------
+
+RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID* dst)
+{
+ return dst;
+}
+
+// ------------------------------ DebuggerStatementNode ---------------------------
+
+RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
+ return dst;
+}
+
+// ------------------------------ ExprStatementNode ----------------------------
+
+RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(dst, m_expr.get());
+}
+
+// ------------------------------ VarStatementNode ----------------------------
+
+VarStatementNode::~VarStatementNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void VarStatementNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(m_expr.get());
+}
+
+// ------------------------------ IfNode ---------------------------------------
+
+IfNode::~IfNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void IfNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_condition);
+ releaser.release(m_ifBlock);
+}
+
+RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<Label> afterThen = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_condition.get());
+ generator.emitJumpIfFalse(cond, afterThen.get());
+
+ if (!m_ifBlock->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
+
+ generator.emitNode(dst, m_ifBlock.get());
+ generator.emitLabel(afterThen.get());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion.
+ return 0;
+}
+
+// ------------------------------ IfElseNode ---------------------------------------
+
+IfElseNode::~IfElseNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void IfElseNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_elseBlock);
+ IfNode::releaseNodes(releaser);
+}
+
+RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<Label> beforeElse = generator.newLabel();
+ RefPtr<Label> afterElse = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_condition.get());
+ generator.emitJumpIfFalse(cond, beforeElse.get());
+
+ if (!m_ifBlock->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
+
+ generator.emitNode(dst, m_ifBlock.get());
+ generator.emitJump(afterElse.get());
+
+ generator.emitLabel(beforeElse.get());
+
+ if (!m_elseBlock->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine());
+
+ generator.emitNode(dst, m_elseBlock.get());
+
+ generator.emitLabel(afterElse.get());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion.
+ return 0;
+}
+
+// ------------------------------ DoWhileNode ----------------------------------
+
+DoWhileNode::~DoWhileNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void DoWhileNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_statement);
+ releaser.release(m_expr);
+}
+
+RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ RefPtr<Label> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
+ RegisterID* cond = generator.emitNode(m_expr.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+
+ generator.emitLabel(scope->breakTarget());
+ return result.get();
+}
+
+// ------------------------------ WhileNode ------------------------------------
+
+WhileNode::~WhileNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void WhileNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_statement);
+}
+
+RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ generator.emitJump(scope->continueTarget());
+
+ RefPtr<Label> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+
+ generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
+ RegisterID* cond = generator.emitNode(m_expr.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+
+ generator.emitLabel(scope->breakTarget());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion
+ return 0;
+}
+
+// ------------------------------ ForNode --------------------------------------
+
+ForNode::~ForNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ForNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr1);
+ releaser.release(m_expr2);
+ releaser.release(m_expr3);
+ releaser.release(m_statement);
+}
+
+RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ dst = 0;
+
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+ if (m_expr1)
+ generator.emitNode(generator.ignoredResult(), m_expr1.get());
+
+ RefPtr<Label> condition = generator.newLabel();
+ generator.emitJump(condition.get());
+
+ RefPtr<Label> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ if (m_expr3)
+ generator.emitNode(generator.ignoredResult(), m_expr3.get());
+
+ generator.emitLabel(condition.get());
+ if (m_expr2) {
+ RegisterID* cond = generator.emitNode(m_expr2.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+ } else
+ generator.emitJump(topOfLoop.get());
+
+ generator.emitLabel(scope->breakTarget());
+ return result.get();
+}
+
+// ------------------------------ ForInNode ------------------------------------
+
+ForInNode::~ForInNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ForInNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_init);
+ releaser.release(m_lexpr);
+ releaser.release(m_expr);
+ releaser.release(m_statement);
+}
+
+ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
+ : StatementNode(globalData)
+ , m_init(0L)
+ , m_lexpr(l)
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_identIsVarDecl(false)
+{
+}
+
+ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
+ : StatementNode(globalData)
+ , m_ident(ident)
+ , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_identIsVarDecl(true)
+{
+ if (in) {
+ AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
+ node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
+ m_init = node;
+ }
+ // for( var foo = bar in baz )
+}
+
+RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
+
+ if (!m_lexpr->isLocation())
+ return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
+
+ RefPtr<Label> continueTarget = generator.newLabel();
+
+ generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
+
+ if (m_init)
+ generator.emitNode(generator.ignoredResult(), m_init.get());
+ RegisterID* forInBase = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
+ generator.emitJump(scope->continueTarget());
+
+ RefPtr<Label> loopStart = generator.newLabel();
+ generator.emitLabel(loopStart.get());
+
+ RegisterID* propertyName;
+ if (m_lexpr->isResolveNode()) {
+ const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
+ propertyName = generator.registerFor(ident);
+ if (!propertyName) {
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
+
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitPutById(base, ident, propertyName);
+ }
+ } else if (m_lexpr->isDotAccessorNode()) {
+ DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
+ const Identifier& ident = assignNode->identifier();
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RegisterID* base = generator.emitNode(assignNode->base());
+
+ generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
+ generator.emitPutById(base, ident, propertyName);
+ } else {
+ ASSERT(m_lexpr->isBracketAccessorNode());
+ BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
+ RegisterID* subscript = generator.emitNode(assignNode->subscript());
+
+ generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
+ generator.emitPutByVal(base.get(), subscript, propertyName);
+ }
+
+ if (!m_statement->isBlock())
+ generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
+ generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
+ generator.emitLabel(scope->breakTarget());
+ return dst;
+}
+
+// ------------------------------ ContinueNode ---------------------------------
+
+// ECMA 12.7
+RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ LabelScope* scope = generator.continueTarget(m_ident);
+
+ if (!scope)
+ return m_ident.isEmpty()
+ ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
+ : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+
+ generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
+ return dst;
+}
+
+// ------------------------------ BreakNode ------------------------------------
+
+// ECMA 12.8
+RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ LabelScope* scope = generator.breakTarget(m_ident);
+
+ if (!scope)
+ return m_ident.isEmpty()
+ ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
+ : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+
+ generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
+ return dst;
+}
+
+// ------------------------------ ReturnNode -----------------------------------
+
+ReturnNode::~ReturnNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ReturnNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_value);
+}
+
+RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.codeType() != FunctionCode)
+ return emitThrowError(generator, SyntaxError, "Invalid return statement.");
+
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
+ if (generator.scopeDepth()) {
+ RefPtr<Label> l0 = generator.newLabel();
+ generator.emitJumpScopes(l0.get(), 0);
+ generator.emitLabel(l0.get());
+ }
+ generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+ return generator.emitReturn(r0);
+}
+
+// ------------------------------ WithNode -------------------------------------
+
+WithNode::~WithNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void WithNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_statement);
+}
+
+RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> scope = generator.newTemporary();
+ generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped
+ generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
+ generator.emitPushScope(scope.get());
+ RegisterID* result = generator.emitNode(dst, m_statement.get());
+ generator.emitPopScope();
+ return result;
+}
+
+// ------------------------------ CaseClauseNode --------------------------------
+
+CaseClauseNode::~CaseClauseNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void CaseClauseNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+// ------------------------------ ClauseListNode --------------------------------
+
+ClauseListNode::~ClauseListNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ClauseListNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_clause);
+ releaser.release(m_next);
+}
+
+// ------------------------------ CaseBlockNode --------------------------------
+
+CaseBlockNode::~CaseBlockNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void CaseBlockNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_list1);
+ releaser.release(m_defaultClause);
+ releaser.release(m_list2);
+}
+
+enum SwitchKind {
+ SwitchUnset = 0,
+ SwitchNumber = 1,
+ SwitchString = 2,
+ SwitchNeither = 3
+};
+
+static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
+{
+ for (; list; list = list->getNext()) {
+ ExpressionNode* clauseExpression = list->getClause()->expr();
+ literalVector.append(clauseExpression);
+ if (clauseExpression->isNumber()) {
+ double value = static_cast<NumberNode*>(clauseExpression)->value();
+ if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
+ typeForTable = SwitchNeither;
+ break;
+ }
+ int32_t intVal = static_cast<int32_t>(value);
+ ASSERT(intVal == value);
+ if (intVal < min_num)
+ min_num = intVal;
+ if (intVal > max_num)
+ max_num = intVal;
+ typeForTable = SwitchNumber;
+ continue;
+ }
+ if (clauseExpression->isString()) {
+ if (typeForTable & ~SwitchString) {
+ typeForTable = SwitchNeither;
+ break;
+ }
+ const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
+ if (singleCharacterSwitch &= value.size() == 1) {
+ int32_t intVal = value.rep()->data()[0];
+ if (intVal < min_num)
+ min_num = intVal;
+ if (intVal > max_num)
+ max_num = intVal;
+ }
+ typeForTable = SwitchString;
+ continue;
+ }
+ typeForTable = SwitchNeither;
+ break;
+ }
+}
+
+SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
+{
+ SwitchKind typeForTable = SwitchUnset;
+ bool singleCharacterSwitch = true;
+
+ processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+ processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
+
+ if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
+ return SwitchInfo::SwitchNone;
+
+ if (typeForTable == SwitchNumber) {
+ int32_t range = max_num - min_num;
+ if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
+ return SwitchInfo::SwitchImmediate;
+ return SwitchInfo::SwitchNone;
+ }
+
+ ASSERT(typeForTable == SwitchString);
+
+ if (singleCharacterSwitch) {
+ int32_t range = max_num - min_num;
+ if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
+ return SwitchInfo::SwitchCharacter;
+ }
+
+ return SwitchInfo::SwitchString;
+}
+
+RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
+{
+ RefPtr<Label> defaultLabel;
+ Vector<RefPtr<Label>, 8> labelVector;
+ Vector<ExpressionNode*, 8> literalVector;
+ int32_t min_num = std::numeric_limits<int32_t>::max();
+ int32_t max_num = std::numeric_limits<int32_t>::min();
+ SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
+
+ if (switchType != SwitchInfo::SwitchNone) {
+ // Prepare the various labels
+ for (uint32_t i = 0; i < literalVector.size(); i++)
+ labelVector.append(generator.newLabel());
+ defaultLabel = generator.newLabel();
+ generator.beginSwitch(switchExpression, switchType);
+ } else {
+ // Setup jumps
+ for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ RefPtr<RegisterID> clauseVal = generator.newTemporary();
+ generator.emitNode(clauseVal.get(), list->getClause()->expr());
+ generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
+ labelVector.append(generator.newLabel());
+ generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
+ }
+
+ for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ RefPtr<RegisterID> clauseVal = generator.newTemporary();
+ generator.emitNode(clauseVal.get(), list->getClause()->expr());
+ generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
+ labelVector.append(generator.newLabel());
+ generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
+ }
+ defaultLabel = generator.newLabel();
+ generator.emitJump(defaultLabel.get());
+ }
+
+ RegisterID* result = 0;
+
+ size_t i = 0;
+ for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ generator.emitLabel(labelVector[i++].get());
+ result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ }
+
+ if (m_defaultClause) {
+ generator.emitLabel(defaultLabel.get());
+ result = statementListEmitCode(m_defaultClause->children(), generator, dst);
+ }
+
+ for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ generator.emitLabel(labelVector[i++].get());
+ result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ }
+ if (!m_defaultClause)
+ generator.emitLabel(defaultLabel.get());
+
+ ASSERT(i == labelVector.size());
+ if (switchType != SwitchInfo::SwitchNone) {
+ ASSERT(labelVector.size() == literalVector.size());
+ generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
+ }
+ return result;
+}
+
+// ------------------------------ SwitchNode -----------------------------------
+
+SwitchNode::~SwitchNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void SwitchNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+ releaser.release(m_block);
+}
+
+RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
+
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
+
+ generator.emitLabel(scope->breakTarget());
+ return r1;
+}
+
+// ------------------------------ LabelNode ------------------------------------
+
+LabelNode::~LabelNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void LabelNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_statement);
+}
+
+RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.breakTarget(m_name))
+ return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
+
+ RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
+ RegisterID* r0 = generator.emitNode(dst, m_statement.get());
+
+ generator.emitLabel(scope->breakTarget());
+ return r0;
+}
+
+// ------------------------------ ThrowNode ------------------------------------
+
+ThrowNode::~ThrowNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ThrowNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_expr);
+}
+
+RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
+ generator.emitExpressionInfo(divot(), startOffset(), endOffset());
+ generator.emitThrow(expr.get());
+ return dst;
+}
+
+// ------------------------------ TryNode --------------------------------------
+
+TryNode::~TryNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void TryNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_tryBlock);
+ releaser.release(m_catchBlock);
+ releaser.release(m_finallyBlock);
+}
+
+RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<Label> tryStartLabel = generator.newLabel();
+ RefPtr<Label> tryEndLabel = generator.newLabel();
+ RefPtr<Label> finallyStart;
+ RefPtr<RegisterID> finallyReturnAddr;
+ if (m_finallyBlock) {
+ finallyStart = generator.newLabel();
+ finallyReturnAddr = generator.newTemporary();
+ generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
+ }
+ generator.emitLabel(tryStartLabel.get());
+ generator.emitNode(dst, m_tryBlock.get());
+ generator.emitLabel(tryEndLabel.get());
+
+ if (m_catchBlock) {
+ RefPtr<Label> handlerEndLabel = generator.newLabel();
+ generator.emitJump(handlerEndLabel.get());
+ RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
+ if (m_catchHasEval) {
+ RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
+ generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
+ generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
+ generator.emitPushScope(exceptionRegister.get());
+ } else
+ generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
+ generator.emitNode(dst, m_catchBlock.get());
+ generator.emitPopScope();
+ generator.emitLabel(handlerEndLabel.get());
+ }
+
+ if (m_finallyBlock) {
+ generator.popFinallyContext();
+ // there may be important registers live at the time we jump
+ // to a finally block (such as for a return or throw) so we
+ // ref the highest register ever used as a conservative
+ // approach to not clobbering anything important
+ RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
+ RefPtr<Label> finallyEndLabel = generator.newLabel();
+ generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ // Use a label to record the subtle fact that sret will return to the
+ // next instruction. sret is the only way to jump without an explicit label.
+ generator.emitLabel(generator.newLabel().get());
+ generator.emitJump(finallyEndLabel.get());
+
+ // Finally block for exception path
+ RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
+ generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ // Use a label to record the subtle fact that sret will return to the
+ // next instruction. sret is the only way to jump without an explicit label.
+ generator.emitLabel(generator.newLabel().get());
+ generator.emitThrow(tempExceptionRegister.get());
+
+ // emit the finally block itself
+ generator.emitLabel(finallyStart.get());
+ generator.emitNode(dst, m_finallyBlock.get());
+ generator.emitSubroutineReturn(finallyReturnAddr.get());
+
+ generator.emitLabel(finallyEndLabel.get());
+ }
+
+ return dst;
+}
+
+// ------------------------------ ParameterNode -----------------------------
+
+ParameterNode::~ParameterNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ParameterNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_next);
+}
+
+// -----------------------------ScopeNodeData ---------------------------
+
+ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants)
+ : m_numConstants(numConstants)
+{
+ if (varStack)
+ m_varStack = *varStack;
+ if (funcStack)
+ m_functionStack = *funcStack;
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+}
+
+// ------------------------------ ScopeNode -----------------------------
+
+ScopeNode::ScopeNode(JSGlobalData* globalData)
+ : StatementNode(globalData)
+ , m_features(NoFeatures)
+{
+#if ENABLE(OPCODE_SAMPLING)
+ globalData->interpreter->sampler()->notifyOfScope(this);
+#endif
+}
+
+ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
+ : StatementNode(globalData)
+ , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants))
+ , m_features(features)
+ , m_source(source)
+{
+#if ENABLE(OPCODE_SAMPLING)
+ globalData->interpreter->sampler()->notifyOfScope(this);
+#endif
+}
+
+ScopeNode::~ScopeNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void ScopeNode::releaseNodes(NodeReleaser& releaser)
+{
+ if (!m_data)
+ return;
+ size_t size = m_data->m_children.size();
+ for (size_t i = 0; i < size; ++i)
+ releaser.release(m_data->m_children[i]);
+}
+
+// ------------------------------ ProgramNode -----------------------------
+
+ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
+{
+}
+
+ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+{
+ return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
+}
+
+RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
+
+ RefPtr<RegisterID> dstRegister = generator.newTemporary();
+ generator.emitLoad(dstRegister.get(), jsUndefined());
+ statementListEmitCode(children(), generator, dstRegister.get());
+
+ generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
+ generator.emitEnd(dstRegister.get());
+ return 0;
+}
+
+void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get());
+ generator.generate();
+
+ destroyData();
+}
+
+// ------------------------------ EvalNode -----------------------------
+
+EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
+{
+}
+
+EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+{
+ return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
+}
+
+RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
+
+ RefPtr<RegisterID> dstRegister = generator.newTemporary();
+ generator.emitLoad(dstRegister.get(), jsUndefined());
+ statementListEmitCode(children(), generator, dstRegister.get());
+
+ generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
+ generator.emitEnd(dstRegister.get());
+ return 0;
+}
+
+void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.generate();
+
+ // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
+ // so the entire ScopeNodeData cannot be destoyed.
+ children().clear();
+}
+
+EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode)
+{
+ ASSERT(!m_code);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.setRegeneratingForExceptionInfo();
+ generator.generate();
+
+ return *m_code;
+}
+
+// ------------------------------ FunctionBodyNode -----------------------------
+
+FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
+ : ScopeNode(globalData)
+ , m_parameters(0)
+ , m_parameterCount(0)
+ , m_refCount(0)
+{
+}
+
+FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
+ , m_parameters(0)
+ , m_parameterCount(0)
+ , m_refCount(0)
+{
+}
+
+FunctionBodyNode::~FunctionBodyNode()
+{
+ ASSERT(!m_refCount);
+ fastFree(m_parameters);
+}
+
+void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
+{
+ Vector<Identifier> parameters;
+ for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
+ parameters.append(parameter->ident());
+ size_t count = parameters.size();
+
+ setSource(source);
+ finishParsing(parameters.releaseBuffer(), count);
+}
+
+void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
+{
+ ASSERT(!source().isNull());
+ m_parameters = parameters;
+ m_parameterCount = parameterCount;
+}
+
+void FunctionBodyNode::mark()
+{
+ if (m_code)
+ m_code->mark();
+}
+
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
+{
+ return new FunctionBodyNode(globalData);
+}
+
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+{
+ return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
+}
+
+void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
+{
+ // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
+ // calling Parser::parse<FunctionBodyNode>().
+ if (!data())
+ scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
+ ASSERT(data());
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.generate();
+
+ destroyData();
+}
+
+CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode)
+{
+ ASSERT(!m_code);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+
+ BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
+ generator.setRegeneratingForExceptionInfo();
+ generator.generate();
+
+ return *m_code;
+}
+
+RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
+ statementListEmitCode(children(), generator, generator.ignoredResult());
+ if (!children().size() || !children().last()->isReturnNode()) {
+ RegisterID* r0 = generator.emitLoad(0, jsUndefined());
+ generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+ generator.emitReturn(r0);
+ }
+ return 0;
+}
+
+UString FunctionBodyNode::paramString() const
+{
+ UString s("");
+ for (size_t pos = 0; pos < m_parameterCount; ++pos) {
+ if (!s.isEmpty())
+ s += ", ";
+ s += parameters()[pos].ustring();
+ }
+
+ return s;
+}
+
+Identifier* FunctionBodyNode::copyParameters()
+{
+ Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
+ VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
+ return parameters;
+}
+
+// ------------------------------ FuncDeclNode ---------------------------------
+
+FuncDeclNode::~FuncDeclNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FuncDeclNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_parameter);
+ releaser.release(m_body);
+}
+
+JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
+}
+
+RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ if (dst == generator.ignoredResult())
+ dst = 0;
+ return dst;
+}
+
+// ------------------------------ FuncExprNode ---------------------------------
+
+FuncExprNode::~FuncExprNode()
+{
+ NodeReleaser::releaseAllNodes(this);
+}
+
+void FuncExprNode::releaseNodes(NodeReleaser& releaser)
+{
+ releaser.release(m_parameter);
+ releaser.release(m_body);
+}
+
+RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
+}
+
+JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
+
+ /*
+ The Identifier in a FunctionExpression can be referenced from inside
+ the FunctionExpression's FunctionBody to allow the function to call
+ itself recursively. However, unlike in a FunctionDeclaration, the
+ Identifier in a FunctionExpression cannot be referenced from and
+ does not affect the scope enclosing the FunctionExpression.
+ */
+
+ if (!m_ident.isNull()) {
+ JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
+ func->scope().push(functionScopeObject);
+ }
+
+ return func;
+}
+
+} // namespace JSC
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h
new file mode 100644
index 0000000..f8512f7
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h
@@ -0,0 +1,2418 @@
+/*
+ * 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 "Opcode.h"
+#include "ResultType.h"
+#include "SourceCode.h"
+#include "SymbolTable.h"
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(X86) && COMPILER(GCC)
+#define JSC_FAST_CALL __attribute__((regparm(3)))
+#else
+#define JSC_FAST_CALL
+#endif
+
+namespace JSC {
+
+ class CodeBlock;
+ class BytecodeGenerator;
+ class FuncDeclNode;
+ class EvalCodeBlock;
+ class JSFunction;
+ class NodeReleaser;
+ class ProgramCodeBlock;
+ class PropertyListNode;
+ class RegisterID;
+ class ScopeChainNode;
+
+ 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 AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature;
+
+ enum Operator {
+ OpEqual,
+ OpPlusEq,
+ OpMinusEq,
+ OpMultEq,
+ OpDivEq,
+ OpPlusPlus,
+ OpMinusMinus,
+ OpAndEq,
+ OpXOrEq,
+ OpOrEq,
+ OpModEq,
+ OpLShift,
+ OpRShift,
+ OpURShift
+ };
+
+ enum LogicalOperator {
+ OpLogicalAnd,
+ OpLogicalOr
+ };
+
+ namespace DeclarationStacks {
+ enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
+ typedef Vector<std::pair<Identifier, unsigned> > VarStack;
+ typedef Vector<RefPtr<FuncDeclNode> > FunctionStack;
+ }
+
+ struct SwitchInfo {
+ enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString };
+ uint32_t bytecodeOffset;
+ SwitchType switchType;
+ };
+
+ class ParserRefCounted : Noncopyable {
+ protected:
+ ParserRefCounted(JSGlobalData*) JSC_FAST_CALL;
+
+ public:
+ virtual ~ParserRefCounted();
+
+ // Nonrecursive destruction.
+ virtual void releaseNodes(NodeReleaser&);
+
+ void ref() JSC_FAST_CALL;
+ void deref() JSC_FAST_CALL;
+ bool hasOneRef() JSC_FAST_CALL;
+
+ static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL;
+
+ private:
+ JSGlobalData* m_globalData;
+ };
+
+ class Node : public ParserRefCounted {
+ public:
+ Node(JSGlobalData*) JSC_FAST_CALL;
+
+ /*
+ Return value: The register holding the production's value.
+ dst: An optional parameter specifying the most efficient
+ destination at which to store the production's value.
+ The callee must honor dst.
+
+ dst provides for a crude form of copy propagation. For example,
+
+ x = 1
+
+ becomes
+
+ load r[x], 1
+
+ instead of
+
+ load r0, 1
+ mov r[x], r0
+
+ because the assignment node, "x =", passes r[x] as dst to the number
+ node, "1".
+ */
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL = 0;
+
+ int lineNo() const { return m_line; }
+
+ protected:
+ int m_line;
+ };
+
+ class ExpressionNode : public Node {
+ public:
+ ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknown()) JSC_FAST_CALL
+ : Node(globalData)
+ , m_resultDesc(resultDesc)
+ {
+ }
+
+ virtual bool isNumber() const JSC_FAST_CALL { return false; }
+ virtual bool isString() const JSC_FAST_CALL { return false; }
+ virtual bool isNull() const JSC_FAST_CALL { return false; }
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return false; }
+ virtual bool isLocation() const JSC_FAST_CALL { return false; }
+ virtual bool isResolveNode() const JSC_FAST_CALL { return false; }
+ virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; }
+ virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; }
+ virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; }
+
+ virtual ExpressionNode* stripUnaryPlus() { return this; }
+
+ ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; }
+
+ // This needs to be in public in order to compile using GCC 3.x
+ typedef enum { EvalOperator, FunctionCall } CallerType;
+
+ private:
+ ResultType m_resultDesc;
+ };
+
+ class StatementNode : public Node {
+ public:
+ StatementNode(JSGlobalData*) JSC_FAST_CALL;
+ void setLoc(int line0, int line1) JSC_FAST_CALL;
+ int firstLine() const JSC_FAST_CALL { return lineNo(); }
+ int lastLine() const JSC_FAST_CALL { return m_lastLine; }
+
+ virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; }
+ virtual bool isReturnNode() const JSC_FAST_CALL { return false; }
+ virtual bool isExprStatement() const JSC_FAST_CALL { return false; }
+
+ virtual bool isBlock() const JSC_FAST_CALL { return false; }
+ virtual bool isLoop() const JSC_FAST_CALL { return false; }
+
+ private:
+ int m_lastLine;
+ };
+
+ class NullNode : public ExpressionNode {
+ public:
+ NullNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::nullType())
+ {
+ }
+
+ virtual bool isNull() const JSC_FAST_CALL { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class BooleanNode : public ExpressionNode {
+ public:
+ BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::boolean())
+ , m_value(value)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+
+ private:
+ bool m_value;
+ };
+
+ class NumberNode : public ExpressionNode {
+ public:
+ NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::constNumber())
+ , m_double(v)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isNumber() const JSC_FAST_CALL { return true; }
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+ double value() const JSC_FAST_CALL { return m_double; }
+ void setValue(double d) JSC_FAST_CALL { m_double = d; }
+
+ private:
+ double m_double;
+ };
+
+ class StringNode : public ExpressionNode {
+ public:
+ StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::string())
+ , m_value(v)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isString() const JSC_FAST_CALL { return true; }
+ const Identifier& value() { return m_value; }
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; }
+
+ private:
+ 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* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg);
+ RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&);
+
+ private:
+ uint32_t m_divot;
+ uint16_t m_startOffset;
+ uint16_t m_endOffset;
+ };
+
+ class ThrowableSubExpressionData : public ThrowableExpressionData {
+ public:
+ ThrowableSubExpressionData()
+ : ThrowableExpressionData()
+ , 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()
+ : ThrowableExpressionData()
+ , 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* globalData, const UString& pattern, const UString& flags) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_pattern(pattern)
+ , m_flags(flags)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ UString m_pattern;
+ UString m_flags;
+ };
+
+ class ThisNode : public ExpressionNode {
+ public:
+ ThisNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class ResolveNode : public ExpressionNode {
+ public:
+ ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_startOffset(startOffset)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL;
+ virtual bool isLocation() const JSC_FAST_CALL { return true; }
+ virtual bool isResolveNode() const JSC_FAST_CALL { return true; }
+ const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+
+ private:
+ Identifier m_ident;
+ int32_t m_startOffset;
+ };
+
+ class ElementNode : public ParserRefCounted {
+ public:
+ ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_elision(elision)
+ , m_node(node)
+ {
+ }
+
+ ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_elision(elision)
+ , m_node(node)
+ {
+ l->m_next = this;
+ }
+
+ virtual ~ElementNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ int elision() const { return m_elision; }
+ ExpressionNode* value() { return m_node.get(); }
+
+ ElementNode* next() { return m_next.get(); }
+
+ private:
+ RefPtr<ElementNode> m_next;
+ int m_elision;
+ RefPtr<ExpressionNode> m_node;
+ };
+
+ class ArrayNode : public ExpressionNode {
+ public:
+ ArrayNode(JSGlobalData* globalData, int elision) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_elision(elision)
+ , m_optional(true)
+ {
+ }
+
+ ArrayNode(JSGlobalData* globalData, ElementNode* element) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_element(element)
+ , m_elision(0)
+ , m_optional(false)
+ {
+ }
+
+ ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_element(element)
+ , m_elision(elision)
+ , m_optional(true)
+ {
+ }
+
+ virtual ~ArrayNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ElementNode> m_element;
+ int m_elision;
+ bool m_optional;
+ };
+
+ class PropertyNode : public ParserRefCounted {
+ public:
+ enum Type { Constant, Getter, Setter };
+
+ PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_name(name)
+ , m_assign(assign)
+ , m_type(type)
+ {
+ }
+
+ virtual ~PropertyNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ const Identifier& name() const { return m_name; }
+
+ private:
+ friend class PropertyListNode;
+ Identifier m_name;
+ RefPtr<ExpressionNode> m_assign;
+ Type m_type;
+ };
+
+ class PropertyListNode : public Node {
+ public:
+ PropertyListNode(JSGlobalData* globalData, PropertyNode* node) JSC_FAST_CALL
+ : Node(globalData)
+ , m_node(node)
+ {
+ }
+
+ PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) JSC_FAST_CALL
+ : Node(globalData)
+ , m_node(node)
+ {
+ list->m_next = this;
+ }
+
+ virtual ~PropertyListNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<PropertyNode> m_node;
+ RefPtr<PropertyListNode> m_next;
+ };
+
+ class ObjectLiteralNode : public ExpressionNode {
+ public:
+ ObjectLiteralNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ {
+ }
+
+ ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_list(list)
+ {
+ }
+
+ virtual ~ObjectLiteralNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<PropertyListNode> m_list;
+ };
+
+ class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ {
+ }
+
+ virtual ~BracketAccessorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLocation() const JSC_FAST_CALL { return true; }
+ virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; }
+ ExpressionNode* base() JSC_FAST_CALL { return m_base.get(); }
+ ExpressionNode* subscript() JSC_FAST_CALL { return m_subscript.get(); }
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ bool m_subscriptHasAssignments;
+ };
+
+ class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_base(base)
+ , m_ident(ident)
+ {
+ }
+
+ virtual ~DotAccessorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLocation() const JSC_FAST_CALL { return true; }
+ virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; }
+ ExpressionNode* base() const JSC_FAST_CALL { return m_base.get(); }
+ const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ };
+
+ class ArgumentListNode : public Node {
+ public:
+ ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : Node(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) JSC_FAST_CALL
+ : Node(globalData)
+ , m_expr(expr)
+ {
+ listNode->m_next = this;
+ }
+
+ virtual ~ArgumentListNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ RefPtr<ArgumentListNode> m_next;
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class ArgumentsNode : public ParserRefCounted {
+ public:
+ ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ {
+ }
+
+ ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_listNode(listNode)
+ {
+ }
+
+ virtual ~ArgumentsNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ RefPtr<ArgumentListNode> m_listNode;
+ };
+
+ class NewExprNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ , m_args(args)
+ {
+ }
+
+ virtual ~NewExprNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_args(args)
+ {
+ }
+
+ virtual ~EvalFunctionCallNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallValueNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallResolveNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ RefPtr<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* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_args(args)
+ {
+ }
+
+ virtual ~FunctionCallDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ RefPtr<ArgumentsNode> m_args;
+ };
+
+ class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::constNumber()) // could be reusable for pre?
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ {
+ }
+
+ protected:
+ Identifier m_ident;
+ };
+
+ class PostfixResolveNode : public PrePostResolveNode {
+ public:
+ PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+ , m_operator(oper)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Operator m_operator;
+ };
+
+ class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PostfixBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ Operator m_operator;
+ };
+
+ class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PostfixDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ Operator m_operator;
+ };
+
+ class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PostfixErrorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ Operator m_operator;
+ };
+
+ class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ };
+
+ class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ {
+ }
+
+ virtual ~DeleteBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ };
+
+ class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ {
+ }
+
+ virtual ~DeleteDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ };
+
+ class DeleteValueNode : public ExpressionNode {
+ public:
+ DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~DeleteValueNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class VoidNode : public ExpressionNode {
+ public:
+ VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~VoidNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class TypeOfResolveNode : public ExpressionNode {
+ public:
+ TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::string())
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
+
+ private:
+ Identifier m_ident;
+ };
+
+ class TypeOfValueNode : public ExpressionNode {
+ public:
+ TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::string())
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~TypeOfValueNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class PrefixResolveNode : public PrePostResolveNode {
+ public:
+ PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+ , m_operator(oper)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Operator m_operator;
+ };
+
+ class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
+ public:
+ PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PrefixBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ Operator m_operator;
+ };
+
+ class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
+ public:
+ PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PrefixDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ Operator m_operator;
+ };
+
+ class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_expr(expr)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~PrefixErrorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ Operator m_operator;
+ };
+
+ class UnaryOpNode : public ExpressionNode {
+ public:
+ UnaryOpNode(JSGlobalData* globalData, ExpressionNode* expr)
+ : ExpressionNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr)
+ : ExpressionNode(globalData, type)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~UnaryOpNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0;
+
+ protected:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class UnaryPlusNode : public UnaryOpNode {
+ public:
+ UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::constNumber(), expr)
+ {
+ }
+
+ virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; }
+ };
+
+ class NegateNode : public UnaryOpNode {
+ public:
+ NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::reusableNumber(), expr)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_negate; }
+ };
+
+ class BitwiseNotNode : public UnaryOpNode {
+ public:
+ BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::reusableNumber(), expr)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitnot; }
+ };
+
+ class LogicalNotNode : public UnaryOpNode {
+ public:
+ LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : UnaryOpNode(globalData, ResultType::boolean(), expr)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_not; }
+ };
+
+ class BinaryOpNode : public ExpressionNode {
+ public:
+ BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ExpressionNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : ExpressionNode(globalData, type)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~BinaryOpNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0;
+
+ protected:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ bool m_rightHasAssignments;
+ };
+
+ class ReverseBinaryOpNode : public BinaryOpNode {
+ public:
+ ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class MultNode : public BinaryOpNode {
+ public:
+ MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mul; }
+ };
+
+ class DivNode : public BinaryOpNode {
+ public:
+ DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_div; }
+ };
+
+ class ModNode : public BinaryOpNode {
+ public:
+ ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mod; }
+ };
+
+ class AddNode : public BinaryOpNode {
+ public:
+ AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; }
+ };
+
+ class SubNode : public BinaryOpNode {
+ public:
+ SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_sub; }
+ };
+
+ class LeftShiftNode : public BinaryOpNode {
+ public:
+ LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lshift; }
+ };
+
+ class RightShiftNode : public BinaryOpNode {
+ public:
+ RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_rshift; }
+ };
+
+ class UnsignedRightShiftNode : public BinaryOpNode {
+ public:
+ UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_urshift; }
+ };
+
+ class LessNode : public BinaryOpNode {
+ public:
+ LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; }
+ };
+
+ class GreaterNode : public ReverseBinaryOpNode {
+ public:
+ GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; }
+ };
+
+ class LessEqNode : public BinaryOpNode {
+ public:
+ LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; }
+ };
+
+ class GreaterEqNode : public ReverseBinaryOpNode {
+ public:
+ GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; }
+ };
+
+ class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData {
+ public:
+ ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments)
+ {
+ }
+ ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
+ {
+ }
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class InstanceOfNode : public ThrowableBinaryOpNode {
+ public:
+ InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ThrowableBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_instanceof; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class InNode : public ThrowableBinaryOpNode {
+ public:
+ InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : ThrowableBinaryOpNode(globalData, expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_in; }
+ };
+
+ class EqualNode : public BinaryOpNode {
+ public:
+ EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; }
+ };
+
+ class NotEqualNode : public BinaryOpNode {
+ public:
+ NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_neq; }
+ };
+
+ class StrictEqualNode : public BinaryOpNode {
+ public:
+ StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; }
+ };
+
+ class NotStrictEqualNode : public BinaryOpNode {
+ public:
+ NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_nstricteq; }
+ };
+
+ class BitAndNode : public BinaryOpNode {
+ public:
+ BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitand; }
+ };
+
+ class BitOrNode : public BinaryOpNode {
+ public:
+ BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitor; }
+ };
+
+ class BitXOrNode : public BinaryOpNode {
+ public:
+ BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
+ : BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
+ {
+ }
+
+ virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitxor; }
+ };
+
+ /**
+ * m_expr1 && m_expr2, m_expr1 || m_expr2
+ */
+ class LogicalOpNode : public ExpressionNode {
+ public:
+ LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL
+ : ExpressionNode(globalData, ResultType::boolean())
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_operator(oper)
+ {
+ }
+
+ virtual ~LogicalOpNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ LogicalOperator m_operator;
+ };
+
+ /**
+ * The ternary operator, "m_logical ? m_expr1 : m_expr2"
+ */
+ class ConditionalNode : public ExpressionNode {
+ public:
+ ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_logical(logical)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ {
+ }
+
+ virtual ~ConditionalNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_logical;
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ };
+
+ class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_ident(ident)
+ , m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~ReadModifyResolveNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~AssignResolveNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ bool m_rightHasAssignments;
+ };
+
+ class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_right(right)
+ , m_operator(oper)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~ReadModifyBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ RefPtr<ExpressionNode> m_right;
+ Operator m_operator : 30;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_subscript(subscript)
+ , m_right(right)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~AssignBracketNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ RefPtr<ExpressionNode> m_subscript;
+ RefPtr<ExpressionNode> m_right;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignDotNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~AssignDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ bool m_rightHasAssignments;
+ };
+
+ class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableSubExpressionData(divot, startOffset, endOffset)
+ , m_base(base)
+ , m_ident(ident)
+ , m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
+ {
+ }
+
+ virtual ~ReadModifyDotNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_base;
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_right;
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_left(left)
+ , m_operator(oper)
+ , m_right(right)
+ {
+ }
+
+ virtual ~AssignErrorNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_left;
+ Operator m_operator;
+ RefPtr<ExpressionNode> m_right;
+ };
+
+ class CommaNode : public ExpressionNode {
+ public:
+ CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ {
+ }
+
+ virtual ~CommaNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ };
+
+ class VarDeclCommaNode : public CommaNode {
+ public:
+ VarDeclCommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL
+ : CommaNode(globalData, expr1, expr2)
+ {
+ }
+ };
+
+ class ConstDeclNode : public ExpressionNode {
+ public:
+ ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL;
+
+ virtual ~ConstDeclNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ Identifier m_ident;
+ RefPtr<ConstDeclNode> m_next;
+ RefPtr<ExpressionNode> m_init;
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual RegisterID* emitCodeSingle(BytecodeGenerator&) JSC_FAST_CALL;
+ };
+
+ class ConstStatementNode : public StatementNode {
+ public:
+ ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_next(next)
+ {
+ }
+
+ virtual ~ConstStatementNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ConstDeclNode> m_next;
+ };
+
+ typedef Vector<RefPtr<StatementNode> > StatementVector;
+
+ class SourceElements : public ParserRefCounted {
+ public:
+ SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {}
+
+ void append(PassRefPtr<StatementNode>);
+ void releaseContentsIntoVector(StatementVector& destination)
+ {
+ ASSERT(destination.isEmpty());
+ m_statements.swap(destination);
+ destination.shrinkToFit();
+ }
+
+ private:
+ StatementVector m_statements;
+ };
+
+ class BlockNode : public StatementNode {
+ public:
+ BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL;
+
+ virtual ~BlockNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ StatementVector& children() { return m_children; }
+
+ virtual bool isBlock() const JSC_FAST_CALL { return true; }
+
+ private:
+ StatementVector m_children;
+ };
+
+ class EmptyStatementNode : public StatementNode {
+ public:
+ EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug
+ : StatementNode(globalData)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; }
+ };
+
+ class DebuggerStatementNode : public StatementNode {
+ public:
+ DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : StatementNode(globalData)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ };
+
+ class ExprStatementNode : public StatementNode {
+ public:
+ ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual bool isExprStatement() const JSC_FAST_CALL { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ ExpressionNode* expr() const { return m_expr.get(); }
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class VarStatementNode : public StatementNode {
+ public:
+ VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~VarStatementNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class IfNode : public StatementNode {
+ public:
+ IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_condition(condition)
+ , m_ifBlock(ifBlock)
+ {
+ }
+
+ virtual ~IfNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ protected:
+ RefPtr<ExpressionNode> m_condition;
+ RefPtr<StatementNode> m_ifBlock;
+ };
+
+ class IfElseNode : public IfNode {
+ public:
+ IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) JSC_FAST_CALL
+ : IfNode(globalData, condition, ifBlock)
+ , m_elseBlock(elseBlock)
+ {
+ }
+
+ virtual ~IfElseNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<StatementNode> m_elseBlock;
+ };
+
+ class DoWhileNode : public StatementNode {
+ public:
+ DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_statement(statement)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~DoWhileNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<StatementNode> m_statement;
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class WhileNode : public StatementNode {
+ public:
+ WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_statement(statement)
+ {
+ }
+
+ virtual ~WhileNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<StatementNode> m_statement;
+ };
+
+ class ForNode : public StatementNode {
+ public:
+ ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr1(expr1)
+ , m_expr2(expr2)
+ , m_expr3(expr3)
+ , m_statement(statement)
+ , m_expr1WasVarDecl(expr1 && expr1WasVarDecl)
+ {
+ ASSERT(statement);
+ }
+
+ virtual ~ForNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<ExpressionNode> m_expr1;
+ RefPtr<ExpressionNode> m_expr2;
+ RefPtr<ExpressionNode> m_expr3;
+ RefPtr<StatementNode> m_statement;
+ bool m_expr1WasVarDecl;
+ };
+
+ class ForInNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL;
+ ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL;
+
+ virtual ~ForInNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ virtual bool isLoop() const JSC_FAST_CALL { return true; }
+
+ private:
+ Identifier m_ident;
+ RefPtr<ExpressionNode> m_init;
+ RefPtr<ExpressionNode> m_lexpr;
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<StatementNode> m_statement;
+ bool m_identIsVarDecl;
+ };
+
+ class ContinueNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ContinueNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : StatementNode(globalData)
+ {
+ }
+
+ ContinueNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ };
+
+ class BreakNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ BreakNode(JSGlobalData* globalData) JSC_FAST_CALL
+ : StatementNode(globalData)
+ {
+ }
+
+ BreakNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_ident;
+ };
+
+ class ReturnNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_value(value)
+ {
+ }
+
+ virtual ~ReturnNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ virtual bool isReturnNode() const JSC_FAST_CALL { return true; }
+
+ private:
+ RefPtr<ExpressionNode> m_value;
+ };
+
+ class WithNode : public StatementNode {
+ public:
+ WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_statement(statement)
+ , m_divot(divot)
+ , m_expressionLength(expressionLength)
+ {
+ }
+
+ virtual ~WithNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<StatementNode> m_statement;
+ uint32_t m_divot;
+ uint32_t m_expressionLength;
+ };
+
+ class LabelNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_name(name)
+ , m_statement(statement)
+ {
+ }
+
+ virtual ~LabelNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ Identifier m_name;
+ RefPtr<StatementNode> m_statement;
+ };
+
+ class ThrowNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ virtual ~ThrowNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ };
+
+ class TryNode : public StatementNode {
+ public:
+ TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_tryBlock(tryBlock)
+ , m_exceptionIdent(exceptionIdent)
+ , m_catchBlock(catchBlock)
+ , m_finallyBlock(finallyBlock)
+ , m_catchHasEval(catchHasEval)
+ {
+ }
+
+ virtual ~TryNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<StatementNode> m_tryBlock;
+ Identifier m_exceptionIdent;
+ RefPtr<StatementNode> m_catchBlock;
+ RefPtr<StatementNode> m_finallyBlock;
+ bool m_catchHasEval;
+ };
+
+ class ParameterNode : public ParserRefCounted {
+ public:
+ ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_ident(ident)
+ {
+ }
+
+ ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_ident(ident)
+ {
+ l->m_next = this;
+ }
+
+ virtual ~ParameterNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ const Identifier& ident() const JSC_FAST_CALL { return m_ident; }
+ ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); }
+
+ private:
+ Identifier m_ident;
+ RefPtr<ParameterNode> m_next;
+ };
+
+ struct ScopeNodeData {
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants);
+
+ VarStack m_varStack;
+ FunctionStack m_functionStack;
+ int m_numConstants;
+ StatementVector m_children;
+ };
+
+ class ScopeNode : public StatementNode {
+ public:
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ ScopeNode(JSGlobalData*) JSC_FAST_CALL;
+ ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ virtual ~ScopeNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ void adoptData(std::auto_ptr<ScopeNodeData> data) { m_data.adopt(data); }
+ ScopeNodeData* data() const { return m_data.get(); }
+ void destroyData() { m_data.clear(); }
+
+ const SourceCode& source() const { return m_source; }
+ const UString& sourceURL() const JSC_FAST_CALL { 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; }
+ void setUsesArguments() { m_features |= ArgumentsFeature; }
+ bool usesThis() const { return m_features & ThisFeature; }
+ bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
+
+ VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
+ FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
+
+ StatementVector& children() { ASSERT(m_data); return m_data->m_children; }
+
+ 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;
+ }
+
+ 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 ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ {
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
+ }
+
+ private:
+ ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ OwnPtr<ProgramCodeBlock> m_code;
+ };
+
+ class EvalNode : public ScopeNode {
+ public:
+ static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ {
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
+ }
+
+ EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*) JSC_FAST_CALL;
+
+ private:
+ EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ OwnPtr<EvalCodeBlock> m_code;
+ };
+
+ class FunctionBodyNode : public ScopeNode {
+ friend class JIT;
+ public:
+ static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL;
+ static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+ virtual ~FunctionBodyNode();
+
+ const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; }
+ size_t parameterCount() const { return m_parameterCount; }
+ UString paramString() const JSC_FAST_CALL;
+ Identifier* copyParameters();
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ CodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL
+ {
+ ASSERT(scopeChain);
+ if (!m_code)
+ generateBytecode(scopeChain);
+ return *m_code;
+ }
+
+ CodeBlock& generatedBytecode() JSC_FAST_CALL
+ {
+ ASSERT(m_code);
+ return *m_code;
+ }
+
+ bool isGenerated() JSC_FAST_CALL
+ {
+ return m_code;
+ }
+
+ void mark();
+
+ void finishParsing(const SourceCode&, ParameterNode*);
+ void finishParsing(Identifier* parameters, size_t parameterCount);
+
+ UString toSourceString() const JSC_FAST_CALL { return UString("{") + source().toString() + UString("}"); }
+
+ // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref.
+ // If the virtual machine changes so this doesn't happen as much we can change back.
+ void ref()
+ {
+ if (++m_refCount == 1)
+ ScopeNode::ref();
+ }
+ void deref()
+ {
+ ASSERT(m_refCount);
+ if (!--m_refCount)
+ ScopeNode::deref();
+ }
+
+ CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChain) JSC_FAST_CALL;
+
+ private:
+ FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL;
+ FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
+
+ void generateBytecode(ScopeChainNode*) JSC_FAST_CALL;
+
+ Identifier* m_parameters;
+ size_t m_parameterCount;
+ OwnPtr<CodeBlock> m_code;
+ unsigned m_refCount;
+ };
+
+ class FuncExprNode : public ExpressionNode {
+ public:
+ FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL
+ : ExpressionNode(globalData)
+ , m_ident(ident)
+ , m_parameter(parameter)
+ , m_body(body)
+ {
+ m_body->finishParsing(source, m_parameter.get());
+ }
+
+ virtual ~FuncExprNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+ JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
+
+ FunctionBodyNode* body() { return m_body.get(); }
+
+ private:
+ Identifier m_ident;
+ RefPtr<ParameterNode> m_parameter;
+ RefPtr<FunctionBodyNode> m_body;
+ };
+
+ class FuncDeclNode : public StatementNode {
+ public:
+ FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_ident(ident)
+ , m_parameter(parameter)
+ , m_body(body)
+ {
+ m_body->finishParsing(source, m_parameter.get());
+ }
+
+ virtual ~FuncDeclNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
+
+ Identifier m_ident;
+
+ FunctionBodyNode* body() { return m_body.get(); }
+
+ private:
+ RefPtr<ParameterNode> m_parameter;
+ RefPtr<FunctionBodyNode> m_body;
+ };
+
+ class CaseClauseNode : public ParserRefCounted {
+ public:
+ CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_expr(expr)
+ {
+ }
+
+ CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_expr(expr)
+ {
+ if (children)
+ children->releaseContentsIntoVector(m_children);
+ }
+
+ virtual ~CaseClauseNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ ExpressionNode* expr() const { return m_expr.get(); }
+ StatementVector& children() { return m_children; }
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ StatementVector m_children;
+ };
+
+ class ClauseListNode : public ParserRefCounted {
+ public:
+ ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_clause(clause)
+ {
+ }
+
+ ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_clause(clause)
+ {
+ clauseList->m_next = this;
+ }
+
+ virtual ~ClauseListNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); }
+ ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); }
+
+ private:
+ RefPtr<CaseClauseNode> m_clause;
+ RefPtr<ClauseListNode> m_next;
+ };
+
+ class CaseBlockNode : public ParserRefCounted {
+ public:
+ CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL
+ : ParserRefCounted(globalData)
+ , m_list1(list1)
+ , m_defaultClause(defaultClause)
+ , m_list2(list2)
+ {
+ }
+
+ virtual ~CaseBlockNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL;
+
+ private:
+ SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
+ RefPtr<ClauseListNode> m_list1;
+ RefPtr<CaseClauseNode> m_defaultClause;
+ RefPtr<ClauseListNode> m_list2;
+ };
+
+ class SwitchNode : public StatementNode {
+ public:
+ SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) JSC_FAST_CALL
+ : StatementNode(globalData)
+ , m_expr(expr)
+ , m_block(block)
+ {
+ }
+
+ virtual ~SwitchNode();
+ virtual void releaseNodes(NodeReleaser&);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
+
+ private:
+ RefPtr<ExpressionNode> m_expr;
+ RefPtr<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_
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Parser.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/Parser.cpp
new file mode 100644
index 0000000..1b1e4d7
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Parser.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 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.
+ *
+ */
+
+#include "config.h"
+#include "Parser.h"
+
+#include "Debugger.h"
+#include "Lexer.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+#include <memory>
+
+using std::auto_ptr;
+
+extern int jscyyparse(void*);
+
+namespace JSC {
+
+void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
+{
+ ASSERT(!m_sourceElements);
+
+ int defaultErrLine;
+ UString defaultErrMsg;
+
+ if (!errLine)
+ errLine = &defaultErrLine;
+ if (!errMsg)
+ errMsg = &defaultErrMsg;
+
+ *errLine = -1;
+ *errMsg = 0;
+
+ Lexer& lexer = *globalData->lexer;
+ lexer.setCode(*m_source);
+
+ int parseError = jscyyparse(globalData);
+ bool lexError = lexer.sawError();
+ lexer.clear();
+
+ ParserRefCounted::deleteNewObjects(globalData);
+
+ if (parseError || lexError) {
+ *errLine = lexer.lineNo();
+ *errMsg = "Parse error";
+ m_sourceElements.clear();
+ }
+}
+
+void Parser::reparseInPlace(JSGlobalData* globalData, FunctionBodyNode* functionBodyNode)
+{
+ ASSERT(!functionBodyNode->data());
+
+ m_source = &functionBodyNode->source();
+ globalData->lexer->setIsReparsing();
+ parse(globalData, 0, 0);
+ ASSERT(m_sourceElements);
+
+ functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(m_sourceElements.get(),
+ m_varDeclarations ? &m_varDeclarations->data : 0,
+ m_funcDeclarations ? &m_funcDeclarations->data : 0,
+ m_numConstants)));
+ bool usesArguments = functionBodyNode->usesArguments();
+ functionBodyNode->setFeatures(m_features);
+ if (usesArguments && !functionBodyNode->usesArguments())
+ functionBodyNode->setUsesArguments();
+
+ m_source = 0;
+ m_sourceElements = 0;
+ m_varDeclarations = 0;
+ m_funcDeclarations = 0;
+}
+
+void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack,
+ ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
+{
+ m_sourceElements = sourceElements;
+ m_varDeclarations = varStack;
+ m_funcDeclarations = funcStack;
+ m_features = features;
+ m_lastLine = lastLine;
+ m_numConstants = numConstants;
+}
+
+} // namespace JSC
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h b/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h
new file mode 100644
index 0000000..6191ccb
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 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 Parser_h
+#define Parser_h
+
+#include "SourceProvider.h"
+#include "Debugger.h"
+#include "Nodes.h"
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class FunctionBodyNode;
+ class ProgramNode;
+ class UString;
+
+ template <typename T>
+ struct ParserRefCountedData : ParserRefCounted {
+ ParserRefCountedData(JSGlobalData* globalData)
+ : ParserRefCounted(globalData)
+ {
+ }
+
+ T data;
+ };
+
+ class Parser : Noncopyable {
+ public:
+ template <class ParsedNode> PassRefPtr<ParsedNode> parse(ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
+ template <class ParsedNode> PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*);
+ void reparseInPlace(JSGlobalData*, FunctionBodyNode*);
+
+ void didFinishParsing(SourceElements*, ParserRefCountedData<DeclarationStacks::VarStack>*,
+ ParserRefCountedData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
+
+ private:
+ void parse(JSGlobalData*, int* errLine, UString* errMsg);
+
+ const SourceCode* m_source;
+ RefPtr<SourceElements> m_sourceElements;
+ RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations;
+ RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations;
+ CodeFeatures m_features;
+ int m_lastLine;
+ int m_numConstants;
+ };
+
+ template <class ParsedNode> PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+ {
+ m_source = &source;
+ parse(&exec->globalData(), errLine, errMsg);
+ RefPtr<ParsedNode> result;
+ if (m_sourceElements) {
+ result = ParsedNode::create(&exec->globalData(),
+ m_sourceElements.get(),
+ m_varDeclarations ? &m_varDeclarations->data : 0,
+ m_funcDeclarations ? &m_funcDeclarations->data : 0,
+ *m_source,
+ m_features,
+ m_numConstants);
+ result->setLoc(m_source->firstLine(), m_lastLine);
+ }
+
+ m_source = 0;
+ m_sourceElements = 0;
+ m_varDeclarations = 0;
+ m_funcDeclarations = 0;
+
+ if (debugger)
+ debugger->sourceParsed(exec, source, *errLine, *errMsg);
+ return result.release();
+ }
+
+ template <class ParsedNode> PassRefPtr<ParsedNode> Parser::reparse(JSGlobalData* globalData, ParsedNode* oldParsedNode)
+ {
+ m_source = &oldParsedNode->source();
+ parse(globalData, 0, 0);
+ RefPtr<ParsedNode> result;
+ if (m_sourceElements) {
+ result = ParsedNode::create(globalData,
+ m_sourceElements.get(),
+ m_varDeclarations ? &m_varDeclarations->data : 0,
+ m_funcDeclarations ? &m_funcDeclarations->data : 0,
+ *m_source,
+ oldParsedNode->features(),
+ m_numConstants);
+ result->setLoc(m_source->firstLine(), m_lastLine);
+ }
+
+ m_source = 0;
+ m_sourceElements = 0;
+ m_varDeclarations = 0;
+ m_funcDeclarations = 0;
+
+ return result.release();
+ }
+
+} // namespace JSC
+
+#endif // Parser_h
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/ResultType.h b/src/3rdparty/webkit/JavaScriptCore/parser/ResultType.h
new file mode 100644
index 0000000..4913887
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/ResultType.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ResultType_h
+#define ResultType_h
+
+namespace JSC {
+
+ struct ResultType {
+ friend struct OperandTypes;
+
+ typedef char Type;
+ static const Type TypeReusable = 1;
+
+ static const Type TypeMaybeNumber = 2;
+ static const Type TypeMaybeString = 4;
+ static const Type TypeMaybeNull = 8;
+ static const Type TypeMaybeBool = 16;
+ static const Type TypeMaybeOther = 32;
+
+ static const Type TypeReusableNumber = 3;
+ static const Type TypeStringOrReusableNumber = 4;
+
+ explicit ResultType(Type type)
+ : m_type(type)
+ {
+ }
+
+ bool isReusable()
+ {
+ return (m_type & TypeReusable);
+ }
+
+ bool definitelyIsNumber()
+ {
+ return ((m_type & ~TypeReusable) == TypeMaybeNumber);
+ }
+
+ bool isNotNumber()
+ {
+ return ((m_type & TypeMaybeNumber) == 0);
+ }
+
+ bool mightBeNumber()
+ {
+ return !isNotNumber();
+ }
+
+ static ResultType nullType()
+ {
+ return ResultType(TypeMaybeNull);
+ }
+
+ static ResultType boolean()
+ {
+ return ResultType(TypeMaybeBool);
+ }
+
+ static ResultType constNumber()
+ {
+ return ResultType(TypeMaybeNumber);
+ }
+
+ static ResultType reusableNumber()
+ {
+ return ResultType(TypeReusable | TypeMaybeNumber);
+ }
+
+ static ResultType reusableNumberOrString()
+ {
+ return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString);
+ }
+
+ static ResultType string()
+ {
+ return ResultType(TypeMaybeString);
+ }
+
+ static ResultType unknown()
+ {
+ return ResultType(TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther);
+ }
+
+ static ResultType forAdd(ResultType op1, ResultType op2)
+ {
+ if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
+ return reusableNumber();
+ if (op1.isNotNumber() || op2.isNotNumber())
+ return string();
+ return reusableNumberOrString();
+ }
+
+ private:
+ Type m_type;
+ };
+
+ struct OperandTypes
+ {
+ OperandTypes(ResultType first = ResultType::unknown(), ResultType second = ResultType::unknown())
+ {
+ m_u.rds.first = first.m_type;
+ m_u.rds.second = second.m_type;
+ }
+
+ union {
+ struct {
+ ResultType::Type first;
+ ResultType::Type second;
+ } rds;
+ int i;
+ } m_u;
+
+ ResultType first()
+ {
+ return ResultType(m_u.rds.first);
+ }
+
+ ResultType second()
+ {
+ return ResultType(m_u.rds.second);
+ }
+
+ int toInt()
+ {
+ return m_u.i;
+ }
+ static OperandTypes fromInt(int value)
+ {
+ OperandTypes types;
+ types.m_u.i = value;
+ return types;
+ }
+ };
+
+} // namespace JSC
+
+#endif // ResultType_h
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h b/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h
new file mode 100644
index 0000000..84360b8
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SourceCode_h
+#define SourceCode_h
+
+#include "SourceProvider.h"
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class SourceCode {
+ public:
+ SourceCode()
+ : m_startChar(0)
+ , m_endChar(0)
+ , m_firstLine(0)
+ {
+ }
+
+ SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 1)
+ : m_provider(provider)
+ , m_startChar(0)
+ , m_endChar(m_provider->length())
+ , m_firstLine(std::max(firstLine, 1))
+ {
+ }
+
+ SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine)
+ : m_provider(provider)
+ , m_startChar(start)
+ , m_endChar(end)
+ , m_firstLine(std::max(firstLine, 1))
+ {
+ }
+
+ UString toString() const
+ {
+ if (!m_provider)
+ return UString();
+ return m_provider->getRange(m_startChar, m_endChar);
+ }
+
+ bool isNull() const { return !m_provider; }
+ SourceProvider* provider() const { return m_provider.get(); }
+ int firstLine() const { return m_firstLine; }
+ int startOffset() const { return m_startChar; }
+ int endOffset() const { return m_endChar; }
+ const UChar* data() const { return m_provider->data() + m_startChar; }
+ int length() const { return m_endChar - m_startChar; }
+
+ private:
+ RefPtr<SourceProvider> m_provider;
+ int m_startChar;
+ int m_endChar;
+ int m_firstLine;
+ };
+
+ inline SourceCode makeSource(const UString& source, const UString& url = UString(), int firstLine = 1)
+ {
+ return SourceCode(UStringSourceProvider::create(source, url), firstLine);
+ }
+
+} // namespace JSC
+
+#endif // SourceCode_h
diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/SourceProvider.h b/src/3rdparty/webkit/JavaScriptCore/parser/SourceProvider.h
new file mode 100644
index 0000000..07da9e0
--- /dev/null
+++ b/src/3rdparty/webkit/JavaScriptCore/parser/SourceProvider.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SourceProvider_h
+#define SourceProvider_h
+
+#include "UString.h"
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+ class SourceProvider : public RefCounted<SourceProvider> {
+ public:
+ SourceProvider(const UString& url)
+ : m_url(url)
+ {
+ }
+ virtual ~SourceProvider() { }
+
+ virtual UString getRange(int start, int end) const = 0;
+ virtual const UChar* data() const = 0;
+ virtual int length() const = 0;
+
+ const UString& url() { return m_url; }
+ intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
+
+ private:
+ UString m_url;
+ };
+
+ class UStringSourceProvider : public SourceProvider {
+ public:
+ static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url)
+ {
+ return adoptRef(new UStringSourceProvider(source, url));
+ }
+
+ UString getRange(int start, int end) const { return m_source.substr(start, end - start); }
+ const UChar* data() const { return m_source.data(); }
+ int length() const { return m_source.size(); }
+
+ private:
+ UStringSourceProvider(const UString& source, const UString& url)
+ : SourceProvider(url)
+ , m_source(source)
+ {
+ }
+
+ UString m_source;
+ };
+
+} // namespace JSC
+
+#endif // SourceProvider_h