1/* 2 * Copyright (C) 2010, 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef ASTBuilder_h 27#define ASTBuilder_h 28 29#include "BuiltinNames.h" 30#include "NodeConstructors.h" 31#include "SyntaxChecker.h" 32#include <utility> 33 34namespace JSC { 35 36class ASTBuilder { 37 struct BinaryOpInfo { 38 BinaryOpInfo() {} 39 BinaryOpInfo(const JSTextPosition& otherStart, const JSTextPosition& otherDivot, const JSTextPosition& otherEnd, bool rhsHasAssignment) 40 : start(otherStart) 41 , divot(otherDivot) 42 , end(otherEnd) 43 , hasAssignment(rhsHasAssignment) 44 { 45 } 46 BinaryOpInfo(const BinaryOpInfo& lhs, const BinaryOpInfo& rhs) 47 : start(lhs.start) 48 , divot(rhs.start) 49 , end(rhs.end) 50 , hasAssignment(lhs.hasAssignment || rhs.hasAssignment) 51 { 52 } 53 JSTextPosition start; 54 JSTextPosition divot; 55 JSTextPosition end; 56 bool hasAssignment; 57 }; 58 59 60 struct AssignmentInfo { 61 AssignmentInfo() {} 62 AssignmentInfo(ExpressionNode* node, const JSTextPosition& start, const JSTextPosition& divot, int initAssignments, Operator op) 63 : m_node(node) 64 , m_start(start) 65 , m_divot(divot) 66 , m_initAssignments(initAssignments) 67 , m_op(op) 68 { 69 ASSERT(m_divot.offset >= m_divot.lineStartOffset); 70 ASSERT(m_start.offset >= m_start.lineStartOffset); 71 } 72 ExpressionNode* m_node; 73 JSTextPosition m_start; 74 JSTextPosition m_divot; 75 int m_initAssignments; 76 Operator m_op; 77 }; 78public: 79 ASTBuilder(VM* vm, SourceCode* sourceCode) 80 : m_vm(vm) 81 , m_sourceCode(sourceCode) 82 , m_scope(vm) 83 , m_evalCount(0) 84 { 85 } 86 87 struct BinaryExprContext { 88 BinaryExprContext(ASTBuilder&) {} 89 }; 90 struct UnaryExprContext { 91 UnaryExprContext(ASTBuilder&) {} 92 }; 93 94 95 typedef SyntaxChecker FunctionBodyBuilder; 96 97 typedef ExpressionNode* Expression; 98 typedef JSC::SourceElements* SourceElements; 99 typedef ArgumentsNode* Arguments; 100 typedef CommaNode* Comma; 101 typedef PropertyNode* Property; 102 typedef PropertyListNode* PropertyList; 103 typedef ElementNode* ElementList; 104 typedef ArgumentListNode* ArgumentsList; 105 typedef ParameterNode* FormalParameterList; 106 typedef FunctionBodyNode* FunctionBody; 107 typedef StatementNode* Statement; 108 typedef ClauseListNode* ClauseList; 109 typedef CaseClauseNode* Clause; 110 typedef ConstDeclNode* ConstDeclList; 111 typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand; 112 typedef RefPtr<DeconstructionPatternNode> DeconstructionPattern; 113 typedef RefPtr<ArrayPatternNode> ArrayPattern; 114 typedef RefPtr<ObjectPatternNode> ObjectPattern; 115 typedef RefPtr<BindingNode> BindingPattern; 116 static const bool CreatesAST = true; 117 static const bool NeedsFreeVariableInfo = true; 118 static const bool CanUseFunctionCache = true; 119 static const int DontBuildKeywords = 0; 120 static const int DontBuildStrings = 0; 121 122 ExpressionNode* makeBinaryNode(const JSTokenLocation&, int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); 123 ExpressionNode* makeFunctionCallNode(const JSTokenLocation&, ExpressionNode* func, ArgumentsNode* args, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd); 124 125 JSC::SourceElements* createSourceElements() { return new (m_vm) JSC::SourceElements(); } 126 127 ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; } 128 ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; } 129 int features() const { return m_scope.m_features; } 130 int numConstants() const { return m_scope.m_numConstants; } 131 132 void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); } 133 134 CommaNode* createCommaExpr(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_vm) CommaNode(location, lhs, rhs); } 135 136 ExpressionNode* makeAssignNode(const JSTokenLocation&, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); 137 ExpressionNode* makePrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); 138 ExpressionNode* makePostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); 139 ExpressionNode* makeTypeOfNode(const JSTokenLocation&, ExpressionNode*); 140 ExpressionNode* makeDeleteNode(const JSTokenLocation&, ExpressionNode*, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end); 141 ExpressionNode* makeNegateNode(const JSTokenLocation&, ExpressionNode*); 142 ExpressionNode* makeBitwiseNotNode(const JSTokenLocation&, ExpressionNode*); 143 ExpressionNode* makeMultNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 144 ExpressionNode* makeDivNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 145 ExpressionNode* makeModNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 146 ExpressionNode* makeAddNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 147 ExpressionNode* makeSubNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 148 ExpressionNode* makeBitXOrNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 149 ExpressionNode* makeBitAndNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 150 ExpressionNode* makeBitOrNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 151 ExpressionNode* makeLeftShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 152 ExpressionNode* makeRightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 153 ExpressionNode* makeURightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); 154 155 ExpressionNode* createLogicalNot(const JSTokenLocation& location, ExpressionNode* expr) 156 { 157 if (expr->isNumber()) 158 return createBoolean(location, isZeroOrUnordered(static_cast<NumberNode*>(expr)->value())); 159 160 return new (m_vm) LogicalNotNode(location, expr); 161 } 162 ExpressionNode* createUnaryPlus(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_vm) UnaryPlusNode(location, expr); } 163 ExpressionNode* createVoid(const JSTokenLocation& location, ExpressionNode* expr) 164 { 165 incConstants(); 166 return new (m_vm) VoidNode(location, expr); 167 } 168 ExpressionNode* thisExpr(const JSTokenLocation& location) 169 { 170 usesThis(); 171 return new (m_vm) ThisNode(location); 172 } 173 ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start) 174 { 175 if (m_vm->propertyNames->arguments == *ident) 176 usesArguments(); 177 return new (m_vm) ResolveNode(location, *ident, start); 178 } 179 ExpressionNode* createObjectLiteral(const JSTokenLocation& location) { return new (m_vm) ObjectLiteralNode(location); } 180 ExpressionNode* createObjectLiteral(const JSTokenLocation& location, PropertyListNode* properties) { return new (m_vm) ObjectLiteralNode(location, properties); } 181 182 ExpressionNode* createArray(const JSTokenLocation& location, int elisions) 183 { 184 if (elisions) 185 incConstants(); 186 return new (m_vm) ArrayNode(location, elisions); 187 } 188 189 ExpressionNode* createArray(const JSTokenLocation& location, ElementNode* elems) { return new (m_vm) ArrayNode(location, elems); } 190 ExpressionNode* createArray(const JSTokenLocation& location, int elisions, ElementNode* elems) 191 { 192 if (elisions) 193 incConstants(); 194 return new (m_vm) ArrayNode(location, elisions, elems); 195 } 196 ExpressionNode* createNumberExpr(const JSTokenLocation& location, double d) 197 { 198 incConstants(); 199 return new (m_vm) NumberNode(location, d); 200 } 201 202 ExpressionNode* createString(const JSTokenLocation& location, const Identifier* string) 203 { 204 incConstants(); 205 return new (m_vm) StringNode(location, *string); 206 } 207 208 ExpressionNode* createBoolean(const JSTokenLocation& location, bool b) 209 { 210 incConstants(); 211 return new (m_vm) BooleanNode(location, b); 212 } 213 214 ExpressionNode* createNull(const JSTokenLocation& location) 215 { 216 incConstants(); 217 return new (m_vm) NullNode(location); 218 } 219 220 ExpressionNode* createBracketAccess(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 221 { 222 BracketAccessorNode* node = new (m_vm) BracketAccessorNode(location, base, property, propertyHasAssignments); 223 setExceptionLocation(node, start, divot, end); 224 return node; 225 } 226 227 ExpressionNode* createDotAccess(const JSTokenLocation& location, ExpressionNode* base, const Identifier* property, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 228 { 229 DotAccessorNode* node = new (m_vm) DotAccessorNode(location, base, *property); 230 setExceptionLocation(node, start, divot, end); 231 return node; 232 } 233 234 ExpressionNode* createSpreadExpression(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 235 { 236 auto node = new (m_vm) SpreadExpressionNode(location, expression); 237 setExceptionLocation(node, start, divot, end); 238 return node; 239 } 240 241 ExpressionNode* createRegExp(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags, const JSTextPosition& start) 242 { 243 if (Yarr::checkSyntax(pattern.string())) 244 return 0; 245 RegExpNode* node = new (m_vm) RegExpNode(location, pattern, flags); 246 int size = pattern.length() + 2; // + 2 for the two /'s 247 JSTextPosition end = start + size; 248 setExceptionLocation(node, start, end, end); 249 return node; 250 } 251 252 ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* arguments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 253 { 254 NewExprNode* node = new (m_vm) NewExprNode(location, expr, arguments); 255 setExceptionLocation(node, start, divot, end); 256 return node; 257 } 258 259 ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& end) 260 { 261 NewExprNode* node = new (m_vm) NewExprNode(location, expr); 262 setExceptionLocation(node, start, end, end); 263 return node; 264 } 265 266 ExpressionNode* createConditionalExpr(const JSTokenLocation& location, ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs) 267 { 268 return new (m_vm) ConditionalNode(location, condition, lhs, rhs); 269 } 270 271 ExpressionNode* createAssignResolve(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* rhs, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 272 { 273 if (rhs->isFuncExprNode()) 274 static_cast<FuncExprNode*>(rhs)->body()->setInferredName(ident); 275 AssignResolveNode* node = new (m_vm) AssignResolveNode(location, ident, rhs); 276 setExceptionLocation(node, start, divot, end); 277 return node; 278 } 279 280 ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned startColumn) 281 { 282 FuncExprNode* result = new (m_vm) FuncExprNode(location, *name, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, startColumn), parameters); 283 body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); 284 return result; 285 } 286 287 FunctionBodyNode* createFunctionBody(const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext) 288 { 289 return FunctionBodyNode::create(m_vm, startLocation, endLocation, startColumn, endColumn, inStrictContext); 290 } 291 292 void setFunctionNameStart(FunctionBodyNode* body, int functionNameStart) 293 { 294 body->setFunctionNameStart(functionNameStart); 295 } 296 297 NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn) 298 { 299 ASSERT(name); 300 body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); 301 body->setInferredName(*name); 302 return new (m_vm) PropertyNode(m_vm, *name, new (m_vm) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn), params), type); 303 } 304 305 NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM*, const JSTokenLocation& location, PropertyNode::Type type, bool, double name, ParameterNode* params, FunctionBodyNode* body, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn) 306 { 307 body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); 308 return new (m_vm) PropertyNode(m_vm, name, new (m_vm) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn), params), type); 309 } 310 311 ArgumentsNode* createArguments() { return new (m_vm) ArgumentsNode(); } 312 ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_vm) ArgumentsNode(args); } 313 ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ExpressionNode* arg) { return new (m_vm) ArgumentListNode(location, arg); } 314 ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_vm) ArgumentListNode(location, args, arg); } 315 316 PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, bool) 317 { 318 if (node->isFuncExprNode()) 319 static_cast<FuncExprNode*>(node)->body()->setInferredName(*propertyName); 320 return new (m_vm) PropertyNode(m_vm, *propertyName, node, type); 321 } 322 PropertyNode* createProperty(VM*, double propertyName, ExpressionNode* node, PropertyNode::Type type, bool) { return new (m_vm) PropertyNode(m_vm, propertyName, node, type); } 323 PropertyNode* createProperty(VM*, ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, bool) { return new (m_vm) PropertyNode(m_vm, propertyName, node, type); } 324 PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_vm) PropertyListNode(location, property); } 325 PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_vm) PropertyListNode(location, property, tail); } 326 327 ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_vm) ElementNode(elisions, expr); } 328 ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_vm) ElementNode(elems, elisions, expr); } 329 330 ParameterNode* createFormalParameterList(DeconstructionPattern pattern) { return new (m_vm) ParameterNode(pattern); } 331 ParameterNode* createFormalParameterList(ParameterNode* list, DeconstructionPattern pattern) { return new (m_vm) ParameterNode(list, pattern); } 332 333 CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_vm) CaseClauseNode(expr, statements); } 334 ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_vm) ClauseListNode(clause); } 335 ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_vm) ClauseListNode(tail, clause); } 336 337 void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); } 338 339 StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn) 340 { 341 FuncDeclNode* decl = new (m_vm) FuncDeclNode(location, *name, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn), parameters); 342 if (*name == m_vm->propertyNames->arguments) 343 usesArguments(); 344 m_scope.m_funcDeclarations->data.append(decl->body()); 345 body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); 346 return decl; 347 } 348 349 StatementNode* createBlockStatement(const JSTokenLocation& location, JSC::SourceElements* elements, int startLine, int endLine) 350 { 351 BlockNode* block = new (m_vm) BlockNode(location, elements); 352 block->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 353 return block; 354 } 355 356 StatementNode* createExprStatement(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, int end) 357 { 358 ExprStatementNode* result = new (m_vm) ExprStatementNode(location, expr); 359 result->setLoc(start.line, end, start.offset, start.lineStartOffset); 360 return result; 361 } 362 363 StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end) 364 { 365 IfElseNode* result = new (m_vm) IfElseNode(location, condition, trueBlock, falseBlock); 366 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 367 return result; 368 } 369 370 StatementNode* createForLoop(const JSTokenLocation& location, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end) 371 { 372 ForNode* result = new (m_vm) ForNode(location, initializer, condition, iter, statements); 373 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 374 return result; 375 } 376 377 StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end) 378 { 379 ForInNode* result = new (m_vm) ForInNode(location, lhs, iter, statements); 380 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 381 setExceptionLocation(result, eStart, eDivot, eEnd); 382 return result; 383 } 384 385 StatementNode* createForInLoop(const JSTokenLocation& location, PassRefPtr<DeconstructionPatternNode> pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end) 386 { 387 ForInNode* result = new (m_vm) ForInNode(m_vm, location, pattern.get(), iter, statements); 388 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 389 setExceptionLocation(result, eStart, eDivot, eEnd); 390 return result; 391 } 392 393 StatementNode* createForOfLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end) 394 { 395 ForOfNode* result = new (m_vm) ForOfNode(location, lhs, iter, statements); 396 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 397 setExceptionLocation(result, eStart, eDivot, eEnd); 398 return result; 399 } 400 401 StatementNode* createForOfLoop(const JSTokenLocation& location, PassRefPtr<DeconstructionPatternNode> pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end) 402 { 403 ForOfNode* result = new (m_vm) ForOfNode(m_vm, location, pattern.get(), iter, statements); 404 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 405 setExceptionLocation(result, eStart, eDivot, eEnd); 406 return result; 407 } 408 409 bool isBindingNode(const DeconstructionPattern& pattern) 410 { 411 return pattern->isBindingNode(); 412 } 413 414 StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_vm) EmptyStatementNode(location); } 415 416 StatementNode* createVarStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) 417 { 418 StatementNode* result; 419 if (!expr) 420 result = new (m_vm) EmptyStatementNode(location); 421 else 422 result = new (m_vm) VarStatementNode(location, expr); 423 result->setLoc(start, end, location.startOffset, location.lineStartOffset); 424 return result; 425 } 426 427 StatementNode* createReturnStatement(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& end) 428 { 429 ReturnNode* result = new (m_vm) ReturnNode(location, expression); 430 setExceptionLocation(result, start, end, end); 431 result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); 432 return result; 433 } 434 435 StatementNode* createBreakStatement(const JSTokenLocation& location, const JSTextPosition& start, const JSTextPosition& end) 436 { 437 BreakNode* result = new (m_vm) BreakNode(m_vm, location); 438 setExceptionLocation(result, start, end, end); 439 result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); 440 return result; 441 } 442 443 StatementNode* createBreakStatement(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end) 444 { 445 BreakNode* result = new (m_vm) BreakNode(location, *ident); 446 setExceptionLocation(result, start, end, end); 447 result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); 448 return result; 449 } 450 451 StatementNode* createContinueStatement(const JSTokenLocation& location, const JSTextPosition& start, const JSTextPosition& end) 452 { 453 ContinueNode* result = new (m_vm) ContinueNode(m_vm, location); 454 setExceptionLocation(result, start, end, end); 455 result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); 456 return result; 457 } 458 459 StatementNode* createContinueStatement(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end) 460 { 461 ContinueNode* result = new (m_vm) ContinueNode(location, *ident); 462 setExceptionLocation(result, start, end, end); 463 result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); 464 return result; 465 } 466 467 StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) 468 { 469 TryNode* result = new (m_vm) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock); 470 if (catchBlock) 471 usesCatch(); 472 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 473 return result; 474 } 475 476 StatementNode* createSwitchStatement(const JSTokenLocation& location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine) 477 { 478 CaseBlockNode* cases = new (m_vm) CaseBlockNode(firstClauses, defaultClause, secondClauses); 479 SwitchNode* result = new (m_vm) SwitchNode(location, expr, cases); 480 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 481 return result; 482 } 483 484 StatementNode* createWhileStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, int startLine, int endLine) 485 { 486 WhileNode* result = new (m_vm) WhileNode(location, expr, statement); 487 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 488 return result; 489 } 490 491 StatementNode* createDoWhileStatement(const JSTokenLocation& location, StatementNode* statement, ExpressionNode* expr, int startLine, int endLine) 492 { 493 DoWhileNode* result = new (m_vm) DoWhileNode(location, statement, expr); 494 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 495 return result; 496 } 497 498 StatementNode* createLabelStatement(const JSTokenLocation& location, const Identifier* ident, StatementNode* statement, const JSTextPosition& start, const JSTextPosition& end) 499 { 500 LabelNode* result = new (m_vm) LabelNode(location, *ident, statement); 501 setExceptionLocation(result, start, end, end); 502 return result; 503 } 504 505 StatementNode* createWithStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, unsigned start, const JSTextPosition& end, unsigned startLine, unsigned endLine) 506 { 507 usesWith(); 508 WithNode* result = new (m_vm) WithNode(location, expr, statement, end, end - start); 509 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 510 return result; 511 } 512 513 StatementNode* createThrowStatement(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& end) 514 { 515 ThrowNode* result = new (m_vm) ThrowNode(location, expr); 516 result->setLoc(start.line, end.line, start.offset, start.lineStartOffset); 517 setExceptionLocation(result, start, end, end); 518 return result; 519 } 520 521 StatementNode* createDebugger(const JSTokenLocation& location, int startLine, int endLine) 522 { 523 DebuggerStatementNode* result = new (m_vm) DebuggerStatementNode(location); 524 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 525 return result; 526 } 527 528 StatementNode* createConstStatement(const JSTokenLocation& location, ConstDeclNode* decls, int startLine, int endLine) 529 { 530 ConstStatementNode* result = new (m_vm) ConstStatementNode(location, decls); 531 result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); 532 return result; 533 } 534 535 ConstDeclNode* appendConstDecl(const JSTokenLocation& location, ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer) 536 { 537 ConstDeclNode* result = new (m_vm) ConstDeclNode(location, *name, initializer); 538 if (tail) 539 tail->m_next = result; 540 return result; 541 } 542 543 void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement) 544 { 545 elements->append(statement); 546 } 547 548 void addVar(const Identifier* ident, int attrs) 549 { 550 if (m_vm->propertyNames->arguments == *ident) 551 usesArguments(); 552 ASSERT(ident->impl()->isAtomic()); 553 m_scope.m_varDeclarations->data.append(std::make_pair(*ident, attrs)); 554 } 555 556 ExpressionNode* combineCommaNodes(const JSTokenLocation& location, ExpressionNode* list, ExpressionNode* init) 557 { 558 if (!list) 559 return init; 560 if (list->isCommaNode()) { 561 static_cast<CommaNode*>(list)->append(init); 562 return list; 563 } 564 return new (m_vm) CommaNode(location, list, init); 565 } 566 567 int evalCount() const { return m_evalCount; } 568 569 void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, const JSTextPosition& exprStart, const JSTextPosition& lhs, const JSTextPosition& rhs, bool hasAssignments) 570 { 571 operandStackDepth++; 572 m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, hasAssignments))); 573 } 574 575 // Logic to handle datastructures used during parsing of binary expressions 576 void operatorStackPop(int& operatorStackDepth) 577 { 578 operatorStackDepth--; 579 m_binaryOperatorStack.removeLast(); 580 } 581 bool operatorStackHasHigherPrecedence(int&, int precedence) 582 { 583 return precedence <= m_binaryOperatorStack.last().second; 584 } 585 const BinaryOperand& getFromOperandStack(int i) { return m_binaryOperandStack[m_binaryOperandStack.size() + i]; } 586 void shrinkOperandStackBy(int& operandStackDepth, int amount) 587 { 588 operandStackDepth -= amount; 589 ASSERT(operandStackDepth >= 0); 590 m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount); 591 } 592 void appendBinaryOperation(const JSTokenLocation& location, int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs) 593 { 594 operandStackDepth++; 595 m_binaryOperandStack.append(std::make_pair(makeBinaryNode(location, m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second))); 596 } 597 void operatorStackAppend(int& operatorStackDepth, int op, int precedence) 598 { 599 operatorStackDepth++; 600 m_binaryOperatorStack.append(std::make_pair(op, precedence)); 601 } 602 ExpressionNode* popOperandStack(int&) 603 { 604 ExpressionNode* result = m_binaryOperandStack.last().first; 605 m_binaryOperandStack.removeLast(); 606 return result; 607 } 608 609 void appendUnaryToken(int& tokenStackDepth, int type, const JSTextPosition& start) 610 { 611 tokenStackDepth++; 612 m_unaryTokenStack.append(std::make_pair(type, start)); 613 } 614 615 int unaryTokenStackLastType(int&) 616 { 617 return m_unaryTokenStack.last().first; 618 } 619 620 const JSTextPosition& unaryTokenStackLastStart(int&) 621 { 622 return m_unaryTokenStack.last().second; 623 } 624 625 void unaryTokenStackRemoveLast(int& tokenStackDepth) 626 { 627 tokenStackDepth--; 628 m_unaryTokenStack.removeLast(); 629 } 630 631 void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, const JSTextPosition& start, const JSTextPosition& divot, int assignmentCount, Operator op) 632 { 633 assignmentStackDepth++; 634 ASSERT(start.offset >= start.lineStartOffset); 635 ASSERT(divot.offset >= divot.lineStartOffset); 636 m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op)); 637 } 638 639 ExpressionNode* createAssignment(const JSTokenLocation& location, int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, const JSTextPosition& lastTokenEnd) 640 { 641 AssignmentInfo& info = m_assignmentInfoStack.last(); 642 ExpressionNode* result = makeAssignNode(location, info.m_node, info.m_op, rhs, info.m_initAssignments != initialAssignmentCount, info.m_initAssignments != currentAssignmentCount, info.m_start, info.m_divot + 1, lastTokenEnd); 643 m_assignmentInfoStack.removeLast(); 644 assignmentStackDepth--; 645 return result; 646 } 647 648 const Identifier* getName(Property property) const { return property->name(); } 649 PropertyNode::Type getType(Property property) const { return property->type(); } 650 651 bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); } 652 653 ExpressionNode* createDeconstructingAssignment(const JSTokenLocation& location, PassRefPtr<DeconstructionPatternNode> pattern, ExpressionNode* initializer) 654 { 655 return new (m_vm) DeconstructingAssignmentNode(location, pattern.get(), initializer); 656 } 657 658 ArrayPattern createArrayPattern(const JSTokenLocation&) 659 { 660 return ArrayPatternNode::create(m_vm); 661 } 662 663 void appendArrayPatternSkipEntry(ArrayPattern node, const JSTokenLocation& location) 664 { 665 node->appendIndex(location, 0); 666 } 667 668 void appendArrayPatternEntry(ArrayPattern node, const JSTokenLocation& location, DeconstructionPattern pattern) 669 { 670 node->appendIndex(location, pattern.get()); 671 } 672 673 ObjectPattern createObjectPattern(const JSTokenLocation&) 674 { 675 return ObjectPatternNode::create(m_vm); 676 } 677 678 void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DeconstructionPattern pattern) 679 { 680 node->appendEntry(location, identifier, wasString, pattern.get()); 681 } 682 683 BindingPattern createBindingLocation(const JSTokenLocation&, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end) 684 { 685 return BindingNode::create(m_vm, boundProperty, start, end); 686 } 687 688private: 689 struct Scope { 690 Scope(VM* vm) 691 : m_varDeclarations(new (vm) ParserArenaData<DeclarationStacks::VarStack>) 692 , m_funcDeclarations(new (vm) ParserArenaData<DeclarationStacks::FunctionStack>) 693 , m_features(0) 694 , m_numConstants(0) 695 { 696 } 697 ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; 698 ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; 699 int m_features; 700 int m_numConstants; 701 }; 702 703 static void setExceptionLocation(ThrowableExpressionData* node, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd) 704 { 705 ASSERT(divot.offset >= divot.lineStartOffset); 706 node->setExceptionSourceCode(divot, divotStart, divotEnd); 707 } 708 709 void incConstants() { m_scope.m_numConstants++; } 710 void usesThis() { m_scope.m_features |= ThisFeature; } 711 void usesCatch() { m_scope.m_features |= CatchFeature; } 712 void usesArguments() { m_scope.m_features |= ArgumentsFeature; } 713 void usesWith() { m_scope.m_features |= WithFeature; } 714 void usesEval() 715 { 716 m_evalCount++; 717 m_scope.m_features |= EvalFeature; 718 } 719 ExpressionNode* createNumber(const JSTokenLocation& location, double d) 720 { 721 return new (m_vm) NumberNode(location, d); 722 } 723 724 VM* m_vm; 725 SourceCode* m_sourceCode; 726 Scope m_scope; 727 Vector<BinaryOperand, 10, UnsafeVectorOverflow> m_binaryOperandStack; 728 Vector<AssignmentInfo, 10, UnsafeVectorOverflow> m_assignmentInfoStack; 729 Vector<std::pair<int, int>, 10, UnsafeVectorOverflow> m_binaryOperatorStack; 730 Vector<std::pair<int, JSTextPosition>, 10, UnsafeVectorOverflow> m_unaryTokenStack; 731 int m_evalCount; 732}; 733 734ExpressionNode* ASTBuilder::makeTypeOfNode(const JSTokenLocation& location, ExpressionNode* expr) 735{ 736 if (expr->isResolveNode()) { 737 ResolveNode* resolve = static_cast<ResolveNode*>(expr); 738 return new (m_vm) TypeOfResolveNode(location, resolve->identifier()); 739 } 740 return new (m_vm) TypeOfValueNode(location, expr); 741} 742 743ExpressionNode* ASTBuilder::makeDeleteNode(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 744{ 745 if (!expr->isLocation()) 746 return new (m_vm) DeleteValueNode(location, expr); 747 if (expr->isResolveNode()) { 748 ResolveNode* resolve = static_cast<ResolveNode*>(expr); 749 return new (m_vm) DeleteResolveNode(location, resolve->identifier(), divot, start, end); 750 } 751 if (expr->isBracketAccessorNode()) { 752 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); 753 return new (m_vm) DeleteBracketNode(location, bracket->base(), bracket->subscript(), divot, start, end); 754 } 755 ASSERT(expr->isDotAccessorNode()); 756 DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); 757 return new (m_vm) DeleteDotNode(location, dot->base(), dot->identifier(), divot, start, end); 758} 759 760ExpressionNode* ASTBuilder::makeNegateNode(const JSTokenLocation& location, ExpressionNode* n) 761{ 762 if (n->isNumber()) { 763 NumberNode* numberNode = static_cast<NumberNode*>(n); 764 numberNode->setValue(-numberNode->value()); 765 return numberNode; 766 } 767 768 return new (m_vm) NegateNode(location, n); 769} 770 771ExpressionNode* ASTBuilder::makeBitwiseNotNode(const JSTokenLocation& location, ExpressionNode* expr) 772{ 773 if (expr->isNumber()) 774 return createNumber(location, ~toInt32(static_cast<NumberNode*>(expr)->value())); 775 return new (m_vm) BitwiseNotNode(location, expr); 776} 777 778ExpressionNode* ASTBuilder::makeMultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 779{ 780 expr1 = expr1->stripUnaryPlus(); 781 expr2 = expr2->stripUnaryPlus(); 782 783 if (expr1->isNumber() && expr2->isNumber()) 784 return createNumber(location, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value()); 785 786 if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1) 787 return new (m_vm) UnaryPlusNode(location, expr2); 788 789 if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1) 790 return new (m_vm) UnaryPlusNode(location, expr1); 791 792 return new (m_vm) MultNode(location, expr1, expr2, rightHasAssignments); 793} 794 795ExpressionNode* ASTBuilder::makeDivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 796{ 797 expr1 = expr1->stripUnaryPlus(); 798 expr2 = expr2->stripUnaryPlus(); 799 800 if (expr1->isNumber() && expr2->isNumber()) 801 return createNumber(location, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value()); 802 return new (m_vm) DivNode(location, expr1, expr2, rightHasAssignments); 803} 804 805ExpressionNode* ASTBuilder::makeModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 806{ 807 expr1 = expr1->stripUnaryPlus(); 808 expr2 = expr2->stripUnaryPlus(); 809 810 if (expr1->isNumber() && expr2->isNumber()) 811 return createNumber(location, fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value())); 812 return new (m_vm) ModNode(location, expr1, expr2, rightHasAssignments); 813} 814 815ExpressionNode* ASTBuilder::makeAddNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 816{ 817 if (expr1->isNumber() && expr2->isNumber()) 818 return createNumber(location, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value()); 819 return new (m_vm) AddNode(location, expr1, expr2, rightHasAssignments); 820} 821 822ExpressionNode* ASTBuilder::makeSubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 823{ 824 expr1 = expr1->stripUnaryPlus(); 825 expr2 = expr2->stripUnaryPlus(); 826 827 if (expr1->isNumber() && expr2->isNumber()) 828 return createNumber(location, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value()); 829 return new (m_vm) SubNode(location, expr1, expr2, rightHasAssignments); 830} 831 832ExpressionNode* ASTBuilder::makeLeftShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 833{ 834 if (expr1->isNumber() && expr2->isNumber()) 835 return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); 836 return new (m_vm) LeftShiftNode(location, expr1, expr2, rightHasAssignments); 837} 838 839ExpressionNode* ASTBuilder::makeRightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 840{ 841 if (expr1->isNumber() && expr2->isNumber()) 842 return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); 843 return new (m_vm) RightShiftNode(location, expr1, expr2, rightHasAssignments); 844} 845 846ExpressionNode* ASTBuilder::makeURightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 847{ 848 if (expr1->isNumber() && expr2->isNumber()) 849 return createNumber(location, toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); 850 return new (m_vm) UnsignedRightShiftNode(location, expr1, expr2, rightHasAssignments); 851} 852 853ExpressionNode* ASTBuilder::makeBitOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 854{ 855 if (expr1->isNumber() && expr2->isNumber()) 856 return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value())); 857 return new (m_vm) BitOrNode(location, expr1, expr2, rightHasAssignments); 858} 859 860ExpressionNode* ASTBuilder::makeBitAndNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 861{ 862 if (expr1->isNumber() && expr2->isNumber()) 863 return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value())); 864 return new (m_vm) BitAndNode(location, expr1, expr2, rightHasAssignments); 865} 866 867ExpressionNode* ASTBuilder::makeBitXOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) 868{ 869 if (expr1->isNumber() && expr2->isNumber()) 870 return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value())); 871 return new (m_vm) BitXOrNode(location, expr1, expr2, rightHasAssignments); 872} 873 874ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location, ExpressionNode* func, ArgumentsNode* args, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd) 875{ 876 ASSERT(divot.offset >= divot.lineStartOffset); 877 if (!func->isLocation()) 878 return new (m_vm) FunctionCallValueNode(location, func, args, divot, divotStart, divotEnd); 879 if (func->isResolveNode()) { 880 ResolveNode* resolve = static_cast<ResolveNode*>(func); 881 const Identifier& identifier = resolve->identifier(); 882 if (identifier == m_vm->propertyNames->eval) { 883 usesEval(); 884 return new (m_vm) EvalFunctionCallNode(location, args, divot, divotStart, divotEnd); 885 } 886 return new (m_vm) FunctionCallResolveNode(location, identifier, args, divot, divotStart, divotEnd); 887 } 888 if (func->isBracketAccessorNode()) { 889 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func); 890 FunctionCallBracketNode* node = new (m_vm) FunctionCallBracketNode(location, bracket->base(), bracket->subscript(), args, divot, divotStart, divotEnd); 891 node->setSubexpressionInfo(bracket->divot(), bracket->divotEnd().offset); 892 return node; 893 } 894 ASSERT(func->isDotAccessorNode()); 895 DotAccessorNode* dot = static_cast<DotAccessorNode*>(func); 896 FunctionCallDotNode* node; 897 if (dot->identifier() == m_vm->propertyNames->builtinNames().callPublicName() || dot->identifier() == m_vm->propertyNames->builtinNames().callPrivateName()) 898 node = new (m_vm) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd); 899 else if (dot->identifier() == m_vm->propertyNames->builtinNames().applyPublicName() || dot->identifier() == m_vm->propertyNames->builtinNames().applyPrivateName()) 900 node = new (m_vm) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd); 901 else 902 node = new (m_vm) FunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd); 903 node->setSubexpressionInfo(dot->divot(), dot->divotEnd().offset); 904 return node; 905} 906 907ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int token, std::pair<ExpressionNode*, BinaryOpInfo> lhs, std::pair<ExpressionNode*, BinaryOpInfo> rhs) 908{ 909 switch (token) { 910 case OR: 911 return new (m_vm) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalOr); 912 913 case AND: 914 return new (m_vm) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalAnd); 915 916 case BITOR: 917 return makeBitOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 918 919 case BITXOR: 920 return makeBitXOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 921 922 case BITAND: 923 return makeBitAndNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 924 925 case EQEQ: 926 return new (m_vm) EqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 927 928 case NE: 929 return new (m_vm) NotEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 930 931 case STREQ: 932 return new (m_vm) StrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 933 934 case STRNEQ: 935 return new (m_vm) NotStrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 936 937 case LT: 938 return new (m_vm) LessNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 939 940 case GT: 941 return new (m_vm) GreaterNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 942 943 case LE: 944 return new (m_vm) LessEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 945 946 case GE: 947 return new (m_vm) GreaterEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 948 949 case INSTANCEOF: { 950 InstanceOfNode* node = new (m_vm) InstanceOfNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 951 setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); 952 return node; 953 } 954 955 case INTOKEN: { 956 InNode* node = new (m_vm) InNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 957 setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); 958 return node; 959 } 960 961 case LSHIFT: 962 return makeLeftShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 963 964 case RSHIFT: 965 return makeRightShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 966 967 case URSHIFT: 968 return makeURightShiftNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 969 970 case PLUS: 971 return makeAddNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 972 973 case MINUS: 974 return makeSubNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 975 976 case TIMES: 977 return makeMultNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 978 979 case DIVIDE: 980 return makeDivNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 981 982 case MOD: 983 return makeModNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); 984 } 985 CRASH(); 986 return 0; 987} 988 989ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 990{ 991 if (!loc->isLocation()) 992 return new (m_vm) AssignErrorNode(location, divot, start, end); 993 994 if (loc->isResolveNode()) { 995 ResolveNode* resolve = static_cast<ResolveNode*>(loc); 996 if (op == OpEqual) { 997 if (expr->isFuncExprNode()) 998 static_cast<FuncExprNode*>(expr)->body()->setInferredName(resolve->identifier()); 999 AssignResolveNode* node = new (m_vm) AssignResolveNode(location, resolve->identifier(), expr); 1000 setExceptionLocation(node, start, divot, end); 1001 return node; 1002 } 1003 return new (m_vm) ReadModifyResolveNode(location, resolve->identifier(), op, expr, exprHasAssignments, divot, start, end); 1004 } 1005 if (loc->isBracketAccessorNode()) { 1006 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc); 1007 if (op == OpEqual) 1008 return new (m_vm) AssignBracketNode(location, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), start, end); 1009 ReadModifyBracketNode* node = new (m_vm) ReadModifyBracketNode(location, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, start, end); 1010 node->setSubexpressionInfo(bracket->divot(), bracket->divotEnd().offset); 1011 return node; 1012 } 1013 ASSERT(loc->isDotAccessorNode()); 1014 DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc); 1015 if (op == OpEqual) { 1016 if (expr->isFuncExprNode()) 1017 static_cast<FuncExprNode*>(expr)->body()->setInferredName(dot->identifier()); 1018 return new (m_vm) AssignDotNode(location, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), start, end); 1019 } 1020 1021 ReadModifyDotNode* node = new (m_vm) ReadModifyDotNode(location, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, start, end); 1022 node->setSubexpressionInfo(dot->divot(), dot->divotEnd().offset); 1023 return node; 1024} 1025 1026ExpressionNode* ASTBuilder::makePrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 1027{ 1028 return new (m_vm) PrefixNode(location, expr, op, divot, start, end); 1029} 1030 1031ExpressionNode* ASTBuilder::makePostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) 1032{ 1033 return new (m_vm) PostfixNode(location, expr, op, divot, start, end); 1034} 1035 1036} 1037 1038#endif 1039