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,
00166                        const Value &v, const Node *expr) const
00167 {
00168   char *vStr = strdup(v.toString(exec).ascii());
00169   char *exprStr = strdup(expr->toCode().ascii());
00170 
00171   int length =  strlen(msg) - 4 /* two %s */ + strlen(vStr) + strlen(exprStr) +
00172  1 /* null terminator */;
00173   char *str = new char[length];
00174   sprintf(str, msg, vStr, exprStr);
00175   free(vStr);
00176   free(exprStr);
00177 
00178   Value result = throwError(exec, e, str);
00179   delete [] str;
00180 
00181   return result;
00182 }
00183 
00184 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Identifier label) const
00185 {
00186   const char *l = label.ascii();
00187   int length = strlen(msg) - 2 /* %s */ + strlen(l) + 1 /* null terminator */;
00188   char *message = new char[length];
00189   sprintf(message, msg, l);
00190 
00191   Value result = throwError(exec, e, message);
00192   delete [] message;
00193 
00194   return result;
00195 }
00196 
00197 // ----------------------------- StatementNode --------------------------------
00198 StatementNode::StatementNode() : l0(-1), l1(-1), sourceCode(0), breakPoint(false)
00199 {
00200 }
00201 
00202 StatementNode::~StatementNode()
00203 {
00204   if (sourceCode)
00205     sourceCode->deref();
00206 }
00207 
00208 void StatementNode::setLoc(int line0, int line1, SourceCode *src)
00209 {
00210   // ### require these to be passed to the constructor
00211   l0 = line0;
00212   l1 = line1;
00213   if (sourceCode != src) {
00214     if (sourceCode)
00215       sourceCode->deref();
00216     sourceCode = src;
00217     sourceCode->ref();
00218   }
00219 }
00220 
00221 // return true if the debugger wants us to stop at this point
00222 bool StatementNode::hitStatement(ExecState *exec)
00223 {
00224   assert(sourceCode);
00225   assert(exec->context().imp()->sourceId == sourceCode->sid);
00226   exec->context().imp()->setLines(l0,l1);
00227   Debugger *dbg = exec->interpreter()->imp()->debugger();
00228   if (dbg)
00229     return dbg->atStatement(exec);
00230   else
00231     return true; // continue
00232 }
00233 
00234 // return true if the debugger wants us to stop at this point
00235 bool StatementNode::abortStatement(ExecState *exec)
00236 {
00237   Debugger *dbg = exec->interpreter()->imp()->debugger();
00238   if (dbg)
00239     return dbg->imp()->aborted();
00240   else
00241     return false;
00242 }
00243 
00244 void StatementNode::processFuncDecl(ExecState *)
00245 {
00246 }
00247 
00248 // ----------------------------- NullNode -------------------------------------
00249 
00250 Value NullNode::evaluate(ExecState *) const
00251 {
00252   return Null();
00253 }
00254 
00255 bool NullNode::toBoolean(ExecState *) const
00256 {
00257   return false;
00258 }
00259 
00260 double NullNode::toNumber(ExecState *) const
00261 {
00262   return 0.0;
00263 }
00264 
00265 UString NullNode::toString(ExecState *) const
00266 {
00267   return "null";
00268 }
00269 
00270 // ----------------------------- BooleanNode ----------------------------------
00271 
00272 Value BooleanNode::evaluate(ExecState *) const
00273 {
00274   return Boolean(val);
00275 }
00276 
00277 bool BooleanNode::toBoolean(ExecState *) const
00278 {
00279   return val;
00280 }
00281 
00282 double BooleanNode::toNumber(ExecState *) const
00283 {
00284   return val ? 1.0 : 0.0;
00285 }
00286 
00287 UString BooleanNode::toString(ExecState *) const
00288 {
00289   return val ? "true" : "false";
00290 }
00291 
00292 // ----------------------------- NumberNode -----------------------------------
00293 
00294 Value NumberNode::evaluate(ExecState *) const
00295 {
00296   return Number(val);
00297 }
00298 
00299 bool NumberNode::toBoolean(ExecState *) const
00300 {
00301   return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
00302 }
00303 
00304 double NumberNode::toNumber(ExecState *) const
00305 {
00306   return val;
00307 }
00308 
00309 UString NumberNode::toString(ExecState *) const
00310 {
00311   return UString::from(val);
00312 }
00313 
00314 // ----------------------------- StringNode -----------------------------------
00315 
00316 Value StringNode::evaluate(ExecState *) const
00317 {
00318   return String(val);
00319 }
00320 
00321 bool StringNode::toBoolean(ExecState *) const
00322 {
00323   return !val.isEmpty();
00324 }
00325 
00326 double StringNode::toNumber(ExecState *) const
00327 {
00328   return val.toDouble();
00329 }
00330 
00331 UString StringNode::toString(ExecState *) const
00332 {
00333   return val;
00334 }
00335 
00336 // ----------------------------- RegExpNode -----------------------------------
00337 
00338 Value RegExpNode::evaluate(ExecState *exec) const
00339 {
00340   List list;
00341   String p(pattern);
00342   String f(flags);
00343   list.append(p);
00344   list.append(f);
00345 
00346   Object reg = exec->interpreter()->imp()->builtinRegExp();
00347   return reg.construct(exec,list);
00348 }
00349 
00350 bool RegExpNode::toBoolean(ExecState *) const
00351 {
00352   return true;
00353 }
00354 
00355 // ----------------------------- ThisNode -------------------------------------
00356 
00357 // ECMA 11.1.1
00358 Value ThisNode::evaluate(ExecState *exec) const
00359 {
00360   return exec->context().imp()->thisValue();
00361 }
00362 
00363 // ----------------------------- ResolveNode ----------------------------------
00364 
00365 // ECMA 11.1.2 & 10.1.4
00366 Value ResolveNode::evaluate(ExecState *exec) const
00367 {
00368   return evaluateReference(exec).getValue(exec);
00369 }
00370 
00371 Reference ResolveNode::evaluateReference(ExecState *exec) const
00372 {
00373   ScopeChain chain = exec->context().imp()->scopeChain();
00374 
00375   while (!chain.isEmpty()) {
00376     ObjectImp *o = chain.top();
00377 
00378     //cerr << "Resolve: looking at '" << ident.ascii() << "'"
00379     //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
00380     if (o->hasProperty(exec,ident)) {
00381       //cerr << "Resolve: FOUND '" << ident.ascii() << "'"
00382       //     << " in " << (void*)o << " " << o->classInfo()->className << endl;
00383       return Reference(o, ident);
00384     }
00385 
00386     chain.pop();
00387   }
00388 
00389   // identifier not found
00390 #ifdef KJS_VERBOSE
00391   cerr << "Resolve::evaluateReference: didn't find '" << ident.ustring().ascii() << "'" << endl;
00392 #endif
00393   return Reference(Null(), ident);
00394 }
00395 
00396 // ----------------------------- GroupNode ------------------------------------
00397 
00398 void GroupNode::ref()
00399 {
00400   Node::ref();
00401   if ( group )
00402     group->ref();
00403 }
00404 
00405 bool GroupNode::deref()
00406 {
00407   if ( group && group->deref() )
00408     delete group;
00409   return Node::deref();
00410 }
00411 
00412 // ECMA 11.1.6
00413 Value GroupNode::evaluate(ExecState *exec) const
00414 {
00415   return group->evaluate(exec);
00416 }
00417 
00418 Reference GroupNode::evaluateReference(ExecState *exec) const
00419 {
00420   return group->evaluateReference(exec);
00421 }
00422 
00423 // ----------------------------- ElementNode ----------------------------------
00424 
00425 void ElementNode::ref()
00426 {
00427   for (ElementNode *n = this; n; n = n->list) {
00428     n->Node::ref();
00429     if (n->node)
00430       n->node->ref();
00431   }
00432 }
00433 
00434 bool ElementNode::deref()
00435 {
00436   ElementNode *next;
00437   for (ElementNode *n = this; n; n = next) {
00438     next = n->list;
00439     if (n->node && n->node->deref())
00440       delete n->node;
00441     if (n != this && n->Node::deref())
00442       delete n;
00443   }
00444   return Node::deref();
00445 }
00446 
00447 // ECMA 11.1.4
00448 Value ElementNode::evaluate(ExecState *exec) const
00449 {
00450   Object array = exec->interpreter()->builtinArray().construct(exec, List::empty());
00451   int length = 0;
00452   for (const ElementNode *n = this; n; n = n->list) {
00453     Value val = n->node->evaluate(exec);
00454     KJS_CHECKEXCEPTIONVALUE
00455     length += n->elision;
00456     array.put(exec, length++, val);
00457   }
00458   return array;
00459 }
00460 
00461 // ----------------------------- ArrayNode ------------------------------------
00462 
00463 void ArrayNode::ref()
00464 {
00465   Node::ref();
00466   if ( element )
00467     element->ref();
00468 }
00469 
00470 bool ArrayNode::deref()
00471 {
00472   if ( element && element->deref() )
00473     delete element;
00474   return Node::deref();
00475 }
00476 
00477 // ECMA 11.1.4
00478 Value ArrayNode::evaluate(ExecState *exec) const
00479 {
00480   Object array;
00481   int length;
00482 
00483   if (element) {
00484     array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
00485     KJS_CHECKEXCEPTIONVALUE
00486     length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0;
00487   } else {
00488     Value newArr = exec->interpreter()->builtinArray().construct(exec,List::empty());
00489     array = Object(static_cast<ObjectImp*>(newArr.imp()));
00490     length = 0;
00491   }
00492 
00493   if (opt)
00494     array.put(exec,lengthPropertyName, Number(elision + length), DontEnum | DontDelete);
00495 
00496   return array;
00497 }
00498 
00499 // ----------------------------- ObjectLiteralNode ----------------------------
00500 
00501 void ObjectLiteralNode::ref()
00502 {
00503   Node::ref();
00504   if ( list )
00505     list->ref();
00506 }
00507 
00508 bool ObjectLiteralNode::deref()
00509 {
00510   if ( list && list->deref() )
00511     delete list;
00512   return Node::deref();
00513 }
00514 
00515 // ECMA 11.1.5
00516 Value ObjectLiteralNode::evaluate(ExecState *exec) const
00517 {
00518   if (list)
00519     return list->evaluate(exec);
00520 
00521   return exec->interpreter()->builtinObject().construct(exec,List::empty());
00522 }
00523 
00524 // ----------------------------- PropertyValueNode ----------------------------
00525 
00526 void PropertyValueNode::ref()
00527 {
00528   for (PropertyValueNode *n = this; n; n = n->list) {
00529     n->Node::ref();
00530     if (n->name)
00531       n->name->ref();
00532     if (n->assign)
00533       n->assign->ref();
00534   }
00535 }
00536 
00537 bool PropertyValueNode::deref()
00538 {
00539   PropertyValueNode *next;
00540   for (PropertyValueNode *n = this; n; n = next) {
00541     next = n->list;
00542     if ( n->name && n->name->deref() )
00543       delete n->name;
00544     if ( n->assign && n->assign->deref() )
00545       delete n->assign;
00546     if (n != this && n->Node::deref() )
00547       delete n;
00548   }
00549   return Node::deref();
00550 }
00551 
00552 // ECMA 11.1.5
00553 Value PropertyValueNode::evaluate(ExecState *exec) const
00554 {
00555   Object obj = exec->interpreter()->builtinObject().construct(exec, List::empty());
00556 
00557   for (const PropertyValueNode *p = this; p; p = p->list) {
00558     Value n = p->name->evaluate(exec);
00559     KJS_CHECKEXCEPTIONVALUE
00560     Value v = p->assign->evaluate(exec);
00561     KJS_CHECKEXCEPTIONVALUE
00562 
00563     obj.put(exec, Identifier(n.toString(exec)), v);
00564   }
00565 
00566   return obj;
00567 }
00568 
00569 // ----------------------------- PropertyNode ---------------------------------
00570 
00571 // ECMA 11.1.5
00572 Value PropertyNode::evaluate(ExecState * /*exec*/) const
00573 {
00574   Value s;
00575 
00576   if (str.isNull()) {
00577     s = String(UString::from(numeric));
00578   } else {
00579     s = String(str.ustring());
00580   }
00581 
00582   return s;
00583 }
00584 
00585 // ----------------------------- AccessorNode1 --------------------------------
00586 
00587 void AccessorNode1::ref()
00588 {
00589   Node::ref();
00590   if ( expr1 )
00591     expr1->ref();
00592   if ( expr2 )
00593     expr2->ref();
00594 }
00595 
00596 bool AccessorNode1::deref()
00597 {
00598   if ( expr1 && expr1->deref() )
00599     delete expr1;
00600   if ( expr2 && expr2->deref() )
00601     delete expr2;
00602   return Node::deref();
00603 }
00604 
00605 // ECMA 11.2.1a
00606 Reference AccessorNode1::evaluateReference(ExecState *exec) const
00607 {
00608   Value v1 = expr1->evaluate(exec);
00609   KJS_CHECKEXCEPTIONREFERENCE
00610   Value v2 = expr2->evaluate(exec);
00611   KJS_CHECKEXCEPTIONREFERENCE
00612 #ifndef NDEBUG
00613   // catch errors before being caught in toObject(). better error message.
00614   if (v1.isA(UndefinedType) || v1.isA(NullType)) {
00615     UString s = "Attempted to access property on %s object "
00616                 "(result of expression %s)";
00617         (void)throwError(exec, TypeError, s.cstring().c_str(), v1, this);
00618     return Reference::makeValueReference(Undefined());
00619   }
00620 #endif
00621   Object o = v1.toObject(exec);
00622   unsigned i;
00623   if (v2.toUInt32(i))
00624     return Reference(o, i);
00625   UString s = v2.toString(exec);
00626   return Reference(o, Identifier(s));
00627 }
00628 
00629 // ----------------------------- AccessorNode2 --------------------------------
00630 
00631 void AccessorNode2::ref()
00632 {
00633   Node::ref();
00634   if ( expr )
00635     expr->ref();
00636 }
00637 
00638 bool AccessorNode2::deref()
00639 {
00640   if ( expr && expr->deref() )
00641     delete expr;
00642   return Node::deref();
00643 }
00644 
00645 // ECMA 11.2.1b
00646 Reference AccessorNode2::evaluateReference(ExecState *exec) const
00647 {
00648   Value v = expr->evaluate(exec);
00649   KJS_CHECKEXCEPTIONREFERENCE
00650   assert(v.isValid());
00651 #ifndef NDEBUG
00652   // catch errors before being caught in toObject(). better error message.
00653   if (v.isA(UndefinedType) || v.isA(NullType)) {
00654     UString s = "Attempted to access '" + ident.ustring() +
00655                 "' property on %s object (result of expression %s)";
00656         (void)throwError(exec, TypeError, s.cstring().c_str(), v, this);
00657     return Reference::makeValueReference(Undefined());
00658   }
00659 #endif
00660   Object o = v.toObject(exec);
00661   return Reference(o, ident);
00662 }
00663 
00664 // ----------------------------- ArgumentListNode -----------------------------
00665 
00666 void ArgumentListNode::ref()
00667 {
00668   for (ArgumentListNode *n = this; n; n = n->list) {
00669     n->Node::ref();
00670     if (n->expr)
00671       n->expr->ref();
00672   }
00673 }
00674 
00675 bool ArgumentListNode::deref()
00676 {
00677   ArgumentListNode *next;
00678   for (ArgumentListNode *n = this; n; n = next) {
00679     next = n->list;
00680     if (n->expr && n->expr->deref())
00681       delete n->expr;
00682     if (n != this && n->Node::deref())
00683       delete n;
00684   }
00685   return Node::deref();
00686 }
00687 
00688 Value ArgumentListNode::evaluate(ExecState * /*exec*/) const
00689 {
00690   assert(0);
00691   return Value(); // dummy, see evaluateList()
00692 }
00693 
00694 // ECMA 11.2.4
00695 List ArgumentListNode::evaluateList(ExecState *exec) const
00696 {
00697   List l;
00698 
00699   for (const ArgumentListNode *n = this; n; n = n->list) {
00700     Value v = n->expr->evaluate(exec);
00701     KJS_CHECKEXCEPTIONLIST
00702     l.append(v);
00703   }
00704 
00705   return l;
00706 }
00707 
00708 // ----------------------------- ArgumentsNode --------------------------------
00709 
00710 void ArgumentsNode::ref()
00711 {
00712   Node::ref();
00713   if ( list )
00714     list->ref();
00715 }
00716 
00717 bool ArgumentsNode::deref()
00718 {
00719   if ( list && list->deref() )
00720     delete list;
00721   return Node::deref();
00722 }
00723 
00724 Value ArgumentsNode::evaluate(ExecState * /*exec*/) const
00725 {
00726   assert(0);
00727   return Value(); // dummy, see evaluateList()
00728 }
00729 
00730 // ECMA 11.2.4
00731 List ArgumentsNode::evaluateList(ExecState *exec) const
00732 {
00733   if (!list)
00734     return List();
00735 
00736   return list->evaluateList(exec);
00737 }
00738 
00739 // ----------------------------- NewExprNode ----------------------------------
00740 
00741 // ECMA 11.2.2
00742 
00743 void NewExprNode::ref()
00744 {
00745   Node::ref();
00746   if ( expr )
00747     expr->ref();
00748   if ( args )
00749     args->ref();
00750 }
00751 
00752 bool NewExprNode::deref()
00753 {
00754   if ( expr && expr->deref() )
00755     delete expr;
00756   if ( args && args->deref() )
00757     delete args;
00758   return Node::deref();
00759 }
00760 
00761 Value NewExprNode::evaluate(ExecState *exec) const
00762 {
00763   Value v = expr->evaluate(exec);
00764   KJS_CHECKEXCEPTIONVALUE
00765 
00766   List argList;
00767   if (args) {
00768     argList = args->evaluateList(exec);
00769     KJS_CHECKEXCEPTIONVALUE
00770   }
00771 
00772   if (v.type() != ObjectType) {
00773     return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr);
00774   }
00775 
00776   Object constr = Object(static_cast<ObjectImp*>(v.imp()));
00777   if (!constr.implementsConstruct()) {
00778     return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr);
00779   }
00780 
00781   Value res = constr.construct(exec,argList);
00782 
00783   return res;
00784 }
00785 
00786 // ----------------------------- FunctionCallNode -----------------------------
00787 
00788 void FunctionCallNode::ref()
00789 {
00790   Node::ref();
00791   if ( expr )
00792     expr->ref();
00793   if ( args )
00794     args->ref();
00795 }
00796 
00797 bool FunctionCallNode::deref()
00798 {
00799   if ( expr && expr->deref() )
00800     delete expr;
00801   if ( args && args->deref() )
00802     delete args;
00803   return Node::deref();
00804 }
00805 
00806 // ECMA 11.2.3
00807 Value FunctionCallNode::evaluate(ExecState *exec) const
00808 {
00809   Reference ref = expr->evaluateReference(exec);
00810   KJS_CHECKEXCEPTIONVALUE
00811 
00812   List argList = args->evaluateList(exec);
00813   KJS_CHECKEXCEPTIONVALUE
00814 
00815   Value v = ref.getValue(exec);
00816   KJS_CHECKEXCEPTIONVALUE
00817 
00818   if (v.type() != ObjectType) {
00819     return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be called.", v, expr);
00820   }
00821 
00822   Object func = Object(static_cast<ObjectImp*>(v.imp()));
00823 
00824   if (!func.implementsCall()) {
00825     return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr);
00826   }
00827 
00828   Value thisVal;
00829   if (ref.isMutable())
00830     thisVal = ref.getBase(exec);
00831   else
00832     thisVal = Null();
00833 
00834   if (thisVal.type() == ObjectType &&
00835       Object::dynamicCast(thisVal).inherits(&ActivationImp::info))
00836     thisVal = Null();
00837 
00838   if (thisVal.type() != ObjectType) {
00839     // ECMA 11.2.3 says that in this situation the this value should be null.
00840     // However, section 10.2.3 says that in the case where the value provided
00841     // by the caller is null, the global object should be used. It also says
00842     // that the section does not apply to interal functions, but for simplicity
00843     // of implementation we use the global object anyway here. This guarantees
00844     // that in host objects you always get a valid object for this.
00845     // thisVal = Null();
00846     thisVal = exec->interpreter()->globalObject();
00847   }
00848 
00849   Object thisObj = Object::dynamicCast(thisVal);
00850   Value result = func.call(exec,thisObj, argList);
00851 
00852   return result;
00853 }
00854 
00855 // ----------------------------- PostfixNode ----------------------------------
00856 
00857 void PostfixNode::ref()
00858 {
00859   Node::ref();
00860   if ( expr )
00861     expr->ref();
00862 }
00863 
00864 bool PostfixNode::deref()
00865 {
00866   if ( expr && expr->deref() )
00867     delete expr;
00868   return Node::deref();
00869 }
00870 
00871 // ECMA 11.3
00872 Value PostfixNode::evaluate(ExecState *exec) const
00873 {
00874   Reference ref = expr->evaluateReference(exec);
00875   KJS_CHECKEXCEPTIONVALUE
00876   Value v = ref.getValue(exec);
00877   double n = v.toNumber(exec);
00878 
00879   double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
00880 
00881   ref.putValue(exec, Number(newValue));
00882 
00883   return Number(n);
00884 }
00885 
00886 // ----------------------------- DeleteNode -----------------------------------
00887 
00888 void DeleteNode::ref()
00889 {
00890   Node::ref();
00891   if ( expr )
00892     expr->ref();
00893 }
00894 
00895 bool DeleteNode::deref()
00896 {
00897   if ( expr && expr->deref() )
00898     delete expr;
00899   return Node::deref();
00900 }
00901 
00902 // ECMA 11.4.1
00903 Value DeleteNode::evaluate(ExecState *exec) const
00904 {
00905   Reference ref = expr->evaluateReference(exec);
00906   KJS_CHECKEXCEPTIONVALUE
00907   return Boolean(ref.deleteValue(exec));
00908 }
00909 
00910 // ----------------------------- VoidNode -------------------------------------
00911 
00912 void VoidNode::ref()
00913 {
00914   Node::ref();
00915   if ( expr )
00916     expr->ref();
00917 }
00918 
00919 bool VoidNode::deref()
00920 {
00921   if ( expr && expr->deref() )
00922     delete expr;
00923   return Node::deref();
00924 }
00925 
00926 // ECMA 11.4.2
00927 Value VoidNode::evaluate(ExecState *exec) const
00928 {
00929   Value dummy1 = expr->evaluate(exec);
00930   KJS_CHECKEXCEPTIONVALUE
00931 
00932   return Undefined();
00933 }
00934 
00935 // ----------------------------- TypeOfNode -----------------------------------
00936 
00937 void TypeOfNode::ref()
00938 {
00939   Node::ref();
00940   if ( expr )
00941     expr->ref();
00942 }
00943 
00944 bool TypeOfNode::deref()
00945 {
00946   if ( expr && expr->deref() )
00947     delete expr;
00948   return Node::deref();
00949 }
00950 
00951 // ECMA 11.4.3
00952 Value TypeOfNode::evaluate(ExecState *exec) const
00953 {
00954   const char *s = 0L;
00955   Reference ref = expr->evaluateReference(exec);
00956   KJS_CHECKEXCEPTIONVALUE
00957   if (ref.isMutable()) {
00958     Value b = ref.getBase(exec);
00959     if (b.type() == NullType)
00960       return String("undefined");
00961   }
00962   Value v = ref.getValue(exec);
00963   switch (v.type())
00964     {
00965     case UndefinedType:
00966       s = "undefined";
00967       break;
00968     case NullType:
00969       s = "object";
00970       break;
00971     case BooleanType:
00972       s = "boolean";
00973       break;
00974     case NumberType:
00975       s = "number";
00976       break;
00977     case StringType:
00978       s = "string";
00979       break;
00980     default:
00981       if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall())
00982     s = "function";
00983       else
00984     s = "object";
00985       break;
00986     }
00987 
00988   return String(s);
00989 }
00990 
00991 // ----------------------------- PrefixNode -----------------------------------
00992 
00993 void PrefixNode::ref()
00994 {
00995   Node::ref();
00996   if ( expr )
00997     expr->ref();
00998 }
00999 
01000 bool PrefixNode::deref()
01001 {
01002   if ( expr && expr->deref() )
01003     delete expr;
01004   return Node::deref();
01005 }
01006 
01007 // ECMA 11.4.4 and 11.4.5
01008 Value PrefixNode::evaluate(ExecState *exec) const
01009 {
01010   Reference ref = expr->evaluateReference(exec);
01011   KJS_CHECKEXCEPTION
01012   Value v = ref.getValue(exec);
01013   double n = v.toNumber(exec);
01014 
01015   double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
01016   Value n2 = Number(newValue);
01017 
01018   ref.putValue(exec,n2);
01019 
01020   return n2;
01021 }
01022 
01023 // ----------------------------- UnaryPlusNode --------------------------------
01024 
01025 void UnaryPlusNode::ref()
01026 {
01027   Node::ref();
01028   if ( expr )
01029     expr->ref();
01030 }
01031 
01032 bool UnaryPlusNode::deref()
01033 {
01034   if ( expr && expr->deref() )
01035     delete expr;
01036   return Node::deref();
01037 }
01038 
01039 // ECMA 11.4.6
01040 double UnaryPlusNode::toNumber(ExecState *exec) const
01041 {
01042   return expr->toNumber(exec);
01043 }
01044 
01045 // could go
01046 Value UnaryPlusNode::evaluate(ExecState *exec) const
01047 {
01048   Value v = expr->evaluate(exec);
01049   KJS_CHECKEXCEPTIONVALUE
01050 
01051   return Number(v.toNumber(exec)); /* TODO: optimize */
01052 }
01053 
01054 // ----------------------------- NegateNode -----------------------------------
01055 
01056 void NegateNode::ref()
01057 {
01058   Node::ref();
01059   if ( expr )
01060     expr->ref();
01061 }
01062 
01063 bool NegateNode::deref()
01064 {
01065   if ( expr && expr->deref() )
01066     delete expr;
01067   return Node::deref();
01068 }
01069 
01070 // ECMA 11.4.7
01071 double NegateNode::toNumber(ExecState *exec) const
01072 {
01073   return -expr->toNumber(exec);
01074 }
01075 
01076 Value NegateNode::evaluate(ExecState *exec) const
01077 {
01078   Value v = expr->evaluate(exec);
01079   KJS_CHECKEXCEPTIONVALUE
01080   double d = -v.toNumber(exec);
01081 
01082   return Number(d);
01083 }
01084 
01085 // ----------------------------- BitwiseNotNode -------------------------------
01086 
01087 void BitwiseNotNode::ref()
01088 {
01089   Node::ref();
01090   if ( expr )
01091     expr->ref();
01092 }
01093 
01094 bool BitwiseNotNode::deref()
01095 {
01096   if ( expr && expr->deref() )
01097     delete expr;
01098   return Node::deref();
01099 }
01100 
01101 // ECMA 11.4.8
01102 Value BitwiseNotNode::evaluate(ExecState *exec) const
01103 {
01104   Value v = expr->evaluate(exec);
01105   KJS_CHECKEXCEPTIONVALUE
01106   int i32 = v.toInt32(exec);
01107 
01108   return Number(~i32);
01109 }
01110 
01111 // ----------------------------- LogicalNotNode -------------------------------
01112 
01113 void LogicalNotNode::ref()
01114 {
01115   Node::ref();
01116   if ( expr )
01117     expr->ref();
01118 }
01119 
01120 bool LogicalNotNode::deref()
01121 {
01122   if ( expr && expr->deref() )
01123     delete expr;
01124   return Node::deref();
01125 }
01126 
01127 // ECMA 11.4.9
01128 bool LogicalNotNode::toBoolean(ExecState *exec) const
01129 {
01130   return !expr->toBoolean(exec);
01131 }
01132 
01133 // could remove this
01134 Value LogicalNotNode::evaluate(ExecState *exec) const
01135 {
01136   bool b = expr->toBoolean(exec);
01137   KJS_CHECKEXCEPTIONVALUE
01138 
01139   return Boolean(!b);
01140 }
01141 
01142 // ----------------------------- MultNode -------------------------------------
01143 
01144 void MultNode::ref()
01145 {
01146   Node::ref();
01147   if ( term1 )
01148     term1->ref();
01149   if ( term2 )
01150     term2->ref();
01151 }
01152 
01153 bool MultNode::deref()
01154 {
01155   if ( term1 && term1->deref() )
01156     delete term1;
01157   if ( term2 && term2->deref() )
01158     delete term2;
01159   return Node::deref();
01160 }
01161 
01162 // ECMA 11.5
01163 Value MultNode::evaluate(ExecState *exec) const
01164 {
01165   Value v1 = term1->evaluate(exec);
01166   KJS_CHECKEXCEPTIONVALUE
01167 
01168   Value v2 = term2->evaluate(exec);
01169   KJS_CHECKEXCEPTIONVALUE
01170 
01171   return mult(exec,v1, v2, oper);
01172 }
01173 
01174 // ----------------------------- AddNode --------------------------------------
01175 
01176 // factory for an appropriate addition or substraction node
01177 Node* AddNode::create(Node *t1, Node *t2, char op)
01178 {
01179   // ### many more combinations to check for
01180   // fold constants
01181   if ((t1->type() == NumberType || t1->type() == BooleanType) &&
01182       (t2->type() == NumberType || t2->type() == BooleanType)) {
01183     double d = t2->toNumber(0);
01184     Node* n = new NumberNode(t1->toNumber(0) + (op == '+' ? d : -d));
01185     delete t1;
01186     delete t2;
01187     return n;
01188   }
01189 
01190   if (op == '+' && t2->type() == StringType)
01191     return new AppendStringNode(t1, t2->toString(0));
01192 
01193   // fall back to generic node
01194   return new AddNode(t1, t2, op);
01195 }
01196 
01197 void AddNode::ref()
01198 {
01199   Node::ref();
01200   if ( term1 )
01201     term1->ref();
01202   if ( term2 )
01203     term2->ref();
01204 }
01205 
01206 bool AddNode::deref()
01207 {
01208   if ( term1 && term1->deref() )
01209     delete term1;
01210   if ( term2 && term2->deref() )
01211     delete term2;
01212   return Node::deref();
01213 }
01214 
01215 // ECMA 11.6
01216 Value AddNode::evaluate(ExecState *exec) const
01217 {
01218   Value v1 = term1->evaluate(exec);
01219   KJS_CHECKEXCEPTIONVALUE
01220 
01221   Value v2 = term2->evaluate(exec);
01222   KJS_CHECKEXCEPTIONVALUE
01223 
01224   return add(exec,v1, v2, oper);
01225 }
01226 
01227 // ------------------------ AddNumberNode ------------------------------------
01228 
01229 void AppendStringNode::ref()
01230 {
01231   Node::ref();
01232   term->ref();
01233 }
01234 
01235 bool AppendStringNode::deref()
01236 {
01237   if (term->deref())
01238     delete term;
01239   return Node::deref();
01240 }
01241 
01242 // ECMA 11.6 (special case of string appending)
01243 Value AppendStringNode::evaluate(ExecState *exec) const
01244 {
01245   UString s = term->toString(exec);
01246   KJS_CHECKEXCEPTIONVALUE
01247 
01248   return String(s + str);
01249 }
01250 
01251 // ----------------------------- ShiftNode ------------------------------------
01252 
01253 void ShiftNode::ref()
01254 {
01255   Node::ref();
01256   if ( term1 )
01257     term1->ref();
01258   if ( term2 )
01259     term2->ref();
01260 }
01261 
01262 bool ShiftNode::deref()
01263 {
01264   if ( term1 && term1->deref() )
01265     delete term1;
01266   if ( term2 && term2->deref() )
01267     delete term2;
01268   return Node::deref();
01269 }
01270 
01271 // ECMA 11.7
01272 Value ShiftNode::evaluate(ExecState *exec) const
01273 {
01274   Value v1 = term1->evaluate(exec);
01275   KJS_CHECKEXCEPTIONVALUE
01276   Value v2 = term2->evaluate(exec);
01277   KJS_CHECKEXCEPTIONVALUE
01278   unsigned int i2 = v2.toUInt32(exec);
01279   i2 &= 0x1f;
01280 
01281   switch (oper) {
01282   case OpLShift:
01283     return Number(v1.toInt32(exec) << i2);
01284   case OpRShift:
01285     return Number(v1.toInt32(exec) >> i2);
01286   case OpURShift:
01287     return Number(v1.toUInt32(exec) >> i2);
01288   default:
01289     assert(!"ShiftNode: unhandled switch case");
01290     return Undefined();
01291   }
01292 }
01293 
01294 // ----------------------------- RelationalNode -------------------------------
01295 
01296 void RelationalNode::ref()
01297 {
01298   Node::ref();
01299   if ( expr1 )
01300     expr1->ref();
01301   if ( expr2 )
01302     expr2->ref();
01303 }
01304 
01305 bool RelationalNode::deref()
01306 {
01307   if ( expr1 && expr1->deref() )
01308     delete expr1;
01309   if ( expr2 && expr2->deref() )
01310     delete expr2;
01311   return Node::deref();
01312 }
01313 
01314 // ECMA 11.8
01315 Value RelationalNode::evaluate(ExecState *exec) const
01316 {
01317   Value v1 = expr1->evaluate(exec);
01318   KJS_CHECKEXCEPTIONVALUE
01319   Value v2 = expr2->evaluate(exec);
01320   KJS_CHECKEXCEPTIONVALUE
01321 
01322   bool b;
01323   if (oper == OpLess || oper == OpGreaterEq) {
01324     int r = relation(exec, v1, v2);
01325     if (r < 0)
01326       b = false;
01327     else
01328       b = (oper == OpLess) ? (r == 1) : (r == 0);
01329   } else if (oper == OpGreater || oper == OpLessEq) {
01330     int r = relation(exec, v2, v1);
01331     if (r < 0)
01332       b = false;
01333     else
01334       b = (oper == OpGreater) ? (r == 1) : (r == 0);
01335   } else if (oper == OpIn) {
01336       // Is all of this OK for host objects?
01337       if (v2.type() != ObjectType)
01338           return throwError(exec,  TypeError,
01339                             "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2);
01340       Object o2(static_cast<ObjectImp*>(v2.imp()));
01341       b = o2.hasProperty(exec,Identifier(v1.toString(exec)));
01342   } else {
01343     if (v2.type() != ObjectType)
01344         return throwError(exec,  TypeError,
01345                           "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2);
01346 
01347     Object o2(static_cast<ObjectImp*>(v2.imp()));
01348     if (!o2.implementsHasInstance()) {
01349       // According to the spec, only some types of objects "imlement" the [[HasInstance]] property.
01350       // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
01351       // property. It seems that all object have the property, but not all implement it, so in this
01352       // case we return false (consistent with mozilla)
01353       return Boolean(false);
01354       //      return throwError(exec, TypeError,
01355       //            "Object does not implement the [[HasInstance]] method." );
01356     }
01357     return o2.hasInstance(exec, v1);
01358   }
01359 
01360   return Boolean(b);
01361 }
01362 
01363 // ----------------------------- EqualNode ------------------------------------
01364 
01365 void EqualNode::ref()
01366 {
01367   Node::ref();
01368   if ( expr1 )
01369     expr1->ref();
01370   if ( expr2 )
01371     expr2->ref();
01372 }
01373 
01374 bool EqualNode::deref()
01375 {
01376   if ( expr1 && expr1->deref() )
01377     delete expr1;
01378   if ( expr2 && expr2->deref() )
01379     delete expr2;
01380   return Node::deref();
01381 }
01382 
01383 // ECMA 11.9
01384 Value EqualNode::evaluate(ExecState *exec) const
01385 {
01386   Value v1 = expr1->evaluate(exec);
01387   KJS_CHECKEXCEPTIONVALUE
01388   Value v2 = expr2->evaluate(exec);
01389   KJS_CHECKEXCEPTIONVALUE
01390 
01391   bool result;
01392   if (oper == OpEqEq || oper == OpNotEq) {
01393     // == and !=
01394     bool eq = equal(exec,v1, v2);
01395     result = oper == OpEqEq ? eq : !eq;
01396   } else {
01397     // === and !==
01398     bool eq = strictEqual(exec,v1, v2);
01399     result = oper == OpStrEq ? eq : !eq;
01400   }
01401   return Boolean(result);
01402 }
01403 
01404 // ----------------------------- BitOperNode ----------------------------------
01405 
01406 void BitOperNode::ref()
01407 {
01408   Node::ref();
01409   if ( expr1 )
01410     expr1->ref();
01411   if ( expr2 )
01412     expr2->ref();
01413 }
01414 
01415 bool BitOperNode::deref()
01416 {
01417   if ( expr1 && expr1->deref() )
01418     delete expr1;
01419   if ( expr2 && expr2->deref() )
01420     delete expr2;
01421   return Node::deref();
01422 }
01423 
01424 // ECMA 11.10
01425 Value BitOperNode::evaluate(ExecState *exec) const
01426 {
01427   Value v1 = expr1->evaluate(exec);
01428   KJS_CHECKEXCEPTIONVALUE
01429   Value v2 = expr2->evaluate(exec);
01430   KJS_CHECKEXCEPTIONVALUE
01431   int i1 = v1.toInt32(exec);
01432   int i2 = v2.toInt32(exec);
01433   int result;
01434   if (oper == OpBitAnd)
01435     result = i1 & i2;
01436   else if (oper == OpBitXOr)
01437     result = i1 ^ i2;
01438   else
01439     result = i1 | i2;
01440 
01441   return Number(result);
01442 }
01443 
01444 // ----------------------------- BinaryLogicalNode ----------------------------
01445 
01446 void BinaryLogicalNode::ref()
01447 {
01448   Node::ref();
01449   if ( expr1 )
01450     expr1->ref();
01451   if ( expr2 )
01452     expr2->ref();
01453 }
01454 
01455 bool BinaryLogicalNode::deref()
01456 {
01457   if ( expr1 && expr1->deref() )
01458     delete expr1;
01459   if ( expr2 && expr2->deref() )
01460     delete expr2;
01461   return Node::deref();
01462 }
01463 
01464 // ECMA 11.11
01465 Value BinaryLogicalNode::evaluate(ExecState *exec) const
01466 {
01467   Value v1 = expr1->evaluate(exec);
01468   KJS_CHECKEXCEPTIONVALUE
01469   bool b1 = v1.toBoolean(exec);
01470   if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
01471     return v1;
01472 
01473   Value v2 = expr2->evaluate(exec);
01474   KJS_CHECKEXCEPTIONVALUE
01475 
01476   return v2;
01477 }
01478 
01479 // ----------------------------- ConditionalNode ------------------------------
01480 
01481 void ConditionalNode::ref()
01482 {
01483   Node::ref();
01484   if ( expr1 )
01485     expr1->ref();
01486   if ( expr2 )
01487     expr2->ref();
01488   if ( logical )
01489     logical->ref();
01490 }
01491 
01492 bool ConditionalNode::deref()
01493 {
01494   if ( expr1 && expr1->deref() )
01495     delete expr1;
01496   if ( expr2 && expr2->deref() )
01497     delete expr2;
01498   if ( logical && logical->deref() )
01499     delete logical;
01500   return Node::deref();
01501 }
01502 
01503 // ECMA 11.12
01504 Value ConditionalNode::evaluate(ExecState *exec) const
01505 {
01506   bool b = logical->toBoolean(exec);
01507   KJS_CHECKEXCEPTIONVALUE
01508 
01509   Value v = b ? expr1->evaluate(exec) : expr2->evaluate(exec);
01510   KJS_CHECKEXCEPTIONVALUE
01511 
01512   return v;
01513 }
01514 
01515 // ----------------------------- AssignNode -----------------------------------
01516 
01517 void AssignNode::ref()
01518 {
01519   Node::ref();
01520   if ( left )
01521     left->ref();
01522   if ( expr )
01523     expr->ref();
01524 }
01525 
01526 bool AssignNode::deref()
01527 {
01528   if ( left && left->deref() )
01529     delete left;
01530   if ( expr && expr->deref() )
01531     delete expr;
01532   return Node::deref();
01533 }
01534 
01535 // ECMA 11.13
01536 Value AssignNode::evaluate(ExecState *exec) const
01537 {
01538   Reference l = left->evaluateReference(exec);
01539   KJS_CHECKEXCEPTIONVALUE
01540   Value v;
01541   if (oper == OpEqual) {
01542     v = expr->evaluate(exec);
01543     KJS_CHECKEXCEPTIONVALUE
01544   } else {
01545     Value v1 = l.getValue(exec);
01546     Value v2 = expr->evaluate(exec);
01547     KJS_CHECKEXCEPTIONVALUE
01548     int i1 = v1.toInt32(exec);
01549     int i2 = v2.toInt32(exec);
01550     unsigned int ui;
01551     switch (oper) {
01552     case OpMultEq:
01553       v = mult(exec, v1, v2, '*');
01554       break;
01555     case OpDivEq:
01556       v = mult(exec, v1, v2, '/');
01557       break;
01558     case OpPlusEq:
01559       v = add(exec, v1, v2, '+');
01560       break;
01561     case OpMinusEq:
01562       v = add(exec, v1, v2, '-');
01563       break;
01564     case OpLShift:
01565       v = Number(i1 <<= i2);
01566       break;
01567     case OpRShift:
01568       v = Number(i1 >>= i2);
01569       break;
01570     case OpURShift:
01571       ui = v1.toUInt32(exec);
01572       v = Number(ui >>= i2);
01573       break;
01574     case OpAndEq:
01575       v = Number(i1 &= i2);
01576       break;
01577     case OpXOrEq:
01578       v = Number(i1 ^= i2);
01579       break;
01580     case OpOrEq:
01581       v = Number(i1 |= i2);
01582       break;
01583     case OpModEq: {
01584       double d1 = v1.toNumber(exec);
01585       double d2 = v2.toNumber(exec);
01586       v = Number(fmod(d1,d2));
01587     }
01588       break;
01589     default:
01590       v = Undefined();
01591     }
01592   };
01593   l.putValue(exec,v);
01594 
01595   KJS_CHECKEXCEPTIONVALUE
01596 
01597   return v;
01598 }
01599 
01600 // ----------------------------- CommaNode ------------------------------------
01601 
01602 void CommaNode::ref()
01603 {
01604   Node::ref();
01605   if ( expr1 )
01606     expr1->ref();
01607   if ( expr2 )
01608     expr2->ref();
01609 }
01610 
01611 bool CommaNode::deref()
01612 {
01613   if ( expr1 && expr1->deref() )
01614     delete expr1;
01615   if ( expr2 && expr2->deref() )
01616     delete expr2;
01617   return Node::deref();
01618 }
01619 
01620 // ECMA 11.14
01621 Value CommaNode::evaluate(ExecState *exec) const
01622 {
01623   (void) expr1->evaluate(exec);  // ignore return value
01624   KJS_CHECKEXCEPTIONVALUE
01625   Value v = expr2->evaluate(exec);
01626   KJS_CHECKEXCEPTIONVALUE
01627 
01628   return v;
01629 }
01630 
01631 // ----------------------------- StatListNode ---------------------------------
01632 
01633 StatListNode::StatListNode(StatementNode *s)
01634   : statement(s), list(this)
01635 {
01636   setLoc(s->firstLine(),s->lastLine(),s->code());
01637 }
01638 
01639 StatListNode::StatListNode(StatListNode *l, StatementNode *s)
01640   : statement(s), list(l->list)
01641 {
01642   l->list = this;
01643   setLoc(l->firstLine(),s->lastLine(),l->code());
01644 }
01645 
01646 void StatListNode::ref()
01647 {
01648   for (StatListNode *n = this; n; n = n->list) {
01649     n->Node::ref();
01650     if (n->statement)
01651       n->statement->ref();
01652   }
01653 }
01654 
01655 bool StatListNode::deref()
01656 {
01657   StatListNode *next;
01658   for (StatListNode *n = this; n; n = next) {
01659     next = n->list;
01660     if (n->statement && n->statement->deref())
01661       delete n->statement;
01662     if (n != this && n->Node::deref())
01663       delete n;
01664   }
01665   return StatementNode::deref();
01666 }
01667 
01668 // ECMA 12.1
01669 Completion StatListNode::execute(ExecState *exec)
01670 {
01671   Completion c = statement->execute(exec);
01672   KJS_ABORTPOINT
01673   if (exec->hadException()) {
01674     Value ex = exec->exception();
01675     exec->clearException();
01676     return Completion(Throw, ex);
01677   }
01678 
01679   if (c.complType() != Normal)
01680     return c;
01681 
01682   Value v = c.value();
01683 
01684   for (StatListNode *n = list; n; n = n->list) {
01685     Completion c2 = n->statement->execute(exec);
01686     KJS_ABORTPOINT
01687     if (c2.complType() != Normal)
01688       return c2;
01689 
01690     if (exec->hadException()) {
01691       Value ex = exec->exception();
01692       exec->clearException();
01693       return Completion(Throw, ex);
01694     }
01695 
01696     if (c2.isValueCompletion())
01697       v = c2.value();
01698     c = c2;
01699   }
01700 
01701   return Completion(c.complType(), v, c.target());
01702 }
01703 
01704 void StatListNode::processVarDecls(ExecState *exec)
01705 {
01706   for (StatListNode *n = this; n; n = n->list)
01707     n->statement->processVarDecls(exec);
01708 }
01709 
01710 // ----------------------------- AssignExprNode -------------------------------
01711 
01712 void AssignExprNode::ref()
01713 {
01714   Node::ref();
01715   if ( expr )
01716     expr->ref();
01717 }
01718 
01719 bool AssignExprNode::deref()
01720 {
01721   if ( expr && expr->deref() )
01722     delete expr;
01723   return Node::deref();
01724 }
01725 
01726 // ECMA 12.2
01727 Value AssignExprNode::evaluate(ExecState *exec) const
01728 {
01729   return expr->evaluate(exec);
01730 }
01731 
01732 // ----------------------------- VarDeclNode ----------------------------------
01733 
01734 VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in)
01735     : ident(id), init(in)
01736 {
01737 }
01738 
01739 void VarDeclNode::ref()
01740 {
01741   Node::ref();
01742   if ( init )
01743     init->ref();
01744 }
01745 
01746 bool VarDeclNode::deref()
01747 {
01748   if ( init && init->deref() )
01749     delete init;
01750   return Node::deref();
01751 }
01752 
01753 // global var/const flag
01754 static VarStatementNode::Type currentVarType;
01755 
01756 // ECMA 12.2
01757 Value VarDeclNode::evaluate(ExecState *exec) const
01758 {
01759   Object variable = Object::dynamicCast(exec->context().imp()->variableObject());
01760 
01761   Value val;
01762   if (init) {
01763       val = init->evaluate(exec);
01764       KJS_CHECKEXCEPTIONVALUE
01765   } else {
01766       if ( variable.hasProperty(exec, ident ) ) // already declared ?
01767           return Value();
01768       val = Undefined();
01769   }
01770 
01771 #ifdef KJS_VERBOSE
01772   printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
01773 #endif
01774   // We use Internal to bypass all checks in derived objects, e.g. so that
01775   // "var location" creates a dynamic property instead of activating window.location.
01776   int flags = Internal;
01777   if (exec->_context->type() != EvalCode)
01778     flags |= DontDelete;
01779   if (currentVarType == VarStatementNode::Constant)
01780     flags |= ReadOnly;
01781   variable.put(exec, ident, val, flags);
01782 
01783   // the spec wants us to return the name of the identifier here
01784   // but we'll save the construction and copying as the return
01785   // value isn't used by the caller
01786   return Value();
01787 }
01788 
01789 void VarDeclNode::processVarDecls(ExecState *exec)
01790 {
01791   Object variable = exec->context().variableObject();
01792   if ( !variable.hasProperty( exec, ident ) ) { // already declared ?
01793     int flags = None;
01794     if (exec->_context->type() != EvalCode)
01795       flags |= DontDelete;
01796     if (currentVarType == VarStatementNode::Constant)
01797       flags |= ReadOnly;
01798     // TODO: check for forbidden redeclaration of consts
01799     variable.put(exec,ident, Undefined(), flags);
01800   }
01801   //else warning "variable %1 hides argument"
01802 }
01803 
01804 // ----------------------------- VarDeclListNode ------------------------------
01805 
01806 void VarDeclListNode::ref()
01807 {
01808   for (VarDeclListNode *n = this; n; n = n->list) {
01809     n->Node::ref();
01810     if (n->var)
01811       n->var->ref();
01812   }
01813 }
01814 
01815 bool VarDeclListNode::deref()
01816 {
01817   VarDeclListNode *next;
01818   for (VarDeclListNode *n = this; n; n = next) {
01819     next = n->list;
01820     if (n->var && n->var->deref())
01821       delete n->var;
01822     if (n != this && n->Node::deref())
01823       delete n;
01824   }
01825   return Node::deref();
01826 }
01827 
01828 
01829 // ECMA 12.2
01830 Value VarDeclListNode::evaluate(ExecState *exec) const
01831 {
01832   for (const VarDeclListNode *n = this; n; n = n->list) {
01833     (void)n->var->evaluate(exec);
01834     KJS_CHECKEXCEPTIONVALUE
01835   }
01836   return Undefined();
01837 }
01838 
01839 void VarDeclListNode::processVarDecls(ExecState *exec)
01840 {
01841   for (VarDeclListNode *n = this; n; n = n->list)
01842     n->var->processVarDecls(exec);
01843 }
01844 
01845 // ----------------------------- VarStatementNode -----------------------------
01846 
01847 void VarStatementNode::ref()
01848 {
01849   StatementNode::ref();
01850   if ( list )
01851     list->ref();
01852 }
01853 
01854 bool VarStatementNode::deref()
01855 {
01856   if ( list && list->deref() )
01857     delete list;
01858   return StatementNode::deref();
01859 }
01860 
01861 // ECMA 12.2
01862 Completion VarStatementNode::execute(ExecState *exec)
01863 {
01864   KJS_BREAKPOINT;
01865 
01866   // set global var/const flag
01867   currentVarType = varType;
01868 
01869   (void) list->evaluate(exec);
01870   KJS_CHECKEXCEPTION
01871 
01872   return Completion(Normal);
01873 }
01874 
01875 void VarStatementNode::processVarDecls(ExecState *exec)
01876 {
01877   // set global var/const flag
01878   currentVarType = varType;
01879 
01880   list->processVarDecls(exec);
01881 }
01882 
01883 // ----------------------------- BlockNode ------------------------------------
01884 
01885 BlockNode::BlockNode(SourceElementsNode *s)
01886 {
01887   if (s) {
01888     source = s->elements;
01889     s->elements = 0;
01890     setLoc(s->firstLine(), s->lastLine(), s->code());
01891   } else {
01892     source = 0;
01893   }
01894 }
01895 
01896 void BlockNode::ref()
01897 {
01898   StatementNode::ref();
01899   if ( source )
01900     source->ref();
01901 }
01902 
01903 bool BlockNode::deref()
01904 {
01905   if ( source && source->deref() )
01906     delete source;
01907   return StatementNode::deref();
01908 }
01909 
01910 // ECMA 12.1
01911 Completion BlockNode::execute(ExecState *exec)
01912 {
01913   if (!source)
01914     return Completion(Normal);
01915 
01916   source->processFuncDecl(exec);
01917 
01918   return source->execute(exec);
01919 }
01920 
01921 void BlockNode::processVarDecls(ExecState *exec)
01922 {
01923   if (source)
01924     source->processVarDecls(exec);
01925 }
01926 
01927 // ----------------------------- EmptyStatementNode ---------------------------
01928 
01929 // ECMA 12.3
01930 Completion EmptyStatementNode::execute(ExecState * /*exec*/)
01931 {
01932   return Completion(Normal);
01933 }
01934 
01935 // ----------------------------- ExprStatementNode ----------------------------
01936 
01937 void ExprStatementNode::ref()
01938 {
01939   StatementNode::ref();
01940   if ( expr )
01941     expr->ref();
01942 }
01943 
01944 bool ExprStatementNode::deref()
01945 {
01946   if ( expr && expr->deref() )
01947     delete expr;
01948   return StatementNode::deref();
01949 }
01950 
01951 // ECMA 12.4
01952 Completion ExprStatementNode::execute(ExecState *exec)
01953 {
01954   KJS_BREAKPOINT;
01955 
01956   Value v = expr->evaluate(exec);
01957   KJS_CHECKEXCEPTION
01958 
01959   return Completion(Normal, v);
01960 }
01961 
01962 // ----------------------------- IfNode ---------------------------------------
01963 
01964 void IfNode::ref()
01965 {
01966   StatementNode::ref();
01967   if ( statement1 )
01968     statement1->ref();
01969   if ( statement2 )
01970     statement2->ref();
01971   if ( expr )
01972     expr->ref();
01973 }
01974 
01975 bool IfNode::deref()
01976 {
01977   if ( statement1 && statement1->deref() )
01978     delete statement1;
01979   if ( statement2 && statement2->deref() )
01980     delete statement2;
01981   if ( expr && expr->deref() )
01982     delete expr;
01983   return StatementNode::deref();
01984 }
01985 
01986 // ECMA 12.5
01987 Completion IfNode::execute(ExecState *exec)
01988 {
01989   KJS_BREAKPOINT;
01990 
01991   assert(expr);
01992   bool b = expr->toBoolean(exec);
01993   KJS_CHECKEXCEPTION
01994 
01995   // if ... then
01996   if (b)
01997     return statement1->execute(exec);
01998 
01999   // no else
02000   if (!statement2)
02001     return Completion(Normal);
02002 
02003   // else
02004   return statement2->execute(exec);
02005 }
02006 
02007 void IfNode::processVarDecls(ExecState *exec)
02008 {
02009   statement1->processVarDecls(exec);
02010 
02011   if (statement2)
02012     statement2->processVarDecls(exec);
02013 }
02014 
02015 // ----------------------------- DoWhileNode ----------------------------------
02016 
02017 void DoWhileNode::ref()
02018 {
02019   StatementNode::ref();
02020   if ( statement )
02021     statement->ref();
02022   if ( expr )
02023     expr->ref();
02024 }
02025 
02026 bool DoWhileNode::deref()
02027 {
02028   if ( statement && statement->deref() )
02029     delete statement;
02030   if ( expr && expr->deref() )
02031     delete expr;
02032   return StatementNode::deref();
02033 }
02034 
02035 // ECMA 12.6.1
02036 Completion DoWhileNode::execute(ExecState *exec)
02037 {
02038   KJS_BREAKPOINT;
02039 
02040   Completion c;
02041   Value value;
02042   bool b;
02043 
02044   do {
02045     // bail out on error
02046     KJS_CHECKEXCEPTION
02047 
02048     exec->context().imp()->seenLabels()->pushIteration();
02049     c = statement->execute(exec);
02050     exec->context().imp()->seenLabels()->popIteration();
02051     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02052       if ((c.complType() == Break) && ls.contains(c.target()))
02053         return Completion(Normal, value);
02054       if (c.complType() != Normal)
02055         return c;
02056     }
02057     b = expr->toBoolean(exec);
02058     KJS_CHECKEXCEPTION
02059   } while (b);
02060 
02061   return Completion(Normal, value);
02062 }
02063 
02064 void DoWhileNode::processVarDecls(ExecState *exec)
02065 {
02066   statement->processVarDecls(exec);
02067 }
02068 
02069 // ----------------------------- WhileNode ------------------------------------
02070 
02071 void WhileNode::ref()
02072 {
02073   StatementNode::ref();
02074   if ( statement )
02075     statement->ref();
02076   if ( expr )
02077     expr->ref();
02078 }
02079 
02080 bool WhileNode::deref()
02081 {
02082   if ( statement && statement->deref() )
02083     delete statement;
02084   if ( expr && expr->deref() )
02085     delete expr;
02086   return StatementNode::deref();
02087 }
02088 
02089 // ECMA 12.6.2
02090 Completion WhileNode::execute(ExecState *exec)
02091 {
02092   KJS_BREAKPOINT;
02093 
02094   Completion c;
02095   Value value;
02096 
02097   while (1) {
02098     bool b = expr->toBoolean(exec);
02099     KJS_CHECKEXCEPTION
02100 
02101     // bail out on error
02102     KJS_CHECKEXCEPTION
02103 
02104     if (!b)
02105       return Completion(Normal, value);
02106 
02107     exec->context().imp()->seenLabels()->pushIteration();
02108     c = statement->execute(exec);
02109     exec->context().imp()->seenLabels()->popIteration();
02110     if (c.isValueCompletion())
02111       value = c.value();
02112 
02113     if ((c.complType() == Continue) && ls.contains(c.target()))
02114       continue;
02115     if ((c.complType() == Break) && ls.contains(c.target()))
02116       return Completion(Normal, value);
02117     if (c.complType() != Normal)
02118       return c;
02119   }
02120 }
02121 
02122 void WhileNode::processVarDecls(ExecState *exec)
02123 {
02124   statement->processVarDecls(exec);
02125 }
02126 
02127 // ----------------------------- ForNode --------------------------------------
02128 
02129 void ForNode::ref()
02130 {
02131   StatementNode::ref();
02132   if ( statement )
02133     statement->ref();
02134   if ( expr1 )
02135     expr1->ref();
02136   if ( expr2 )
02137     expr2->ref();
02138   if ( expr3 )
02139     expr3->ref();
02140 }
02141 
02142 bool ForNode::deref()
02143 {
02144   if ( statement && statement->deref() )
02145     delete statement;
02146   if ( expr1 && expr1->deref() )
02147     delete expr1;
02148   if ( expr2 && expr2->deref() )
02149     delete expr2;
02150   if ( expr3 && expr3->deref() )
02151     delete expr3;
02152   return StatementNode::deref();
02153 }
02154 
02155 // ECMA 12.6.3
02156 Completion ForNode::execute(ExecState *exec)
02157 {
02158   Value v, cval;
02159 
02160   if (expr1) {
02161     v = expr1->evaluate(exec);
02162     KJS_CHECKEXCEPTION
02163   }
02164   for (;;) {
02165     if (expr2) {
02166       bool b = expr2->toBoolean(exec);
02167       KJS_CHECKEXCEPTION
02168       if (!b)
02169     return Completion(Normal, cval);
02170     }
02171     // bail out on error
02172     KJS_CHECKEXCEPTION
02173 
02174     exec->context().imp()->seenLabels()->pushIteration();
02175     Completion c = statement->execute(exec);
02176     exec->context().imp()->seenLabels()->popIteration();
02177     if (c.isValueCompletion())
02178       cval = c.value();
02179     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02180       if ((c.complType() == Break) && ls.contains(c.target()))
02181         return Completion(Normal, cval);
02182       if (c.complType() != Normal)
02183         return c;
02184     }
02185     if (expr3) {
02186       v = expr3->evaluate(exec);
02187       KJS_CHECKEXCEPTION
02188     }
02189   }
02190 }
02191 
02192 void ForNode::processVarDecls(ExecState *exec)
02193 {
02194   if (expr1)
02195     expr1->processVarDecls(exec);
02196 
02197   statement->processVarDecls(exec);
02198 }
02199 
02200 // ----------------------------- ForInNode ------------------------------------
02201 
02202 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
02203   : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
02204 {
02205 }
02206 
02207 ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
02208   : ident(i), init(in), expr(e), statement(s)
02209 {
02210   // for( var foo = bar in baz )
02211   varDecl = new VarDeclNode(ident, init);
02212   lexpr = new ResolveNode(ident);
02213 }
02214 
02215 void ForInNode::ref()
02216 {
02217   StatementNode::ref();
02218   if ( statement )
02219     statement->ref();
02220   if ( expr )
02221     expr->ref();
02222   if ( lexpr )
02223     lexpr->ref();
02224   if ( init )
02225     init->ref();
02226   if ( varDecl )
02227     varDecl->ref();
02228 }
02229 
02230 bool ForInNode::deref()
02231 {
02232   if ( statement && statement->deref() )
02233     delete statement;
02234   if ( expr && expr->deref() )
02235     delete expr;
02236   if ( lexpr && lexpr->deref() )
02237     delete lexpr;
02238   if ( init && init->deref() )
02239     delete init;
02240   if ( varDecl && varDecl->deref() )
02241     delete varDecl;
02242   return StatementNode::deref();
02243 }
02244 
02245 // ECMA 12.6.4
02246 Completion ForInNode::execute(ExecState *exec)
02247 {
02248   Value retval;
02249   Completion c;
02250 
02251   if ( varDecl ) {
02252     (void)varDecl->evaluate(exec);
02253     KJS_CHECKEXCEPTION
02254   }
02255 
02256   Value v = expr->evaluate(exec);
02257   // for Null and Undefined, we want to make sure not to go through
02258   // the loop at all, because their object wrappers will have a
02259   // property list but will throw an exception if you attempt to
02260   // access any property.
02261   if (v.isA(NullType) || v.isA(UndefinedType))
02262     return Completion(Normal, retval);
02263 
02264   Object o = v.toObject(exec);
02265   KJS_CHECKEXCEPTION
02266   ReferenceList propList = o.propList(exec);
02267 
02268   ReferenceListIterator propIt = propList.begin();
02269 
02270   while (propIt != propList.end()) {
02271     Identifier name = propIt->getPropertyName(exec);
02272     if (!o.hasProperty(exec,name)) {
02273       propIt++;
02274       continue;
02275     }
02276 
02277     Reference ref = lexpr->evaluateReference(exec);
02278     KJS_CHECKEXCEPTION
02279     ref.putValue(exec, String(name.ustring()));
02280 
02281     exec->context().imp()->seenLabels()->pushIteration();
02282     c = statement->execute(exec);
02283     exec->context().imp()->seenLabels()->popIteration();
02284     if (c.isValueCompletion())
02285       retval = c.value();
02286 
02287     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02288       if ((c.complType() == Break) && ls.contains(c.target()))
02289         break;
02290       if (c.complType() != Normal) {
02291         return c;
02292       }
02293     }
02294 
02295     propIt++;
02296   }
02297 
02298   // bail out on error
02299   KJS_CHECKEXCEPTION
02300 
02301   return Completion(Normal, retval);
02302 }
02303 
02304 void ForInNode::processVarDecls(ExecState *exec)
02305 {
02306   statement->processVarDecls(exec);
02307 }
02308 
02309 // ----------------------------- ContinueNode ---------------------------------
02310 
02311 // ECMA 12.7
02312 Completion ContinueNode::execute(ExecState *exec)
02313 {
02314   KJS_BREAKPOINT;
02315 
02316   Value dummy;
02317 
02318   if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration())
02319     return Completion(Throw,
02320               throwError(exec, SyntaxError, "continue used outside of iteration statement"));
02321   else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
02322     return Completion(Throw,
02323                       throwError(exec, SyntaxError, "Label %s not found in containing block. Can't continue.", ident));
02324   else
02325     return Completion(Continue, dummy, ident);
02326 }
02327 
02328 // ----------------------------- BreakNode ------------------------------------
02329 
02330 // ECMA 12.8
02331 Completion BreakNode::execute(ExecState *exec)
02332 {
02333   KJS_BREAKPOINT;
02334 
02335   Value dummy;
02336 
02337   if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration() &&
02338       !exec->context().imp()->seenLabels()->inSwitch())
02339     return Completion(Throw,
02340               throwError(exec, SyntaxError, "break used outside of iteration or switch statement"));
02341   else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
02342     return Completion(Throw,
02343                       throwError(exec, SyntaxError, "Label %s not found in containing block. Can't break.", ident));
02344   else
02345     return Completion(Break, dummy, ident);
02346 }
02347 
02348 // ----------------------------- ReturnNode -----------------------------------
02349 
02350 void ReturnNode::ref()
02351 {
02352   StatementNode::ref();
02353   if ( value )
02354     value->ref();
02355 }
02356 
02357 bool ReturnNode::deref()
02358 {
02359   if ( value && value->deref() )
02360     delete value;
02361   return StatementNode::deref();
02362 }
02363 
02364 // ECMA 12.9
02365 Completion ReturnNode::execute(ExecState *exec)
02366 {
02367   KJS_BREAKPOINT;
02368 
02369   if (!value)
02370     return Completion(ReturnValue, Undefined());
02371 
02372   Value v = value->evaluate(exec);
02373   KJS_CHECKEXCEPTION
02374 
02375   return Completion(ReturnValue, v);
02376 }
02377 
02378 // ----------------------------- WithNode -------------------------------------
02379 
02380 void WithNode::ref()
02381 {
02382   StatementNode::ref();
02383   if ( statement )
02384     statement->ref();
02385   if ( expr )
02386     expr->ref();
02387 }
02388 
02389 bool WithNode::deref()
02390 {
02391   if ( statement && statement->deref() )
02392     delete statement;
02393   if ( expr && expr->deref() )
02394     delete expr;
02395   return StatementNode::deref();
02396 }
02397 
02398 // ECMA 12.10
02399 Completion WithNode::execute(ExecState *exec)
02400 {
02401   KJS_BREAKPOINT;
02402 
02403   Value v = expr->evaluate(exec);
02404   KJS_CHECKEXCEPTION
02405   Object o = v.toObject(exec);
02406   KJS_CHECKEXCEPTION
02407   exec->context().imp()->pushScope(o);
02408   Completion res = statement->execute(exec);
02409   exec->context().imp()->popScope();
02410 
02411   return res;
02412 }
02413 
02414 void WithNode::processVarDecls(ExecState *exec)
02415 {
02416   statement->processVarDecls(exec);
02417 }
02418 
02419 // ----------------------------- CaseClauseNode -------------------------------
02420 
02421 void CaseClauseNode::ref()
02422 {
02423   Node::ref();
02424   if ( expr )
02425     expr->ref();
02426   if ( list )
02427     list->ref();
02428 }
02429 
02430 bool CaseClauseNode::deref()
02431 {
02432   if ( expr && expr->deref() )
02433     delete expr;
02434   if ( list && list->deref() )
02435     delete list;
02436   return Node::deref();
02437 }
02438 
02439 // ECMA 12.11
02440 Value CaseClauseNode::evaluate(ExecState *exec) const
02441 {
02442   Value v = expr->evaluate(exec);
02443   KJS_CHECKEXCEPTIONVALUE
02444 
02445   return v;
02446 }
02447 
02448 // ECMA 12.11
02449 Completion CaseClauseNode::evalStatements(ExecState *exec) const
02450 {
02451   if (list)
02452     return list->execute(exec);
02453   else
02454     return Completion(Normal, Undefined());
02455 }
02456 
02457 void CaseClauseNode::processVarDecls(ExecState *exec)
02458 {
02459   if (list)
02460     list->processVarDecls(exec);
02461 }
02462 
02463 // ----------------------------- ClauseListNode -------------------------------
02464 
02465 void ClauseListNode::ref()
02466 {
02467   for (ClauseListNode *n = this; n; n = n->nx) {
02468     n->Node::ref();
02469     if (n->cl)
02470       n->cl->ref();
02471   }
02472 }
02473 
02474 bool ClauseListNode::deref()
02475 {
02476   ClauseListNode *next;
02477   for (ClauseListNode *n = this; n; n = next) {
02478     next = n->nx;
02479     if (n->cl && n->cl->deref())
02480       delete n->cl;
02481     if (n != this && n->Node::deref())
02482       delete n;
02483   }
02484   return Node::deref();
02485 }
02486 
02487 Value ClauseListNode::evaluate(ExecState * /*exec*/) const
02488 {
02489   /* should never be called */
02490   assert(false);
02491   return Value();
02492 }
02493 
02494 // ECMA 12.11
02495 void ClauseListNode::processVarDecls(ExecState *exec)
02496 {
02497   for (ClauseListNode *n = this; n; n = n->nx)
02498     if (n->cl)
02499       n->cl->processVarDecls(exec);
02500 }
02501 
02502 // ----------------------------- CaseBlockNode --------------------------------
02503 
02504 CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
02505                              ClauseListNode *l2)
02506 {
02507   def = d;
02508   if (l1) {
02509     list1 = l1->nx;
02510     l1->nx = 0;
02511   } else {
02512     list1 = 0;
02513   }
02514   if (l2) {
02515     list2 = l2->nx;
02516     l2->nx = 0;
02517   } else {
02518     list2 = 0;
02519   }
02520 }
02521 
02522 void CaseBlockNode::ref()
02523 {
02524   Node::ref();
02525   if ( def )
02526     def->ref();
02527   if ( list1 )
02528     list1->ref();
02529   if ( list2 )
02530     list2->ref();
02531 }
02532 
02533 bool CaseBlockNode::deref()
02534 {
02535   if ( def && def->deref() )
02536     delete def;
02537   if ( list1 && list1->deref() )
02538     delete list1;
02539   if ( list2 && list2->deref() )
02540     delete list2;
02541   return Node::deref();
02542 }
02543 
02544 Value CaseBlockNode::evaluate(ExecState * /*exec*/) const
02545 {
02546   /* should never be called */
02547   assert(false);
02548   return Value();
02549 }
02550 
02551 // ECMA 12.11
02552 Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input) const
02553 {
02554   Value v;
02555   Completion res;
02556   ClauseListNode *a = list1, *b = list2;
02557   CaseClauseNode *clause;
02558 
02559     while (a) {
02560       clause = a->clause();
02561       a = a->next();
02562       v = clause->evaluate(exec);
02563       KJS_CHECKEXCEPTION
02564       if (strictEqual(exec, input, v)) {
02565     res = clause->evalStatements(exec);
02566     if (res.complType() != Normal)
02567       return res;
02568     while (a) {
02569       res = a->clause()->evalStatements(exec);
02570       if (res.complType() != Normal)
02571         return res;
02572       a = a->next();
02573     }
02574     break;
02575       }
02576     }
02577 
02578   while (b) {
02579     clause = b->clause();
02580     b = b->next();
02581     v = clause->evaluate(exec);
02582     KJS_CHECKEXCEPTION
02583     if (strictEqual(exec, input, v)) {
02584       res = clause->evalStatements(exec);
02585       if (res.complType() != Normal)
02586     return res;
02587       goto step18;
02588     }
02589   }
02590 
02591   // default clause
02592   if (def) {
02593     res = def->evalStatements(exec);
02594     if (res.complType() != Normal)
02595       return res;
02596   }
02597   b = list2;
02598  step18:
02599   while (b) {
02600     clause = b->clause();
02601     res = clause->evalStatements(exec);
02602     if (res.complType() != Normal)
02603       return res;
02604     b = b->next();
02605   }
02606 
02607   // bail out on error
02608   KJS_CHECKEXCEPTION
02609 
02610   return Completion(Normal);
02611 }
02612 
02613 void CaseBlockNode::processVarDecls(ExecState *exec)
02614 {
02615   if (list1)
02616     list1->processVarDecls(exec);
02617   if (def)
02618     def->processVarDecls(exec);
02619   if (list2)
02620     list2->processVarDecls(exec);
02621 }
02622 
02623 // ----------------------------- SwitchNode -----------------------------------
02624 
02625 void SwitchNode::ref()
02626 {
02627   StatementNode::ref();
02628   if ( expr )
02629     expr->ref();
02630   if ( block )
02631     block->ref();
02632 }
02633 
02634 bool SwitchNode::deref()
02635 {
02636   if ( expr && expr->deref() )
02637     delete expr;
02638   if ( block && block->deref() )
02639     delete block;
02640   return StatementNode::deref();
02641 }
02642 
02643 // ECMA 12.11
02644 Completion SwitchNode::execute(ExecState *exec)
02645 {
02646   KJS_BREAKPOINT;
02647 
02648   Value v = expr->evaluate(exec);
02649   KJS_CHECKEXCEPTION
02650   exec->context().imp()->seenLabels()->pushSwitch();
02651   Completion res = block->evalBlock(exec,v);
02652   exec->context().imp()->seenLabels()->popSwitch();
02653 
02654   if ((res.complType() == Break) && ls.contains(res.target()))
02655     return Completion(Normal, res.value());
02656   else
02657     return res;
02658 }
02659 
02660 void SwitchNode::processVarDecls(ExecState *exec)
02661 {
02662   block->processVarDecls(exec);
02663 }
02664 
02665 // ----------------------------- LabelNode ------------------------------------
02666 
02667 void LabelNode::ref()
02668 {
02669   StatementNode::ref();
02670   if ( statement )
02671     statement->ref();
02672 }
02673 
02674 bool LabelNode::deref()
02675 {
02676   if ( statement && statement->deref() )
02677     delete statement;
02678   return StatementNode::deref();
02679 }
02680 
02681 // ECMA 12.12
02682 Completion LabelNode::execute(ExecState *exec)
02683 {
02684   Completion e;
02685 
02686   if (!exec->context().imp()->seenLabels()->push(label)) {
02687     return Completion( Throw,
02688                        throwError(exec, SyntaxError, "Duplicated label %s found.", label));
02689   };
02690   e = statement->execute(exec);
02691   exec->context().imp()->seenLabels()->pop();
02692 
02693   if ((e.complType() == Break) && (e.target() == label))
02694     return Completion(Normal, e.value());
02695   else
02696     return e;
02697 }
02698 
02699 void LabelNode::processVarDecls(ExecState *exec)
02700 {
02701   statement->processVarDecls(exec);
02702 }
02703 
02704 // ----------------------------- ThrowNode ------------------------------------
02705 
02706 void ThrowNode::ref()
02707 {
02708   StatementNode::ref();
02709   if ( expr )
02710     expr->ref();
02711 }
02712 
02713 bool ThrowNode::deref()
02714 {
02715   if ( expr && expr->deref() )
02716     delete expr;
02717   return StatementNode::deref();
02718 }
02719 
02720 // ECMA 12.13
02721 Completion ThrowNode::execute(ExecState *exec)
02722 {
02723   KJS_BREAKPOINT;
02724 
02725   Value v = expr->evaluate(exec);
02726   KJS_CHECKEXCEPTION
02727 
02728   // bail out on error
02729   KJS_CHECKEXCEPTION
02730 
02731   Debugger *dbg = exec->interpreter()->imp()->debugger();
02732   if (dbg)
02733     dbg->exception(exec,v,exec->context().imp()->inTryCatch());
02734 
02735   return Completion(Throw, v);
02736 }
02737 
02738 // ----------------------------- CatchNode ------------------------------------
02739 
02740 void CatchNode::ref()
02741 {
02742   StatementNode::ref();
02743   if ( block )
02744     block->ref();
02745 }
02746 
02747 bool CatchNode::deref()
02748 {
02749   if ( block && block->deref() )
02750     delete block;
02751   return StatementNode::deref();
02752 }
02753 
02754 Completion CatchNode::execute(ExecState * /*exec*/)
02755 {
02756   // should never be reached. execute(exec, arg) is used instead
02757   assert(0L);
02758   return Completion();
02759 }
02760 
02761 // ECMA 12.14
02762 Completion CatchNode::execute(ExecState *exec, const Value &arg)
02763 {
02764   /* TODO: correct ? Not part of the spec */
02765 
02766   exec->clearException();
02767 
02768   Object obj(new ObjectImp());
02769   obj.put(exec, ident, arg, DontDelete);
02770   exec->context().imp()->pushScope(obj);
02771   Completion c = block->execute(exec);
02772   exec->context().imp()->popScope();
02773 
02774   return c;
02775 }
02776 
02777 void CatchNode::processVarDecls(ExecState *exec)
02778 {
02779   block->processVarDecls(exec);
02780 }
02781 
02782 // ----------------------------- FinallyNode ----------------------------------
02783 
02784 void FinallyNode::ref()
02785 {
02786   StatementNode::ref();
02787   if ( block )
02788     block->ref();
02789 }
02790 
02791 bool FinallyNode::deref()
02792 {
02793   if ( block && block->deref() )
02794     delete block;
02795   return StatementNode::deref();
02796 }
02797 
02798 // ECMA 12.14
02799 Completion FinallyNode::execute(ExecState *exec)
02800 {
02801   return block->execute(exec);
02802 }
02803 
02804 void FinallyNode::processVarDecls(ExecState *exec)
02805 {
02806   block->processVarDecls(exec);
02807 }
02808 
02809 // ----------------------------- TryNode --------------------------------------
02810 
02811 void TryNode::ref()
02812 {
02813   StatementNode::ref();
02814   if ( block )
02815     block->ref();
02816   if ( _final )
02817     _final->ref();
02818   if ( _catch )
02819     _catch->ref();
02820 }
02821 
02822 bool TryNode::deref()
02823 {
02824   if ( block && block->deref() )
02825     delete block;
02826   if ( _final && _final->deref() )
02827     delete _final;
02828   if ( _catch && _catch->deref() )
02829     delete _catch;
02830   return StatementNode::deref();
02831 }
02832 
02833 // ECMA 12.14
02834 Completion TryNode::execute(ExecState *exec)
02835 {
02836   KJS_BREAKPOINT;
02837 
02838   Completion c, c2;
02839 
02840   if (_catch)
02841     exec->context().imp()->pushTryCatch();
02842   c = block->execute(exec);
02843   if (_catch)
02844     exec->context().imp()->popTryCatch();
02845 
02846   if (!_final) {
02847     if (c.complType() != Throw)
02848       return c;
02849     return _catch->execute(exec,c.value());
02850   }
02851 
02852   if (!_catch) {
02853     Value exception = exec->_exception;
02854     exec->_exception = Value();
02855 
02856     c2 = _final->execute(exec);
02857 
02858     if (!exec->hadException() && c2.complType() != Throw)
02859       exec->_exception = exception;
02860 
02861     return (c2.complType() == Normal) ? c : c2;
02862   }
02863 
02864   if (c.complType() == Throw)
02865     c = _catch->execute(exec,c.value());
02866 
02867   c2 = _final->execute(exec);
02868   return (c2.complType() == Normal) ? c : c2;
02869 }
02870 
02871 void TryNode::processVarDecls(ExecState *exec)
02872 {
02873   block->processVarDecls(exec);
02874   if (_final)
02875     _final->processVarDecls(exec);
02876   if (_catch)
02877     _catch->processVarDecls(exec);
02878 }
02879 
02880 // ----------------------------- ParameterNode --------------------------------
02881 
02882 void ParameterNode::ref()
02883 {
02884   for (ParameterNode *n = this; n; n = n->next)
02885     n->Node::ref();
02886 }
02887 
02888 bool ParameterNode::deref()
02889 {
02890   ParameterNode *next;
02891   for (ParameterNode *n = this; n; n = next) {
02892     next = n->next;
02893     if (n != this && n->Node::deref())
02894       delete n;
02895   }
02896   return Node::deref();
02897 }
02898 
02899 // ECMA 13
02900 Value ParameterNode::evaluate(ExecState * /*exec*/) const
02901 {
02902   return Undefined();
02903 }
02904 
02905 // ----------------------------- FunctionBodyNode -----------------------------
02906 
02907 
02908 FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
02909   : BlockNode(s), program(false)
02910 {
02911   //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
02912 }
02913 
02914 void FunctionBodyNode::processFuncDecl(ExecState *exec)
02915 {
02916   if (source)
02917     source->processFuncDecl(exec);
02918 }
02919 
02920 Completion FunctionBodyNode::execute(ExecState *exec)
02921 {
02922   Completion c = BlockNode::execute(exec);
02923   if (program && c.complType() == ReturnValue)
02924     return Completion(Throw,
02925               throwError(exec, SyntaxError, "return outside of function body"));
02926   else
02927     return c;
02928 }
02929 
02930 // ----------------------------- FuncDeclNode ---------------------------------
02931 
02932 void FuncDeclNode::ref()
02933 {
02934   StatementNode::ref();
02935   if ( param )
02936     param->ref();
02937   if ( body )
02938     body->ref();
02939 }
02940 
02941 bool FuncDeclNode::deref()
02942 {
02943   if ( param && param->deref() )
02944     delete param;
02945   if ( body && body->deref() )
02946     delete body;
02947   return StatementNode::deref();
02948 }
02949 
02950 // ECMA 13
02951 void FuncDeclNode::processFuncDecl(ExecState *exec)
02952 {
02953   ContextImp *ctx = exec->context().imp();
02954   // TODO: let this be an object with [[Class]] property "Function"
02955   FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
02956   Object func(fimp); // protect from GC
02957 
02958   //  Value proto = exec->interpreter()->builtinObject().construct(exec,List::empty());
02959   List empty;
02960   Object proto = exec->interpreter()->builtinObject().construct(exec,empty);
02961   proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
02962   func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
02963 
02964   int plen = 0;
02965   for(const ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
02966     fimp->addParameter(p->ident());
02967 
02968   func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
02969 
02970 #ifdef KJS_VERBOSE
02971   fprintf(stderr,"KJS: new function %s in %p\n", ident.ustring().cstring().c_str(), ctx->variableObject().imp());
02972 #endif
02973   if (exec->_context->type() == EvalCode)
02974     ctx->variableObject().put(exec,ident,func,Internal);
02975   else
02976     ctx->variableObject().put(exec,ident,func,DontDelete|Internal);
02977 
02978   if (body) {
02979     // hack the scope so that the function gets put as a property of func, and it's scope
02980     // contains the func as well as our current scope
02981     Object oldVar = ctx->variableObject();
02982     ctx->setVariableObject(func);
02983     ctx->pushScope(func);
02984     body->processFuncDecl(exec);
02985     ctx->popScope();
02986     ctx->setVariableObject(oldVar);
02987   }
02988 }
02989 
02990 // ----------------------------- FuncExprNode ---------------------------------
02991 
02992 void FuncExprNode::ref()
02993 {
02994   Node::ref();
02995   if ( param )
02996     param->ref();
02997   if ( body )
02998     body->ref();
02999 }
03000 
03001 bool FuncExprNode::deref()
03002 {
03003   if ( param && param->deref() )
03004     delete param;
03005   if ( body && body->deref() )
03006     delete body;
03007   return Node::deref();
03008 }
03009 
03010 
03011 // ECMA 13
03012 Value FuncExprNode::evaluate(ExecState *exec) const
03013 {
03014   FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain());
03015   Value ret(fimp);
03016   List empty;
03017   Value proto = exec->interpreter()->builtinObject().construct(exec,empty);
03018   fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
03019 
03020   for(const ParameterNode *p = param; p != 0L; p = p->nextParam())
03021     fimp->addParameter(p->ident());
03022 
03023   return ret;
03024 }
03025 
03026 // ----------------------------- SourceElementsNode ---------------------------
03027 
03028 SourceElementsNode::SourceElementsNode(StatementNode *s1)
03029 {
03030   element = s1;
03031   elements = this;
03032   setLoc(s1->firstLine(),s1->lastLine(),s1->code());
03033 }
03034 
03035 SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
03036 {
03037   elements = s1->elements;
03038   s1->elements = this;
03039   element = s2;
03040   setLoc(s1->firstLine(),s2->lastLine(),s1->code());
03041 }
03042 
03043 void SourceElementsNode::ref()
03044 {
03045   for (SourceElementsNode *n = this; n; n = n->elements) {
03046     n->Node::ref();
03047     if (n->element)
03048       n->element->ref();
03049   }
03050 }
03051 
03052 bool SourceElementsNode::deref()
03053 {
03054   SourceElementsNode *next;
03055   for (SourceElementsNode *n = this; n; n = next) {
03056     next = n->elements;
03057     if (n->element && n->element->deref())
03058       delete n->element;
03059     if (n != this && n->Node::deref())
03060       delete n;
03061   }
03062   return StatementNode::deref();
03063 }
03064 
03065 // ECMA 14
03066 Completion SourceElementsNode::execute(ExecState *exec)
03067 {
03068   KJS_CHECKEXCEPTION
03069 
03070   Completion c1 = element->execute(exec);
03071   KJS_CHECKEXCEPTION;
03072   if (c1.complType() != Normal)
03073     return c1;
03074 
03075   for (SourceElementsNode *node = elements; node; node = node->elements) {
03076     Completion c2 = node->element->execute(exec);
03077     if (c2.complType() != Normal)
03078       return c2;
03079     // The spec says to return c2 here, but it seems that mozilla returns c1 if
03080     // c2 doesn't have a value
03081     if (c2.value().isValid())
03082       c1 = c2;
03083   }
03084 
03085   return c1;
03086 }
03087 
03088 // ECMA 14
03089 void SourceElementsNode::processFuncDecl(ExecState *exec)
03090 {
03091   for (SourceElementsNode *n = this; n; n = n->elements)
03092     n->element->processFuncDecl(exec);
03093 }
03094 
03095 void SourceElementsNode::processVarDecls(ExecState *exec)
03096 {
03097   for (SourceElementsNode *n = this; n; n = n->elements)
03098     n->element->processVarDecls(exec);
03099 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Feb 8 08:01:46 2006 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003