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