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