1 /*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
4 * Copyright (C) 2006 Apple Computer, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #ifndef MAKENODES_H
23 #define MAKENODES_H
24
25 #include "nodes.h"
26 #include "identifier.h"
27
28 #define OPTIMIZE_NODES
29 //#define TRACE_OPTIMIZER
30
31 namespace KJS
32 {
33
34 // Shorthand wrappers for entering function contexts
inFuncExpr()35 static void inFuncExpr()
36 {
37 parser().pushFunctionContext(FuncFl_Expr);
38 }
39
inFuncDecl()40 static void inFuncDecl()
41 {
42 parser().pushFunctionContext(FuncFl_Decl);
43 }
44
makeAssignNode(Node * loc,Operator op,Node * expr)45 static Node *makeAssignNode(Node *loc, Operator op, Node *expr)
46 {
47 return new AssignNode(loc, op, expr);
48 }
49
makeConditionalNode(Node * l,Node * e1,Node * e2)50 static Node *makeConditionalNode(Node *l, Node *e1, Node *e2)
51 {
52 return new ConditionalNode(l, e1, e2);
53 }
54
makePrefixNode(Node * expr,Operator op)55 static Node *makePrefixNode(Node *expr, Operator op)
56 {
57 return new PrefixNode(expr, op);
58 }
59
makePostfixNode(Node * expr,Operator op)60 static Node *makePostfixNode(Node *expr, Operator op)
61 {
62 return new PostfixNode(expr, op);
63 }
64
makeFunctionCallNode(Node * func,ArgumentsNode * args)65 static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args)
66 {
67 Node *n = func->nodeInsideAllParens();
68
69 if (!n->isLocation()) {
70 return new FunctionCallValueNode(func, args);
71 } else {
72 return new FunctionCallReferenceNode(func, args);
73 }
74 }
75
makeTypeOfNode(Node * expr)76 static Node *makeTypeOfNode(Node *expr)
77 {
78 Node *n = expr->nodeInsideAllParens();
79
80 // We only need to use the special path for variable references,
81 // since they may throw a ResolveError on evaluate where we don't
82 // want that...
83 if (n->isVarAccessNode()) {
84 return new TypeOfVarNode(static_cast<VarAccessNode *>(n));
85 } else {
86 return new TypeOfValueNode(expr);
87 }
88 }
89
makeDeleteNode(Node * expr)90 static Node *makeDeleteNode(Node *expr)
91 {
92 Node *n = expr->nodeInsideAllParens();
93
94 if (!n->isLocation()) {
95 return new DeleteValueNode(expr);
96 } else {
97 return new DeleteReferenceNode(static_cast<LocationNode *>(n)); //### not 100% faithful listing?
98 }
99 }
100
makeGetterOrSetterPropertyNode(PropertyNode * & result,Identifier & getOrSet,Identifier & name,ParameterNode * params,FunctionBodyNode * body)101 static bool makeGetterOrSetterPropertyNode(PropertyNode *&result, Identifier &getOrSet, Identifier &name, ParameterNode *params, FunctionBodyNode *body)
102 {
103 PropertyNode::Type type;
104
105 if (getOrSet == "get") {
106 type = PropertyNode::Getter;
107 } else if (getOrSet == "set") {
108 type = PropertyNode::Setter;
109 } else {
110 return false;
111 }
112
113 result = new PropertyNode(new PropertyNameNode(name),
114 new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, params), type);
115
116 return true;
117 }
118
makeAddNode(Node * n1,Node * n2,Operator op)119 static Node *makeAddNode(Node *n1, Node *n2, Operator op)
120 {
121 #ifdef OPTIMIZE_NODES
122 if (n1->isNumber()) {
123 if (n2->isNumber()) {
124 #ifdef TRACE_OPTIMIZER
125 printf("Optimizing ADDNODE NUMBER NUMBER as NUMBER\n");
126 #endif
127 NumberNode *number1 = static_cast< NumberNode * >(n1);
128 NumberNode *number2 = static_cast< NumberNode * >(n2);
129 double d1 = number1->value();
130 double d2 = number2->value();
131 number1->setValue(op == OpPlus ? d1 + d2 : d1 - d2);
132 return number1;
133 }
134 #ifdef TRACE_OPTIMIZER
135 printf("could optimize as ADD NODE NUMBER\n");
136 #endif
137 }
138 if (n2->isNumber()) {
139 #ifdef TRACE_OPTIMIZER
140 printf("could optimize as ADD NODE NUMBER\n");
141 #endif
142 }
143 if (op == OpPlus && n1->isString() && n2->isString()) {
144 #ifdef TRACE_OPTIMIZER
145 printf("Optimizing ADDNODE STRING STRING as STRING\n");
146 #endif
147 StringNode *str1 = static_cast<StringNode *>(n1);
148 StringNode *str2 = static_cast<StringNode *>(n2);
149 str1->setValue(str1->value() + str2->value());
150 return str1;
151 }
152 #endif
153 return new BinaryOperatorNode(n1, n2, op);
154 }
155
makeMultNode(Node * n1,Node * n2,Operator op)156 static Node *makeMultNode(Node *n1, Node *n2, Operator op)
157 {
158 #ifdef OPTIMIZE_NODES
159 if (n1->isNumber()) {
160 if (n2->isNumber()) {
161 #ifdef TRACE_OPTIMIZER
162 printf("Optimizing MULTNODE NUMBER NUMBER as NUMBER\n");
163 #endif
164 NumberNode *number1 = static_cast< NumberNode * >(n1);
165 NumberNode *number2 = static_cast< NumberNode * >(n2);
166 double d1 = number1->value();
167 double d2 = number2->value();
168 double res;
169 if (op == OpMult) {
170 res = d1 * d2;
171 } else if (op == OpDiv) {
172 res = d1 / d2;
173 } else if (op == OpMod) {
174 res = fmod(d1, d2);
175 } else { // OpExp
176 res = exponentiation(d1, d2);
177 }
178 number1->setValue(res);
179 return number1;
180 }
181 #ifdef TRACE_OPTIMIZER
182 printf("could optimize as MULT NODE NUMBER\n");
183 #endif
184 }
185 if (n2->isNumber()) {
186 #ifdef TRACE_OPTIMIZER
187 printf("could optimize as MULT NODE NUMBER\n");
188 #endif
189 }
190 #endif
191 return new BinaryOperatorNode(n1, n2, op);
192 }
193
makeShiftNode(Node * n1,Node * n2,Operator op)194 static Node *makeShiftNode(Node *n1, Node *n2, Operator op)
195 {
196 #ifdef OPTIMIZE_NODES
197 if (n1->isNumber() && n2->isNumber()) {
198 #ifdef TRACE_OPTIMIZER
199 printf("Optimizing MULTNODE NUMBER NUMBER as NUMBER\n");
200 #endif
201 NumberNode *number1 = static_cast< NumberNode * >(n1);
202 NumberNode *number2 = static_cast< NumberNode * >(n2);
203 double val = number1->value();
204 uint32_t shiftAmount = toUInt32(number2->value());
205 switch (op) {
206 case OpLShift:
207 // operator <<
208 number1->setValue(toInt32(val) << (shiftAmount & 0x1f));
209 break;
210 case OpRShift:
211 // operator >>
212 number1->setValue(toInt32(val) >> (shiftAmount & 0x1f));
213 break;
214 case OpURShift:
215 // operator >>>
216 number1->setValue(toUInt32(val) >> (shiftAmount & 0x1f));
217 break;
218 default:
219 assert(false);
220 break;
221 }
222 return number1;
223 }
224 #endif
225 return new BinaryOperatorNode(n1, n2, op);
226 }
227
makeRelationalNode(Node * n1,Operator op,Node * n2)228 static Node *makeRelationalNode(Node *n1, Operator op, Node *n2)
229 {
230 return new BinaryOperatorNode(n1, n2, op);
231 }
232
makeEqualNode(Node * n1,Operator op,Node * n2)233 static Node *makeEqualNode(Node *n1, Operator op, Node *n2)
234 {
235 return new BinaryOperatorNode(n1, n2, op);
236 }
237
makeBitOperNode(Node * n1,Operator op,Node * n2)238 static Node *makeBitOperNode(Node *n1, Operator op, Node *n2)
239 {
240 return new BinaryOperatorNode(n1, n2, op);
241 }
242
makeBinaryLogicalNode(Node * n1,Operator op,Node * n2)243 static Node *makeBinaryLogicalNode(Node *n1, Operator op, Node *n2)
244 {
245 return new BinaryLogicalNode(n1, op, n2);
246 }
247
makeUnaryPlusNode(Node * n)248 static Node *makeUnaryPlusNode(Node *n)
249 {
250 #ifdef OPTIMIZE_NODES
251 if (n->isNumber()) {
252 #ifdef TRACE_OPTIMIZER
253 printf("Optimizing UNARYPLUS NUMBER\n");
254 #endif
255 return n;
256 }
257 #endif
258 return new UnaryPlusNode(n);
259 }
260
makeNegateNode(Node * n)261 static Node *makeNegateNode(Node *n)
262 {
263 #ifdef OPTIMIZE_NODES
264 if (n->isNumber()) {
265 #ifdef TRACE_OPTIMIZER
266 printf("Optimizing NEGATE NUMBER\n");
267 #endif
268 NumberNode *number = static_cast <NumberNode *>(n);
269 number->setValue(-number->value());
270 return number;
271 }
272 #endif
273 return new NegateNode(n);
274 }
275
makeBitwiseNotNode(Node * n)276 static Node *makeBitwiseNotNode(Node *n)
277 {
278 #ifdef OPTIMIZE_NODES
279 if (n->isNumber()) {
280 #ifdef TRACE_OPTIMIZER
281 printf("Optimizing BITWISENOT NUMBER\n");
282 #endif
283 NumberNode *number = static_cast <NumberNode *>(n);
284 number->setValue(~toInt32(number->value()));
285 return number;
286 }
287 #endif
288 return new BitwiseNotNode(n);
289 }
290
makeLogicalNotNode(Node * n)291 static Node *makeLogicalNotNode(Node *n)
292 {
293 return new LogicalNotNode(n);
294 }
295
makeGroupNode(Node * n)296 static Node *makeGroupNode(Node *n)
297 {
298 if (n->isVarAccessNode() || n->isGroupNode()) {
299 return n;
300 }
301 return new GroupNode(n);
302 }
303
makeIfNode(Node * e,StatementNode * s1,StatementNode * s2)304 static StatementNode *makeIfNode(Node *e, StatementNode *s1, StatementNode *s2)
305 {
306 return new IfNode(e, s1, s2);
307 }
308
makeImportNode(PackageNameNode * n,bool wildcard,const Identifier & a)309 static StatementNode *makeImportNode(PackageNameNode *n,
310 bool wildcard, const Identifier &a)
311 {
312 ImportStatement *stat = new ImportStatement(n);
313 if (wildcard) {
314 stat->enableWildcard();
315 }
316 stat->setAlias(a);
317
318 return stat;
319 }
320
makeLabelNode(const Identifier & l,StatementNode * s)321 static StatementNode *makeLabelNode(const Identifier &l, StatementNode *s)
322 {
323 return new LabelNode(l, s);
324 }
325
326 } // namespace KJS
327
328 #endif
329 // vi: set sw=4 :
330