source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 3313

Last change on this file since 3313 was 3313, checked in by darin, 22 years ago

Reviewed by Maciej.

  • turned more recursion into iteration, and fixed some backwards stuff
  • kjs/grammar.y: Use the normal idiom for CaseClauses and FormalParameterList rather than using append().
  • kjs/grammar.cpp: Regenerated.
  • kjs/nodes.h: Change ClauseListNode and ParameterNode to use the normal idiom, and got rid of append methods. Also added friend declarations and calls to reverseList().
  • kjs/nodes.cpp: (StatListNode::ref): Iteration, not recursion. (StatListNode::deref): Iteration, not recursion. (StatListNode::execute): Iteration, not recursion. (StatListNode::processVarDecls): Iteration, not recursion. (CaseClauseNode::reverseList): Added. (ClauseListNode::ref): Iteration, not recursion. (ClauseListNode::deref): Iteration, not recursion. (ClauseListNode::processVarDecls): Iteration, not recursion. (CaseBlockNode::reverseLists): Added. (ParameterNode::ref): Iteration, not recursion. (ParameterNode::deref): Iteration, not recursion. (FuncDeclNode::reverseParameterList): Added. (FuncExprNode::reverseParameterList): Added. (SourceElementsNode::ref): Iteration, not recursion. (SourceElementsNode::deref): Iteration, not recursion. (SourceElementsNode::execute): Use variable name of n to match other functions. (SourceElementsNode::processFuncDecl): Ditto. (SourceElementsNode::processVarDecls): Ditto.
  • kjs/nodes2string.cpp: (SourceStream::operator<<): Used a switch statement for a bit of added clarity. (ElementNode::streamTo): Iteration, not recursion. (PropertyValueNode::streamTo): Iteration, not recursion. (ArgumentListNode::streamTo): Iteration, not recursion. (StatListNode::streamTo): Iteration, not recursion, and fixed order. (VarDeclListNode::streamTo): Iteration, not recursion. (ClauseListNode::streamTo): Used for statement to match other functions. (CaseBlockNode::streamTo): Used for statement to match other functions. (ParameterNode::streamTo): Iteration, not recursion. (SourceElementsNode::streamTo): Iteration, not recursion, and fixed order that has been backwards since I changed how this works in nodes.cpp.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.0 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2002 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2002 Apple Computer, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 *
