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 std.algorithm.sorting;
22 
23 import dmdscript.script;
24 import dmdscript.dobject;
25 import dmdscript.value;
26 import dmdscript.property;
27 
28 Dobject getPrototype(Dobject o)
29 {
30     version(all)
31     {
32         return o.internal_prototype;    // use internal [[Prototype]]
33     }
34     else
35     {
36         // use "prototype"
37         Value *v;
38 
39         v = o.Get(TEXT_prototype);
40         if(!v || v.isPrimitive())
41             return null;
42         o = v.toObject();
43         return o;
44     }
45 }
46 
47 struct Iterator
48 {
49             Value[] keys;
50     size_t  keyindex;
51     Dobject o;
52     Dobject ostart;
53 
54     debug
55     {
56         enum uint ITERATOR_VALUE = 0x1992836;
57         uint foo = ITERATOR_VALUE;
58     }
59 
60     invariant()
61     {
62         debug assert(foo == ITERATOR_VALUE);
63     }
64 
65     void ctor(Dobject o)
66     {
67         debug foo = ITERATOR_VALUE;
68         //writef("Iterator: o = %p, p = %p\n", o, p);
69         ostart = o;
70         this.o = o;
71         keys = o.proptable.table.keys.sort().release;
72         keyindex = 0;
73     }
74 
75     Value *next()
76     {
77         Property* p;
78 
79         //writef("Iterator::done() p = %p\n", p);
80 
81         for(;; keyindex++)
82         {
83             while(keyindex == keys.length)
84             {
85                 delete keys;
86                 o = getPrototype(o);
87                 if(!o)
88                     return null;
89                 keys = o.proptable.table.keys.sort().release;
90                 keyindex = 0;
91             }
92             Value* key = &keys[keyindex];
93             p = *key in o.proptable.table;
94             if(!p)                      // if no longer in property table
95                 continue;
96             if(p.attributes & DontEnum)
97                 continue;
98             else
99             {
100                 // ECMA 12.6.3
101                 // Do not enumerate those properties in prototypes
102                 // that are overridden
103                 if(o != ostart)
104                 {
105                     for(Dobject ot = ostart; ot != o; ot = getPrototype(ot))
106                     {
107                         // If property p is in t, don't enumerate
108                         if(*key in ot.proptable.table)
109                             goto Lcontinue;
110                     }
111                 }
112                 keyindex++;
113                 return key; //&p.value;
114 
115                 Lcontinue:
116                 ;
117             }
118         }
119         assert(0);
120     }
121 }