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