1 /* Digital Mars DMDScript source code.
2  * Copyright (c) 2000-2002 by Chromium Communications
3  * D version Copyright (c) 2004-2010 by Digital Mars
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  * written by Walter Bright
7  * http://www.digitalmars.com
8  *
9  * D2 port by Dmitry Olshansky 
10  *
11  * DMDScript is implemented in the D Programming Language,
12  * http://www.digitalmars.com/d/
13  *
14  * For a C++ implementation of DMDScript, including COM support, see
15  * http://www.digitalmars.com/dscript/cppscript.html
16  */
17 
18 
19 module dmdscript.iterator;
20 
21 import dmdscript.script;
22 import dmdscript.dobject;
23 import dmdscript.value;
24 import dmdscript.property;
25 
26 Dobject getPrototype(Dobject o)
27 {
28     version(all)
29     {
30         return o.internal_prototype;    // use internal [[Prototype]]
31     }
32     else
33     {
34         // use "prototype"
35         Value *v;
36 
37         v = o.Get(TEXT_prototype);
38         if(!v || v.isPrimitive())
39             return null;
40         o = v.toObject();
41         return o;
42     }
43 }
44 
45 struct Iterator
46 {
47             Value[] keys;
48     size_t  keyindex;
49     Dobject o;
50     Dobject ostart;
51 
52     debug
53     {
54         enum uint ITERATOR_VALUE = 0x1992836;
55         uint foo = ITERATOR_VALUE;
56     }
57 
58     invariant()
59     {
60         debug assert(foo == ITERATOR_VALUE);
61     }
62 
63     void ctor(Dobject o)
64     {
65         debug foo = ITERATOR_VALUE;
66         //writef("Iterator: o = %p, p = %p\n", o, p);
67         ostart = o;
68         this.o = o;
69         keys = o.proptable.table.keys.sort;
70         keyindex = 0;
71     }
72 
73     Value *next()
74     {
75         Property* p;
76 
77         //writef("Iterator::done() p = %p\n", p);
78 
79         for(;; keyindex++)
80         {
81             while(keyindex == keys.length)
82             {
83                 delete keys;
84                 o = getPrototype(o);
85                 if(!o)
86                     return null;
87                 keys = o.proptable.table.keys.sort;
88                 keyindex = 0;
89             }
90             Value* key = &keys[keyindex];
91             p = *key in o.proptable.table;
92             if(!p)                      // if no longer in property table
93                 continue;
94             if(p.attributes & DontEnum)
95                 continue;
96             else
97             {
98                 // ECMA 12.6.3
99                 // Do not enumerate those properties in prototypes
100                 // that are overridden
101                 if(o != ostart)
102                 {
103                     for(Dobject ot = ostart; ot != o; ot = getPrototype(ot))
104                     {
105                         // If property p is in t, don't enumerate
106                         if(*key in ot.proptable.table)
107                             goto Lcontinue;
108                     }
109                 }
110                 keyindex++;
111                 return key; //&p.value;
112 
113                 Lcontinue:
114                 ;
115             }
116         }
117         assert(0);
118     }
119 }