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 CallContext* callcontext; 54 55 debug 56 { 57 enum uint ITERATOR_VALUE = 0x1992836; 58 uint foo = ITERATOR_VALUE; 59 } 60 61 invariant() 62 { 63 debug assert(foo == ITERATOR_VALUE); 64 } 65 66 void ctor(CallContext* cc, Dobject o) 67 { 68 debug foo = ITERATOR_VALUE; 69 //writef("Iterator: o = %p, p = %p\n", o, p); 70 ostart = o; 71 this.o = o; 72 this.callcontext = cc; 73 keys = o.proptable.table.keys.sort!((a, b) => a.compare(cc, b) < 0).release; 74 keyindex = 0; 75 } 76 77 Value *next() 78 { 79 Property* p; 80 81 //writef("Iterator::done() p = %p\n", p); 82 83 for(;; keyindex++) 84 { 85 while(keyindex == keys.length) 86 { 87 destroy(keys); 88 o = getPrototype(o); 89 if(!o) 90 return null; 91 keys = o.proptable.table.keys.sort!((a, b) => a.compare(this.callcontext, b) < 0).release; 92 keyindex = 0; 93 } 94 Value* key = &keys[keyindex]; 95 p = *key in o.proptable.table; 96 if(!p) // if no longer in property table 97 continue; 98 if(p.attributes & DontEnum) 99 continue; 100 else 101 { 102 // ECMA 12.6.3 103 // Do not enumerate those properties in prototypes 104 // that are overridden 105 if(o != ostart) 106 { 107 for(Dobject ot = ostart; ot != o; ot = getPrototype(ot)) 108 { 109 // If property p is in t, don't enumerate 110 if(*key in ot.proptable.table) 111 goto Lcontinue; 112 } 113 } 114 keyindex++; 115 return key; //&p.value; 116 117 Lcontinue: 118 ; 119 } 120 } 121 assert(0); 122 } 123 }