File indexing completed on 2024-05-12 15:43:26
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2006 Apple Computer, Inc. 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 * 0020 */ 0021 0022 #ifndef MAKENODES_H 0023 #define MAKENODES_H 0024 0025 #include "nodes.h" 0026 #include "identifier.h" 0027 0028 #define OPTIMIZE_NODES 0029 //#define TRACE_OPTIMIZER 0030 0031 namespace KJS 0032 { 0033 0034 // Shorthand wrappers for entering function contexts 0035 static void inFuncExpr() 0036 { 0037 parser().pushFunctionContext(FuncFl_Expr); 0038 } 0039 0040 static void inFuncDecl() 0041 { 0042 parser().pushFunctionContext(FuncFl_Decl); 0043 } 0044 0045 static Node *makeAssignNode(Node *loc, Operator op, Node *expr) 0046 { 0047 return new AssignNode(loc, op, expr); 0048 } 0049 0050 static Node *makeConditionalNode(Node *l, Node *e1, Node *e2) 0051 { 0052 return new ConditionalNode(l, e1, e2); 0053 } 0054 0055 static Node *makePrefixNode(Node *expr, Operator op) 0056 { 0057 return new PrefixNode(expr, op); 0058 } 0059 0060 static Node *makePostfixNode(Node *expr, Operator op) 0061 { 0062 return new PostfixNode(expr, op); 0063 } 0064 0065 static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args) 0066 { 0067 Node *n = func->nodeInsideAllParens(); 0068 0069 if (!n->isLocation()) { 0070 return new FunctionCallValueNode(func, args); 0071 } else { 0072 return new FunctionCallReferenceNode(func, args); 0073 } 0074 } 0075 0076 static Node *makeTypeOfNode(Node *expr) 0077 { 0078 Node *n = expr->nodeInsideAllParens(); 0079 0080 // We only need to use the special path for variable references, 0081 // since they may throw a ResolveError on evaluate where we don't 0082 // want that... 0083 if (n->isVarAccessNode()) { 0084 return new TypeOfVarNode(static_cast<VarAccessNode *>(n)); 0085 } else { 0086 return new TypeOfValueNode(expr); 0087 } 0088 } 0089 0090 static Node *makeDeleteNode(Node *expr) 0091 { 0092 Node *n = expr->nodeInsideAllParens(); 0093 0094 if (!n->isLocation()) { 0095 return new DeleteValueNode(expr); 0096 } else { 0097 return new DeleteReferenceNode(static_cast<LocationNode *>(n)); //### not 100% faithful listing? 0098 } 0099 } 0100 0101 static bool makeGetterOrSetterPropertyNode(PropertyNode *&result, Identifier &getOrSet, Identifier &name, ParameterNode *params, FunctionBodyNode *body) 0102 { 0103 PropertyNode::Type type; 0104 0105 if (getOrSet == "get") { 0106 type = PropertyNode::Getter; 0107 } else if (getOrSet == "set") { 0108 type = PropertyNode::Setter; 0109 } else { 0110 return false; 0111 } 0112 0113 result = new PropertyNode(new PropertyNameNode(name), 0114 new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, params), type); 0115 0116 return true; 0117 } 0118 0119 static Node *makeAddNode(Node *n1, Node *n2, Operator op) 0120 { 0121 #ifdef OPTIMIZE_NODES 0122 if (n1->isNumber()) { 0123 if (n2->isNumber()) { 0124 #ifdef TRACE_OPTIMIZER 0125 printf("Optimizing ADDNODE NUMBER NUMBER as NUMBER\n"); 0126 #endif 0127 NumberNode *number1 = static_cast< NumberNode * >(n1); 0128 NumberNode *number2 = static_cast< NumberNode * >(n2); 0129 double d1 = number1->value(); 0130 double d2 = number2->value(); 0131 number1->setValue(op == OpPlus ? d1 + d2 : d1 - d2); 0132 return number1; 0133 } 0134 #ifdef TRACE_OPTIMIZER 0135 printf("could optimize as ADD NODE NUMBER\n"); 0136 #endif 0137 } 0138 if (n2->isNumber()) { 0139 #ifdef TRACE_OPTIMIZER 0140 printf("could optimize as ADD NODE NUMBER\n"); 0141 #endif 0142 } 0143 if (op == OpPlus && n1->isString() && n2->isString()) { 0144 #ifdef TRACE_OPTIMIZER 0145 printf("Optimizing ADDNODE STRING STRING as STRING\n"); 0146 #endif 0147 StringNode *str1 = static_cast<StringNode *>(n1); 0148 StringNode *str2 = static_cast<StringNode *>(n2); 0149 str1->setValue(str1->value() + str2->value()); 0150 return str1; 0151 } 0152 #endif 0153 return new BinaryOperatorNode(n1, n2, op); 0154 } 0155 0156 static Node *makeMultNode(Node *n1, Node *n2, Operator op) 0157 { 0158 #ifdef OPTIMIZE_NODES 0159 if (n1->isNumber()) { 0160 if (n2->isNumber()) { 0161 #ifdef TRACE_OPTIMIZER 0162 printf("Optimizing MULTNODE NUMBER NUMBER as NUMBER\n"); 0163 #endif 0164 NumberNode *number1 = static_cast< NumberNode * >(n1); 0165 NumberNode *number2 = static_cast< NumberNode * >(n2); 0166 double d1 = number1->value(); 0167 double d2 = number2->value(); 0168 double res; 0169 if (op == OpMult) { 0170 res = d1 * d2; 0171 } else if (op == OpDiv) { 0172 res = d1 / d2; 0173 } else if (op == OpMod) { 0174 res = fmod(d1, d2); 0175 } else { // OpExp 0176 res = exponentiation(d1, d2); 0177 } 0178 number1->setValue(res); 0179 return number1; 0180 } 0181 #ifdef TRACE_OPTIMIZER 0182 printf("could optimize as MULT NODE NUMBER\n"); 0183 #endif 0184 } 0185 if (n2->isNumber()) { 0186 #ifdef TRACE_OPTIMIZER 0187 printf("could optimize as MULT NODE NUMBER\n"); 0188 #endif 0189 } 0190 #endif 0191 return new BinaryOperatorNode(n1, n2, op); 0192 } 0193 0194 static Node *makeShiftNode(Node *n1, Node *n2, Operator op) 0195 { 0196 #ifdef OPTIMIZE_NODES 0197 if (n1->isNumber() && n2->isNumber()) { 0198 #ifdef TRACE_OPTIMIZER 0199 printf("Optimizing MULTNODE NUMBER NUMBER as NUMBER\n"); 0200 #endif 0201 NumberNode *number1 = static_cast< NumberNode * >(n1); 0202 NumberNode *number2 = static_cast< NumberNode * >(n2); 0203 double val = number1->value(); 0204 uint32_t shiftAmount = toUInt32(number2->value()); 0205 switch (op) { 0206 case OpLShift: 0207 // operator << 0208 number1->setValue(toInt32(val) << (shiftAmount & 0x1f)); 0209 break; 0210 case OpRShift: 0211 // operator >> 0212 number1->setValue(toInt32(val) >> (shiftAmount & 0x1f)); 0213 break; 0214 case OpURShift: 0215 // operator >>> 0216 number1->setValue(toUInt32(val) >> (shiftAmount & 0x1f)); 0217 break; 0218 default: 0219 assert(false); 0220 break; 0221 } 0222 return number1; 0223 } 0224 #endif 0225 return new BinaryOperatorNode(n1, n2, op); 0226 } 0227 0228 static Node *makeRelationalNode(Node *n1, Operator op, Node *n2) 0229 { 0230 return new BinaryOperatorNode(n1, n2, op); 0231 } 0232 0233 static Node *makeEqualNode(Node *n1, Operator op, Node *n2) 0234 { 0235 return new BinaryOperatorNode(n1, n2, op); 0236 } 0237 0238 static Node *makeBitOperNode(Node *n1, Operator op, Node *n2) 0239 { 0240 return new BinaryOperatorNode(n1, n2, op); 0241 } 0242 0243 static Node *makeBinaryLogicalNode(Node *n1, Operator op, Node *n2) 0244 { 0245 return new BinaryLogicalNode(n1, op, n2); 0246 } 0247 0248 static Node *makeUnaryPlusNode(Node *n) 0249 { 0250 #ifdef OPTIMIZE_NODES 0251 if (n->isNumber()) { 0252 #ifdef TRACE_OPTIMIZER 0253 printf("Optimizing UNARYPLUS NUMBER\n"); 0254 #endif 0255 return n; 0256 } 0257 #endif 0258 return new UnaryPlusNode(n); 0259 } 0260 0261 static Node *makeNegateNode(Node *n) 0262 { 0263 #ifdef OPTIMIZE_NODES 0264 if (n->isNumber()) { 0265 #ifdef TRACE_OPTIMIZER 0266 printf("Optimizing NEGATE NUMBER\n"); 0267 #endif 0268 NumberNode *number = static_cast <NumberNode *>(n); 0269 number->setValue(-number->value()); 0270 return number; 0271 } 0272 #endif 0273 return new NegateNode(n); 0274 } 0275 0276 static Node *makeBitwiseNotNode(Node *n) 0277 { 0278 #ifdef OPTIMIZE_NODES 0279 if (n->isNumber()) { 0280 #ifdef TRACE_OPTIMIZER 0281 printf("Optimizing BITWISENOT NUMBER\n"); 0282 #endif 0283 NumberNode *number = static_cast <NumberNode *>(n); 0284 number->setValue(~toInt32(number->value())); 0285 return number; 0286 } 0287 #endif 0288 return new BitwiseNotNode(n); 0289 } 0290 0291 static Node *makeLogicalNotNode(Node *n) 0292 { 0293 return new LogicalNotNode(n); 0294 } 0295 0296 static Node *makeGroupNode(Node *n) 0297 { 0298 if (n->isVarAccessNode() || n->isGroupNode()) { 0299 return n; 0300 } 0301 return new GroupNode(n); 0302 } 0303 0304 static StatementNode *makeIfNode(Node *e, StatementNode *s1, StatementNode *s2) 0305 { 0306 return new IfNode(e, s1, s2); 0307 } 0308 0309 static StatementNode *makeImportNode(PackageNameNode *n, 0310 bool wildcard, const Identifier &a) 0311 { 0312 ImportStatement *stat = new ImportStatement(n); 0313 if (wildcard) { 0314 stat->enableWildcard(); 0315 } 0316 stat->setAlias(a); 0317 0318 return stat; 0319 } 0320 0321 static StatementNode *makeLabelNode(const Identifier &l, StatementNode *s) 0322 { 0323 return new LabelNode(l, s); 0324 } 0325 0326 } // namespace KJS 0327 0328 #endif 0329 // vi: set sw=4 :