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