kjs Library API Documentation

nodes.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2002, 2003 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
00006  *  Copyright (C) 2003 Apple Computer, Inc.
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public License
00019  *  along with this library; see the file COPYING.LIB.  If not, write to
00020  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021  *  Boston, MA 02111-1307, USA.
00022  *
00023  */
00024 
00025 #include "nodes.h"
00026 
00027 #include <math.h>
00028 #include <assert.h>
00029 #ifdef KJS_DEBUG_MEM
00030 #include <stdio.h>
00031 #include <typeinfo>
00032 #endif
00033 #ifdef KJS_VERBOSE
00034 #include <iostream>
00035 using namespace std;
00036 #endif
00037 
00038 #include "collector.h"
00039 #include "context.h"
00040 #include "debugger.h"
00041 #include "function_object.h"
00042 #include "internal.h"
00043 #include "value.h"
00044 #include "object.h"
00045 #include "types.h"
00046 #include "interpreter.h"
00047 #include "lexer.h"
00048 #include "operations.h"
00049 #include "ustring.h"
00050 
00051 using namespace KJS;
00052 
00053 #define KJS_BREAKPOINT \
00054   if (!hitStatement(exec)) \
00055     return Completion(Normal);
00056 
00057 #define KJS_ABORTPOINT \
00058   if (exec->interpreter()->imp()->debugger() && \
00059       exec->interpreter()->imp()->debugger()->imp()->aborted()) \
00060     return Completion(Normal);
00061 
00062 #define KJS_CHECKEXCEPTION \
00063   if (exec->hadException()) \
00064     return Completion(Throw, exec->exception()); \
00065   if (Collector::outOfMemory()) \
00066     return Completion(Throw, Error::create(exec,GeneralError,"Out of memory"));
00067 
00068 #define KJS_CHECKEXCEPTIONVALUE \
00069   if (exec->hadException()) \
00070     return exec->exception(); \
00071   if (Collector::outOfMemory()) \
00072     return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
00073 
00074 #define KJS_CHECKEXCEPTIONREFERENCE \
00075   if (exec->hadException()) \
00076     return Reference::makeValueReference(Undefined()); \
00077   if (Collector::outOfMemory()) \
00078     return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION
00079 
00080 #define KJS_CHECKEXCEPTIONLIST \
00081   if (exec->hadException()) \
00082     return List(); \
00083   if (Collector::outOfMemory()) \
00084     return List(); // will be picked up by KJS_CHECKEXCEPTION
00085 
00086 #ifdef KJS_DEBUG_MEM
00087 std::list<Node *> * Node::s_nodes = 0L;
00088 #endif
00089 
00090 // ----------------------------- Node -----------------------------------------
00091 
00092 Node::Node()
00093 {
00094   line = Lexer::curr()->lineNo();
00095   refcount = 0;
00096 #ifdef KJS_DEBUG_MEM
00097   if (!s_nodes)
00098     s_nodes = new std::list<Node *>;
00099   s_nodes->push_back(this);
00100 #endif
00101 }
00102 
00103 Node::~Node()
00104 {
00105 #ifdef KJS_DEBUG_MEM
00106   s_nodes->remove( this );
00107 #endif
00108 }
00109 
00110 Reference Node::evaluateReference(ExecState *exec) const
00111 {
00112   Value v = evaluate(exec);
00113   KJS_CHECKEXCEPTIONREFERENCE
00114   return Reference::makeValueReference(v);
00115 }
00116 
00117 // fallback for those nodes without a evaluate() reimplementation
00118 // TODO: reimplemint in each sub class, make Node::evaluate() pure virtual
00119 Value Node::evaluate(ExecState *exec) const
00120 {
00121   //  fprintf(stderr, "%s::evaluate()\n", typeid(*this).name());
00122   return evaluateReference(exec).getValue(exec);
00123 }
00124 
00125 bool Node::toBoolean(ExecState *exec) const
00126 {
00127 //   fprintf(stderr, "Node(%s)::toBoolean()\n", typeid(*this).name());
00128   return evaluate(exec).toBoolean(exec);
00129 }
00130 
00131 double Node::toNumber(ExecState *exec) const
00132 {
00133 //   fprintf(stderr, "Node(%s)::toNumber()\n", typeid(*this).name());
00134   return evaluate(exec).toNumber(exec);
00135 }
00136 
00137 UString Node::toString(ExecState *exec) const
00138 {
00139   return evaluate(exec).toString(exec);
00140 }
00141 
00142 #ifdef KJS_DEBUG_MEM
00143 void Node::finalCheck()
00144 {
00145   if (!s_nodes) {
00146       fprintf(stderr, "Node::finalCheck(): list 0\n");
00147       return;
00148   }
00149   fprintf( stderr, "Node::finalCheck(): list count       : %d\n", (int)s_nodes->size() );
00150   std::list<Node *>::iterator it = s_nodes->begin();
00151   for ( uint i = 0; it != s_nodes->end() ; ++it, ++i )
00152     fprintf( stderr, "[%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount );
00153   delete s_nodes;
00154   s_nodes = 0L;
00155 }
00156 #endif
00157 
00158 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg) const
00159 {
00160   Object err = Error::create(exec, e, msg, lineNo(), sourceId());
00161   exec->setException(err);
00162   return err;
00163 }
00164 
00165 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Value v, Node *expr) const
00166 {
00167   char *vStr = strdup(v.toString(exec).ascii());
00168   char *exprStr = strdup(expr->toCode().ascii());
00169 
00170   int length =  strlen(msg) - 4 /* two %s */ + strlen(vStr) + strlen(exprStr) +
00171  1 /* null terminator */;
00172   char *str = new char[length];
00173   sprintf(str, msg, vStr, exprStr);
00174   free(vStr);
00175   free(exprStr);
00176 
00177   Value result = throwError(exec, e, str);
00178   delete [] str;
00179 
00180   return result;
00181 }
00182 
00183 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Identifier label) const
00184 {
00185   const char *l = label.ascii();
00186   int length = strlen(msg) - 2 /* %s */ + strlen(l) + 1 /* null terminator */;
00187   char *message = new char[length];
00188   sprintf(message, msg, l);
00189 
00190   Value result = throwError(exec, e, message);
00191   delete [] message;
00192 
00193   return result;
00194 }
00195 
00196 // ----------------------------- StatementNode --------------------------------
00197 StatementNode::StatementNode() : l0(-1), l1(-1), sourceCode(0), breakPoint(false)
00198 {
00199 }
00200 
00201 StatementNode::~StatementNode()
00202 {
00203   if (sourceCode)
00204     sourceCode->deref();
00205 }
00206 
00207 void StatementNode::setLoc(int line0, int line1, SourceCode *src)
00208 {
00209   // ### require these to be passed to the constructor
00210   l0 = line0;
00211   l1 = line1;
00212   if (sourceCode != src) {
00213     if (sourceCode)
00214       sourceCode->deref();
00215     sourceCode = src;
00216     sourceCode->ref();
00217   }
00218 }
00219 
00220 // return true if the debugger wants us to stop at this point
00221 bool StatementNode::hitStatement(ExecState *exec)
00222 {
00223   assert(sourceCode);
00224   assert(exec->context().imp()->sourceId == sourceCode->sid);
00225   exec->context().imp()->setLines(l0,l1);
00226   Debugger *dbg = exec->interpreter()->imp()->debugger();
00227   if (dbg)
00228     return dbg->atStatement(exec);
00229   else
00230     return true; // continue
00231 }
00232 
00233 // return true if the debugger wants us to stop at this point
00234 bool StatementNode::abortStatement(ExecState *exec)
00235 {
00236   Debugger *dbg = exec->interpreter()->imp()->debugger();
00237   if (dbg)
00238     return dbg->imp()->aborted();
00239   else
00240     return false;
00241 }
00242 
00243 void StatementNode::processFuncDecl(ExecState *)
00244 {
00245 }
00246 
00247 // ----------------------------- NullNode -------------------------------------
00248 
00249 Value NullNode::evaluate(ExecState *) const
00250 {
00251   return Null();
00252 }
00253 
00254 bool NullNode::toBoolean(ExecState *) const
00255 {
00256   return false;
00257 }
00258 
00259 double NullNode::toNumber(ExecState *) const
00260 {
00261   return 0.0;
00262 }
00263 
00264 UString NullNode::toString(ExecState *) const
00265 {
00266   return "null";
00267 }
00268 
00269 // ----------------------------- BooleanNode ----------------------------------
00270 
00271 Value BooleanNode::evaluate(ExecState *) const
00272 {
00273   return Boolean(val);
00274 }
00275 
00276 bool BooleanNode::toBoolean(ExecState *) const
00277 {
00278   return val;
00279 }
00280 
00281 double BooleanNode::toNumber(ExecState *) const
00282 {
00283   return val ? 1.0 : 0.0;
00284 }
00285 
00286 UString BooleanNode::toString(ExecState *) const
00287 {
00288   return val ? "true" : "false";
00289 }
00290 
00291 // ----------------------------- NumberNode -----------------------------------
00292 
00293 Value NumberNode::evaluate(ExecState *) const
00294 {
00295   return Number(val);
00296 }
00297 
00298 bool NumberNode::toBoolean(ExecState *) const
00299 {
00300   return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
00301 }
00302 
00303 double NumberNode::toNumber(ExecState *) const
00304 {
00305   return val;
00306 }
00307 
00308 UString NumberNode::toString(ExecState *) const
00309 {
00310   return UString::from(val);
00311 }
00312 
00313 // ----------------------------- StringNode -----------------------------------
00314 
00315 Value StringNode::evaluate(ExecState *) const
00316 {
00317   return String(val);
00318 }
00319 
00320 bool StringNode::toBoolean(ExecState *) const
00321 {
00322   return !val.isEmpty();
00323 }
00324 
00325 double StringNode::toNumber(ExecState *) const
00326 {
00327   return val.toDouble();
00328 }
00329 
00330 UString StringNode::toString(ExecState *) const
00331 {
00332   return val;
00333 }
00334 
00335 // ----------------------------- RegExpNode -----------------------------------
00336 
00337 Value RegExpNode::evaluate(ExecState *exec) const
00338 {
00339   List list;
00340   String p(pattern);
00341   String f(flags);
00342   list.append(p);
00343   list.append(f);
00344 
00345   Object reg = exec->interpreter()->imp()->builtinRegExp();
00346   return reg.construct(exec,list);
00347 }
00348 
00349 bool RegExpNode::toBoolean(ExecState *) const
00350 {
00351   return true;
00352 }
00353 
00354 // ----------------------------- ThisNode -------------------------------------
00355 
00356 // ECMA 11.1.1
00357 Value ThisNode::evaluate(ExecState *exec) const
00358 {
00359   return exec->context().imp()->thisValue();
00360 }
00361 
00362 // ----------------------------- ResolveNode ----------------------------------
00363 
00364 // ECMA 11.1.2 & 10.1.4
00365 Value ResolveNode::evaluate(ExecState *exec) const
00366 {
00367   return evaluateReference(exec).getValue(exec);
00368 }
00369 
00370 Reference ResolveNode::evaluateReference(ExecState *exec) const
00371 {
00372   ScopeChain chain = exec->context().imp()->scopeChain();
00373 
00374   while (!chain.isEmpty()) {
00375     ObjectImp *o = chain.top();
00376 
00377     //cerr << "Resolve: looking at '" << ident.ascii() << "'"
00378     //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
00379     if (o->hasProperty(exec,ident)) {
00380       //cerr << "Resolve: FOUND '" << ident.ascii() << "'"
00381       //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
00382       return Reference(o, ident);
00383     }
00384 
00385     chain.pop();
00386   }
00387 
00388   // identifier not found
00389 #ifdef KJS_VERBOSE
00390   cerr << "Resolve::evaluateReference: didn't find '" << ident.ustring().ascii() << "'" << endl;
00391 #endif
00392   return Reference(Null(), ident);
00393 }
00394 
00395 // ----------------------------- GroupNode ------------------------------------
00396 
00397 void GroupNode::ref()
00398 {
00399   Node::ref();
00400   if ( group )
00401     group->ref();
00402 }
00403 
00404 bool GroupNode::deref()
00405 {
00406   if ( group && group->deref() )
00407     delete group;
00408   return Node::deref();
00409 }
00410 
00411 // ECMA 11.1.6
00412 Value GroupNode::evaluate(ExecState *exec) const
00413 {
00414   return group->evaluate(exec);
00415 }
00416 
00417 Reference GroupNode::evaluateReference(ExecState *exec) const
00418 {
00419   return group->evaluateReference(exec);
00420 }
00421 
00422 // ----------------------------- ElementNode ----------------------------------
00423 
00424 void ElementNode::ref()
00425 {
00426   for (ElementNode *n = this; n; n = n->list) {
00427     n->Node::ref();
00428     if (n->node)
00429       n->node->ref();
00430   }
00431 }
00432 
00433 bool ElementNode::deref()
00434 {
00435   ElementNode *next;
00436   for (ElementNode *n = this; n; n = next) {
00437     next = n->list;
00438     if (n->node && n->node->deref())
00439       delete n->node;
00440     if (n != this && n->Node::deref())
00441       delete n;
00442   }
00443   return Node::deref();
00444 }
00445 
00446 // ECMA 11.1.4
00447 Value ElementNode::evaluate(ExecState *exec) const
00448 {
00449   Object array = exec->interpreter()->builtinArray().construct(exec, List::empty());
00450   int length = 0;
00451   for (const ElementNode *n = this; n; n = n->list) {
00452     Value val = n->node->evaluate(exec);
00453     KJS_CHECKEXCEPTIONVALUE
00454     length += n->elision;
00455     array.put(exec, length++, val);
00456   }
00457   return array;
00458 }
00459 
00460 // ----------------------------- ArrayNode ------------------------------------
00461 
00462 void ArrayNode::ref()
00463 {
00464   Node::ref();
00465   if ( element )
00466     element->ref();
00467 }
00468 
00469 bool ArrayNode::deref()
00470 {
00471   if ( element && element->deref() )
00472     delete element;
00473   return Node::deref();
00474 }
00475 
00476 // ECMA 11.1.4
00477 Value ArrayNode::evaluate(ExecState *exec) const
00478 {
00479   Object array;
00480   int length;
00481 
00482   if (element) {
00483     array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
00484     KJS_CHECKEXCEPTIONVALUE
00485     length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0;
00486   } else {
00487     Value newArr = exec->interpreter()->builtinArray().construct(exec,List::empty());
00488     array = Object(static_cast<ObjectImp*>(newArr.imp()));
00489     length = 0;
00490   }
00491 
00492   if (opt)
00493     array.put(exec,lengthPropertyName, Number(elision + length), DontEnum | DontDelete);
00494 
00495   return array;
00496 }
00497 
00498 // ----------------------------- ObjectLiteralNode ----------------------------
00499 
00500 void ObjectLiteralNode::ref()
00501 {
00502   Node::ref();
00503   if ( list )
00504     list->ref();
00505 }
00506 
00507 bool ObjectLiteralNode::deref()
00508 {
00509   if ( list && list->deref() )
00510     delete list;
00511   return Node::deref();
00512 }
00513 
00514 // ECMA 11.1.5
00515 Value ObjectLiteralNode::evaluate(ExecState *exec) const
00516 {
00517   if (list)
00518     return list->evaluate(exec);
00519 
00520   return exec->interpreter()->builtinObject().construct(exec,List::empty());
00521 }
00522 
00523 // ----------------------------- PropertyValueNode ----------------------------
00524 
00525 void PropertyValueNode::ref()
00526 {
00527   for (PropertyValueNode *n = this; n; n = n->list) {
00528     n->Node::ref();
00529     if (n->name)
00530       n->name->ref();
00531     if (n->assign)
00532       n->assign->ref();
00533   }
00534 }
00535 
00536 bool PropertyValueNode::deref()
00537 {
00538   PropertyValueNode *next;
00539   for (PropertyValueNode *n = this; n; n = next) {
00540     next = n->list;
00541     if ( n->name && n->name->deref() )
00542       delete n->name;
00543     if ( n->assign && n->assign->deref() )
00544       delete n->assign;
00545     if (n != this && n->Node::deref() )
00546       delete n;
00547   }
00548   return Node::deref();
00549 }
00550 
00551 // ECMA 11.1.5
00552 Value PropertyValueNode::evaluate(ExecState *exec) const
00553 {
00554   Object obj = exec->interpreter()->builtinObject().construct(exec, List::empty());
00555 
00556   for (const PropertyValueNode *p = this; p; p = p->list) {
00557     Value n = p->name->evaluate(exec);
00558     KJS_CHECKEXCEPTIONVALUE
00559     Value v = p->assign->evaluate(exec);
00560     KJS_CHECKEXCEPTIONVALUE
00561 
00562     obj.put(exec, Identifier(n.toString(exec)), v);
00563   }
00564 
00565   return obj;
00566 }
00567 
00568 // ----------------------------- PropertyNode ---------------------------------
00569 
00570 // ECMA 11.1.5
00571 Value PropertyNode::evaluate(ExecState */*exec*/) const
00572 {
00573   Value s;
00574 
00575   if (str.isNull()) {
00576     s = String(UString::from(numeric));
00577   } else {
00578     s = String(str.ustring());
00579   }
00580 
00581   return s;
00582 }
00583 
00584 // ----------------------------- AccessorNode1 --------------------------------
00585 
00586 void AccessorNode1::ref()
00587 {
00588   Node::ref();
00589   if ( expr1 )
00590     expr1->ref();
00591   if ( expr2 )
00592     expr2->ref();
00593 }
00594 
00595 bool AccessorNode1::deref()
00596 {
00597   if ( expr1 && expr1->deref() )
00598     delete expr1;
00599   if ( expr2 && expr2->deref() )
00600     delete expr2;
00601   return Node::deref();
00602 }
00603 
00604 // ECMA 11.2.1a
00605 Reference AccessorNode1::evaluateReference(ExecState *exec) const
00606 {
00607   Value v1 = expr1->evaluate(exec);
00608   KJS_CHECKEXCEPTIONREFERENCE
00609   Value v2 = expr2->evaluate(exec);
00610   KJS_CHECKEXCEPTIONREFERENCE
00611   Object o = v1.toObject(exec);
00612   unsigned i;
00613   if (v2.toUInt32(i))
00614     return Reference(o, i);
00615   UString s = v2.toString(exec);
00616   return Reference(o, Identifier(s));
00617 }
00618 
00619 // ----------------------------- AccessorNode2 --------------------------------
00620 
00621 void AccessorNode2::ref()
00622 {
00623   Node::ref();
00624   if ( expr )
00625     expr->ref();
00626 }
00627 
00628 bool AccessorNode2::deref()
00629 {
00630   if ( expr && expr->deref() )
00631     delete expr;
00632   return Node::deref();
00633 }
00634 
00635 // ECMA 11.2.1b
00636 Reference AccessorNode2::evaluateReference(ExecState *exec) const
00637 {
00638   Value v = expr->evaluate(exec);
00639   assert(v.isValid());
00640   KJS_CHECKEXCEPTIONREFERENCE
00641   Object o = v.toObject(exec);
00642   return Reference(o, ident);
00643 }
00644 
00645 // ----------------------------- ArgumentListNode -----------------------------
00646 
00647 void ArgumentListNode::ref()
00648 {
00649   for (ArgumentListNode *n = this; n; n = n->list) {
00650     n->Node::ref();
00651     if (n->expr)
00652       n->expr->ref();
00653   }
00654 }
00655 
00656 bool ArgumentListNode::deref()
00657 {
00658   ArgumentListNode *next;
00659   for (ArgumentListNode *n = this; n; n = next) {
00660     next = n->list;
00661     if (n->expr && n->expr->deref())
00662       delete n->expr;
00663     if (n != this && n->Node::deref())
00664       delete n;
00665   }
00666   return Node::deref();
00667 }
00668 
00669 Value ArgumentListNode::evaluate(ExecState */*exec*/) const
00670 {
00671   assert(0);
00672   return Value(); // dummy, see evaluateList()
00673 }
00674 
00675 // ECMA 11.2.4
00676 List ArgumentListNode::evaluateList(ExecState *exec) const
00677 {
00678   List l;
00679 
00680   for (const ArgumentListNode *n = this; n; n = n->list) {
00681     Value v = n->expr->evaluate(exec);
00682     KJS_CHECKEXCEPTIONLIST
00683     l.append(v);
00684   }
00685 
00686   return l;
00687 }
00688 
00689 // ----------------------------- ArgumentsNode --------------------------------
00690 
00691 void ArgumentsNode::ref()
00692 {
00693   Node::ref();
00694   if ( list )
00695     list->ref();
00696 }
00697 
00698 bool ArgumentsNode::deref()
00699 {
00700   if ( list && list->deref() )
00701     delete list;
00702   return Node::deref();
00703 }
00704 
00705 Value ArgumentsNode::evaluate(ExecState */*exec*/) const
00706 {
00707   assert(0);
00708   return Value(); // dummy, see evaluateList()
00709 }
00710 
00711 // ECMA 11.2.4
00712 List ArgumentsNode::evaluateList(ExecState *exec) const
00713 {
00714   if (!list)
00715     return List();
00716 
00717   return list->evaluateList(exec);
00718 }
00719 
00720 // ----------------------------- NewExprNode ----------------------------------
00721 
00722 // ECMA 11.2.2
00723 
00724 void NewExprNode::ref()
00725 {
00726   Node::ref();
00727   if ( expr )
00728     expr->ref();
00729   if ( args )
00730     args->ref();
00731 }
00732 
00733 bool NewExprNode::deref()
00734 {
00735   if ( expr && expr->deref() )
00736     delete expr;
00737   if ( args && args->deref() )
00738     delete args;
00739   return Node::deref();
00740 }
00741 
00742 Value NewExprNode::evaluate(ExecState *exec) const
00743 {
00744   Value v = expr->evaluate(exec);
00745   KJS_CHECKEXCEPTIONVALUE
00746 
00747   List argList;
00748   if (args) {
00749     argList = args->evaluateList(exec);
00750     KJS_CHECKEXCEPTIONVALUE
00751   }
00752 
00753   if (v.type() != ObjectType) {
00754     return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr);
00755   }
00756 
00757   Object constr = Object(static_cast<ObjectImp*>(v.imp()));
00758   if (!constr.implementsConstruct()) {
00759     return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr);
00760   }
00761 
00762   Value res = constr.construct(exec,argList);
00763 
00764   return res;
00765 }
00766 
00767 // ----------------------------- FunctionCallNode -----------------------------
00768 
00769 void FunctionCallNode::ref()
00770 {
00771   Node::ref();
00772   if ( expr )
00773     expr->ref();
00774   if ( args )
00775     args->ref();
00776 }
00777 
00778 bool FunctionCallNode::deref()
00779 {
00780   if ( expr && expr->deref() )
00781     delete expr;
00782   if ( args && args->deref() )
00783     delete args;
00784   return Node::deref();
00785 }
00786 
00787 // ECMA 11.2.3
00788 Value FunctionCallNode::evaluate(ExecState *exec) const
00789 {
00790   Reference ref = expr->evaluateReference(exec);
00791   KJS_CHECKEXCEPTIONVALUE
00792 
00793   List argList = args->evaluateList(exec);
00794   KJS_CHECKEXCEPTIONVALUE
00795 
00796   Value v = ref.getValue(exec);
00797   KJS_CHECKEXCEPTIONVALUE
00798 
00799   if (v.type() != ObjectType) {
00800     return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be called.", v, expr);
00801   }
00802 
00803   Object func = Object(static_cast<ObjectImp*>(v.imp()));
00804 
00805   if (!func.implementsCall()) {
00806     return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr);
00807   }
00808 
00809   Value thisVal;
00810   if (ref.isMutable())
00811     thisVal = ref.getBase(exec);
00812   else
00813     thisVal = Null();
00814 
00815   if (thisVal.type() == ObjectType &&
00816       Object::dynamicCast(thisVal).inherits(&ActivationImp::info))
00817     thisVal = Null();
00818 
00819   if (thisVal.type() != ObjectType) {
00820     // ECMA 11.2.3 says that in this situation the this value should be null.
00821     // However, section 10.2.3 says that in the case where the value provided
00822     // by the caller is null, the global object should be used. It also says
00823     // that the section does not apply to interal functions, but for simplicity
00824     // of implementation we use the global object anyway here. This guarantees
00825     // that in host objects you always get a valid object for this.
00826     // thisVal = Null();
00827     thisVal = exec->interpreter()->globalObject();
00828   }
00829 
00830   Object thisObj = Object::dynamicCast(thisVal);
00831   Value result = func.call(exec,thisObj, argList);
00832 
00833   return result;
00834 }
00835 
00836 // ----------------------------- PostfixNode ----------------------------------
00837 
00838 void PostfixNode::ref()
00839 {
00840   Node::ref();
00841   if ( expr )
00842     expr->ref();
00843 }
00844 
00845 bool PostfixNode::deref()
00846 {
00847   if ( expr && expr->deref() )
00848     delete expr;
00849   return Node::deref();
00850 }
00851 
00852 // ECMA 11.3
00853 Value PostfixNode::evaluate(ExecState *exec) const
00854 {
00855   Reference ref = expr->evaluateReference(exec);
00856   KJS_CHECKEXCEPTIONVALUE
00857   Value v = ref.getValue(exec);
00858   double n = v.toNumber(exec);
00859 
00860   double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
00861 
00862   ref.putValue(exec, Number(newValue));
00863 
00864   return Number(n);
00865 }
00866 
00867 // ----------------------------- DeleteNode -----------------------------------
00868 
00869 void DeleteNode::ref()
00870 {
00871   Node::ref();
00872   if ( expr )
00873     expr->ref();
00874 }
00875 
00876 bool DeleteNode::deref()
00877 {
00878   if ( expr && expr->deref() )
00879     delete expr;
00880   return Node::deref();
00881 }
00882 
00883 // ECMA 11.4.1
00884 Value DeleteNode::evaluate(ExecState *exec) const
00885 {
00886   Reference ref = expr->evaluateReference(exec);
00887   KJS_CHECKEXCEPTIONVALUE
00888   return Boolean(ref.deleteValue(exec));
00889 }
00890 
00891 // ----------------------------- VoidNode -------------------------------------
00892 
00893 void VoidNode::ref()
00894 {
00895   Node::ref();
00896   if ( expr )
00897     expr->ref();
00898 }
00899 
00900 bool VoidNode::deref()
00901 {
00902   if ( expr && expr->deref() )
00903     delete expr;
00904   return Node::deref();
00905 }
00906 
00907 // ECMA 11.4.2
00908 Value VoidNode::evaluate(ExecState *exec) const
00909 {
00910   Value dummy1 = expr->evaluate(exec);
00911   KJS_CHECKEXCEPTIONVALUE
00912 
00913   return Undefined();
00914 }
00915 
00916 // ----------------------------- TypeOfNode -----------------------------------
00917 
00918 void TypeOfNode::ref()
00919 {
00920   Node::ref();
00921   if ( expr )
00922     expr->ref();
00923 }
00924 
00925 bool TypeOfNode::deref()
00926 {
00927   if ( expr && expr->deref() )
00928     delete expr;
00929   return Node::deref();
00930 }
00931 
00932 // ECMA 11.4.3
00933 Value TypeOfNode::evaluate(ExecState *exec) const
00934 {
00935   const char *s = 0L;
00936   Reference ref = expr->evaluateReference(exec);
00937   KJS_CHECKEXCEPTIONVALUE
00938   if (ref.isMutable()) {
00939     Value b = ref.getBase(exec);
00940     if (b.type() == NullType)
00941       return String("undefined");
00942   }
00943   Value v = ref.getValue(exec);
00944   switch (v.type())
00945     {
00946     case UndefinedType:
00947       s = "undefined";
00948       break;
00949     case NullType:
00950       s = "object";
00951       break;
00952     case BooleanType:
00953       s = "boolean";
00954       break;
00955     case NumberType:
00956       s = "number";
00957       break;
00958     case StringType:
00959       s = "string";
00960       break;
00961     default:
00962       if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall())
00963     s = "function";
00964       else
00965     s = "object";
00966       break;
00967     }
00968 
00969   return String(s);
00970 }
00971 
00972 // ----------------------------- PrefixNode -----------------------------------
00973 
00974 void PrefixNode::ref()
00975 {
00976   Node::ref();
00977   if ( expr )
00978     expr->ref();
00979 }
00980 
00981 bool PrefixNode::deref()
00982 {
00983   if ( expr && expr->deref() )
00984     delete expr;
00985   return Node::deref();
00986 }
00987 
00988 // ECMA 11.4.4 and 11.4.5
00989 Value PrefixNode::evaluate(ExecState *exec) const
00990 {
00991   Reference ref = expr->evaluateReference(exec);
00992   KJS_CHECKEXCEPTION
00993   Value v = ref.getValue(exec);
00994   double n = v.toNumber(exec);
00995 
00996   double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
00997   Value n2 = Number(newValue);
00998 
00999   ref.putValue(exec,n2);
01000 
01001   return n2;
01002 }
01003 
01004 // ----------------------------- UnaryPlusNode --------------------------------
01005 
01006 void UnaryPlusNode::ref()
01007 {
01008   Node::ref();
01009   if ( expr )
01010     expr->ref();
01011 }
01012 
01013 bool UnaryPlusNode::deref()
01014 {
01015   if ( expr && expr->deref() )
01016     delete expr;
01017   return Node::deref();
01018 }
01019 
01020 // ECMA 11.4.6
01021 double UnaryPlusNode::toNumber(ExecState *exec) const
01022 {
01023   return expr->toNumber(exec);
01024 }
01025 
01026 // could go
01027 Value UnaryPlusNode::evaluate(ExecState *exec) const
01028 {
01029   Value v = expr->evaluate(exec);
01030   KJS_CHECKEXCEPTIONVALUE
01031 
01032   return Number(v.toNumber(exec)); /* TODO: optimize */
01033 }
01034 
01035 // ----------------------------- NegateNode -----------------------------------
01036 
01037 void NegateNode::ref()
01038 {
01039   Node::ref();
01040   if ( expr )
01041     expr->ref();
01042 }
01043 
01044 bool NegateNode::deref()
01045 {
01046   if ( expr && expr->deref() )
01047     delete expr;
01048   return Node::deref();
01049 }
01050 
01051 // ECMA 11.4.7
01052 double NegateNode::toNumber(ExecState *exec) const
01053 {
01054   return -expr->toNumber(exec);
01055 }
01056 
01057 Value NegateNode::evaluate(ExecState *exec) const
01058 {
01059   Value v = expr->evaluate(exec);
01060   KJS_CHECKEXCEPTIONVALUE
01061   double d = -v.toNumber(exec);
01062 
01063   return Number(d);
01064 }
01065 
01066 // ----------------------------- BitwiseNotNode -------------------------------
01067 
01068 void BitwiseNotNode::ref()
01069 {
01070   Node::ref();
01071   if ( expr )
01072     expr->ref();
01073 }
01074 
01075 bool BitwiseNotNode::deref()
01076 {
01077   if ( expr && expr->deref() )
01078     delete expr;
01079   return Node::deref();
01080 }
01081 
01082 // ECMA 11.4.8
01083 Value BitwiseNotNode::evaluate(ExecState *exec) const
01084 {
01085   Value v = expr->evaluate(exec);
01086   KJS_CHECKEXCEPTIONVALUE
01087   int i32 = v.toInt32(exec);
01088 
01089   return Number(~i32);
01090 }
01091 
01092 // ----------------------------- LogicalNotNode -------------------------------
01093 
01094 void LogicalNotNode::ref()
01095 {
01096   Node::ref();
01097   if ( expr )
01098     expr->ref();
01099 }
01100 
01101 bool LogicalNotNode::deref()
01102 {
01103   if ( expr && expr->deref() )
01104     delete expr;
01105   return Node::deref();
01106 }
01107 
01108 // ECMA 11.4.9
01109 bool LogicalNotNode::toBoolean(ExecState *exec) const
01110 {
01111   return !expr->toBoolean(exec);
01112 }
01113 
01114 // could remove this
01115 Value LogicalNotNode::evaluate(ExecState *exec) const
01116 {
01117   bool b = expr->toBoolean(exec);
01118   KJS_CHECKEXCEPTIONVALUE
01119 
01120   return Boolean(!b);
01121 }
01122 
01123 // ----------------------------- MultNode -------------------------------------
01124 
01125 void MultNode::ref()
01126 {
01127   Node::ref();
01128   if ( term1 )
01129     term1->ref();
01130   if ( term2 )
01131     term2->ref();
01132 }
01133 
01134 bool MultNode::deref()
01135 {
01136   if ( term1 && term1->deref() )
01137     delete term1;
01138   if ( term2 && term2->deref() )
01139     delete term2;
01140   return Node::deref();
01141 }
01142 
01143 // ECMA 11.5
01144 Value MultNode::evaluate(ExecState *exec) const
01145 {
01146   Value v1 = term1->evaluate(exec);
01147   KJS_CHECKEXCEPTIONVALUE
01148 
01149   Value v2 = term2->evaluate(exec);
01150   KJS_CHECKEXCEPTIONVALUE
01151 
01152   return mult(exec,v1, v2, oper);
01153 }
01154 
01155 // ----------------------------- AddNode --------------------------------------
01156 
01157 // factory for an appropriate addition or substraction node
01158 Node* AddNode::create(Node *t1, Node *t2, char op)
01159 {
01160   // ### many more combinations to check for
01161   // fold constants
01162   if ((t1->type() == NumberType || t1->type() == BooleanType) &&
01163       (t2->type() == NumberType || t2->type() == BooleanType)) {
01164     double d = t2->toNumber(0);
01165     Node* n = new NumberNode(t1->toNumber(0) + (op == '+' ? d : -d));
01166     delete t1;
01167     delete t2;
01168     return n;
01169   }
01170 
01171   if (op == '+' && t2->type() == StringType)
01172     return new AppendStringNode(t1, t2->toString(0));
01173 
01174   // fall back to generic node
01175   return new AddNode(t1, t2, op);
01176 }
01177 
01178 void AddNode::ref()
01179 {
01180   Node::ref();
01181   if ( term1 )
01182     term1->ref();
01183   if ( term2 )
01184     term2->ref();
01185 }
01186 
01187 bool AddNode::deref()
01188 {
01189   if ( term1 && term1->deref() )
01190     delete term1;
01191   if ( term2 && term2->deref() )
01192     delete term2;
01193   return Node::deref();
01194 }
01195 
01196 // ECMA 11.6
01197 Value AddNode::evaluate(ExecState *exec) const
01198 {
01199   Value v1 = term1->evaluate(exec);
01200   KJS_CHECKEXCEPTIONVALUE
01201 
01202   Value v2 = term2->evaluate(exec);
01203   KJS_CHECKEXCEPTIONVALUE
01204 
01205   return add(exec,v1, v2, oper);
01206 }
01207 
01208 // ------------------------ AddNumberNode ------------------------------------
01209 
01210 void AppendStringNode::ref()
01211 {
01212   Node::ref();
01213   term->ref();
01214 }
01215 
01216 bool AppendStringNode::deref()
01217 {
01218   if (term->deref())
01219     delete term;
01220   return Node::deref();
01221 }
01222 
01223 // ECMA 11.6 (special case of string appending)
01224 Value AppendStringNode::evaluate(ExecState *exec) const
01225 {
01226   UString s = term->toString(exec);
01227   KJS_CHECKEXCEPTIONVALUE;
01228 
01229   return String(s + str);
01230 }
01231 
01232 // ----------------------------- ShiftNode ------------------------------------
01233 
01234 void ShiftNode::ref()
01235 {
01236   Node::ref();
01237   if ( term1 )
01238     term1->ref();
01239   if ( term2 )
01240     term2->ref();
01241 }
01242 
01243 bool ShiftNode::deref()
01244 {
01245   if ( term1 && term1->deref() )
01246     delete term1;
01247   if ( term2 && term2->deref() )
01248     delete term2;
01249   return Node::deref();
01250 }
01251 
01252 // ECMA 11.7
01253 Value ShiftNode::evaluate(ExecState *exec) const
01254 {
01255   Value v1 = term1->evaluate(exec);
01256   KJS_CHECKEXCEPTIONVALUE
01257   Value v2 = term2->evaluate(exec);
01258   KJS_CHECKEXCEPTIONVALUE
01259   unsigned int i2 = v2.toUInt32(exec);
01260   i2 &= 0x1f;
01261 
01262   switch (oper) {
01263   case OpLShift:
01264     return Number(v1.toInt32(exec) << i2);
01265   case OpRShift:
01266     return Number(v1.toInt32(exec) >> i2);
01267   case OpURShift:
01268     return Number(v1.toUInt32(exec) >> i2);
01269   default:
01270     assert(!"ShiftNode: unhandled switch case");
01271     return Undefined();
01272   }
01273 }
01274 
01275 // ----------------------------- RelationalNode -------------------------------
01276 
01277 void RelationalNode::ref()
01278 {
01279   Node::ref();
01280   if ( expr1 )
01281     expr1->ref();
01282   if ( expr2 )
01283     expr2->ref();
01284 }
01285 
01286 bool RelationalNode::deref()
01287 {
01288   if ( expr1 && expr1->deref() )
01289     delete expr1;
01290   if ( expr2 && expr2->deref() )
01291     delete expr2;
01292   return Node::deref();
01293 }
01294 
01295 // ECMA 11.8
01296 Value RelationalNode::evaluate(ExecState *exec) const
01297 {
01298   Value v1 = expr1->evaluate(exec);
01299   KJS_CHECKEXCEPTIONVALUE
01300   Value v2 = expr2->evaluate(exec);
01301   KJS_CHECKEXCEPTIONVALUE
01302 
01303   bool b;
01304   if (oper == OpLess || oper == OpGreaterEq) {
01305     int r = relation(exec, v1, v2);
01306     if (r < 0)
01307       b = false;
01308     else
01309       b = (oper == OpLess) ? (r == 1) : (r == 0);
01310   } else if (oper == OpGreater || oper == OpLessEq) {
01311     int r = relation(exec, v2, v1);
01312     if (r < 0)
01313       b = false;
01314     else
01315       b = (oper == OpGreater) ? (r == 1) : (r == 0);
01316   } else if (oper == OpIn) {
01317       // Is all of this OK for host objects?
01318       if (v2.type() != ObjectType)
01319           return throwError(exec,  TypeError,
01320                             "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2);
01321       Object o2(static_cast<ObjectImp*>(v2.imp()));
01322       b = o2.hasProperty(exec,Identifier(v1.toString(exec)));
01323   } else {
01324     if (v2.type() != ObjectType)
01325         return throwError(exec,  TypeError,
01326                           "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2);
01327 
01328     Object o2(static_cast<ObjectImp*>(v2.imp()));
01329     if (!o2.implementsHasInstance()) {
01330       // According to the spec, only some types of objects "imlement" the [[HasInstance]] property.
01331       // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
01332       // property. It seems that all object have the property, but not all implement it, so in this
01333       // case we return false (consistent with mozilla)
01334       return Boolean(false);
01335       //      return throwError(exec, TypeError,
01336       //            "Object does not implement the [[HasInstance]] method." );
01337     }
01338     return o2.hasInstance(exec, v1);
01339   }
01340 
01341   return Boolean(b);
01342 }
01343 
01344 // ----------------------------- EqualNode ------------------------------------
01345 
01346 void EqualNode::ref()
01347 {
01348   Node::ref();
01349   if ( expr1 )
01350     expr1->ref();
01351   if ( expr2 )
01352     expr2->ref();
01353 }
01354 
01355 bool EqualNode::deref()
01356 {
01357   if ( expr1 && expr1->deref() )
01358     delete expr1;
01359   if ( expr2 && expr2->deref() )
01360     delete expr2;
01361   return Node::deref();
01362 }
01363 
01364 // ECMA 11.9
01365 Value EqualNode::evaluate(ExecState *exec) const
01366 {
01367   Value v1 = expr1->evaluate(exec);
01368   KJS_CHECKEXCEPTIONVALUE
01369   Value v2 = expr2->evaluate(exec);
01370   KJS_CHECKEXCEPTIONVALUE
01371 
01372   bool result;
01373   if (oper == OpEqEq || oper == OpNotEq) {
01374     // == and !=
01375     bool eq = equal(exec,v1, v2);
01376     result = oper == OpEqEq ? eq : !eq;
01377   } else {
01378     // === and !==
01379     bool eq = strictEqual(exec,v1, v2);
01380     result = oper == OpStrEq ? eq : !eq;
01381   }
01382   return Boolean(result);
01383 }
01384 
01385 // ----------------------------- BitOperNode ----------------------------------
01386 
01387 void BitOperNode::ref()
01388 {
01389   Node::ref();
01390   if ( expr1 )
01391     expr1->ref();
01392   if ( expr2 )
01393     expr2->ref();
01394 }
01395 
01396 bool BitOperNode::deref()
01397 {
01398   if ( expr1 && expr1->deref() )
01399     delete expr1;
01400   if ( expr2 && expr2->deref() )
01401     delete expr2;
01402   return Node::deref();
01403 }
01404 
01405 // ECMA 11.10
01406 Value BitOperNode::evaluate(ExecState *exec) const
01407 {
01408   Value v1 = expr1->evaluate(exec);
01409   KJS_CHECKEXCEPTIONVALUE
01410   Value v2 = expr2->evaluate(exec);
01411   KJS_CHECKEXCEPTIONVALUE
01412   int i1 = v1.toInt32(exec);
01413   int i2 = v2.toInt32(exec);
01414   int result;
01415   if (oper == OpBitAnd)
01416     result = i1 & i2;
01417   else if (oper == OpBitXOr)
01418     result = i1 ^ i2;
01419   else
01420     result = i1 | i2;
01421 
01422   return Number(result);
01423 }
01424 
01425 // ----------------------------- BinaryLogicalNode ----------------------------
01426 
01427 void BinaryLogicalNode::ref()
01428 {
01429   Node::ref();
01430   if ( expr1 )
01431     expr1->ref();
01432   if ( expr2 )
01433     expr2->ref();
01434 }
01435 
01436 bool BinaryLogicalNode::deref()
01437 {
01438   if ( expr1 && expr1->deref() )
01439     delete expr1;
01440   if ( expr2 && expr2->deref() )
01441     delete expr2;
01442   return Node::deref();
01443 }
01444 
01445 // ECMA 11.11
01446 Value BinaryLogicalNode::evaluate(ExecState *exec) const
01447 {
01448   Value v1 = expr1->evaluate(exec);
01449   KJS_CHECKEXCEPTIONVALUE;
01450   bool b1 = v1.toBoolean(exec);
01451   if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
01452     return v1;
01453 
01454   Value v2 = expr2->evaluate(exec);
01455   KJS_CHECKEXCEPTIONVALUE
01456 
01457   return v2;
01458 }
01459 
01460 // ----------------------------- ConditionalNode ------------------------------
01461 
01462 void ConditionalNode::ref()
01463 {
01464   Node::ref();
01465   if ( expr1 )
01466     expr1->ref();
01467   if ( expr2 )
01468     expr2->ref();
01469   if ( logical )
01470     logical->ref();
01471 }
01472 
01473 bool ConditionalNode::deref()
01474 {
01475   if ( expr1 && expr1->deref() )
01476     delete expr1;
01477   if ( expr2 && expr2->deref() )
01478     delete expr2;
01479   if ( logical && logical->deref() )
01480     delete logical;
01481   return Node::deref();
01482 }
01483 
01484 // ECMA 11.12
01485 Value ConditionalNode::evaluate(ExecState *exec) const
01486 {
01487   bool b = logical->toBoolean(exec);
01488   KJS_CHECKEXCEPTIONVALUE
01489 
01490   Value v = b ? expr1->evaluate(exec) : expr2->evaluate(exec);
01491   KJS_CHECKEXCEPTIONVALUE
01492 
01493   return v;
01494 }
01495 
01496 // ----------------------------- AssignNode -----------------------------------
01497 
01498 void AssignNode::ref()
01499 {
01500   Node::ref();
01501   if ( left )
01502     left->ref();
01503   if ( expr )
01504     expr->ref();
01505 }
01506 
01507 bool AssignNode::deref()
01508 {
01509   if ( left && left->deref() )
01510     delete left;
01511   if ( expr && expr->deref() )
01512     delete expr;
01513   return Node::deref();
01514 }
01515 
01516 // ECMA 11.13
01517 Value AssignNode::evaluate(ExecState *exec) const
01518 {
01519   Reference l = left->evaluateReference(exec);
01520   KJS_CHECKEXCEPTIONVALUE
01521   Value v;
01522   if (oper == OpEqual) {
01523     v = expr->evaluate(exec);
01524     KJS_CHECKEXCEPTIONVALUE
01525   } else {
01526     Value v1 = l.getValue(exec);
01527     Value v2 = expr->evaluate(exec);
01528     KJS_CHECKEXCEPTIONVALUE
01529     int i1 = v1.toInt32(exec);
01530     int i2 = v2.toInt32(exec);
01531     unsigned int ui;
01532     switch (oper) {
01533     case OpMultEq:
01534       v = mult(exec, v1, v2, '*');
01535       break;
01536     case OpDivEq:
01537       v = mult(exec, v1, v2, '/');
01538       break;
01539     case OpPlusEq:
01540       v = add(exec, v1, v2, '+');
01541       break;
01542     case OpMinusEq:
01543       v = add(exec, v1, v2, '-');
01544       break;
01545     case OpLShift:
01546       v = Number(i1 <<= i2);
01547       break;
01548     case OpRShift:
01549       v = Number(i1 >>= i2);
01550       break;
01551     case OpURShift:
01552       ui = v1.toUInt32(exec);
01553       v = Number(ui >>= i2);
01554       break;
01555     case OpAndEq:
01556       v = Number(i1 &= i2);
01557       break;
01558     case OpXOrEq:
01559       v = Number(i1 ^= i2);
01560       break;
01561     case OpOrEq:
01562       v = Number(i1 |= i2);
01563       break;
01564     case OpModEq: {
01565       double d1 = v1.toNumber(exec);
01566       double d2 = v2.toNumber(exec);
01567       v = Number(fmod(d1,d2));
01568     }
01569       break;
01570     default:
01571       v = Undefined();
01572     }
01573   };
01574   l.putValue(exec,v);
01575 
01576   KJS_CHECKEXCEPTIONVALUE
01577 
01578   return v;
01579 }
01580 
01581 // ----------------------------- CommaNode ------------------------------------
01582 
01583 void CommaNode::ref()
01584 {
01585   Node::ref();
01586   if ( expr1 )
01587     expr1->ref();
01588   if ( expr2 )
01589     expr2->ref();
01590 }
01591 
01592 bool CommaNode::deref()
01593 {
01594   if ( expr1 && expr1->deref() )
01595     delete expr1;
01596   if ( expr2 && expr2->deref() )
01597     delete expr2;
01598   return Node::deref();
01599 }
01600 
01601 // ECMA 11.14
01602 Value CommaNode::evaluate(ExecState *exec) const
01603 {
01604   (void) expr1->evaluate(exec);  // ignore return value
01605   KJS_CHECKEXCEPTIONVALUE
01606   Value v = expr2->evaluate(exec);
01607   KJS_CHECKEXCEPTIONVALUE
01608 
01609   return v;
01610 }
01611 
01612 // ----------------------------- StatListNode ---------------------------------
01613 
01614 StatListNode::StatListNode(StatementNode *s)
01615   : statement(s), list(this)
01616 {
01617   setLoc(s->firstLine(),s->lastLine(),s->code());
01618 }
01619 
01620 StatListNode::StatListNode(StatListNode *l, StatementNode *s)
01621   : statement(s), list(l->list)
01622 {
01623   l->list = this;
01624   setLoc(l->firstLine(),s->lastLine(),l->code());
01625 }
01626 
01627 void StatListNode::ref()
01628 {
01629   for (StatListNode *n = this; n; n = n->list) {
01630     n->Node::ref();
01631     if (n->statement)
01632       n->statement->ref();
01633   }
01634 }
01635 
01636 bool StatListNode::deref()
01637 {
01638   StatListNode *next;
01639   for (StatListNode *n = this; n; n = next) {
01640     next = n->list;
01641     if (n->statement && n->statement->deref())
01642       delete n->statement;
01643     if (n != this && n->Node::deref())
01644       delete n;
01645   }
01646   return StatementNode::deref();
01647 }
01648 
01649 // ECMA 12.1
01650 Completion StatListNode::execute(ExecState *exec)
01651 {
01652   Completion c = statement->execute(exec);
01653   KJS_ABORTPOINT
01654   if (exec->hadException()) {
01655     Value ex = exec->exception();
01656     exec->clearException();
01657     return Completion(Throw, ex);
01658   }
01659 
01660   if (c.complType() != Normal)
01661     return c;
01662 
01663   Value v = c.value();
01664 
01665   for (StatListNode *n = list; n; n = n->list) {
01666     Completion c2 = n->statement->execute(exec);
01667     KJS_ABORTPOINT
01668     if (c2.complType() != Normal)
01669       return c2;
01670 
01671     if (exec->hadException()) {
01672       Value ex = exec->exception();
01673       exec->clearException();
01674       return Completion(Throw, ex);
01675     }
01676 
01677     if (c2.isValueCompletion())
01678       v = c2.value();
01679     c = c2;
01680   }
01681 
01682   return Completion(c.complType(), v, c.target());
01683 }
01684 
01685 void StatListNode::processVarDecls(ExecState *exec)
01686 {
01687   for (StatListNode *n = this; n; n = n->list)
01688     n->statement->processVarDecls(exec);
01689 }
01690 
01691 // ----------------------------- AssignExprNode -------------------------------
01692 
01693 void AssignExprNode::ref()
01694 {
01695   Node::ref();
01696   if ( expr )
01697     expr->ref();
01698 }
01699 
01700 bool AssignExprNode::deref()
01701 {
01702   if ( expr && expr->deref() )
01703     delete expr;
01704   return Node::deref();
01705 }
01706 
01707 // ECMA 12.2
01708 Value AssignExprNode::evaluate(ExecState *exec) const
01709 {
01710   return expr->evaluate(exec);
01711 }
01712 
01713 // ----------------------------- VarDeclNode ----------------------------------
01714 
01715 VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in)
01716     : ident(id), init(in)
01717 {
01718 }
01719 
01720 void VarDeclNode::ref()
01721 {
01722   Node::ref();
01723   if ( init )
01724     init->ref();
01725 }
01726 
01727 bool VarDeclNode::deref()
01728 {
01729   if ( init && init->deref() )
01730     delete init;
01731   return Node::deref();
01732 }
01733 
01734 // ECMA 12.2
01735 Value VarDeclNode::evaluate(ExecState *exec) const
01736 {
01737   Object variable = Object::dynamicCast(exec->context().imp()->variableObject());
01738 
01739   Value val;
01740   if (init) {
01741       val = init->evaluate(exec);
01742       KJS_CHECKEXCEPTIONVALUE
01743   } else {
01744       if ( variable.hasProperty(exec, ident ) ) // already declared ?
01745           return Value();
01746       val = Undefined();
01747   }
01748 
01749 #ifdef KJS_VERBOSE
01750   printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
01751 #endif
01752   // We use Internal to bypass all checks in derived objects, e.g. so that
01753   // "var location" creates a dynamic property instead of activating window.location.
01754   if (exec->_context->type() == EvalCode)
01755     variable.put(exec, ident, val, Internal);
01756   else
01757     variable.put(exec, ident, val, DontDelete | Internal);
01758 
01759   return String(ident.ustring());
01760 }
01761 
01762 void VarDeclNode::processVarDecls(ExecState *exec)
01763 {
01764   Object variable = exec->context().variableObject();
01765   if ( !variable.hasProperty( exec, ident ) ) // already declared ?
01766     variable.put(exec,ident, Undefined(), exec->_context->type() == EvalCode ? None : DontDelete);
01767   //else warning "variable %1 hides argument"
01768 }
01769 
01770 // ----------------------------- VarDeclListNode ------------------------------
01771 
01772 void VarDeclListNode::ref()
01773 {
01774   for (VarDeclListNode *n = this; n; n = n->list) {
01775     n->Node::ref();
01776     if (n->var)
01777       n->var->ref();
01778   }
01779 }
01780 
01781 bool VarDeclListNode::deref()
01782 {
01783   VarDeclListNode *next;
01784   for (VarDeclListNode *n = this; n; n = next) {
01785     next = n->list;
01786     if (n->var && n->var->deref())
01787       delete n->var;
01788     if (n != this && n->Node::deref())
01789       delete n;
01790   }
01791   return Node::deref();
01792 }
01793 
01794 
01795 // ECMA 12.2
01796 Value VarDeclListNode::evaluate(ExecState *exec) const
01797 {
01798   for (const VarDeclListNode *n = this; n; n = n->list) {
01799     n->var->evaluate(exec);
01800     KJS_CHECKEXCEPTIONVALUE
01801   }
01802   return Undefined();
01803 }
01804 
01805 void VarDeclListNode::processVarDecls(ExecState *exec)
01806 {
01807   for (VarDeclListNode *n = this; n; n = n->list)
01808     n->var->processVarDecls(exec);
01809 }
01810 
01811 // ----------------------------- VarStatementNode -----------------------------
01812 
01813 void VarStatementNode::ref()
01814 {
01815   StatementNode::ref();
01816   if ( list )
01817     list->ref();
01818 }
01819 
01820 bool VarStatementNode::deref()
01821 {
01822   if ( list && list->deref() )
01823     delete list;
01824   return StatementNode::deref();
01825 }
01826 
01827 // ECMA 12.2
01828 Completion VarStatementNode::execute(ExecState *exec)
01829 {
01830   KJS_BREAKPOINT;
01831 
01832   (void) list->evaluate(exec); // returns 0L
01833   KJS_CHECKEXCEPTION
01834 
01835   return Completion(Normal);
01836 }
01837 
01838 void VarStatementNode::processVarDecls(ExecState *exec)
01839 {
01840   list->processVarDecls(exec);
01841 }
01842 
01843 // ----------------------------- BlockNode ------------------------------------
01844 
01845 BlockNode::BlockNode(SourceElementsNode *s)
01846 {
01847   if (s) {
01848     source = s->elements;
01849     s->elements = 0;
01850     setLoc(s->firstLine(), s->lastLine(), s->code());
01851   } else {
01852     source = 0;
01853   }
01854 }
01855 
01856 void BlockNode::ref()
01857 {
01858   StatementNode::ref();
01859   if ( source )
01860     source->ref();
01861 }
01862 
01863 bool BlockNode::deref()
01864 {
01865   if ( source && source->deref() )
01866     delete source;
01867   return StatementNode::deref();
01868 }
01869 
01870 // ECMA 12.1
01871 Completion BlockNode::execute(ExecState *exec)
01872 {
01873   if (!source)
01874     return Completion(Normal);
01875 
01876   source->processFuncDecl(exec);
01877 
01878   return source->execute(exec);
01879 }
01880 
01881 void BlockNode::processVarDecls(ExecState *exec)
01882 {
01883   if (source)
01884     source->processVarDecls(exec);
01885 }
01886 
01887 // ----------------------------- EmptyStatementNode ---------------------------
01888 
01889 // ECMA 12.3
01890 Completion EmptyStatementNode::execute(ExecState */*exec*/)
01891 {
01892   return Completion(Normal);
01893 }
01894 
01895 // ----------------------------- ExprStatementNode ----------------------------
01896 
01897 void ExprStatementNode::ref()
01898 {
01899   StatementNode::ref();
01900   if ( expr )
01901     expr->ref();
01902 }
01903 
01904 bool ExprStatementNode::deref()
01905 {
01906   if ( expr && expr->deref() )
01907     delete expr;
01908   return StatementNode::deref();
01909 }
01910 
01911 // ECMA 12.4
01912 Completion ExprStatementNode::execute(ExecState *exec)
01913 {
01914   KJS_BREAKPOINT;
01915 
01916   Value v = expr->evaluate(exec);
01917   KJS_CHECKEXCEPTION
01918 
01919   return Completion(Normal, v);
01920 }
01921 
01922 // ----------------------------- IfNode ---------------------------------------
01923 
01924 void IfNode::ref()
01925 {
01926   StatementNode::ref();
01927   if ( statement1 )
01928     statement1->ref();
01929   if ( statement2 )
01930     statement2->ref();
01931   if ( expr )
01932     expr->ref();
01933 }
01934 
01935 bool IfNode::deref()
01936 {
01937   if ( statement1 && statement1->deref() )
01938     delete statement1;
01939   if ( statement2 && statement2->deref() )
01940     delete statement2;
01941   if ( expr && expr->deref() )
01942     delete expr;
01943   return StatementNode::deref();
01944 }
01945 
01946 // ECMA 12.5
01947 Completion IfNode::execute(ExecState *exec)
01948 {
01949   KJS_BREAKPOINT;
01950 
01951   bool b = expr->toBoolean(exec);
01952   KJS_CHECKEXCEPTION
01953 
01954   // if ... then
01955   if (b)
01956     return statement1->execute(exec);
01957 
01958   // no else
01959   if (!statement2)
01960     return Completion(Normal);
01961 
01962   // else
01963   return statement2->execute(exec);
01964 }
01965 
01966 void IfNode::processVarDecls(ExecState *exec)
01967 {
01968   statement1->processVarDecls(exec);
01969 
01970   if (statement2)
01971     statement2->processVarDecls(exec);
01972 }
01973 
01974 // ----------------------------- DoWhileNode ----------------------------------
01975 
01976 void DoWhileNode::ref()
01977 {
01978   StatementNode::ref();
01979   if ( statement )
01980     statement->ref();
01981   if ( expr )
01982     expr->ref();
01983 }
01984 
01985 bool DoWhileNode::deref()
01986 {
01987   if ( statement && statement->deref() )
01988     delete statement;
01989   if ( expr && expr->deref() )
01990     delete expr;
01991   return StatementNode::deref();
01992 }
01993 
01994 // ECMA 12.6.1
01995 Completion DoWhileNode::execute(ExecState *exec)
01996 {
01997   KJS_BREAKPOINT;
01998 
01999   Completion c;
02000   Value value;
02001   bool b;
02002 
02003   do {
02004     // bail out on error
02005     KJS_CHECKEXCEPTION
02006 
02007     exec->context().imp()->seenLabels()->pushIteration();
02008     c = statement->execute(exec);
02009     exec->context().imp()->seenLabels()->popIteration();
02010     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02011       if ((c.complType() == Break) && ls.contains(c.target()))
02012         return Completion(Normal, value);
02013       if (c.complType() != Normal)
02014         return c;
02015     }
02016     b = expr->toBoolean(exec);
02017     KJS_CHECKEXCEPTION
02018   } while (b);
02019 
02020   return Completion(Normal, value);
02021 }
02022 
02023 void DoWhileNode::processVarDecls(ExecState *exec)
02024 {
02025   statement->processVarDecls(exec);
02026 }
02027 
02028 // ----------------------------- WhileNode ------------------------------------
02029 
02030 void WhileNode::ref()
02031 {
02032   StatementNode::ref();
02033   if ( statement )
02034     statement->ref();
02035   if ( expr )
02036     expr->ref();
02037 }
02038 
02039 bool WhileNode::deref()
02040 {
02041   if ( statement && statement->deref() )
02042     delete statement;
02043   if ( expr && expr->deref() )
02044     delete expr;
02045   return StatementNode::deref();
02046 }
02047 
02048 // ECMA 12.6.2
02049 Completion WhileNode::execute(ExecState *exec)
02050 {
02051   KJS_BREAKPOINT;
02052 
02053   Completion c;
02054   Value value;
02055 
02056   while (1) {
02057     bool b = expr->toBoolean(exec);
02058     KJS_CHECKEXCEPTION
02059 
02060     // bail out on error
02061     KJS_CHECKEXCEPTION
02062 
02063     if (!b)
02064       return Completion(Normal, value);
02065 
02066     exec->context().imp()->seenLabels()->pushIteration();
02067     c = statement->execute(exec);
02068     exec->context().imp()->seenLabels()->popIteration();
02069     if (c.isValueCompletion())
02070       value = c.value();
02071 
02072     if ((c.complType() == Continue) && ls.contains(c.target()))
02073       continue;
02074     if ((c.complType() == Break) && ls.contains(c.target()))
02075       return Completion(Normal, value);
02076     if (c.complType() != Normal)
02077       return c;
02078   }
02079 }
02080 
02081 void WhileNode::processVarDecls(ExecState *exec)
02082 {
02083   statement->processVarDecls(exec);
02084 }
02085 
02086 // ----------------------------- ForNode --------------------------------------
02087 
02088 void ForNode::ref()
02089 {
02090   StatementNode::ref();
02091   if ( statement )
02092     statement->ref();
02093   if ( expr1 )
02094     expr1->ref();
02095   if ( expr2 )
02096     expr2->ref();
02097   if ( expr3 )
02098     expr3->ref();
02099 }
02100 
02101 bool ForNode::deref()
02102 {
02103   if ( statement && statement->deref() )
02104     delete statement;
02105   if ( expr1 && expr1->deref() )
02106     delete expr1;
02107   if ( expr2 && expr2->deref() )
02108     delete expr2;
02109   if ( expr3 && expr3->deref() )
02110     delete expr3;
02111   return StatementNode::deref();
02112 }
02113 
02114 // ECMA 12.6.3
02115 Completion ForNode::execute(ExecState *exec)
02116 {
02117   Value v, cval;
02118 
02119   if (expr1) {
02120     v = expr1->evaluate(exec);
02121     KJS_CHECKEXCEPTION
02122   }
02123   for (;;) {
02124     if (expr2) {
02125       bool b = expr2->toBoolean(exec);
02126       KJS_CHECKEXCEPTION
02127       if (!b)
02128     return Completion(Normal, cval);
02129     }
02130     // bail out on error
02131     KJS_CHECKEXCEPTION
02132 
02133     exec->context().imp()->seenLabels()->pushIteration();
02134     Completion c = statement->execute(exec);
02135     exec->context().imp()->seenLabels()->popIteration();
02136     if (c.isValueCompletion())
02137       cval = c.value();
02138     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02139       if ((c.complType() == Break) && ls.contains(c.target()))
02140         return Completion(Normal, cval);
02141       if (c.complType() != Normal)
02142         return c;
02143     }
02144     if (expr3) {
02145       v = expr3->evaluate(exec);
02146       KJS_CHECKEXCEPTION
02147     }
02148   }
02149 }
02150 
02151 void ForNode::processVarDecls(ExecState *exec)
02152 {
02153   if (expr1)
02154     expr1->processVarDecls(exec);
02155 
02156   statement->processVarDecls(exec);
02157 }
02158 
02159 // ----------------------------- ForInNode ------------------------------------
02160 
02161 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
02162   : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
02163 {
02164 }
02165 
02166 ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
02167   : ident(i), init(in), expr(e), statement(s)
02168 {
02169   // for( var foo = bar in baz )
02170   varDecl = new VarDeclNode(ident, init);
02171   lexpr = new ResolveNode(ident);
02172 }
02173 
02174 void ForInNode::ref()
02175 {
02176   StatementNode::ref();
02177   if ( statement )
02178     statement->ref();
02179   if ( expr )
02180     expr->ref();
02181   if ( lexpr )
02182     lexpr->ref();
02183   if ( init )
02184     init->ref();
02185   if ( varDecl )
02186     varDecl->ref();
02187 }
02188 
02189 bool ForInNode::deref()
02190 {
02191   if ( statement && statement->deref() )
02192     delete statement;
02193   if ( expr && expr->deref() )
02194     delete expr;
02195   if ( lexpr && lexpr->deref() )
02196     delete lexpr;
02197   if ( init && init->deref() )
02198     delete init;
02199   if ( varDecl && varDecl->deref() )
02200     delete varDecl;
02201   return StatementNode::deref();
02202 }
02203 
02204 // ECMA 12.6.4
02205 Completion ForInNode::execute(ExecState *exec)
02206 {
02207   Value retval;
02208   Completion c;
02209 
02210   if ( varDecl ) {
02211     varDecl->evaluate(exec);
02212     KJS_CHECKEXCEPTION
02213   }
02214 
02215   Value v = expr->evaluate(exec);
02216   // for Null and Undefined, we want to make sure not to go through
02217   // the loop at all, because their object wrappers will have a
02218   // property list but will throw an exception if you attempt to
02219   // access any property.
02220   if (v.isA(NullType) || v.isA(UndefinedType))
02221     return Completion(Normal, retval);
02222 
02223   Object o = v.toObject(exec);
02224   KJS_CHECKEXCEPTION
02225   ReferenceList propList = o.propList(exec);
02226 
02227   ReferenceListIterator propIt = propList.begin();
02228 
02229   while (propIt != propList.end()) {
02230     Identifier name = propIt->getPropertyName(exec);
02231     if (!o.hasProperty(exec,name)) {
02232       propIt++;
02233       continue;
02234     }
02235 
02236     Reference ref = lexpr->evaluateReference(exec);
02237     KJS_CHECKEXCEPTION
02238     ref.putValue(exec, String(name.ustring()));
02239 
02240     exec->context().imp()->seenLabels()->pushIteration();
02241     c = statement->execute(exec);
02242     exec->context().imp()->seenLabels()->popIteration();
02243     if (c.isValueCompletion())
02244       retval = c.value();
02245 
02246     if (!((c.complType() == Continue) && ls.c