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 :