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
31namespace KJS {
32
33// Shorthand wrappers for entering function contexts
34static void inFuncExpr() {
35 parser().pushFunctionContext(FuncFl_Expr);
36}
37
38static void inFuncDecl() {
39 parser().pushFunctionContext(FuncFl_Decl);
40}
41
42
43static Node* makeAssignNode(Node* loc, Operator op, Node* expr)
44{
45 return new AssignNode(loc, op, expr);
46}
47
48static Node* makeConditionalNode(Node* l, Node* e1, Node* e2)
49{
50 return new ConditionalNode(l, e1, e2);
51}
52
53static Node* makePrefixNode(Node *expr, Operator op)
54{
55 return new PrefixNode(expr, op);
56}
57
58static Node* makePostfixNode(Node* expr, Operator op)
59{
60 return new PostfixNode(expr, op);
61}
62
63static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args)
64{
65 Node *n = func->nodeInsideAllParens();
66
67 if (!n->isLocation())
68 return new FunctionCallValueNode(func, args);
69 else
70 return new FunctionCallReferenceNode(func, args);
71}
72
73static Node *makeTypeOfNode(Node *expr)
74{
75 Node *n = expr->nodeInsideAllParens();
76
77 // We only need to use the special path for variable references,
78 // since they may throw a ResolveError on evaluate where we don't
79 // want that...
80 if (n->isVarAccessNode())
81 return new TypeOfVarNode(static_cast<VarAccessNode*>(n));
82 else
83 return new TypeOfValueNode(expr);
84}
85
86static Node *makeDeleteNode(Node *expr)
87{
88 Node *n = expr->nodeInsideAllParens();
89
90 if (!n->isLocation())
91 return new DeleteValueNode(expr);
92 else
93 return new DeleteReferenceNode(static_cast<LocationNode*>(n));//### not 100% faithful listing?
94}
95
96static bool makeGetterOrSetterPropertyNode(PropertyNode*& result, Identifier& getOrSet, Identifier& name, ParameterNode *params, FunctionBodyNode *body)
97{
98 PropertyNode::Type type;
99
100 if (getOrSet == "get")
101 type = PropertyNode::Getter;
102 else if (getOrSet == "set")
103 type = PropertyNode::Setter;
104 else
105 return false;
106
107 result = new PropertyNode(new PropertyNameNode(name),
108 new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, params), type);
109
110 return true;
111}
112
113static Node* makeAddNode(Node* n1, Node* n2, Operator op)
114{
115#ifdef OPTIMIZE_NODES
116 if (n1->isNumber()) {
117 if (n2->isNumber()) {
118#ifdef TRACE_OPTIMIZER
119 printf("Optimizing ADDNODE NUMBER NUMBER as NUMBER\n");
120#endif
121 NumberNode* number1 = static_cast< NumberNode * >(n1);
122 NumberNode* number2 = static_cast< NumberNode * >(n2);
123 double d1 = number1->value();
124 double d2 = number2->value();
125 number1->setValue(op == OpPlus ? d1 + d2 : d1 - d2);
126 return number1;
127 }
128#ifdef TRACE_OPTIMIZER
129 printf("could optimize as ADD NODE NUMBER\n");
130#endif
131 }
132 if (n2->isNumber()) {
133#ifdef TRACE_OPTIMIZER
134 printf("could optimize as ADD NODE NUMBER\n");
135#endif
136 }
137 if (op == OpPlus && n1->isString() && n2->isString()) {
138#ifdef TRACE_OPTIMIZER
139 printf("Optimizing ADDNODE STRING STRING as STRING\n");
140#endif
141 StringNode* str1 = static_cast<StringNode*>(n1);
142 StringNode* str2 = static_cast<StringNode*>(n2);
143 str1->setValue(str1->value() + str2->value());
144 return str1;
145 }
146#endif
147 return new BinaryOperatorNode(n1, n2, op);
148}
149
150static Node* makeMultNode(Node* n1, Node* n2, Operator op)
151{
152#ifdef OPTIMIZE_NODES
153 if (n1->isNumber()) {
154 if (n2->isNumber()) {
155#ifdef TRACE_OPTIMIZER
156 printf("Optimizing MULTNODE NUMBER NUMBER as NUMBER\n");
157#endif
158 NumberNode* number1 = static_cast< NumberNode * >(n1);
159 NumberNode* number2 = static_cast< NumberNode * >(n2);
160 double d1 = number1->value();
161 double d2 = number2->value();
162 double res;
163 if (op == OpMult)
164 res = d1 * d2;
165 else if (op == OpDiv)
166 res = d1 / d2;
167 else // OpMod
168 res = fmod(d1, d2);
169 number1->setValue(res);
170 return number1;
171 }
172#ifdef TRACE_OPTIMIZER
173 printf("could optimize as MULT NODE NUMBER\n");
174#endif
175 }
176 if (n2->isNumber()) {
177#ifdef TRACE_OPTIMIZER
178 printf("could optimize as MULT NODE NUMBER\n");
179#endif
180 }
181#endif
182 return new BinaryOperatorNode(n1, n2, op);
183}
184
185static Node* makeShiftNode(Node* n1, Node* n2, Operator op)
186{
187#ifdef OPTIMIZE_NODES
188 if (n1->isNumber() && n2->isNumber()) {
189#ifdef TRACE_OPTIMIZER
190 printf("Optimizing MULTNODE NUMBER NUMBER as NUMBER\n");
191#endif
192 NumberNode* number1 = static_cast< NumberNode * >(n1);
193 NumberNode* number2 = static_cast< NumberNode * >(n2);
194 double val = number1->value();
195 uint32_t shiftAmount = toUInt32(number2->value());
196 switch (op) {
197 case OpLShift:
198 // operator <<
199 number1->setValue(toInt32(val) << (shiftAmount & 0x1f));
200 break;
201 case OpRShift:
202 // operator >>
203 number1->setValue(toInt32(val) >> (shiftAmount & 0x1f));
204 break;
205 case OpURShift:
206 // operator >>>
207 number1->setValue(toUInt32(val) >> (shiftAmount & 0x1f));
208 break;
209 default:
210 assert(false);
211 break;
212 }
213 return number1;
214 }
215#endif
216 return new BinaryOperatorNode(n1, n2, op);
217}
218
219static Node* makeRelationalNode(Node* n1, Operator op, Node* n2)
220{
221 return new BinaryOperatorNode(n1, n2, op);
222}
223
224static Node* makeEqualNode(Node* n1, Operator op, Node* n2)
225{
226 return new BinaryOperatorNode(n1, n2, op);
227}
228
229static Node* makeBitOperNode(Node* n1, Operator op, Node* n2)
230{
231 return new BinaryOperatorNode(n1, n2, op);
232}
233
234static Node* makeBinaryLogicalNode(Node* n1, Operator op, Node* n2)
235{
236 return new BinaryLogicalNode(n1, op, n2);
237}
238
239static Node* makeUnaryPlusNode(Node *n)
240{
241#ifdef OPTIMIZE_NODES
242 if (n->isNumber()) {
243#ifdef TRACE_OPTIMIZER
244 printf("Optimizing UNARYPLUS NUMBER\n");
245#endif
246 return n;
247 }
248#endif
249 return new UnaryPlusNode(n);
250}
251
252static Node* makeNegateNode(Node *n)
253{
254#ifdef OPTIMIZE_NODES
255 if (n->isNumber()) {
256#ifdef TRACE_OPTIMIZER
257 printf("Optimizing NEGATE NUMBER\n");
258#endif
259 NumberNode *number = static_cast <NumberNode *>(n);
260 number->setValue(-number->value());
261 return number;
262 }
263#endif
264 return new NegateNode(n);
265}
266
267static Node* makeBitwiseNotNode(Node *n)
268{
269#ifdef OPTIMIZE_NODES
270 if (n->isNumber()) {
271#ifdef TRACE_OPTIMIZER
272 printf("Optimizing BITWISENOT NUMBER\n");
273#endif
274 NumberNode *number = static_cast <NumberNode *>(n);
275 number->setValue(~toInt32(number->value()));
276 return number;
277 }
278#endif
279 return new BitwiseNotNode(n);
280}
281
282static Node* makeLogicalNotNode(Node *n)
283{
284 return new LogicalNotNode(n);
285}
286
287static Node* makeGroupNode(Node *n)
288{
289 if (n->isVarAccessNode() || n->isGroupNode())
290 return n;
291 return new GroupNode(n);
292}
293
294static StatementNode* makeIfNode(Node *e, StatementNode *s1, StatementNode *s2)
295{
296 return new IfNode(e, s1, s2);
297}
298
299static StatementNode *makeImportNode(PackageNameNode *n,
300 bool wildcard, const Identifier &a)
301{
302 ImportStatement *stat = new ImportStatement(n);
303 if (wildcard)
304 stat->enableWildcard();
305 stat->setAlias(a);
306
307 return stat;
308}
309
310static StatementNode *makeLabelNode(const Identifier& l, StatementNode* s)
311{
312 return new LabelNode(l, s);
313}
314
315} // namespace KJS
316
317#endif
318// vi: set sw=4 :
319