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   return String(ident.ustring());
01784 }
01785 
01786 void VarDeclNode::processVarDecls(ExecState *exec)
01787 {
01788   Object variable = exec->context().variableObject();
01789   if ( !variable.hasProperty( exec, ident ) ) { // already declared ?
01790     int flags = None;
01791     if (exec->_context->type() != EvalCode)
01792       flags |= DontDelete;
01793     if (currentVarType == VarStatementNode::Constant)
01794       flags |= ReadOnly;
01795     // TODO: check for forbidden redeclaration of consts
01796     variable.put(exec,ident, Undefined(), flags);
01797   }
01798   //else warning "variable %1 hides argument"
01799 }
01800 
01801 // ----------------------------- VarDeclListNode ------------------------------
01802 
01803 void VarDeclListNode::ref()
01804 {
01805   for (VarDeclListNode *n = this; n; n = n->list) {
01806     n->Node::ref();
01807     if (n->var)
01808       n->var->ref();
01809   }
01810 }
01811 
01812 bool VarDeclListNode::deref()
01813 {
01814   VarDeclListNode *next;
01815   for (VarDeclListNode *n = this; n; n = next) {
01816     next = n->list;
01817     if (n->var && n->var->deref())
01818       delete n->var;
01819     if (n != this && n->Node::deref())
01820       delete n;
01821   }
01822   return Node::deref();
01823 }
01824 
01825 
01826 // ECMA 12.2
01827 Value VarDeclListNode::evaluate(ExecState *exec) const
01828 {
01829   for (const VarDeclListNode *n = this; n; n = n->list) {
01830     n->var->evaluate(exec);
01831     KJS_CHECKEXCEPTIONVALUE
01832   }
01833   return Undefined();
01834 }
01835 
01836 void VarDeclListNode::processVarDecls(ExecState *exec)
01837 {
01838   for (VarDeclListNode *n = this; n; n = n->list)
01839     n->var->processVarDecls(exec);
01840 }
01841 
01842 // ----------------------------- VarStatementNode -----------------------------
01843 
01844 void VarStatementNode::ref()
01845 {
01846   StatementNode::ref();
01847   if ( list )
01848     list->ref();
01849 }
01850 
01851 bool VarStatementNode::deref()
01852 {
01853   if ( list && list->deref() )
01854     delete list;
01855   return StatementNode::deref();
01856 }
01857 
01858 // ECMA 12.2
01859 Completion VarStatementNode::execute(ExecState *exec)
01860 {
01861   KJS_BREAKPOINT;
01862 
01863   // set global var/const flag
01864   currentVarType = varType;
01865 
01866   (void) list->evaluate(exec);
01867   KJS_CHECKEXCEPTION
01868 
01869   return Completion(Normal);
01870 }
01871 
01872 void VarStatementNode::processVarDecls(ExecState *exec)
01873 {
01874   // set global var/const flag
01875   currentVarType = varType;
01876 
01877   list->processVarDecls(exec);
01878 }
01879 
01880 // ----------------------------- BlockNode ------------------------------------
01881 
01882 BlockNode::BlockNode(SourceElementsNode *s)
01883 {
01884   if (s) {
01885     source = s->elements;
01886     s->elements = 0;
01887     setLoc(s->firstLine(), s->lastLine(), s->code());
01888   } else {
01889     source = 0;
01890   }
01891 }
01892 
01893 void BlockNode::ref()
01894 {
01895   StatementNode::ref();
01896   if ( source )
01897     source->ref();
01898 }
01899 
01900 bool BlockNode::deref()
01901 {
01902   if ( source && source->deref() )
01903     delete source;
01904   return StatementNode::deref();
01905 }
01906 
01907 // ECMA 12.1
01908 Completion BlockNode::execute(ExecState *exec)
01909 {
01910   if (!source)
01911     return Completion(Normal);
01912 
01913   source->processFuncDecl(exec);
01914 
01915   return source->execute(exec);
01916 }
01917 
01918 void BlockNode::processVarDecls(ExecState *exec)
01919 {
01920   if (source)
01921     source->processVarDecls(exec);
01922 }
01923 
01924 // ----------------------------- EmptyStatementNode ---------------------------
01925 
01926 // ECMA 12.3
01927 Completion EmptyStatementNode::execute(ExecState * /*exec*/)
01928 {
01929   return Completion(Normal);
01930 }
01931 
01932 // ----------------------------- ExprStatementNode ----------------------------
01933 
01934 void ExprStatementNode::ref()
01935 {
01936   StatementNode::ref();
01937   if ( expr )
01938     expr->ref();
01939 }
01940 
01941 bool ExprStatementNode::deref()
01942 {
01943   if ( expr && expr->deref() )
01944     delete expr;
01945   return StatementNode::deref();
01946 }
01947 
01948 // ECMA 12.4
01949 Completion ExprStatementNode::execute(ExecState *exec)
01950 {
01951   KJS_BREAKPOINT;
01952 
01953   Value v = expr->evaluate(exec);
01954   KJS_CHECKEXCEPTION
01955 
01956   return Completion(Normal, v);
01957 }
01958 
01959 // ----------------------------- IfNode ---------------------------------------
01960 
01961 void IfNode::ref()
01962 {
01963   StatementNode::ref();
01964   if ( statement1 )
01965     statement1->ref();
01966   if ( statement2 )
01967     statement2->ref();
01968   if ( expr )
01969     expr->ref();
01970 }
01971 
01972 bool IfNode::deref()
01973 {
01974   if ( statement1 && statement1->deref() )
01975     delete statement1;
01976   if ( statement2 && statement2->deref() )
01977     delete statement2;
01978   if ( expr && expr->deref() )
01979     delete expr;
01980   return StatementNode::deref();
01981 }
01982 
01983 // ECMA 12.5
01984 Completion IfNode::execute(ExecState *exec)
01985 {
01986   KJS_BREAKPOINT;
01987 
01988   assert(expr);
01989   bool b = expr->toBoolean(exec);
01990   KJS_CHECKEXCEPTION
01991 
01992   // if ... then
01993   if (b)
01994     return statement1->execute(exec);
01995 
01996   // no else
01997   if (!statement2)
01998     return Completion(Normal);
01999 
02000   // else
02001   return statement2->execute(exec);
02002 }
02003 
02004 void IfNode::processVarDecls(ExecState *exec)
02005 {
02006   statement1->processVarDecls(exec);
02007 
02008   if (statement2)
02009     statement2->processVarDecls(exec);
02010 }
02011 
02012 // ----------------------------- DoWhileNode ----------------------------------
02013 
02014 void DoWhileNode::ref()
02015 {
02016   StatementNode::ref();
02017   if ( statement )
02018     statement->ref();
02019   if ( expr )
02020     expr->ref();
02021 }
02022 
02023 bool DoWhileNode::deref()
02024 {
02025   if ( statement && statement->deref() )
02026     delete statement;
02027   if ( expr && expr->deref() )
02028     delete expr;
02029   return StatementNode::deref();
02030 }
02031 
02032 // ECMA 12.6.1
02033 Completion DoWhileNode::execute(ExecState *exec)
02034 {
02035   KJS_BREAKPOINT;
02036 
02037   Completion c;
02038   Value value;
02039   bool b;
02040 
02041   do {
02042     // bail out on error
02043     KJS_CHECKEXCEPTION
02044 
02045     exec->context().imp()->seenLabels()->pushIteration();
02046     c = statement->execute(exec);
02047     exec->context().imp()->seenLabels()->popIteration();
02048     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02049       if ((c.complType() == Break) && ls.contains(c.target()))
02050         return Completion(Normal, value);
02051       if (c.complType() != Normal)
02052         return c;
02053     }
02054     b = expr->toBoolean(exec);
02055     KJS_CHECKEXCEPTION
02056   } while (b);
02057 
02058   return Completion(Normal, value);
02059 }
02060 
02061 void DoWhileNode::processVarDecls(ExecState *exec)
02062 {
02063   statement->processVarDecls(exec);
02064 }
02065 
02066 // ----------------------------- WhileNode ------------------------------------
02067 
02068 void WhileNode::ref()
02069 {
02070   StatementNode::ref();
02071   if ( statement )
02072     statement->ref();
02073   if ( expr )
02074     expr->ref();
02075 }
02076 
02077 bool WhileNode::deref()
02078 {
02079   if ( statement && statement->deref() )
02080     delete statement;
02081   if ( expr && expr->deref() )
02082     delete expr;
02083   return StatementNode::deref();
02084 }
02085 
02086 // ECMA 12.6.2
02087 Completion WhileNode::execute(ExecState *exec)
02088 {
02089   KJS_BREAKPOINT;
02090 
02091   Completion c;
02092   Value value;
02093 
02094   while (1) {
02095     bool b = expr->toBoolean(exec);
02096     KJS_CHECKEXCEPTION
02097 
02098     // bail out on error
02099     KJS_CHECKEXCEPTION
02100 
02101     if (!b)
02102       return Completion(Normal, value);
02103 
02104     exec->context().imp()->seenLabels()->pushIteration();
02105     c = statement->execute(exec);
02106     exec->context().imp()->seenLabels()->popIteration();
02107     if (c.isValueCompletion())
02108       value = c.value();
02109 
02110     if ((c.complType() == Continue) && ls.contains(c.target()))
02111       continue;
02112     if ((c.complType() == Break) && ls.contains(c.target()))
02113       return Completion(Normal, value);
02114     if (c.complType() != Normal)
02115       return c;
02116   }
02117 }
02118 
02119 void WhileNode::processVarDecls(ExecState *exec)
02120 {
02121   statement->processVarDecls(exec);
02122 }
02123 
02124 // ----------------------------- ForNode --------------------------------------
02125 
02126 void ForNode::ref()
02127 {
02128   StatementNode::ref();
02129   if ( statement )
02130     statement->ref();
02131   if ( expr1 )
02132     expr1->ref();
02133   if ( expr2 )
02134     expr2->ref();
02135   if ( expr3 )
02136     expr3->ref();
02137 }
02138 
02139 bool ForNode::deref()
02140 {
02141   if ( statement && statement->deref() )
02142     delete statement;
02143   if ( expr1 && expr1->deref() )
02144     delete expr1;
02145   if ( expr2 && expr2->deref() )
02146     delete expr2;
02147   if ( expr3 && expr3->deref() )
02148     delete expr3;
02149   return StatementNode::deref();
02150 }
02151 
02152 // ECMA 12.6.3
02153 Completion ForNode::execute(ExecState *exec)
02154 {
02155   Value v, cval;
02156 
02157   if (expr1) {
02158     v = expr1->evaluate(exec);
02159     KJS_CHECKEXCEPTION
02160   }
02161   for (;;) {
02162     if (expr2) {
02163       bool b = expr2->toBoolean(exec);
02164       KJS_CHECKEXCEPTION
02165       if (!b)
02166     return Completion(Normal, cval);
02167     }
02168     // bail out on error
02169     KJS_CHECKEXCEPTION
02170 
02171     exec->context().imp()->seenLabels()->pushIteration();
02172     Completion c = statement->execute(exec);
02173     exec->context().imp()->seenLabels()->popIteration();
02174     if (c.isValueCompletion())
02175       cval = c.value();
02176     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02177       if ((c.complType() == Break) && ls.contains(c.target()))
02178         return Completion(Normal, cval);
02179       if (c.complType() != Normal)
02180         return c;
02181     }
02182     if (expr3) {
02183       v = expr3->evaluate(exec);
02184       KJS_CHECKEXCEPTION
02185     }
02186   }
02187 }
02188 
02189 void ForNode::processVarDecls(ExecState *exec)
02190 {
02191   if (expr1)
02192     expr1->processVarDecls(exec);
02193 
02194   statement->processVarDecls(exec);
02195 }
02196 
02197 // ----------------------------- ForInNode ------------------------------------
02198 
02199 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
02200   : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
02201 {
02202 }
02203 
02204 ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
02205   : ident(i), init(in), expr(e), statement(s)
02206 {
02207   // for( var foo = bar in baz )
02208   varDecl = new VarDeclNode(ident, init);
02209   lexpr = new ResolveNode(ident);
02210 }
02211 
02212 void ForInNode::ref()
02213 {
02214   StatementNode::ref();
02215   if ( statement )
02216     statement->ref();
02217   if ( expr )
02218     expr->ref();
02219   if ( lexpr )
02220     lexpr->ref();
02221   if ( init )
02222     init->ref();
02223   if ( varDecl )
02224     varDecl->ref();
02225 }
02226 
02227 bool ForInNode::deref()
02228 {
02229   if ( statement && statement->deref() )
02230     delete statement;
02231   if ( expr && expr->deref() )
02232     delete expr;
02233   if ( lexpr && lexpr->deref() )
02234     delete lexpr;
02235   if ( init && init->deref() )
02236     delete init;
02237   if ( varDecl && varDecl->deref() )
02238     delete varDecl;
02239   return StatementNode::deref();
02240 }
02241 
02242 // ECMA 12.6.4
02243 Completion ForInNode::execute(ExecState *exec)
02244 {
02245   Value retval;
02246   Completion c;
02247 
02248   if ( varDecl ) {
02249     varDecl->evaluate(exec);
02250     KJS_CHECKEXCEPTION
02251   }
02252 
02253   Value v = expr->evaluate(exec);
02254   // for Null and Undefined, we want to make sure not to go through
02255   // the loop at all, because their object wrappers will have a
02256   // property list but will throw an exception if you attempt to
02257   // access any property.
02258   if (v.isA(NullType) || v.isA(UndefinedType))
02259     return Completion(Normal, retval);
02260 
02261   Object o = v.toObject(exec);
02262   KJS_CHECKEXCEPTION
02263   ReferenceList propList = o.propList(exec);
02264 
02265   ReferenceListIterator propIt = propList.begin();
02266 
02267   while (propIt != propList.end()) {
02268     Identifier name = propIt->getPropertyName(exec);
02269     if (!o.hasProperty(exec,name)) {
02270       propIt++;
02271       continue;
02272     }
02273 
02274     Reference ref = lexpr->evaluateReference(exec);
02275     KJS_CHECKEXCEPTION
02276     ref.putValue(exec, String(name.ustring()));
02277 
02278     exec->context().imp()->seenLabels()->pushIteration();
02279     c = statement->execute(exec);
02280     exec->context().imp()->seenLabels()->popIteration();
02281     if (c.isValueCompletion())
02282       retval = c.value();
02283 
02284     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
02285       if ((c.complType() == Break) && ls.contains(c.target()))
02286         break;
02287       if (c.complType() != Normal) {
02288         return c;
02289       }
02290     }
02291 
02292     propIt++;
02293   }
02294 
02295   // bail out on error
02296   KJS_CHECKEXCEPTION
02297 
02298   return Completion(Normal, retval);
02299 }
02300 
02301 void ForInNode::processVarDecls(ExecState *exec)
02302 {
02303   statement->processVarDecls(exec);
02304 }
02305 
02306 // ----------------------------- ContinueNode ---------------------------------
02307 
02308 // ECMA 12.7
02309 Completion ContinueNode::execute(ExecState *exec)
02310 {
02311   KJS_BREAKPOINT;
02312 
02313   Value dummy;
02314 
02315   if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration())
02316     return Completion(Throw,
02317               throwError(exec, SyntaxError, "continue used outside of iteration statement"));
02318   else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
02319     return Completion(Throw,
02320                       throwError(exec, SyntaxError, "Label %s not found in containing block. Can't continue.", ident));
02321   else
02322     return Completion(Continue, dummy, ident);
02323 }
02324 
02325 // ----------------------------- BreakNode ------------------------------------
02326 
02327 // ECMA 12.8
02328 Completion BreakNode::execute(ExecState *exec)
02329 {
02330   KJS_BREAKPOINT;
02331 
02332   Value dummy;
02333 
02334   if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration() &&
02335       !exec->context().imp()->seenLabels()->inSwitch())
02336     return Completion(Throw,
02337               throwError(exec, SyntaxError, "break used outside of iteration or switch statement"));
02338   else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
02339     return Completion(Throw,
02340                       throwError(exec, SyntaxError, "Label %s not found in containing block. Can't break.", ident));
02341   else
02342     return Completion(Break, dummy, ident);
02343 }
02344 
02345 // ----------------------------- ReturnNode -----------------------------------
02346 
02347 void ReturnNode::ref()
02348 {
02349   StatementNode::ref();
02350   if ( value )
02351     value->ref();
02352 }
02353 
02354 bool ReturnNode::deref()
02355 {
02356   if ( value && value->deref() )
02357     delete value;
02358   return StatementNode::deref();
02359 }
02360 
02361 // ECMA 12.9
02362 Completion ReturnNode::execute(ExecState *exec)
02363 {
02364   KJS_BREAKPOINT;
02365 
02366   if (!value)
02367     return Completion(ReturnValue, Undefined());
02368 
02369   Value v = value->evaluate(exec);
02370   KJS_CHECKEXCEPTION
02371 
02372   return Completion(ReturnValue, v);
02373 }
02374 
02375 // ----------------------------- WithNode -------------------------------------
02376 
02377 void WithNode::ref()
02378 {
02379   StatementNode::ref();
02380   if ( statement )
02381     statement->ref();
02382   if ( expr )
02383     expr->ref();
02384 }
02385 
02386 bool WithNode::deref()
02387 {
02388   if ( statement && statement->deref() )
02389     delete statement;
02390   if ( expr && expr->deref() )
02391     delete expr;
02392   return StatementNode::deref();
02393 }
02394 
02395 // ECMA 12.10
02396 Completion WithNode::execute(ExecState *exec)
02397 {
02398   KJS_BREAKPOINT;
02399 
02400   Value v = expr->evaluate(exec);
02401   KJS_CHECKEXCEPTION
02402   Object o = v.toObject(exec);
02403   KJS_CHECKEXCEPTION
02404   exec->context().imp()->pushScope(o);
02405   Completion res = statement->execute(exec);
02406   exec->context().imp()->popScope();
02407 
02408   return res;
02409 }
02410 
02411 void WithNode::processVarDecls(ExecState *exec)
02412 {
02413   statement->processVarDecls(exec);
02414 }
02415 
02416 // ----------------------------- CaseClauseNode -------------------------------
02417 
02418 void CaseClauseNode::ref()
02419 {
02420   Node::ref();
02421   if ( expr )
02422     expr->ref();
02423   if ( list )
02424     list->ref();
02425 }
02426 
02427 bool CaseClauseNode::deref()
02428 {
02429   if ( expr && expr->deref() )
02430     delete expr;
02431   if ( list && list->deref() )
02432     delete list;
02433   return Node::deref();
02434 }
02435 
02436 // ECMA 12.11
02437 Value CaseClauseNode::evaluate(ExecState *exec) const
02438 {
02439   Value v = expr->evaluate(exec);
02440   KJS_CHECKEXCEPTIONVALUE
02441 
02442   return v;
02443 }
02444 
02445 // ECMA 12.11
02446 Completion CaseClauseNode::evalStatements(ExecState *exec) const
02447 {
02448   if (list)
02449     return list->execute(exec);
02450   else
02451     return Completion(Normal, Undefined());
02452 }
02453 
02454 void CaseClauseNode::processVarDecls(ExecState *exec)
02455 {
02456   if (list)
02457     list->processVarDecls(exec);
02458 }
02459 
02460 // ----------------------------- ClauseListNode -------------------------------
02461 
02462 void ClauseListNode::ref()
02463 {
02464   for (ClauseListNode *n = this; n; n = n->nx) {
02465     n->Node::ref();
02466     if (n->cl)
02467       n->cl->ref();
02468   }
02469 }
02470 
02471 bool ClauseListNode::deref()
02472 {
02473   ClauseListNode *next;
02474   for (ClauseListNode *n = this; n; n = next) {
02475     next = n->nx;
02476     if (n->cl && n->cl->deref())
02477       delete n->cl;
02478     if (n != this && n->Node::deref())
02479       delete n;
02480   }
02481   return Node::deref();
02482 }
02483 
02484 Value ClauseListNode::evaluate(ExecState * /*exec*/) const
02485 {
02486   /* should never be called */
02487   assert(false);
02488   return Value();
02489 }
02490 
02491 // ECMA 12.11
02492 void ClauseListNode::processVarDecls(ExecState *exec)
02493 {
02494   for (ClauseListNode *n = this; n; n = n->nx)
02495     if (n->cl)
02496       n->cl->processVarDecls(exec);
02497 }
02498 
02499 // ----------------------------- CaseBlockNode --------------------------------
02500 
02501 CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
02502                              ClauseListNode *l2)
02503 {
02504   def = d;
02505   if (l1) {
02506     list1 = l1->nx;
02507     l1->nx = 0;
02508   } else {
02509     list1 = 0;
02510   }
02511   if (l2) {
02512     list2 = l2->nx;
02513     l2->nx = 0;
02514   } else {
02515     list2 = 0;
02516   }
02517 }
02518 
02519 void CaseBlockNode::ref()
02520 {
02521   Node::ref();
02522   if ( def )
02523     def->ref();
02524   if ( list1 )
02525     list1->ref();
02526   if ( list2 )
02527     list2->ref();
02528 }
02529 
02530 bool CaseBlockNode::deref()
02531 {
02532   if ( def && def->deref() )
02533     delete def;
02534   if ( list1 && list1->deref() )
02535     delete list1;
02536   if ( list2 && list2->deref() )
02537     delete list2;
02538   return Node::deref();
02539 }
02540 
02541 Value CaseBlockNode::evaluate(ExecState * /*exec*/) const
02542 {
02543   /* should never be called */
02544   assert(false);
02545   return Value();
02546 }
02547 
02548 // ECMA 12.11
02549 Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input) const
02550 {
02551   Value v;
02552   Completion res;
02553   ClauseListNode *a = list1, *b = list2;
02554   CaseClauseNode *clause;
02555 
02556     while (a) {
02557       clause = a->clause();
02558       a = a->next();
02559       v = clause->evaluate(exec);
02560       KJS_CHECKEXCEPTION
02561       if (strictEqual(exec, input, v)) {
02562     res = clause->evalStatements(exec);
02563     if (res.complType() != Normal)
02564       return res;
02565     while (a) {
02566       res = a->clause()->evalStatements(exec);
02567       if (res.complType() != Normal)
02568         return res;
02569       a = a->next();
02570     }
02571     break;
02572       }
02573     }
02574 
02575   while (b) {
02576     clause = b->clause();
02577     b = b->next();
02578     v = clause->evaluate(exec);
02579     KJS_CHECKEXCEPTION
02580     if (strictEqual(exec, input, v)) {
02581       res = clause->evalStatements(exec);
02582       if (res.complType() != Normal)
02583     return res;
02584       goto step18;
02585     }
02586   }
02587 
02588   // default clause
02589   if (def) {
02590     res = def->evalStatements(exec);
02591     if (res.complType() != Normal)
02592       return res;
02593   }
02594   b = list2;
02595  step18:
02596   while (b) {
02597     clause = b->clause();
02598     res = clause->evalStatements(exec);
02599     if (res.complType() != Normal)
02600       return res;
02601     b = b->next();
02602   }
02603 
02604   // bail out on error
02605   KJS_CHECKEXCEPTION
02606 
02607   return Completion(Normal);
02608 }
02609 
02610 void CaseBlockNode::processVarDecls(ExecState *exec)
02611 {
02612   if (list1)
02613     list1->processVarDecls(exec);
02614   if (def)
02615     def->processVarDecls(exec);
02616   if (list2)
02617     list2->processVarDecls(exec);
02618 }
02619 
02620 // ----------------------------- SwitchNode -----------------------------------
02621 
02622 void SwitchNode::ref()
02623 {
02624   StatementNode::ref();
02625   if ( expr )
02626     expr->ref();
02627   if ( block )
02628     block->ref();
02629 }
02630 
02631 bool SwitchNode::deref()
02632 {
02633   if ( expr && expr->deref() )
02634     delete expr;
02635   if ( block && block->deref() )
02636     delete block;
02637   return StatementNode::deref();
02638 }
02639 
02640 // ECMA 12.11
02641 Completion SwitchNode::execute(ExecState *exec)
02642 {
02643   KJS_BREAKPOINT;
02644 
02645   Value v = expr->evaluate(exec);
02646   KJS_CHECKEXCEPTION
02647   exec->context().imp()->seenLabels()->pushSwitch();
02648   Completion res = block->evalBlock(exec,v);
02649   exec->context().imp()->seenLabels()->popSwitch();
02650 
02651   if ((res.complType() == Break) && ls.contains(res.target()))
02652     return Completion(Normal, res.value());
02653   else
02654     return res;
02655 }
02656 
02657 void SwitchNode::processVarDecls(ExecState *exec)
02658 {
02659   block->processVarDecls(exec);
02660 }
02661 
02662 // ----------------------------- LabelNode ------------------------------------
02663 
02664 void LabelNode::ref()
02665 {
02666   StatementNode::ref();
02667   if ( statement )
02668     statement->ref();
02669 }
02670 
02671 bool LabelNode::deref()
02672 {
02673   if ( statement && statement->deref() )
02674     delete statement;
02675   return StatementNode::deref();
02676 }
02677 
02678 // ECMA 12.12
02679 Completion LabelNode::execute(ExecState *exec)
02680 {
02681   Completion e;
02682 
02683   if (!exec->context().imp()->seenLabels()->push(label)) {
02684     return Completion( Throw,
02685                        throwError(exec, SyntaxError, "Duplicated label %s found.", label));
02686   };
02687   e = statement->execute(exec);
02688   exec->context().imp()->seenLabels()->pop();
02689 
02690   if ((e.complType() == Break) && (e.target() == label))
02691     return Completion(Normal, e.value());
02692   else
02693     return e;
02694 }
02695 
02696 void LabelNode::processVarDecls(ExecState *exec)
02697 {
02698   statement->processVarDecls(exec);
02699 }
02700 
02701 // ----------------------------- ThrowNode ------------------------------------
02702 
02703 void ThrowNode::ref()
02704 {
02705   StatementNode::ref();
02706   if ( expr )
02707     expr->ref();
02708 }
02709 
02710 bool ThrowNode::deref()
02711 {
02712   if ( expr && expr->deref() )
02713     delete expr;
02714   return StatementNode::deref();
02715 }
02716 
02717 // ECMA 12.13
02718 Completion ThrowNode::execute(ExecState *exec)
02719 {
02720   KJS_BREAKPOINT;
02721 
02722   Value v = expr->evaluate(exec);
02723   KJS_CHECKEXCEPTION
02724 
02725   // bail out on error
02726   KJS_CHECKEXCEPTION
02727 
02728   Debugger *dbg = exec->interpreter()->imp()->debugger();
02729   if (dbg)
02730     dbg->exception(exec,v,exec->context().imp()->inTryCatch());
02731 
02732   return Completion(Throw, v);
02733 }
02734 
02735 // ----------------------------- CatchNode ------------------------------------
02736 
02737 void CatchNode::ref()
02738 {
02739   StatementNode::ref();
02740   if ( block )
02741     block->ref();
02742 }
02743 
02744 bool CatchNode::deref()
02745 {
02746   if ( block && block->deref() )
02747     delete block;
02748   return StatementNode::deref();
02749 }
02750 
02751 Completion CatchNode::execute(ExecState * /*exec*/)
02752 {
02753   // should never be reached. execute(exec, arg) is used instead
02754   assert(0L);
02755   return Completion();
02756 }
02757 
02758 // ECMA 12.14
02759 Completion CatchNode::execute(ExecState *exec, const Value &arg)
02760 {
02761   /* TODO: correct ? Not part of the spec */
02762 
02763   exec->clearException();
02764 
02765   Object obj(new ObjectImp());
02766   obj.put(exec, ident, arg, DontDelete);
02767   exec->context().imp()->pushScope(obj);
02768   Completion c = block->execute(exec);
02769   exec->context().imp()->popScope();
02770 
02771   return c;
02772 }
02773 
02774 void CatchNode::processVarDecls(ExecState *exec)
02775 {
02776   block->processVarDecls(exec);
02777 }
02778 
02779 // ----------------------------- FinallyNode ----------------------------------
02780 
02781 void FinallyNode::ref()
02782 {
02783   StatementNode::ref();
02784   if ( block )
02785     block->ref();
02786 }
02787 
02788 bool FinallyNode::deref()
02789 {
02790   if ( block && block->deref() )
02791     delete block;
02792   return StatementNode::deref();
02793 }
02794 
02795 // ECMA 12.14
02796 Completion FinallyNode::execute(ExecState *exec)
02797 {
02798   return block->execute(exec);
02799 }
02800 
02801 void FinallyNode::processVarDecls(ExecState *exec)
02802 {
02803   block->processVarDecls(exec);
02804 }
02805 
02806 // ----------------------------- TryNode --------------------------------------
02807 
02808 void TryNode::ref()
02809 {
02810   StatementNode::ref();
02811   if ( block )
02812     block->ref();
02813   if ( _final )
02814     _final->ref();
02815   if ( _catch )
02816     _catch->ref();
02817 }
02818 
02819 bool TryNode::deref()
02820 {
02821   if ( block && block->deref() )
02822     delete block;
02823   if ( _final && _final->deref() )
02824     delete _final;
02825   if ( _catch && _catch->deref() )
02826     delete _catch;
02827   return StatementNode::deref();
02828 }
02829 
02830 // ECMA 12.14
02831 Completion TryNode::execute(ExecState *exec)
02832 {
02833   KJS_BREAKPOINT;
02834 
02835   Completion c, c2;
02836 
02837   if (_catch)
02838     exec->context().imp()->pushTryCatch();
02839   c = block->execute(exec);
02840   if (_catch)
02841     exec->context().imp()->popTryCatch();
02842 
02843   if (!_final) {
02844     if (c.complType() != Throw)
02845       return c;
02846     return _catch->execute(exec,c.value());
02847   }
02848 
02849   if (!_catch) {
02850     Value exception = exec->_exception;
02851     exec->_exception = Value();
02852 
02853     c2 = _final->execute(exec);
02854 
02855     if (!exec->hadException() && c2.complType() != Throw)
02856       exec->_exception = exception;
02857 
02858     return (c2.complType() == Normal) ? c : c2;
02859   }
02860 
02861   if (c.complType() == Throw)
02862     c = _catch->execute(exec,c.value());
02863 
02864   c2 = _final->execute(exec);
02865   return (c2.complType() == Normal) ? c : c2;
02866 }
02867 
02868 void TryNode::processVarDecls(ExecState *exec)
02869 {
02870   block->processVarDecls(exec);
02871   if (_final)
02872     _final->processVarDecls(exec);
02873   if (_catch)
02874     _catch->processVarDecls(exec);
02875 }
02876 
02877 // ----------------------------- ParameterNode --------------------------------
02878 
02879 void ParameterNode::ref()
02880 {
02881   for (ParameterNode *n = this; n; n = n->next)
02882     n->Node::ref();
02883 }
02884 
02885 bool ParameterNode::deref()
02886 {
02887   ParameterNode *next;
02888   for (ParameterNode *n = this; n; n = next) {
02889     next = n->next;
02890     if (n != this && n->Node::deref())
02891       delete n;
02892   }
02893   return Node::deref();
02894 }
02895 
02896 // ECMA 13
02897 Value ParameterNode::evaluate(ExecState * /*exec*/) const
02898 {
02899   return Undefined();
02900 }
02901 
02902 // ----------------------------- FunctionBodyNode -----------------------------
02903 
02904 
02905 FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
02906   : BlockNode(s), program(false)
02907 {
02908   //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
02909 }
02910 
02911 void FunctionBodyNode::processFuncDecl(ExecState *exec)
02912 {
02913   if (source)
02914     source->processFuncDecl(exec);
02915 }
02916 
02917 Completion FunctionBodyNode::execute(ExecState *exec)
02918 {
02919   Completion c = BlockNode::execute(exec);
02920   if (program && c.complType() == ReturnValue)
02921     return Completion(Throw,
02922               throwError(exec, SyntaxError, "return outside of function body"));
02923   else
02924     return c;
02925 }
02926 
02927 // ----------------------------- FuncDeclNode ---------------------------------
02928 
02929 void FuncDeclNode::ref()
02930 {
02931   StatementNode::ref();
02932   if ( param )
02933     param->ref();
02934   if ( body )
02935     body->ref();
02936 }
02937 
02938 bool FuncDeclNode::deref()
02939 {
02940   if ( param && param->deref() )
02941     delete param;
02942   if ( body && body->deref() )
02943     delete body;
02944   return StatementNode::deref();
02945 }
02946 
02947 // ECMA 13
02948 void FuncDeclNode::processFuncDecl(ExecState *exec)
02949 {
02950   ContextImp *ctx = exec->context().imp();
02951   // TODO: let this be an object with [[Class]] property "Function"
02952   FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
02953   Object func(fimp); // protect from GC
02954 
02955   //  Value proto = exec->interpreter()->builtinObject().construct(exec,List::empty());
02956   List empty;
02957   Object proto = exec->interpreter()->builtinObject().construct(exec,empty);
02958   proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
02959   func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
02960 
02961   int plen = 0;
02962   for(const ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
02963     fimp->addParameter(p->ident());
02964 
02965   func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
02966 
02967 #ifdef KJS_VERBOSE
02968   fprintf(stderr,"KJS: new function %s in %p\n", ident.ustring().cstring().c_str(), ctx->variableObject().imp());
02969 #endif
02970   if (exec->_context->type() == EvalCode)
02971     ctx->variableObject().put(exec,ident,func,Internal);
02972   else
02973     ctx->variableObject().put(exec,ident,func,DontDelete|Internal);
02974 
02975   if (body) {
02976     // hack the scope so that the function gets put as a property of func, and it's scope
02977     // contains the func as well as our current scope
02978     Object oldVar = ctx->variableObject();
02979     ctx->setVariableObject(func);
02980     ctx->pushScope(func);
02981     body->processFuncDecl(exec);
02982     ctx->popScope();
02983     ctx->setVariableObject(oldVar);
02984   }
02985 }
02986 
02987 // ----------------------------- FuncExprNode ---------------------------------
02988 
02989 void FuncExprNode::ref()
02990 {
02991   Node::ref();
02992   if ( param )
02993     param->ref();
02994   if ( body )
02995     body->ref();
02996 }
02997 
02998 bool FuncExprNode::deref()
02999 {
03000   if ( param && param->deref() )
03001     delete param;
03002   if ( body && body->deref() )
03003     delete body;
03004   return Node::deref();
03005 }
03006 
03007 
03008 // ECMA 13
03009 Value FuncExprNode::evaluate(ExecState *exec) const
03010 {
03011   FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain());
03012   Value ret(fimp);
03013   List empty;
03014   Value proto = exec->interpreter()->builtinObject().construct(exec,empty);
03015   fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
03016 
03017   for(const ParameterNode *p = param; p != 0L; p = p->nextParam())
03018     fimp->addParameter(p->ident());
03019 
03020   return ret;
03021 }
03022 
03023 // ----------------------------- SourceElementsNode ---------------------------
03024 
03025 SourceElementsNode::SourceElementsNode(StatementNode *s1)
03026 {
03027   element = s1;
03028   elements = this;
03029   setLoc(s1->firstLine(),s1->lastLine(),s1->code());
03030 }
03031 
03032 SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
03033 {
03034   elements = s1->elements;
03035   s1->elements = this;
03036   element = s2;
03037   setLoc(s1->firstLine(),s2->lastLine(),s1->code());
03038 }
03039 
03040 void SourceElementsNode::ref()
03041 {
03042   for (SourceElementsNode *n = this; n; n = n->elements) {
03043     n->Node::ref();
03044     if (n->element)
03045       n->element->ref();
03046   }
03047 }
03048 
03049 bool SourceElementsNode::deref()
03050 {
03051   SourceElementsNode *next;
03052   for (SourceElementsNode *n = this; n; n = next) {
03053     next = n->elements;
03054     if (n->element && n->element->deref())
03055       delete n->element;
03056     if (n != this && n->Node::deref())
03057       delete n;
03058   }
03059   return StatementNode::deref();
03060 }
03061 
03062 // ECMA 14
03063 Completion SourceElementsNode::execute(ExecState *exec)
03064 {
03065   KJS_CHECKEXCEPTION
03066 
03067   Completion c1 = element->execute(exec);
03068   KJS_CHECKEXCEPTION;
03069   if (c1.complType() != Normal)
03070     return c1;
03071 
03072   for (SourceElementsNode *node = elements; node; node = node->elements) {
03073     Completion c2 = node->element->execute(exec);
03074     if (c2.complType() != Normal)
03075       return c2;
03076     // The spec says to return c2 here, but it seems that mozilla returns c1 if
03077     // c2 doesn't have a value
03078     if (c2.value().isValid())
03079       c1 = c2;
03080   }
03081 
03082   return c1;
03083 }
03084 
03085 // ECMA 14
03086 void SourceElementsNode::processFuncDecl(ExecState *exec)
03087 {
03088   for (SourceElementsNode *n = this; n; n = n->elements)
03089     n->element->processFuncDecl(exec);
03090 }
03091 
03092 void SourceElementsNode::processVarDecls(ExecState *exec)
03093 {
03094   for (SourceElementsNode *n = this; n; n = n->elements)
03095     n->element->processVarDecls(exec);
03096 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Jul 21 13:14:14 2006 by doxygen 1.4.0 written by Dimitri van Heesch, © 1997-2003