kjs Library API Documentation

nodes.cpp

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