23 */
24
25#include "nodes.h"
26
27//#include <iostream>
28#include <math.h>
29#include <assert.h>
30#ifdef KJS_DEBUG_MEM
31#include <stdio.h>
32#include <typeinfo>
33#endif
34
35#include "collector.h"
36#include "context.h"
37#include "debugger.h"
38#include "function_object.h"
39#include "internal.h"
40#include "value.h"
41#include "object.h"
42#include "types.h"
43#include "interpreter.h"
44#include "lexer.h"
45#include "operations.h"
46#include "ustring.h"
47
48using namespace KJS;
49
50#define KJS_BREAKPOINT \
51 if (!hitStatement(exec)) \
52 return Completion(Normal);
53
54#define KJS_ABORTPOINT \
55 if (exec->interpreter()->imp()->debugger() && \
56 exec->interpreter()->imp()->debugger()->imp()->aborted()) \
57 return Completion(Normal);
58
59#define KJS_CHECKEXCEPTION \
60 if (exec->hadException()) \
61 return Completion(Throw, exec->exception()); \
62 if (Collector::outOfMemory()) \
63 return Completion(Throw, Error::create(exec,GeneralError,"Out of memory"));
64
65#define KJS_CHECKEXCEPTIONVALUE \
66 if (exec->hadException()) \
67 return exec->exception(); \
68 if (Collector::outOfMemory()) \
69 return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
70
71#define KJS_CHECKEXCEPTIONREFERENCE \
72 if (exec->hadException()) \
73 return Reference::makeValueReference(Undefined());; \
74 if (Collector::outOfMemory()) \
75 return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION
76
77#define KJS_CHECKEXCEPTIONLIST \
78 if (exec->hadException()) \
79 return List(); \
80 if (Collector::outOfMemory()) \
81 return List(); // will be picked up by KJS_CHECKEXCEPTION
82
83#ifdef KJS_DEBUG_MEM
84std::list<Node *> * Node::s_nodes = 0L;
85#endif
86
87// ------------------------------ Node -----------------------------------------
88
89Node::Node()
90{
91 line = Lexer::curr()->lineNo();
92 refcount = 0;
93#ifdef KJS_DEBUG_MEM
94 if (!s_nodes)
95 s_nodes = new std::list<Node *>;
96 s_nodes->push_back(this);
97#endif
98}
99
100Node::~Node()
101{
102#ifdef KJS_DEBUG_MEM
103 s_nodes->remove( this );
104#endif
105}
106
107Reference Node::evaluateReference(ExecState *exec)
108{
109 Value v = evaluate(exec);
110 KJS_CHECKEXCEPTIONREFERENCE
111 return Reference::makeValueReference(v);
112}
113
114#ifdef KJS_DEBUG_MEM
115void Node::finalCheck()
116{
117 fprintf( stderr, "Node::finalCheck(): list count : %d\n", (int)s_nodes.size() );
118 std::list<Node *>::iterator it = s_nodes->begin();
119 for ( uint i = 0; it != s_nodes->end() ; ++it, ++i )
120 fprintf( stderr, "[%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount );
121 delete s_nodes;
122 s_nodes = 0L;
123}
124#endif
125
126Value Node::throwError(ExecState *exec, ErrorType e, const char *msg)
127{
128 Object err = Error::create(exec, e, msg, lineNo(), sourceId());
129 exec->setException(err);
130 return err;
131}
132
133// ------------------------------ StatementNode --------------------------------
134StatementNode::StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false)
135{
136}
137
138void StatementNode::setLoc(int line0, int line1, int sourceId)
139{
140 l0 = line0;
141 l1 = line1;
142 sid = sourceId;
143}
144
145// return true if the debugger wants us to stop at this point
146bool StatementNode::hitStatement(ExecState *exec)
147{
148 Debugger *dbg = exec->interpreter()->imp()->debugger();
149 if (dbg)
150 return dbg->atStatement(exec,sid,l0,l1);
151 else
152 return true; // continue
153}
154
155// return true if the debugger wants us to stop at this point
156bool StatementNode::abortStatement(ExecState *exec)
157{
158 Debugger *dbg = exec->interpreter()->imp()->debugger();
159 if (dbg)
160 return dbg->imp()->aborted();
161 else
162 return false;
163}
164
165void StatementNode::processFuncDecl(ExecState *exec)
166{
167}
168
169// ------------------------------ NullNode -------------------------------------
170
171Value NullNode::evaluate(ExecState */*exec*/)
172{
173 return Null();
174}
175
176// ------------------------------ BooleanNode ----------------------------------
177
178Value BooleanNode::evaluate(ExecState */*exec*/)
179{
180 return Boolean(value);
181}
182
183// ------------------------------ NumberNode -----------------------------------
184
185Value NumberNode::evaluate(ExecState */*exec*/)
186{
187 return Number(value);
188}
189
190// ------------------------------ StringNode -----------------------------------
191
192Value StringNode::evaluate(ExecState */*exec*/)
193{
194 return String(value);
195}
196
197// ------------------------------ RegExpNode -----------------------------------
198
199Value RegExpNode::evaluate(ExecState *exec)
200{
201 List list;
202 String p(pattern);
203 String f(flags);
204 list.append(p);
205 list.append(f);
206
207 Object reg = exec->interpreter()->imp()->builtinRegExp();
208 return reg.construct(exec,list);
209}
210
211// ------------------------------ ThisNode -------------------------------------
212
213// ECMA 11.1.1
214Value ThisNode::evaluate(ExecState *exec)
215{
216 return exec->context().imp()->thisValue();
217}
218
219// ------------------------------ ResolveNode ----------------------------------
220
221// ECMA 11.1.2 & 10.1.4
222Value ResolveNode::evaluate(ExecState *exec)
223{
224 return evaluateReference(exec).getValue(exec);
225}
226
227Reference ResolveNode::evaluateReference(ExecState *exec)
228{
229 ScopeChain chain = exec->context().imp()->scopeChain();
230
231 while (!chain.isEmpty()) {
232 ObjectImp *o = chain.top();
233
234 //cout << "Resolve: looking at '" << ident.ascii() << "'"
235 // << " in " << (void*)o << " " << o->classInfo()->className << endl;
236 if (o->hasProperty(exec,ident)) {
237 //cout << "Resolve: FOUND '" << ident.ascii() << "'"
238 // << " in " << (void*)o << " " << o->classInfo()->className << endl;
239 return Reference(o, ident);
240 }
241
242 chain.pop();
243 }
244
245 // identifier not found
246 //cout << "Resolve: didn't find '" << ident.ascii() << "'" << endl;
247 return Reference(Null(), ident);
248}
249
250
251// ------------------------------ GroupNode ------------------------------------
252
253void GroupNode::ref()
254{
255 Node::ref();
256 if ( group )
257 group->ref();
258}
259
260bool GroupNode::deref()
261{
262 if ( group && group->deref() )
263 delete group;
264 return Node::deref();
265}
266
267// ECMA 11.1.6
268Value GroupNode::evaluate(ExecState *exec)
269{
270 return group->evaluate(exec);
271}
272
273// ------------------------------ ElementNode ----------------------------------
274
275void ElementNode::ref()
276{
277 for (ElementNode *n = this; n; n = n->list) {
278 n->Node::ref();
279 if (n->node)
280 n->node->ref();
281 }
282}
283
284bool ElementNode::deref()
285{
286 ElementNode *next;
287 for (ElementNode *n = this; n; n = next) {
288 next = n->list;
289 if (n->node && n->node->deref())
290 delete n->node;
291 if (n != this && n->Node::deref())
292 delete n;
293 }
294 return Node::deref();
295}
296
297// ECMA 11.1.4
298Value ElementNode::evaluate(ExecState *exec)
299{
300 Object array = exec->interpreter()->builtinArray().construct(exec, List::empty());
301 int length = 0;
302 for (ElementNode *n = this; n; n = n->list) {
303 Value val = n->node->evaluate(exec);
304 KJS_CHECKEXCEPTIONVALUE
305 length += n->elision;
306 array.put(exec, length++, val);
307 }
308 return array;
309}
310
311// ------------------------------ ArrayNode ------------------------------------
312
313void ArrayNode::reverseElementList()
314{
315 ElementNode *head = 0;
316 ElementNode *next;
317 for (ElementNode *n = element; n; n = next) {
318 next = n->list;
319 n->list = head;
320 head = n;
321 }
322 element = head;
323}
324
325void ArrayNode::ref()
326{
327 Node::ref();
328 if ( element )
329 element->ref();
330}
331
332bool ArrayNode::deref()
333{
334 if ( element && element->deref() )
335 delete element;
336 return Node::deref();
337}
338
339// ECMA 11.1.4
340Value ArrayNode::evaluate(ExecState *exec)
341{
342 Object array;
343 int length;
344
345 if (element) {
346 array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
347 KJS_CHECKEXCEPTIONVALUE
348 length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0;
349 } else {
350 Value newArr = exec->interpreter()->builtinArray().construct(exec,List::empty());
351 array = Object(static_cast<ObjectImp*>(newArr.imp()));
352 length = 0;
353 }
354
355 if (opt)
356 array.put(exec,lengthPropertyName, Number(elision + length), DontEnum | DontDelete);
357
358 return array;
359}
360
361// ------------------------------ ObjectLiteralNode ----------------------------
362
363void ObjectLiteralNode::reverseList()
364{
365 PropertyValueNode *head = 0;
366 PropertyValueNode *next;
367 for (PropertyValueNode *n = list; n; n = next) {
368 next = n->list;
369 n->list = head;
370 head = n;
371 }
372 list = head;
373}
374
375void ObjectLiteralNode::ref()
376{
377 Node::ref();
378 if ( list )
379 list->ref();
380}
381
382bool ObjectLiteralNode::deref()
383{
384 if ( list && list->deref() )
385 delete list;
386 return Node::deref();
387}
388
389// ECMA 11.1.5
390Value ObjectLiteralNode::evaluate(ExecState *exec)
391{
392 if (list)
393 return list->evaluate(exec);
394
395 return exec->interpreter()->builtinObject().construct(exec,List::empty());
396}
397
398// ------------------------------ PropertyValueNode ----------------------------
399
400void PropertyValueNode::ref()
401{
402 for (PropertyValueNode *n = this; n; n = n->list) {
403 n->Node::ref();
404 if (n->name)
405 n->name->ref();
406 if (n->assign)
407 n->assign->ref();
408 }
409}
410
411bool PropertyValueNode::deref()
412{
413 PropertyValueNode *next;
414 for (PropertyValueNode *n = this; n; n = next) {
415 next = n->list;
416 if ( n->name && n->name->deref() )
417 delete n->name;
418 if ( n->assign && n->assign->deref() )
419 delete n->assign;
420 if (n != this && n->Node::deref() )
421 delete n;
422 }
423 return Node::deref();
424}
425
426// ECMA 11.1.5
427Value PropertyValueNode::evaluate(ExecState *exec)
428{
429 Object obj = exec->interpreter()->builtinObject().construct(exec, List::empty());
430
431 for (PropertyValueNode *p = this; p; p = p->list) {
432 Value n = p->name->evaluate(exec);
433 KJS_CHECKEXCEPTIONVALUE
434 Value v = p->assign->evaluate(exec);
435 KJS_CHECKEXCEPTIONVALUE
436
437 obj.put(exec, Identifier(n.toString(exec)), v);
438 }
439
440 return obj;
441}
442
443// ------------------------------ PropertyNode ---------------------------------
444
445// ECMA 11.1.5
446Value PropertyNode::evaluate(ExecState */*exec*/)
447{
448 Value s;
449
450 if (str.isNull()) {
451 s = String(UString::from(numeric));
452 } else {
453 s = String(str.ustring());
454 }
455
456 return s;
457}
458
459// ------------------------------ AccessorNode1 --------------------------------
460
461void AccessorNode1::ref()
462{
463 Node::ref();
464 if ( expr1 )
465 expr1->ref();
466 if ( expr2 )
467 expr2->ref();
468}
469
470bool AccessorNode1::deref()
471{
472 if ( expr1 && expr1->deref() )
473 delete expr1;
474 if ( expr2 && expr2->deref() )
475 delete expr2;
476 return Node::deref();
477}
478
479// ECMA 11.2.1a
480Value AccessorNode1::evaluate(ExecState *exec)
481{
482 return evaluateReference(exec).getValue(exec);
483}
484
485Reference AccessorNode1::evaluateReference(ExecState *exec)
486{
487 Value v1 = expr1->evaluate(exec);
488 KJS_CHECKEXCEPTIONREFERENCE
489 Value v2 = expr2->evaluate(exec);
490 KJS_CHECKEXCEPTIONREFERENCE
491 Object o = v1.toObject(exec);
492 unsigned i;
493 if (v2.toUInt32(i))
494 return Reference(o, i);
495 String s = v2.toString(exec);
496 return Reference(o, Identifier(s.value()));
497}
498
499
500// ------------------------------ AccessorNode2 --------------------------------
501
502void AccessorNode2::ref()
503{
504 Node::ref();
505 if ( expr )
506 expr->ref();
507}
508
509bool AccessorNode2::deref()
510{
511 if ( expr && expr->deref() )
512 delete expr;
513 return Node::deref();
514}
515
516// ECMA 11.2.1b
517Value AccessorNode2::evaluate(ExecState *exec)
518{
519 return evaluateReference(exec).getValue(exec);
520}
521
522Reference AccessorNode2::evaluateReference(ExecState *exec)
523{
524 Value v = expr->evaluate(exec);
525 KJS_CHECKEXCEPTIONREFERENCE
526 Object o = v.toObject(exec);
527 return Reference(o, ident);
528}
529
530// ------------------------------ ArgumentListNode -----------------------------
531
532ArgumentListNode::ArgumentListNode(Node *e) : list(0L), expr(e)
533{
534}
535
536ArgumentListNode::ArgumentListNode(ArgumentListNode *l, Node *e)
537 : list(l), expr(e)
538{
539}
540
541void ArgumentListNode::ref()
542{
543 for (ArgumentListNode *n = this; n; n = n->list) {
544 n->Node::ref();
545 if (n->expr)
546 n->expr->ref();
547 }
548}
549
550bool ArgumentListNode::deref()
551{
552 ArgumentListNode *next;
553 for (ArgumentListNode *n = this; n; n = next) {
554 next = n->list;
555 if (n->expr && n->expr->deref())
556 delete n->expr;
557 if (n != this && n->Node::deref())
558 delete n;
559 }
560 return Node::deref();
561}
562
563Value ArgumentListNode::evaluate(ExecState */*exec*/)
564{
565 assert(0);
566 return Value(); // dummy, see evaluateList()
567}
568
569// ECMA 11.2.4
570List ArgumentListNode::evaluateList(ExecState *exec)
571{
572 List l;
573
574 for (ArgumentListNode *n = this; n; n = n->list) {
575 Value v = n->expr->evaluate(exec);
576 KJS_CHECKEXCEPTIONLIST
577 l.append(v);
578 }
579
580 return l;
581}
582
583// ------------------------------ ArgumentsNode --------------------------------
584
585void ArgumentsNode::reverseList()
586{
587 ArgumentListNode *head = 0;
588 ArgumentListNode *next;
589 for (ArgumentListNode *n = list; n; n = next) {
590 next = n->list;
591 n->list = head;
592 head = n;
593 }
594 list = head;
595}
596
597void ArgumentsNode::ref()
598{
599 Node::ref();
600 if ( list )
601 list->ref();
602}
603
604bool ArgumentsNode::deref()
605{
606 if ( list && list->deref() )
607 delete list;
608 return Node::deref();
609}
610
611Value ArgumentsNode::evaluate(ExecState */*exec*/)
612{
613 assert(0);
614 return Value(); // dummy, see evaluateList()
615}
616
617// ECMA 11.2.4
618List ArgumentsNode::evaluateList(ExecState *exec)
619{
620 if (!list)
621 return List();
622
623 return list->evaluateList(exec);
624}
625
626// ------------------------------ NewExprNode ----------------------------------
627
628// ECMA 11.2.2
629
630void NewExprNode::ref()
631{
632 Node::ref();
633 if ( expr )
634 expr->ref();
635 if ( args )
636 args->ref();
637}
638
639bool NewExprNode::deref()
640{
641 if ( expr && expr->deref() )
642 delete expr;
643 if ( args && args->deref() )
644 delete args;
645 return Node::deref();
646}
647
648Value NewExprNode::evaluate(ExecState *exec)
649{
650 Value v = expr->evaluate(exec);
651 KJS_CHECKEXCEPTIONVALUE
652
653 List argList;
654 if (args) {
655 argList = args->evaluateList(exec);
656 KJS_CHECKEXCEPTIONVALUE
657 }
658
659 if (v.type() != ObjectType) {
660 return throwError(exec, TypeError, "Value used with new is not object.");
661 }
662
663 Object constr = Object(static_cast<ObjectImp*>(v.imp()));
664 if (!constr.implementsConstruct()) {
665 return throwError(exec, TypeError, "Value asked to construct is not a constructor.");
666 }
667
668 Value res = constr.construct(exec,argList);
669
670 return res;
671}
672
673// ------------------------------ FunctionCallNode -----------------------------
674
675void FunctionCallNode::ref()
676{
677 Node::ref();
678 if ( expr )
679 expr->ref();
680 if ( args )
681 args->ref();
682}
683
684bool FunctionCallNode::deref()
685{
686 if ( expr && expr->deref() )
687 delete expr;
688 if ( args && args->deref() )
689 delete args;
690 return Node::deref();
691}
692
693// ECMA 11.2.3
694Value FunctionCallNode::evaluate(ExecState *exec)
695{
696 Reference ref = expr->evaluateReference(exec);
697 KJS_CHECKEXCEPTIONVALUE
698
699 List argList = args->evaluateList(exec);
700
701 KJS_CHECKEXCEPTIONVALUE
702
703 Value v = ref.getValue(exec);
704
705 if (v.type() != ObjectType) {
706#ifndef NDEBUG
707 printInfo(exec, "WARNING: Failed function call attempt on", v, line);
708#endif
709 return throwError(exec, TypeError, "Value is not object. Cannot be called.");
710 }
711
712 Object func = Object(static_cast<ObjectImp*>(v.imp()));
713
714 if (!func.implementsCall()) {
715#ifndef NDEBUG
716 printInfo(exec, "Failed function call attempt on", v, line);
717#endif
718 return throwError(exec, TypeError, "Object does not allow calls.");
719 }
720
721#if KJS_MAX_STACK > 0
722 static int depth = 0; // sum of all concurrent interpreters
723 if (++depth > KJS_MAX_STACK) {
724#ifndef NDEBUG
725 printInfo(exec, "Exceeded maximum function call depth", v, line);
726#endif
727 return throwError(exec, RangeError, "Exceeded maximum function call depth.");
728 }
729#endif
730
731 Value thisVal;
732 if (ref.isMutable())
733 thisVal = ref.getBase(exec);
734 else
735 thisVal = Null();
736
737 if (thisVal.type() == ObjectType &&
738 Object::dynamicCast(thisVal).inherits(&ActivationImp::info))
739 thisVal = Null();
740
741 if (thisVal.type() != ObjectType) {
742 // ECMA 11.2.3 says that in this situation the this value should be null.
743 // However, section 10.2.3 says that in the case where the value provided
744 // by the caller is null, the global object should be used. It also says
745 // that the section does not apply to interal functions, but for simplicity
746 // of implementation we use the global object anyway here. This guarantees
747 // that in host objects you always get a valid object for this.
748 // thisVal = Null();
749 thisVal = exec->interpreter()->globalObject();
750 }
751
752 Object thisObj = Object::dynamicCast(thisVal);
753 Value result = func.call(exec,thisObj, argList);
754
755#if KJS_MAX_STACK > 0
756 --depth;
757#endif
758
759 return result;
760}
761
762// ------------------------------ PostfixNode ----------------------------------
763
764void PostfixNode::ref()
765{
766 Node::ref();
767 if ( expr )
768 expr->ref();
769}
770
771bool PostfixNode::deref()
772{
773 if ( expr && expr->deref() )
774 delete expr;
775 return Node::deref();
776}
777
778// ECMA 11.3
779Value PostfixNode::evaluate(ExecState *exec)
780{
781 Reference ref = expr->evaluateReference(exec);
782 KJS_CHECKEXCEPTIONVALUE
783 Value v = ref.getValue(exec);
784 Number n = v.toNumber(exec);
785
786 double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
787 Value n2 = Number(newValue);
788
789 ref.putValue(exec,n2);
790
791 return n;
792}
793
794// ------------------------------ DeleteNode -----------------------------------
795
796void DeleteNode::ref()
797{
798 Node::ref();
799 if ( expr )
800 expr->ref();
801}
802
803bool DeleteNode::deref()
804{
805 if ( expr && expr->deref() )
806 delete expr;
807 return Node::deref();
808}
809
810// ECMA 11.4.1
811Value DeleteNode::evaluate(ExecState *exec)
812{
813 Reference ref = expr->evaluateReference(exec);
814 KJS_CHECKEXCEPTIONVALUE
815 return Boolean(ref.deleteValue(exec));
816}
817
818// ------------------------------ VoidNode -------------------------------------
819
820void VoidNode::ref()
821{
822 Node::ref();
823 if ( expr )
824 expr->ref();
825}
826
827bool VoidNode::deref()
828{
829 if ( expr && expr->deref() )
830 delete expr;
831 return Node::deref();
832}
833
834// ECMA 11.4.2
835Value VoidNode::evaluate(ExecState *exec)
836{
837 Value dummy1 = expr->evaluate(exec);
838 KJS_CHECKEXCEPTIONVALUE
839
840 return Undefined();
841}
842
843// ------------------------------ TypeOfNode -----------------------------------
844
845void TypeOfNode::ref()
846{
847 Node::ref();
848 if ( expr )
849 expr->ref();
850}
851
852bool TypeOfNode::deref()
853{
854 if ( expr && expr->deref() )
855 delete expr;
856 return Node::deref();
857}
858
859// ECMA 11.4.3
860Value TypeOfNode::evaluate(ExecState *exec)
861{
862 const char *s = 0L;
863 Reference ref = expr->evaluateReference(exec);
864 KJS_CHECKEXCEPTIONVALUE
865 if (ref.isMutable()) {
866 Value b = ref.getBase(exec);
867 if (b.type() == NullType)
868 return String("undefined");
869 }
870 Value v = ref.getValue(exec);
871 switch (v.type())
872 {
873 case UndefinedType:
874 s = "undefined";
875 break;
876 case NullType:
877 s = "object";
878 break;
879 case BooleanType:
880 s = "boolean";
881 break;
882 case NumberType:
883 s = "number";
884 break;
885 case StringType:
886 s = "string";
887 break;
888 default:
889 if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall())
890 s = "function";
891 else
892 s = "object";
893 break;
894 }
895
896 return String(s);
897}
898
899// ------------------------------ PrefixNode -----------------------------------
900
901void PrefixNode::ref()
902{
903 Node::ref();
904 if ( expr )
905 expr->ref();
906}
907
908bool PrefixNode::deref()
909{
910 if ( expr && expr->deref() )
911 delete expr;
912 return Node::deref();
913}
914
915// ECMA 11.4.4 and 11.4.5
916Value PrefixNode::evaluate(ExecState *exec)
917{
918 Reference ref = expr->evaluateReference(exec);
919 KJS_CHECKEXCEPTIONVALUE
920 Value v = ref.getValue(exec);
921 Number n = v.toNumber(exec);
922
923 double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
924 Value n2 = Number(newValue);
925
926 ref.putValue(exec,n2);
927
928 return n2;
929}
930
931// ------------------------------ UnaryPlusNode --------------------------------
932
933void UnaryPlusNode::ref()
934{
935 Node::ref();
936 if ( expr )
937 expr->ref();
938}
939
940bool UnaryPlusNode::deref()
941{
942 if ( expr && expr->deref() )
943 delete expr;
944 return Node::deref();
945}
946
947// ECMA 11.4.6
948Value UnaryPlusNode::evaluate(ExecState *exec)
949{
950 Value v = expr->evaluate(exec);
951 KJS_CHECKEXCEPTIONVALUE
952
953 return Number(v.toNumber(exec)); /* TODO: optimize */
954}
955
956// ------------------------------ NegateNode -----------------------------------
957
958void NegateNode::ref()
959{
960 Node::ref();
961 if ( expr )
962 expr->ref();
963}
964
965bool NegateNode::deref()
966{
967 if ( expr && expr->deref() )
968 delete expr;
969 return Node::deref();
970}
971
972// ECMA 11.4.7
973Value NegateNode::evaluate(ExecState *exec)
974{
975 Value v = expr->evaluate(exec);
976 KJS_CHECKEXCEPTIONVALUE
977 Number n = v.toNumber(exec);
978
979 double d = -n.value();
980
981 return Number(d);
982}
983
984// ------------------------------ BitwiseNotNode -------------------------------
985
986void BitwiseNotNode::ref()
987{
988 Node::ref();
989 if ( expr )
990 expr->ref();
991}
992
993bool BitwiseNotNode::deref()
994{
995 if ( expr && expr->deref() )
996 delete expr;
997 return Node::deref();
998}
999
1000// ECMA 11.4.8
1001Value BitwiseNotNode::evaluate(ExecState *exec)
1002{
1003 Value v = expr->evaluate(exec);
1004 KJS_CHECKEXCEPTIONVALUE
1005 int i32 = v.toInt32(exec);
1006
1007 return Number(~i32);
1008}
1009
1010// ------------------------------ LogicalNotNode -------------------------------
1011
1012void LogicalNotNode::ref()
1013{
1014 Node::ref();
1015 if ( expr )
1016 expr->ref();
1017}
1018
1019bool LogicalNotNode::deref()
1020{
1021 if ( expr && expr->deref() )
1022 delete expr;
1023 return Node::deref();
1024}
1025
1026// ECMA 11.4.9
1027Value LogicalNotNode::evaluate(ExecState *exec)
1028{
1029 Value v = expr->evaluate(exec);
1030 KJS_CHECKEXCEPTIONVALUE
1031 bool b = v.toBoolean(exec);
1032
1033 return Boolean(!b);
1034}
1035
1036// ------------------------------ MultNode -------------------------------------
1037
1038void MultNode::ref()
1039{
1040 Node::ref();
1041 if ( term1 )
1042 term1->ref();
1043 if ( term2 )
1044 term2->ref();
1045}
1046
1047bool MultNode::deref()
1048{
1049 if ( term1 && term1->deref() )
1050 delete term1;
1051 if ( term2 && term2->deref() )
1052 delete term2;
1053 return Node::deref();
1054}
1055
1056// ECMA 11.5
1057Value MultNode::evaluate(ExecState *exec)
1058{
1059 Value v1 = term1->evaluate(exec);
1060 KJS_CHECKEXCEPTIONVALUE
1061
1062 Value v2 = term2->evaluate(exec);
1063 KJS_CHECKEXCEPTIONVALUE
1064
1065 return mult(exec,v1, v2, oper);
1066}
1067
1068// ------------------------------ AddNode --------------------------------------
1069
1070void AddNode::ref()
1071{
1072 Node::ref();
1073 if ( term1 )
1074 term1->ref();
1075 if ( term2 )
1076 term2->ref();
1077}
1078
1079bool AddNode::deref()
1080{
1081 if ( term1 && term1->deref() )
1082 delete term1;
1083 if ( term2 && term2->deref() )
1084 delete term2;
1085 return Node::deref();
1086}
1087
1088// ECMA 11.6
1089Value AddNode::evaluate(ExecState *exec)
1090{
1091 Value v1 = term1->evaluate(exec);
1092 KJS_CHECKEXCEPTIONVALUE
1093
1094 Value v2 = term2->evaluate(exec);
1095 KJS_CHECKEXCEPTIONVALUE
1096
1097 return add(exec,v1, v2, oper);
1098}
1099
1100// ------------------------------ ShiftNode ------------------------------------
1101
1102void ShiftNode::ref()
1103{
1104 Node::ref();
1105 if ( term1 )
1106 term1->ref();
1107 if ( term2 )
1108 term2->ref();
1109}
1110
1111bool ShiftNode::deref()
1112{
1113 if ( term1 && term1->deref() )
1114 delete term1;
1115 if ( term2 && term2->deref() )
1116 delete term2;
1117 return Node::deref();
1118}
1119
1120// ECMA 11.7
1121Value ShiftNode::evaluate(ExecState *exec)
1122{
1123 Value v1 = term1->evaluate(exec);
1124 KJS_CHECKEXCEPTIONVALUE
1125 Value v2 = term2->evaluate(exec);
1126 KJS_CHECKEXCEPTIONVALUE
1127 unsigned int i2 = v2.toUInt32(exec);
1128 i2 &= 0x1f;
1129
1130 long result;
1131 switch (oper) {
1132 case OpLShift:
1133 result = v1.toInt32(exec) << i2;
1134 break;
1135 case OpRShift:
1136 result = v1.toInt32(exec) >> i2;
1137 break;
1138 case OpURShift:
1139 result = v1.toUInt32(exec) >> i2;
1140 break;
1141 default:
1142 assert(!"ShiftNode: unhandled switch case");
1143 result = 0L;
1144 }
1145
1146 return Number(static_cast<double>(result));
1147}
1148
1149// ------------------------------ RelationalNode -------------------------------
1150
1151void RelationalNode::ref()
1152{
1153 Node::ref();
1154 if ( expr1 )
1155 expr1->ref();
1156 if ( expr2 )
1157 expr2->ref();
1158}
1159
1160bool RelationalNode::deref()
1161{
1162 if ( expr1 && expr1->deref() )
1163 delete expr1;
1164 if ( expr2 && expr2->deref() )
1165 delete expr2;
1166 return Node::deref();
1167}
1168
1169// ECMA 11.8
1170Value RelationalNode::evaluate(ExecState *exec)
1171{
1172 Value v1 = expr1->evaluate(exec);
1173 KJS_CHECKEXCEPTIONVALUE
1174 Value v2 = expr2->evaluate(exec);
1175 KJS_CHECKEXCEPTIONVALUE
1176
1177 bool b;
1178 if (oper == OpLess || oper == OpGreaterEq) {
1179 int r = relation(exec, v1, v2);
1180 if (r < 0)
1181 b = false;
1182 else
1183 b = (oper == OpLess) ? (r == 1) : (r == 0);
1184 } else if (oper == OpGreater || oper == OpLessEq) {
1185 int r = relation(exec, v2, v1);
1186 if (r < 0)
1187 b = false;
1188 else
1189 b = (oper == OpGreater) ? (r == 1) : (r == 0);
1190 } else if (oper == OpIn) {
1191 // Is all of this OK for host objects?
1192 if (v2.type() != ObjectType)
1193 return throwError(exec, TypeError,
1194 "Used IN expression with non-object." );
1195 Object o2(static_cast<ObjectImp*>(v2.imp()));
1196 b = o2.hasProperty(exec, Identifier(v1.toString(exec)));
1197 } else {
1198 if (v2.type() != ObjectType)
1199 return throwError(exec, TypeError,
1200 "Used instanceof operator on non-object." );
1201
1202 Object o2(static_cast<ObjectImp*>(v2.imp()));
1203 if (!o2.implementsHasInstance()) {
1204 // According to the spec, only some types of objects "imlement" the [[HasInstance]] property.
1205 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
1206 // property. It seems that all object have the property, but not all implement it, so in this
1207 // case we return false (consistent with mozilla)
1208 return Boolean(false);
1209 // return throwError(exec, TypeError,
1210 // "Object does not implement the [[HasInstance]] method." );
1211 }
1212 return o2.hasInstance(exec, v1);
1213 }
1214
1215 return Boolean(b);
1216}
1217
1218// ------------------------------ EqualNode ------------------------------------
1219
1220void EqualNode::ref()
1221{
1222 Node::ref();
1223 if ( expr1 )
1224 expr1->ref();
1225 if ( expr2 )
1226 expr2->ref();
1227}
1228
1229bool EqualNode::deref()
1230{
1231 if ( expr1 && expr1->deref() )
1232 delete expr1;
1233 if ( expr2 && expr2->deref() )
1234 delete expr2;
1235 return Node::deref();
1236}
1237
1238// ECMA 11.9
1239Value EqualNode::evaluate(ExecState *exec)
1240{
1241 Value v1 = expr1->evaluate(exec);
1242 KJS_CHECKEXCEPTIONVALUE
1243 Value v2 = expr2->evaluate(exec);
1244 KJS_CHECKEXCEPTIONVALUE
1245
1246 bool result;
1247 if (oper == OpEqEq || oper == OpNotEq) {
1248 // == and !=
1249 bool eq = equal(exec,v1, v2);
1250 result = oper == OpEqEq ? eq : !eq;
1251 } else {
1252 // === and !==
1253 bool eq = strictEqual(exec,v1, v2);
1254 result = oper == OpStrEq ? eq : !eq;
1255 }
1256 return Boolean(result);
1257}
1258
1259// ------------------------------ BitOperNode ----------------------------------
1260
1261void BitOperNode::ref()
1262{
1263 Node::ref();
1264 if ( expr1 )
1265 expr1->ref();
1266 if ( expr2 )
1267 expr2->ref();
1268}
1269
1270bool BitOperNode::deref()
1271{
1272 if ( expr1 && expr1->deref() )
1273 delete expr1;
1274 if ( expr2 && expr2->deref() )
1275 delete expr2;
1276 return Node::deref();
1277}
1278
1279// ECMA 11.10
1280Value BitOperNode::evaluate(ExecState *exec)
1281{
1282 Value v1 = expr1->evaluate(exec);
1283 KJS_CHECKEXCEPTIONVALUE
1284 Value v2 = expr2->evaluate(exec);
1285 KJS_CHECKEXCEPTIONVALUE
1286 int i1 = v1.toInt32(exec);
1287 int i2 = v2.toInt32(exec);
1288 int result;
1289 if (oper == OpBitAnd)
1290 result = i1 & i2;
1291 else if (oper == OpBitXOr)
1292 result = i1 ^ i2;
1293 else
1294 result = i1 | i2;
1295
1296 return Number(result);
1297}
1298
1299// ------------------------------ BinaryLogicalNode ----------------------------
1300
1301void BinaryLogicalNode::ref()
1302{
1303 Node::ref();
1304 if ( expr1 )
1305 expr1->ref();
1306 if ( expr2 )
1307 expr2->ref();
1308}
1309
1310bool BinaryLogicalNode::deref()
1311{
1312 if ( expr1 && expr1->deref() )
1313 delete expr1;
1314 if ( expr2 && expr2->deref() )
1315 delete expr2;
1316 return Node::deref();
1317}
1318
1319// ECMA 11.11
1320Value BinaryLogicalNode::evaluate(ExecState *exec)
1321{
1322 Value v1 = expr1->evaluate(exec);
1323 KJS_CHECKEXCEPTIONVALUE
1324 bool b1 = v1.toBoolean(exec);
1325 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
1326 return v1;
1327
1328 Value v2 = expr2->evaluate(exec);
1329 KJS_CHECKEXCEPTIONVALUE
1330
1331 return v2;
1332}
1333
1334// ------------------------------ ConditionalNode ------------------------------
1335
1336void ConditionalNode::ref()
1337{
1338 Node::ref();
1339 if ( expr1 )
1340 expr1->ref();
1341 if ( expr2 )
1342 expr2->ref();
1343 if ( logical )
1344 logical->ref();
1345}
1346
1347bool ConditionalNode::deref()
1348{
1349 if ( expr1 && expr1->deref() )
1350 delete expr1;
1351 if ( expr2 && expr2->deref() )
1352 delete expr2;
1353 if ( logical && logical->deref() )
1354 delete logical;
1355 return Node::deref();
1356}
1357
1358// ECMA 11.12
1359Value ConditionalNode::evaluate(ExecState *exec)
1360{
1361 Value v = logical->evaluate(exec);
1362 KJS_CHECKEXCEPTIONVALUE
1363 bool b = v.toBoolean(exec);
1364
1365 if (b)
1366 v = expr1->evaluate(exec);
1367 else
1368 v = expr2->evaluate(exec);
1369 KJS_CHECKEXCEPTIONVALUE
1370
1371 return v;
1372}
1373
1374// ------------------------------ AssignNode -----------------------------------
1375
1376void AssignNode::ref()
1377{
1378 Node::ref();
1379 if ( left )
1380 left->ref();
1381 if ( expr )
1382 expr->ref();
1383}
1384
1385bool AssignNode::deref()
1386{
1387 if ( left && left->deref() )
1388 delete left;
1389 if ( expr && expr->deref() )
1390 delete expr;
1391 return Node::deref();
1392}
1393
1394// ECMA 11.13
1395Value AssignNode::evaluate(ExecState *exec)
1396{
1397 Reference l = left->evaluateReference(exec);
1398 KJS_CHECKEXCEPTIONVALUE
1399 Value e, v;
1400 if (oper == OpEqual) {
1401 v = expr->evaluate(exec);
1402 KJS_CHECKEXCEPTIONVALUE
1403 } else {
1404 Value v1 = l.getValue(exec);
1405 Value v2 = expr->evaluate(exec);
1406 KJS_CHECKEXCEPTIONVALUE
1407 int i1 = v1.toInt32(exec);
1408 int i2 = v2.toInt32(exec);
1409 unsigned int ui;
1410 switch (oper) {
1411 case OpMultEq:
1412 v = mult(exec, v1, v2, '*');
1413 break;
1414 case OpDivEq:
1415 v = mult(exec, v1, v2, '/');
1416 break;
1417 case OpPlusEq:
1418 v = add(exec, v1, v2, '+');
1419 break;
1420 case OpMinusEq:
1421 v = add(exec, v1, v2, '-');
1422 break;
1423 case OpLShift:
1424 v = Number(i1 <<= i2);
1425 break;
1426 case OpRShift:
1427 v = Number(i1 >>= i2);
1428 break;
1429 case OpURShift:
1430 ui = v1.toUInt32(exec);
1431 v = Number(ui >>= i2);
1432 break;
1433 case OpAndEq:
1434 v = Number(i1 &= i2);
1435 break;
1436 case OpXOrEq:
1437 v = Number(i1 ^= i2);
1438 break;
1439 case OpOrEq:
1440 v = Number(i1 |= i2);
1441 break;
1442 case OpModEq: {
1443 double d1 = v1.toNumber(exec);
1444 double d2 = v2.toNumber(exec);
1445 v = Number(fmod(d1,d2));
1446 }
1447 break;
1448 default:
1449 v = Undefined();
1450 }
1451 };
1452 l.putValue(exec,v);
1453
1454 KJS_CHECKEXCEPTIONVALUE
1455
1456 return v;
1457}
1458
1459// ------------------------------ CommaNode ------------------------------------
1460
1461void CommaNode::ref()
1462{
1463 Node::ref();
1464 if ( expr1 )
1465 expr1->ref();
1466 if ( expr2 )
1467 expr2->ref();
1468}
1469
1470bool CommaNode::deref()
1471{
1472 if ( expr1 && expr1->deref() )
1473 delete expr1;
1474 if ( expr2 && expr2->deref() )
1475 delete expr2;
1476 return Node::deref();
1477}
1478
1479// ECMA 11.14
1480Value CommaNode::evaluate(ExecState *exec)
1481{
1482 Value dummy = expr1->evaluate(exec);
1483 KJS_CHECKEXCEPTIONVALUE
1484 Value v = expr2->evaluate(exec);
1485 KJS_CHECKEXCEPTIONVALUE
1486
1487 return v;
1488}
1489
1490// ------------------------------ StatListNode ---------------------------------
1491
1492void StatListNode::ref()
1493{
1494 for (StatListNode *n = this; n; n = n->list) {
1495 n->Node::ref();
1496 if (n->statement)
1497 n->statement->ref();
1498 }
1499}
1500
1501bool StatListNode::deref()
1502{
1503 StatListNode *next;
1504 for (StatListNode *n = this; n; n = next) {
1505 next = n->list;
1506 if (n->statement && n->statement->deref())
1507 delete n->statement;
1508 if (n != this && n->Node::deref())
1509 delete n;
1510 }
1511 return Node::deref();
1512}
1513
1514// ECMA 12.1
1515Completion StatListNode::execute(ExecState *exec)
1516{
1517 Completion c = statement->execute(exec);
1518 KJS_ABORTPOINT
1519 if (exec->hadException()) {
1520 Value ex = exec->exception();
1521 exec->clearException();
1522 return Completion(Throw, ex);
1523 }
1524
1525 Value v = c.value();
1526
1527 for (StatListNode *n = list; n; n = n->list) {
1528 Completion c2 = n->statement->execute(exec);
1529 KJS_ABORTPOINT
1530 if (c2.complType() != Normal)
1531 return c2;
1532
1533 if (exec->hadException()) {
1534 Value ex = exec->exception();
1535 exec->clearException();
1536 return Completion(Throw, ex);
1537 }
1538
1539 if (c2.isValueCompletion())
1540 v = c2.value();
1541 c = c2;
1542 }
1543
1544 return Completion(c.complType(), v, c.target());
1545}
1546
1547void StatListNode::processVarDecls(ExecState *exec)
1548{
1549 for (StatListNode *n = this; n; n = n->list)
1550 n->statement->processVarDecls(exec);
1551}
1552
1553// ------------------------------ AssignExprNode -------------------------------
1554
1555void AssignExprNode::ref()
1556{
1557 Node::ref();
1558 if ( expr )
1559 expr->ref();
1560}
1561
1562bool AssignExprNode::deref()
1563{
1564 if ( expr && expr->deref() )
1565 delete expr;
1566 return Node::deref();
1567}
1568
1569// ECMA 12.2
1570Value AssignExprNode::evaluate(ExecState *exec)
1571{
1572 return expr->evaluate(exec);
1573}
1574
1575// ------------------------------ VarDeclNode ----------------------------------
1576
1577VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in)
1578 : ident(id), init(in)
1579{
1580}
1581
1582void VarDeclNode::ref()
1583{
1584 Node::ref();
1585 if ( init )
1586 init->ref();
1587}
1588
1589bool VarDeclNode::deref()
1590{
1591 if ( init && init->deref() )
1592 delete init;
1593 return Node::deref();
1594}
1595
1596// ECMA 12.2
1597Value VarDeclNode::evaluate(ExecState *exec)
1598{
1599 Object variable = Object::dynamicCast(exec->context().imp()->variableObject());
1600
1601 Value val;
1602 if (init) {
1603 val = init->evaluate(exec);
1604 KJS_CHECKEXCEPTIONVALUE
1605 } else {
1606 if ( variable.hasProperty(exec, ident ) ) // already declared ?
1607 return Value();
1608 val = Undefined();
1609 }
1610
1611#ifdef KJS_VERBOSE
1612 printInfo(exec,(UString("new variable ")+ident).cstring().c_str(),val);
1613#endif
1614 // We use Internal to bypass all checks in derived objects, e.g. so that
1615 // "var location" creates a dynamic property instead of activating window.location.
1616 variable.put(exec, ident, val, DontDelete | Internal);
1617
1618 return String(ident.ustring());
1619}
1620
1621void VarDeclNode::processVarDecls(ExecState *exec)
1622{
1623 Object variable = exec->context().imp()->variableObject();
1624
1625 // If a variable by this name already exists, don't clobber it -
1626 // it might be a function parameter
1627 if (!variable.hasProperty(exec, ident)) {
1628 variable.put(exec,ident, Undefined(), DontDelete);
1629 }
1630}
1631
1632// ------------------------------ VarDeclListNode ------------------------------
1633
1634void VarDeclListNode::ref()
1635{
1636 for (VarDeclListNode *n = this; n; n = n->list) {
1637 n->Node::ref();
1638 if (n->var)
1639 n->var->ref();
1640 }
1641}
1642
1643bool VarDeclListNode::deref()
1644{
1645 VarDeclListNode *next;
1646 for (VarDeclListNode *n = this; n; n = next) {
1647 next = n->list;
1648 if (n->var && n->var->deref())
1649 delete n->var;
1650 if (n != this && n->Node::deref())
1651 delete n;
1652 }
1653 return Node::deref();
1654}
1655
1656
1657// ECMA 12.2
1658Value VarDeclListNode::evaluate(ExecState *exec)
1659{
1660 for (VarDeclListNode *n = this; n; n = n->list) {
1661 n->var->evaluate(exec);
1662 KJS_CHECKEXCEPTIONVALUE
1663 }
1664 return Undefined();
1665}
1666
1667void VarDeclListNode::processVarDecls(ExecState *exec)
1668{
1669 for (VarDeclListNode *n = this; n; n = n->list)
1670 n->var->processVarDecls(exec);
1671}
1672
1673// ------------------------------ VarStatementNode -----------------------------
1674
1675void VarStatementNode::reverseList()
1676{
1677 VarDeclListNode *head = 0;
1678 VarDeclListNode *next;
1679 for (VarDeclListNode *n = list; n; n = next) {
1680 next = n->list;
1681 n->list = head;
1682 head = n;
1683 }
1684 list = head;
1685}
1686
1687void VarStatementNode::ref()
1688{
1689 Node::ref();
1690 if ( list )
1691 list->ref();
1692}
1693
1694bool VarStatementNode::deref()
1695{
1696 if ( list && list->deref() )
1697 delete list;
1698 return Node::deref();
1699}
1700
1701// ECMA 12.2
1702Completion VarStatementNode::execute(ExecState *exec)
1703{
1704 KJS_BREAKPOINT;
1705
1706 (void) list->evaluate(exec); // returns 0L
1707 KJS_CHECKEXCEPTION
1708
1709 return Completion(Normal);
1710}
1711
1712void VarStatementNode::processVarDecls(ExecState *exec)
1713{
1714 list->processVarDecls(exec);
1715}
1716
1717// ------------------------------ BlockNode ------------------------------------
1718
1719void BlockNode::reverseList()
1720{
1721 SourceElementsNode *head = 0;
1722 SourceElementsNode *next;
1723 for (SourceElementsNode *n = source; n; n = next) {
1724 next = n->elements;
1725 n->elements = head;
1726 head = n;
1727 }
1728 source = head;
1729}
1730
1731void BlockNode::ref()
1732{
1733 Node::ref();
1734 if ( source )
1735 source->ref();
1736}
1737
1738bool BlockNode::deref()
1739{
1740 if ( source && source->deref() )
1741 delete source;
1742 return Node::deref();
1743}
1744
1745// ECMA 12.1
1746Completion BlockNode::execute(ExecState *exec)
1747{
1748 if (!source)
1749 return Completion(Normal);
1750
1751 source->processFuncDecl(exec);
1752
1753 return source->execute(exec);
1754}
1755
1756void BlockNode::processVarDecls(ExecState *exec)
1757{
1758 if (source)
1759 source->processVarDecls(exec);
1760}
1761
1762// ------------------------------ EmptyStatementNode ---------------------------
1763
1764// ECMA 12.3
1765Completion EmptyStatementNode::execute(ExecState */*exec*/)
1766{
1767 return Completion(Normal);
1768}
1769
1770// ------------------------------ ExprStatementNode ----------------------------
1771
1772void ExprStatementNode::ref()
1773{
1774 Node::ref();
1775 if ( expr )
1776 expr->ref();
1777}
1778
1779bool ExprStatementNode::deref()
1780{
1781 if ( expr && expr->deref() )
1782 delete expr;
1783 return Node::deref();
1784}
1785
1786// ECMA 12.4
1787Completion ExprStatementNode::execute(ExecState *exec)
1788{
1789 KJS_BREAKPOINT;
1790
1791 Value v = expr->evaluate(exec);
1792 KJS_CHECKEXCEPTION
1793
1794 return Completion(Normal, v);
1795}
1796
1797// ------------------------------ IfNode ---------------------------------------
1798
1799void IfNode::ref()
1800{
1801 Node::ref();
1802 if ( statement1 )
1803 statement1->ref();
1804 if ( statement2 )
1805 statement2->ref();
1806 if ( expr )
1807 expr->ref();
1808}
1809
1810bool IfNode::deref()
1811{
1812 if ( statement1 && statement1->deref() )
1813 delete statement1;
1814 if ( statement2 && statement2->deref() )
1815 delete statement2;
1816 if ( expr && expr->deref() )
1817 delete expr;
1818 return Node::deref();
1819}
1820
1821// ECMA 12.5
1822Completion IfNode::execute(ExecState *exec)
1823{
1824 KJS_BREAKPOINT;
1825
1826 Value v = expr->evaluate(exec);
1827 KJS_CHECKEXCEPTION
1828 bool b = v.toBoolean(exec);
1829
1830 // if ... then
1831 if (b)
1832 return statement1->execute(exec);
1833
1834 // no else
1835 if (!statement2)
1836 return Completion(Normal);
1837
1838 // else
1839 return statement2->execute(exec);
1840}
1841
1842void IfNode::processVarDecls(ExecState *exec)
1843{
1844 statement1->processVarDecls(exec);
1845
1846 if (statement2)
1847 statement2->processVarDecls(exec);
1848}
1849
1850// ------------------------------ DoWhileNode ----------------------------------
1851
1852void DoWhileNode::ref()
1853{
1854 Node::ref();
1855 if ( statement )
1856 statement->ref();
1857 if ( expr )
1858 expr->ref();
1859}
1860
1861bool DoWhileNode::deref()
1862{
1863 if ( statement && statement->deref() )
1864 delete statement;
1865 if ( expr && expr->deref() )
1866 delete expr;
1867 return Node::deref();
1868}
1869
1870// ECMA 12.6.1
1871Completion DoWhileNode::execute(ExecState *exec)
1872{
1873 KJS_BREAKPOINT;
1874
1875 Value be, bv;
1876 Completion c;
1877 Value value;
1878
1879 do {
1880 // bail out on error
1881 KJS_CHECKEXCEPTION
1882
1883 c = statement->execute(exec);
1884 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1885 if ((c.complType() == Break) && ls.contains(c.target()))
1886 return Completion(Normal, value);
1887 if (c.complType() != Normal)
1888 return c;
1889 }
1890 bv = expr->evaluate(exec);
1891 KJS_CHECKEXCEPTION
1892 } while (bv.toBoolean(exec));
1893
1894 return Completion(Normal, value);
1895}
1896
1897void DoWhileNode::processVarDecls(ExecState *exec)
1898{
1899 statement->processVarDecls(exec);
1900}
1901
1902// ------------------------------ WhileNode ------------------------------------
1903
1904void WhileNode::ref()
1905{
1906 Node::ref();
1907 if ( statement )
1908 statement->ref();
1909 if ( expr )
1910 expr->ref();
1911}
1912
1913bool WhileNode::deref()
1914{
1915 if ( statement && statement->deref() )
1916 delete statement;
1917 if ( expr && expr->deref() )
1918 delete expr;
1919 return Node::deref();
1920}
1921
1922// ECMA 12.6.2
1923Completion WhileNode::execute(ExecState *exec)
1924{
1925 KJS_BREAKPOINT;
1926
1927 Value be, bv;
1928 Completion c;
1929 bool b(false);
1930 Value value;
1931
1932 while (1) {
1933 bv = expr->evaluate(exec);
1934 KJS_CHECKEXCEPTION
1935 b = bv.toBoolean(exec);
1936
1937 // bail out on error
1938 KJS_CHECKEXCEPTION
1939
1940 if (!b)
1941 return Completion(Normal, value);
1942
1943 c = statement->execute(exec);
1944 if (c.isValueCompletion())
1945 value = c.value();
1946
1947 if ((c.complType() == Continue) && ls.contains(c.target()))
1948 continue;
1949 if ((c.complType() == Break) && ls.contains(c.target()))
1950 return Completion(Normal, value);
1951 if (c.complType() != Normal)
1952 return c;
1953 }
1954}
1955
1956void WhileNode::processVarDecls(ExecState *exec)
1957{
1958 statement->processVarDecls(exec);
1959}
1960
1961// ------------------------------ ForNode --------------------------------------
1962
1963void ForNode::ref()
1964{
1965 Node::ref();
1966 if ( statement )
1967 statement->ref();
1968 if ( expr1 )
1969 expr1->ref();
1970 if ( expr2 )
1971 expr2->ref();
1972 if ( expr3 )
1973 expr3->ref();
1974}
1975
1976bool ForNode::deref()
1977{
1978 if ( statement && statement->deref() )
1979 delete statement;
1980 if ( expr1 && expr1->deref() )
1981 delete expr1;
1982 if ( expr2 && expr2->deref() )
1983 delete expr2;
1984 if ( expr3 && expr3->deref() )
1985 delete expr3;
1986 return Node::deref();
1987}
1988
1989// ECMA 12.6.3
1990Completion ForNode::execute(ExecState *exec)
1991{
1992 Value e, v, cval;
1993 bool b;
1994
1995 if (expr1) {
1996 v = expr1->evaluate(exec);
1997 KJS_CHECKEXCEPTION
1998 }
1999 while (1) {
2000 if (expr2) {
2001 v = expr2->evaluate(exec);
2002 KJS_CHECKEXCEPTION
2003 b = v.toBoolean(exec);
2004 if (b == false)
2005 return Completion(Normal, cval);
2006 }
2007 // bail out on error
2008 KJS_CHECKEXCEPTION
2009
2010 Completion c = statement->execute(exec);
2011 if (c.isValueCompletion())
2012 cval = c.value();
2013 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2014 if ((c.complType() == Break) && ls.contains(c.target()))
2015 return Completion(Normal, cval);
2016 if (c.complType() != Normal)
2017 return c;
2018 }
2019 if (expr3) {
2020 v = expr3->evaluate(exec);
2021 KJS_CHECKEXCEPTION
2022 }
2023 }
2024}
2025
2026void ForNode::processVarDecls(ExecState *exec)
2027{
2028 if (expr1)
2029 expr1->processVarDecls(exec);
2030
2031 statement->processVarDecls(exec);
2032}
2033
2034// ------------------------------ ForInNode ------------------------------------
2035
2036ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
2037 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
2038{
2039}
2040
2041ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
2042 : ident(i), init(in), expr(e), statement(s)
2043{
2044 // for( var foo = bar in baz )
2045 varDecl = new VarDeclNode(ident, init);
2046 lexpr = new ResolveNode(ident);
2047}
2048
2049void ForInNode::ref()
2050{
2051 Node::ref();
2052 if ( statement )
2053 statement->ref();
2054 if ( expr )
2055 expr->ref();
2056 if ( lexpr )
2057 lexpr->ref();
2058 if ( init )
2059 init->ref();
2060 if ( varDecl )
2061 varDecl->ref();
2062}
2063
2064bool ForInNode::deref()
2065{
2066 if ( statement && statement->deref() )
2067 delete statement;
2068 if ( expr && expr->deref() )
2069 delete expr;
2070 if ( lexpr && lexpr->deref() )
2071 delete lexpr;
2072 if ( init && init->deref() )
2073 delete init;
2074 if ( varDecl && varDecl->deref() )
2075 delete varDecl;
2076 return Node::deref();
2077}
2078
2079// ECMA 12.6.4
2080Completion ForInNode::execute(ExecState *exec)
2081{
2082 Value e, retval;
2083 Object v;
2084 Completion c;
2085 ReferenceList propList;
2086
2087 if ( varDecl ) {
2088 varDecl->evaluate(exec);
2089 KJS_CHECKEXCEPTION
2090 }
2091
2092 e = expr->evaluate(exec);
2093 KJS_CHECKEXCEPTION
2094 v = e.toObject(exec);
2095 propList = v.propList(exec);
2096
2097 ReferenceListIterator propIt = propList.begin();
2098
2099 while (propIt != propList.end()) {
2100 Identifier name = propIt->getPropertyName(exec);
2101 if (!v.hasProperty(exec,name)) {
2102 propIt++;
2103 continue;
2104 }
2105
2106 Reference ref = lexpr->evaluateReference(exec);
2107 KJS_CHECKEXCEPTION
2108 ref.putValue(exec, String(name.ustring()));
2109
2110 c = statement->execute(exec);
2111 if (c.isValueCompletion())
2112 retval = c.value();
2113
2114 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2115 if ((c.complType() == Break) && ls.contains(c.target()))
2116 break;
2117 if (c.complType() != Normal) {
2118 return c;
2119 }
2120 }
2121
2122 propIt++;
2123 }
2124
2125 // bail out on error
2126 KJS_CHECKEXCEPTION
2127
2128 return Completion(Normal, retval);
2129}
2130
2131void ForInNode::processVarDecls(ExecState *exec)
2132{
2133 statement->processVarDecls(exec);
2134}
2135
2136// ------------------------------ ContinueNode ---------------------------------
2137
2138// ECMA 12.7
2139Completion ContinueNode::execute(ExecState *exec)
2140{
2141 KJS_BREAKPOINT;
2142
2143 Value dummy;
2144 return exec->context().imp()->seenLabels()->contains(ident) ?
2145 Completion(Continue, dummy, ident) :
2146 Completion(Throw,
2147 throwError(exec, SyntaxError, "Label not found in containing block"));
2148}
2149
2150// ------------------------------ BreakNode ------------------------------------
2151
2152// ECMA 12.8
2153Completion BreakNode::execute(ExecState *exec)
2154{
2155 KJS_BREAKPOINT;
2156
2157 Value dummy;
2158 return exec->context().imp()->seenLabels()->contains(ident) ?
2159 Completion(Break, dummy, ident) :
2160 Completion(Throw,
2161 throwError(exec, SyntaxError, "Label not found in containing block"));
2162}
2163
2164// ------------------------------ ReturnNode -----------------------------------
2165
2166void ReturnNode::ref()
2167{
2168 Node::ref();
2169 if ( value )
2170 value->ref();
2171}
2172
2173bool ReturnNode::deref()
2174{
2175 if ( value && value->deref() )
2176 delete value;
2177 return Node::deref();
2178}
2179
2180// ECMA 12.9
2181Completion ReturnNode::execute(ExecState *exec)
2182{
2183 KJS_BREAKPOINT;
2184
2185 if (!value)
2186 return Completion(ReturnValue, Undefined());
2187
2188 Value v = value->evaluate(exec);
2189 KJS_CHECKEXCEPTION
2190
2191 return Completion(ReturnValue, v);
2192}
2193
2194// ------------------------------ WithNode -------------------------------------
2195
2196void WithNode::ref()
2197{
2198 Node::ref();
2199 if ( statement )
2200 statement->ref();
2201 if ( expr )
2202 expr->ref();
2203}
2204
2205bool WithNode::deref()
2206{
2207 if ( statement && statement->deref() )
2208 delete statement;
2209 if ( expr && expr->deref() )
2210 delete expr;
2211 return Node::deref();
2212}
2213
2214// ECMA 12.10
2215Completion WithNode::execute(ExecState *exec)
2216{
2217 KJS_BREAKPOINT;
2218
2219 Value v = expr->evaluate(exec);
2220 KJS_CHECKEXCEPTION
2221 Object o = v.toObject(exec);
2222 KJS_CHECKEXCEPTION
2223 exec->context().imp()->pushScope(o);
2224 Completion res = statement->execute(exec);
2225 exec->context().imp()->popScope();
2226
2227 return res;
2228}
2229
2230void WithNode::processVarDecls(ExecState *exec)
2231{
2232 statement->processVarDecls(exec);
2233}
2234
2235// ------------------------------ CaseClauseNode -------------------------------
2236
2237void CaseClauseNode::reverseList()
2238{
2239 StatListNode *head = 0;
2240 StatListNode *next;
2241 for (StatListNode *n = list; n; n = next) {
2242 next = n->list;
2243 n->list = head;
2244 head = n;
2245 }
2246 list = head;
2247}
2248
2249void CaseClauseNode::ref()
2250{
2251 Node::ref();
2252 if ( expr )
2253 expr->ref();
2254 if ( list )
2255 list->ref();
2256}
2257
2258bool CaseClauseNode::deref()
2259{
2260 if ( expr && expr->deref() )
2261 delete expr;
2262 if ( list && list->deref() )
2263 delete list;
2264 return Node::deref();
2265}
2266
2267// ECMA 12.11
2268Value CaseClauseNode::evaluate(ExecState *exec)
2269{
2270 Value v = expr->evaluate(exec);
2271 KJS_CHECKEXCEPTIONVALUE
2272
2273 return v;
2274}
2275
2276// ECMA 12.11
2277Completion CaseClauseNode::evalStatements(ExecState *exec)
2278{
2279 if (list)
2280 return list->execute(exec);
2281 else
2282 return Completion(Normal, Undefined());
2283}
2284
2285void CaseClauseNode::processVarDecls(ExecState *exec)
2286{
2287 if (list)
2288 list->processVarDecls(exec);
2289}
2290
2291// ------------------------------ ClauseListNode -------------------------------
2292
2293void ClauseListNode::ref()
2294{
2295 for (ClauseListNode *n = this; n; n = n->nx) {
2296 n->Node::ref();
2297 if (n->cl)
2298 n->cl->ref();
2299 }
2300}
2301
2302bool ClauseListNode::deref()
2303{
2304 ClauseListNode *next;
2305 for (ClauseListNode *n = this; n; n = next) {
2306 next = n->nx;
2307 if (n->cl && n->cl->deref())
2308 delete n->cl;
2309 if (n != this && n->Node::deref())
2310 delete n;
2311 }
2312 return Node::deref();
2313}
2314
2315Value ClauseListNode::evaluate(ExecState */*exec*/)
2316{
2317 /* should never be called */
2318 assert(false);
2319 return Value();
2320}
2321
2322// ECMA 12.11
2323void ClauseListNode::processVarDecls(ExecState *exec)
2324{
2325 for (ClauseListNode *n = this; n; n = n->nx)
2326 if (n->cl)
2327 n->cl->processVarDecls(exec);
2328}
2329
2330// ------------------------------ CaseBlockNode --------------------------------
2331
2332void CaseBlockNode::reverseLists()
2333{
2334 ClauseListNode *head = 0;
2335 ClauseListNode *next;
2336 for (ClauseListNode *n = list1; n; n = next) {
2337 next = n->nx;
2338 n->nx = head;
2339 head = n;
2340 }
2341 list1 = head;
2342
2343 head = 0;
2344 for (ClauseListNode *n = list2; n; n = next) {
2345 next = n->nx;
2346 n->nx = head;
2347 head = n;
2348 }
2349 list2 = head;
2350}
2351
2352void CaseBlockNode::ref()
2353{
2354 Node::ref();
2355 if ( def )
2356 def->ref();
2357 if ( list1 )
2358 list1->ref();
2359 if ( list2 )
2360 list2->ref();
2361}
2362
2363bool CaseBlockNode::deref()
2364{
2365 if ( def && def->deref() )
2366 delete def;
2367 if ( list1 && list1->deref() )
2368 delete list1;
2369 if ( list2 && list2->deref() )
2370 delete list2;
2371 return Node::deref();
2372}
2373
2374Value CaseBlockNode::evaluate(ExecState */*exec*/)
2375{
2376 /* should never be called */
2377 assert(false);
2378 return Value();
2379}
2380
2381// ECMA 12.11
2382Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input)
2383{
2384 Value v;
2385 Completion res;
2386 ClauseListNode *a = list1, *b = list2;
2387 CaseClauseNode *clause;
2388
2389 while (a) {
2390 clause = a->clause();
2391 a = a->next();
2392 v = clause->evaluate(exec);
2393 KJS_CHECKEXCEPTION
2394 if (strictEqual(exec, input, v)) {
2395 res = clause->evalStatements(exec);
2396 if (res.complType() != Normal)
2397 return res;
2398 while (a) {
2399 res = a->clause()->evalStatements(exec);
2400 if (res.complType() != Normal)
2401 return res;
2402 a = a->next();
2403 }
2404 break;
2405 }
2406 }
2407
2408 while (b) {
2409 clause = b->clause();
2410 b = b->next();
2411 v = clause->evaluate(exec);
2412 KJS_CHECKEXCEPTION
2413 if (strictEqual(exec, input, v)) {
2414 res = clause->evalStatements(exec);
2415 if (res.complType() != Normal)
2416 return res;
2417 goto step18;
2418 }
2419 }
2420
2421 // default clause
2422 if (def) {
2423 res = def->evalStatements(exec);
2424 if (res.complType() != Normal)
2425 return res;
2426 }
2427 b = list2;
2428 step18:
2429 while (b) {
2430 clause = b->clause();
2431 res = clause->evalStatements(exec);
2432 if (res.complType() != Normal)
2433 return res;
2434 b = b->next();
2435 }
2436
2437 // bail out on error
2438 KJS_CHECKEXCEPTION
2439
2440 return Completion(Normal);
2441}
2442
2443void CaseBlockNode::processVarDecls(ExecState *exec)
2444{
2445 if (list1)
2446 list1->processVarDecls(exec);
2447 if (def)
2448 def->processVarDecls(exec);
2449 if (list2)
2450 list2->processVarDecls(exec);
2451}
2452
2453// ------------------------------ SwitchNode -----------------------------------
2454
2455void SwitchNode::ref()
2456{
2457 Node::ref();
2458 if ( expr )
2459 expr->ref();
2460 if ( block )
2461 block->ref();
2462}
2463
2464bool SwitchNode::deref()
2465{
2466 if ( expr && expr->deref() )
2467 delete expr;
2468 if ( block && block->deref() )
2469 delete block;
2470 return Node::deref();
2471}
2472
2473// ECMA 12.11
2474Completion SwitchNode::execute(ExecState *exec)
2475{
2476 KJS_BREAKPOINT;
2477
2478 Value v = expr->evaluate(exec);
2479 KJS_CHECKEXCEPTION
2480 Completion res = block->evalBlock(exec,v);
2481
2482 if ((res.complType() == Break) && ls.contains(res.target()))
2483 return Completion(Normal, res.value());
2484 else
2485 return res;
2486}
2487
2488void SwitchNode::processVarDecls(ExecState *exec)
2489{
2490 block->processVarDecls(exec);
2491}
2492
2493// ------------------------------ LabelNode ------------------------------------
2494
2495void LabelNode::ref()
2496{
2497 Node::ref();
2498 if ( statement )
2499 statement->ref();
2500}
2501
2502bool LabelNode::deref()
2503{
2504 if ( statement && statement->deref() )
2505 delete statement;
2506 return Node::deref();
2507}
2508
2509// ECMA 12.12
2510Completion LabelNode::execute(ExecState *exec)
2511{
2512 Completion e;
2513
2514 if (!exec->context().imp()->seenLabels()->push(label)) {
2515 return Completion( Throw,
2516 throwError(exec, SyntaxError, "Duplicated label found" ));
2517 };
2518 e = statement->execute(exec);
2519 exec->context().imp()->seenLabels()->pop();
2520
2521 if ((e.complType() == Break) && (e.target() == label))
2522 return Completion(Normal, e.value());
2523 else
2524 return e;
2525}
2526
2527void LabelNode::processVarDecls(ExecState *exec)
2528{
2529 statement->processVarDecls(exec);
2530}
2531
2532// ------------------------------ ThrowNode ------------------------------------
2533
2534void ThrowNode::ref()
2535{
2536 Node::ref();
2537 if ( expr )
2538 expr->ref();
2539}
2540
2541bool ThrowNode::deref()
2542{
2543 if ( expr && expr->deref() )
2544 delete expr;
2545 return Node::deref();
2546}
2547
2548// ECMA 12.13
2549Completion ThrowNode::execute(ExecState *exec)
2550{
2551 KJS_BREAKPOINT;
2552
2553 Value v = expr->evaluate(exec);
2554 KJS_CHECKEXCEPTION
2555
2556 // bail out on error
2557 KJS_CHECKEXCEPTION
2558
2559 return Completion(Throw, v);
2560}
2561
2562// ------------------------------ CatchNode ------------------------------------
2563
2564void CatchNode::ref()
2565{
2566 Node::ref();
2567 if ( block )
2568 block->ref();
2569}
2570
2571bool CatchNode::deref()
2572{
2573 if ( block && block->deref() )
2574 delete block;
2575 return Node::deref();
2576}
2577
2578Completion CatchNode::execute(ExecState */*exec*/)
2579{
2580 // should never be reached. execute(exec, arg) is used instead
2581 assert(0L);
2582 return Completion();
2583}
2584
2585// ECMA 12.14
2586Completion CatchNode::execute(ExecState *exec, const Value &arg)
2587{
2588 /* TODO: correct ? Not part of the spec */
2589
2590 exec->clearException();
2591
2592 Object obj(new ObjectImp());
2593 obj.put(exec, ident, arg, DontDelete);
2594 exec->context().imp()->pushScope(obj);
2595 Completion c = block->execute(exec);
2596 exec->context().imp()->popScope();
2597
2598 return c;
2599}
2600
2601void CatchNode::processVarDecls(ExecState *exec)
2602{
2603 block->processVarDecls(exec);
2604}
2605
2606// ------------------------------ FinallyNode ----------------------------------
2607
2608void FinallyNode::ref()
2609{
2610 Node::ref();
2611 if ( block )
2612 block->ref();
2613}
2614
2615bool FinallyNode::deref()
2616{
2617 if ( block && block->deref() )
2618 delete block;
2619 return Node::deref();
2620}
2621
2622// ECMA 12.14
2623Completion FinallyNode::execute(ExecState *exec)
2624{
2625 return block->execute(exec);
2626}
2627
2628void FinallyNode::processVarDecls(ExecState *exec)
2629{
2630 block->processVarDecls(exec);
2631}
2632
2633// ------------------------------ TryNode --------------------------------------
2634
2635void TryNode::ref()
2636{
2637 Node::ref();
2638 if ( block )
2639 block->ref();
2640 if ( _final )
2641 _final->ref();
2642 if ( _catch )
2643 _catch->ref();
2644}
2645
2646bool TryNode::deref()
2647{
2648 if ( block && block->deref() )
2649 delete block;
2650 if ( _final && _final->deref() )
2651 delete _final;
2652 if ( _catch && _catch->deref() )
2653 delete _catch;
2654 return Node::deref();
2655}
2656
2657// ECMA 12.14
2658Completion TryNode::execute(ExecState *exec)
2659{
2660 KJS_BREAKPOINT;
2661
2662 Completion c, c2;
2663
2664 c = block->execute(exec);
2665
2666 if (!_final) {
2667 if (c.complType() != Throw)
2668 return c;
2669 return _catch->execute(exec,c.value());
2670 }
2671
2672 if (!_catch) {
2673 c2 = _final->execute(exec);
2674 return (c2.complType() == Normal) ? c : c2;
2675 }
2676
2677 if (c.complType() == Throw)
2678 c = _catch->execute(exec,c.value());
2679
2680 c2 = _final->execute(exec);
2681 return (c2.complType() == Normal) ? c : c2;
2682}
2683
2684void TryNode::processVarDecls(ExecState *exec)
2685{
2686 block->processVarDecls(exec);
2687 if (_final)
2688 _final->processVarDecls(exec);
2689 if (_catch)
2690 _catch->processVarDecls(exec);
2691}
2692
2693// ------------------------------ ParameterNode --------------------------------
2694
2695void ParameterNode::ref()
2696{
2697 for (ParameterNode *n = this; n; n = n->next)
2698 n->Node::ref();
2699}
2700
2701bool ParameterNode::deref()
2702{
2703 ParameterNode *next;
2704 for (ParameterNode *n = this; n; n = next) {
2705 next = n->next;
2706 if (n != this && n->Node::deref())
2707 delete n;
2708 }
2709 return Node::deref();
2710}
2711
2712// ECMA 13
2713Value ParameterNode::evaluate(ExecState */*exec*/)
2714{
2715 return Undefined();
2716}
2717
2718// ------------------------------ FunctionBodyNode -----------------------------
2719
2720FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2721 : BlockNode(s)
2722{
2723 setLoc(-1, -1, -1);
2724 //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
2725}
2726
2727void FunctionBodyNode::processFuncDecl(ExecState *exec)
2728{
2729 if (source)
2730 source->processFuncDecl(exec);
2731}
2732
2733// ------------------------------ FuncDeclNode ---------------------------------
2734
2735void FuncDeclNode::reverseParameterList()
2736{
2737 ParameterNode *head = 0;
2738 ParameterNode *next;
2739 for (ParameterNode *n = param; n; n = next) {
2740 next = n->next;
2741 n->next = head;
2742 head = n;
2743 }
2744 param = head;
2745}
2746
2747void FuncDeclNode::ref()
2748{
2749 Node::ref();
2750 if ( param )
2751 param->ref();
2752 if ( body )
2753 body->ref();
2754}
2755
2756bool FuncDeclNode::deref()
2757{
2758 if ( param && param->deref() )
2759 delete param;
2760 if ( body && body->deref() )
2761 delete body;
2762 return Node::deref();
2763}
2764
2765// ECMA 13
2766void FuncDeclNode::processFuncDecl(ExecState *exec)
2767{
2768 // TODO: let this be an object with [[Class]] property "Function"
2769 FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
2770 Object func(fimp); // protect from GC
2771
2772 // Value proto = exec->interpreter()->builtinObject().construct(exec,List::empty());
2773 List empty;
2774 Value proto = exec->interpreter()->builtinObject().construct(exec,empty);
2775 func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
2776
2777 int plen = 0;
2778 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2779 fimp->addParameter(p->ident());
2780
2781 func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
2782
2783 exec->context().imp()->variableObject().put(exec,ident,func);
2784
2785 if (body) {
2786 // hack the scope so that the function gets put as a property of func, and it's scope
2787 // contains the func as well as our current scope
2788 Object oldVar = exec->context().imp()->variableObject();
2789 exec->context().imp()->setVariableObject(func);
2790 exec->context().imp()->pushScope(func);
2791 body->processFuncDecl(exec);
2792 exec->context().imp()->popScope();
2793 exec->context().imp()->setVariableObject(oldVar);
2794 }
2795}
2796
2797// ------------------------------ FuncExprNode ---------------------------------
2798
2799void FuncExprNode::reverseParameterList()
2800{
2801 ParameterNode *head = 0;
2802 ParameterNode *next;
2803 for (ParameterNode *n = param; n; n = next) {
2804 next = n->next;
2805 n->next = head;
2806 head = n;
2807 }
2808 param = head;
2809}
2810
2811void FuncExprNode::ref()
2812{
2813 Node::ref();
2814 if ( param )
2815 param->ref();
2816 if ( body )
2817 body->ref();
2818}
2819
2820bool FuncExprNode::deref()
2821{
2822 if ( param && param->deref() )
2823 delete param;
2824 if ( body && body->deref() )
2825 delete body;
2826 return Node::deref();
2827}
2828
2829
2830// ECMA 13
2831Value FuncExprNode::evaluate(ExecState *exec)
2832{
2833 FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null, body, exec->context().imp()->scopeChain());
2834 Value ret(fimp);
2835 List empty;
2836 Value proto = exec->interpreter()->builtinObject().construct(exec,empty);
2837 fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2838
2839 int plen = 0;
2840 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2841 fimp->addParameter(p->ident());
2842
2843 return ret;
2844}
2845
2846// ------------------------------ SourceElementsNode ---------------------------
2847
2848void SourceElementsNode::ref()
2849{
2850 for (SourceElementsNode *n = this; n; n = n->elements) {
2851 n->Node::ref();
2852 if (n->element)
2853 n->element->ref();
2854 }
2855}
2856
2857bool SourceElementsNode::deref()
2858{
2859 SourceElementsNode *next;
2860 for (SourceElementsNode *n = this; n; n = next) {
2861 next = n->elements;
2862 if (n->element && n->element->deref())
2863 delete n->element;
2864 if (n != this && n->Node::deref())
2865 delete n;
2866 }
2867 return Node::deref();
2868}
2869
2870// ECMA 14
2871Completion SourceElementsNode::execute(ExecState *exec)
2872{
2873 KJS_CHECKEXCEPTION
2874
2875 Completion c1 = element->execute(exec);
2876 KJS_CHECKEXCEPTION;
2877 if (c1.complType() != Normal)
2878 return c1;
2879
2880 for (SourceElementsNode *n = elements; n; n = n->elements) {
2881 Completion c2 = n->element->execute(exec);
2882 if (c2.complType() != Normal)
2883 return c2;
2884 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2885 // c2 doesn't have a value
2886 if (!c2.value().isNull())
2887 c1 = c2;
2888 }
2889
2890 return c1;
2891}
2892
2893// ECMA 14
2894void SourceElementsNode::processFuncDecl(ExecState *exec)
2895{
2896 for (SourceElementsNode *n = this; n; n = n->elements)
2897 n->element->processFuncDecl(exec);
2898}
2899
2900void SourceElementsNode::processVarDecls(ExecState *exec)
2901{
2902 for (SourceElementsNode *n = this; n; n = n->elements)
2903 n->element->processVarDecls(exec);
2904}
2905
2906ProgramNode::ProgramNode(SourceElementsNode *s): FunctionBodyNode(s) {
2907 //fprintf(stderr,"ProgramNode::ProgramNode %p\n",this);
2908}
Note: See TracBrowser for help on using the repository browser.