Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

root/trunk/src/object_.d

Revision 519, 70.7 kB (checked in by jmdavis, 14 years ago)

Added Throwable and default arguments to most Exception and Error constructors.

For whatever reason, a number of Exception and Error types didn't take a
Throwable for chaining exceptions, and most of them didn't have default
arguments for file and line number (some didn't even take file and line
number in the first place). So, most of the Exception and Error types in
core.exception and object_.d/object.di now have take an optional
Throwable argument and optional file and line number arguments which
default to FILE and LINE. In at least one case (AssertError?), I
couldn't make it take default arguments for file and line number without
breaking code, so it doesn't. But if I could do it and maintain
backwards comptability, I did. I also added unit tests to verify that
the various constructors work properly.

  • Property svn:eol-style set to native
Line 
1 /**
2  * Forms the symbols available to all D programs. Includes Object, which is
3  * the root of the class object hierarchy.  This module is implicitly
4  * imported.
5  * Macros:
6  *      WIKI = Object
7  *
8  * Copyright: Copyright Digital Mars 2000 - 2011.
9  * License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
10  * Authors:   Walter Bright, Sean Kelly
11  */
12
13 /*          Copyright Digital Mars 2000 - 2011.
14  * Distributed under the Boost Software License, Version 1.0.
15  *    (See accompanying file LICENSE_1_0.txt or copy at
16  *          http://www.boost.org/LICENSE_1_0.txt)
17  */
18 module object;
19
20 //debug=PRINTF;
21
22 private
23 {
24     import core.atomic;
25     import core.stdc.string;
26     import core.stdc.stdlib;
27     import rt.util.hash;
28     import rt.util.string;
29     import rt.util.console;
30     debug(PRINTF) import core.stdc.stdio;
31
32     extern (C) void onOutOfMemoryError();
33     extern (C) Object _d_newclass(TypeInfo_Class ci);
34     extern (C) void _d_arrayshrinkfit(TypeInfo ti, void[] arr);
35     extern (C) size_t _d_arraysetcapacity(TypeInfo ti, size_t newcapacity, void *arrptr);
36 }
37
38 // NOTE: For some reason, this declaration method doesn't work
39 //       in this particular file (and this file only).  It must
40 //       be a DMD thing.
41 //alias typeof(int.sizeof)                    size_t;
42 //alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
43
44 version(X86_64)
45 {
46     alias ulong size_t;
47     alias long  ptrdiff_t;
48     alias long  sizediff_t;
49 }
50 else
51 {
52     alias uint  size_t;
53     alias int   ptrdiff_t;
54     alias int   sizediff_t;
55 }
56
57 alias size_t hash_t;
58 alias bool equals_t;
59
60 alias immutable(char)[]  string;
61 alias immutable(wchar)[] wstring;
62 alias immutable(dchar)[] dstring;
63
64 /**
65  * All D class objects inherit from Object.
66  */
67 class Object
68 {
69     /**
70      * Convert Object to a human readable string.
71      */
72     string toString()
73     {
74         return this.classinfo.name;
75     }
76
77     /**
78      * Compute hash function for Object.
79      */
80     hash_t toHash()
81     {
82         // BUG: this prevents a compacting GC from working, needs to be fixed
83         return cast(hash_t)cast(void*)this;
84     }
85
86     /**
87      * Compare with another Object obj.
88      * Returns:
89      *  $(TABLE
90      *  $(TR $(TD this &lt; obj) $(TD &lt; 0))
91      *  $(TR $(TD this == obj) $(TD 0))
92      *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
93      *  )
94      */
95     int opCmp(Object o)
96     {
97         // BUG: this prevents a compacting GC from working, needs to be fixed
98         //return cast(int)cast(void*)this - cast(int)cast(void*)o;
99
100         throw new Exception("need opCmp for class " ~ this.classinfo.name);
101         //return this !is o;
102     }
103
104     /**
105      * Returns !=0 if this object does have the same contents as obj.
106      */
107     equals_t opEquals(Object o)
108     {
109         return this is o;
110     }
111    
112     equals_t opEquals(Object lhs, Object rhs)
113     {
114         if (lhs is rhs)
115             return true;
116         if (lhs is null || rhs is null)
117             return false;
118         if (typeid(lhs) == typeid(rhs))
119             return lhs.opEquals(rhs);
120         return lhs.opEquals(rhs) &&
121                rhs.opEquals(lhs);
122     }
123
124     interface Monitor
125     {
126         void lock();
127         void unlock();
128     }
129
130     /**
131      * Create instance of class specified by classname.
132      * The class must either have no constructors or have
133      * a default constructor.
134      * Returns:
135      *   null if failed
136      */
137     static Object factory(string classname)
138     {
139         auto ci = TypeInfo_Class.find(classname);
140         if (ci)
141         {
142             return ci.create();
143         }
144         return null;
145     }
146 }
147
148 /************************
149  * Returns true if lhs and rhs are equal.
150  */
151 bool opEquals(Object lhs, Object rhs)
152 {
153     // If aliased to the same object or both null => equal
154     if (lhs is rhs) return true;
155
156     // If either is null => non-equal
157     if (lhs is null || rhs is null) return false;
158
159     // If same exact type => one call to method opEquals
160     if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
161         return lhs.opEquals(rhs);
162
163     // General case => symmetric calls to method opEquals
164     return lhs.opEquals(rhs) && rhs.opEquals(lhs);
165 }
166
167 bool opEquals(TypeInfo lhs, TypeInfo rhs)
168 {
169     // If aliased to the same object or both null => equal
170     if (lhs is rhs) return true;
171
172     // If either is null => non-equal
173     if (lhs is null || rhs is null) return false;
174
175     // If same exact type => one call to method opEquals
176     if (typeid(lhs) == typeid(rhs)) return lhs.opEquals(rhs);
177
178     //printf("%.*s and %.*s, %d %d\n", lhs.toString(), rhs.toString(), lhs.opEquals(rhs), rhs.opEquals(lhs));
179
180     // Factor out top level const
181     // (This still isn't right, should follow same rules as compiler does for type equality.)
182     TypeInfo_Const c = cast(TypeInfo_Const) lhs;
183     if (c)
184         lhs = c.base;
185     c = cast(TypeInfo_Const) rhs;
186     if (c)
187         rhs = c.base;
188
189     // General case => symmetric calls to method opEquals
190     return lhs.opEquals(rhs) && rhs.opEquals(lhs);
191 }
192
193 /**
194  * Information about an interface.
195  * When an object is accessed via an interface, an Interface* appears as the
196  * first entry in its vtbl.
197  */
198 struct Interface
199 {
200     TypeInfo_Class   classinfo;  /// .classinfo for this interface (not for containing class)
201     void*[]     vtbl;
202     ptrdiff_t   offset;     /// offset to Interface 'this' from Object 'this'
203 }
204
205 /**
206  * Runtime type information about a class. Can be retrieved for any class type
207  * or instance by using the .classinfo property.
208  * A pointer to this appears as the first entry in the class's vtbl[].
209  */
210 alias TypeInfo_Class Classinfo;
211
212 /**
213  * Array of pairs giving the offset and type information for each
214  * member in an aggregate.
215  */
216 struct OffsetTypeInfo
217 {
218     size_t   offset;    /// Offset of member from start of object
219     TypeInfo ti;        /// TypeInfo for this member
220 }
221
222 /**
223  * Runtime type information about a type.
224  * Can be retrieved for any type using a
225  * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
226  */
227 class TypeInfo
228 {
229     override hash_t toHash()
230     {
231         auto data = this.toString();
232         return hashOf(data.ptr, data.length);
233     }
234
235     override int opCmp(Object o)
236     {
237         if (this is o)
238             return 0;
239         TypeInfo ti = cast(TypeInfo)o;
240         if (ti is null)
241             return 1;
242         return dstrcmp(this.toString(), ti.toString());
243     }
244
245     override equals_t opEquals(Object o)
246     {
247         /* TypeInfo instances are singletons, but duplicates can exist
248          * across DLL's. Therefore, comparing for a name match is
249          * sufficient.
250          */
251         if (this is o)
252             return true;
253         TypeInfo ti = cast(TypeInfo)o;
254         return ti && this.toString() == ti.toString();
255     }
256
257     /// Returns a hash of the instance of a type.
258     hash_t getHash(in void* p) { return cast(hash_t)p; }
259
260     /// Compares two instances for equality.
261     equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
262
263     /// Compares two instances for &lt;, ==, or &gt;.
264     int compare(in void* p1, in void* p2) { return 0; }
265
266     /// Returns size of the type.
267     size_t tsize() { return 0; }
268
269     /// Swaps two instances of the type.
270     void swap(void* p1, void* p2)
271     {
272         size_t n = tsize();
273         for (size_t i = 0; i < n; i++)
274         {
275             byte t = (cast(byte *)p1)[i];
276             (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
277             (cast(byte*)p2)[i] = t;
278         }
279     }
280
281     /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
282     /// null if none.
283     TypeInfo next() { return null; }
284
285     /// Return default initializer, null if default initialize to 0
286     void[] init() { return null; }
287
288     /// Get flags for type: 1 means GC should scan for pointers
289     uint flags() { return 0; }
290
291     /// Get type information on the contents of the type; null if not available
292     OffsetTypeInfo[] offTi() { return null; }
293     /// Run the destructor on the object and all its sub-objects
294     void destroy(void* p) {}
295     /// Run the postblit on the object and all its sub-objects
296     void postblit(void* p) {}
297
298
299     /// Return alignment of type
300     size_t talign() { return tsize(); }
301
302     /** Return internal info on arguments fitting into 8byte.
303      * See X86-64 ABI 3.2.3
304      */
305     version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2)
306     {   arg1 = this;
307         return 0;
308     }
309 }
310
311 class TypeInfo_Typedef : TypeInfo
312 {
313     override string toString() { return name; }
314
315     override equals_t opEquals(Object o)
316     {
317         TypeInfo_Typedef c;
318         return this is o ||
319                ((c = cast(TypeInfo_Typedef)o) !is null &&
320                 this.name == c.name &&
321                 this.base == c.base);
322     }
323
324     override hash_t getHash(in void* p) { return base.getHash(p); }
325     override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
326     override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
327     override size_t tsize() { return base.tsize(); }
328     override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
329
330     override TypeInfo next() { return base.next(); }
331     override uint flags() { return base.flags(); }
332     override void[] init() { return m_init.length ? m_init : base.init(); }
333
334     override size_t talign() { return base.talign(); }
335
336     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
337     {   return base.argTypes(arg1, arg2);
338     }
339
340     TypeInfo base;
341     string   name;
342     void[]   m_init;
343 }
344
345 class TypeInfo_Enum : TypeInfo_Typedef
346 {
347
348 }
349
350 class TypeInfo_Pointer : TypeInfo
351 {
352     override string toString() { return m_next.toString() ~ "*"; }
353
354     override equals_t opEquals(Object o)
355     {
356         TypeInfo_Pointer c;
357         return this is o ||
358                 ((c = cast(TypeInfo_Pointer)o) !is null &&
359                  this.m_next == c.m_next);
360     }
361
362     override hash_t getHash(in void* p)
363     {
364         return cast(hash_t)*cast(void**)p;
365     }
366
367     override equals_t equals(in void* p1, in void* p2)
368     {
369         return *cast(void**)p1 == *cast(void**)p2;
370     }
371
372     override int compare(in void* p1, in void* p2)
373     {
374         if (*cast(void**)p1 < *cast(void**)p2)
375             return -1;
376         else if (*cast(void**)p1 > *cast(void**)p2)
377             return 1;
378         else
379             return 0;
380     }
381
382     override size_t tsize()
383     {
384         return (void*).sizeof;
385     }
386
387     override void swap(void* p1, void* p2)
388     {
389         void* tmp = *cast(void**)p1;
390         *cast(void**)p1 = *cast(void**)p2;
391         *cast(void**)p2 = tmp;
392     }
393
394     override TypeInfo next() { return m_next; }
395     override uint flags() { return 1; }
396
397     TypeInfo m_next;
398 }
399
400 class TypeInfo_Array : TypeInfo
401 {
402     override string toString() { return value.toString() ~ "[]"; }
403
404     override equals_t opEquals(Object o)
405     {
406         TypeInfo_Array c;
407         return this is o ||
408                ((c = cast(TypeInfo_Array)o) !is null &&
409                 this.value == c.value);
410     }
411
412     override hash_t getHash(in void* p)
413     {
414         void[] a = *cast(void[]*)p;
415         return hashOf(a.ptr, a.length);
416     }
417
418     override equals_t equals(in void* p1, in void* p2)
419     {
420         void[] a1 = *cast(void[]*)p1;
421         void[] a2 = *cast(void[]*)p2;
422         if (a1.length != a2.length)
423             return false;
424         size_t sz = value.tsize();
425         for (size_t i = 0; i < a1.length; i++)
426         {
427             if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
428                 return false;
429         }
430         return true;
431     }
432
433     override int compare(in void* p1, in void* p2)
434     {
435         void[] a1 = *cast(void[]*)p1;
436         void[] a2 = *cast(void[]*)p2;
437         size_t sz = value.tsize();
438         size_t len = a1.length;
439
440         if (a2.length < len)
441             len = a2.length;
442         for (size_t u = 0; u < len; u++)
443         {
444             int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
445             if (result)
446                 return result;
447         }
448         return cast(int)a1.length - cast(int)a2.length;
449     }
450
451     override size_t tsize()
452     {
453         return (void[]).sizeof;
454     }
455
456     override void swap(void* p1, void* p2)
457     {
458         void[] tmp = *cast(void[]*)p1;
459         *cast(void[]*)p1 = *cast(void[]*)p2;
460         *cast(void[]*)p2 = tmp;
461     }
462
463     TypeInfo value;
464
465     override TypeInfo next()
466     {
467         return value;
468     }
469
470     override uint flags() { return 1; }
471
472     override size_t talign()
473     {
474         return (void[]).alignof;
475     }
476
477     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
478     {   //arg1 = typeid(size_t);
479         //arg2 = typeid(void*);
480         return 0;
481     }
482 }
483
484 class TypeInfo_StaticArray : TypeInfo
485 {
486     override string toString()
487     {
488         char[20] tmp = void;
489         return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
490     }
491
492     override equals_t opEquals(Object o)
493     {
494         TypeInfo_StaticArray c;
495         return this is o ||
496                ((c = cast(TypeInfo_StaticArray)o) !is null &&
497                 this.len == c.len &&
498                 this.value == c.value);
499     }
500
501     override hash_t getHash(in void* p)
502     {
503         size_t sz = value.tsize();
504         hash_t hash = 0;
505         for (size_t i = 0; i < len; i++)
506             hash += value.getHash(p + i * sz);
507         return hash;
508     }
509
510     override equals_t equals(in void* p1, in void* p2)
511     {
512         size_t sz = value.tsize();
513
514         for (size_t u = 0; u < len; u++)
515         {
516             if (!value.equals(p1 + u * sz, p2 + u * sz))
517                 return false;
518         }
519         return true;
520     }
521
522     override int compare(in void* p1, in void* p2)
523     {
524         size_t sz = value.tsize();
525
526         for (size_t u = 0; u < len; u++)
527         {
528             int result = value.compare(p1 + u * sz, p2 + u * sz);
529             if (result)
530                 return result;
531         }
532         return 0;
533     }
534
535     override size_t tsize()
536     {
537         return len * value.tsize();
538     }
539
540     override void swap(void* p1, void* p2)
541     {
542         void* tmp;
543         size_t sz = value.tsize();
544         ubyte[16] buffer;
545         void* pbuffer;
546
547         if (sz < buffer.sizeof)
548             tmp = buffer.ptr;
549         else
550             tmp = pbuffer = (new void[sz]).ptr;
551
552         for (size_t u = 0; u < len; u += sz)
553         {   size_t o = u * sz;
554             memcpy(tmp, p1 + o, sz);
555             memcpy(p1 + o, p2 + o, sz);
556             memcpy(p2 + o, tmp, sz);
557         }
558         if (pbuffer)
559             delete pbuffer;
560     }
561
562     override void[] init() { return value.init(); }
563     override TypeInfo next() { return value; }
564     override uint flags() { return value.flags(); }
565
566     override void destroy(void* p)
567     {
568         auto sz = value.tsize();
569         p += sz * len;
570         foreach (i; 0 .. len)
571         {
572             p -= sz;
573             value.destroy(p);
574         }
575     }
576
577     override void postblit(void* p)
578     {
579         auto sz = value.tsize();
580         foreach (i; 0 .. len)
581         {
582             value.postblit(p);
583             p += sz;
584         }
585     }
586
587     TypeInfo value;
588     size_t   len;
589
590     override size_t talign()
591     {
592         return value.talign();
593     }
594
595     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
596     {   arg1 = typeid(void*);
597         return 0;
598     }
599 }
600
601 class TypeInfo_AssociativeArray : TypeInfo
602 {
603     override string toString()
604     {
605         return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
606     }
607
608     override equals_t opEquals(Object o)
609     {
610         TypeInfo_AssociativeArray c;
611         return this is o ||
612                 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
613                  this.key == c.key &&
614                  this.value == c.value);
615     }
616
617     // BUG: need to add the rest of the functions
618
619     override size_t tsize()
620     {
621         return (char[int]).sizeof;
622     }
623
624     override TypeInfo next() { return value; }
625     override uint flags() { return 1; }
626
627     TypeInfo value;
628     TypeInfo key;
629
630     TypeInfo impl;
631
632     override size_t talign()
633     {
634         return (char[int]).alignof;
635     }
636
637     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
638     {   arg1 = typeid(void*);
639         return 0;
640     }
641 }
642
643 class TypeInfo_Function : TypeInfo
644 {
645     override string toString()
646     {
647         return cast(string)(next.toString() ~ "()");
648     }
649
650     override equals_t opEquals(Object o)
651     {
652         TypeInfo_Function c;
653         return this is o ||
654                 ((c = cast(TypeInfo_Function)o) !is null &&
655                  this.next == c.next);
656     }
657
658     // BUG: need to add the rest of the functions
659
660     override size_t tsize()
661     {
662         return 0;       // no size for functions
663     }
664
665     TypeInfo next;
666 }
667
668 class TypeInfo_Delegate : TypeInfo
669 {
670     override string toString()
671     {
672         return cast(string)(next.toString() ~ " delegate()");
673     }
674
675     override equals_t opEquals(Object o)
676     {
677         TypeInfo_Delegate c;
678         return this is o ||
679                 ((c = cast(TypeInfo_Delegate)o) !is null &&
680                  this.next == c.next);
681     }
682
683     // BUG: need to add the rest of the functions
684
685     override size_t tsize()
686     {
687         alias int delegate() dg;
688         return dg.sizeof;
689     }
690
691     override uint flags() { return 1; }
692
693     TypeInfo next;
694
695     override size_t talign()
696     {   alias int delegate() dg;
697         return dg.alignof;
698     }
699
700     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
701     {   //arg1 = typeid(void*);
702         //arg2 = typeid(void*);
703         return 0;
704     }
705 }
706
707 /**
708  * Runtime type information about a class.
709  * Can be retrieved from an object instance by using the
710  * $(LINK2 ../property.html#classinfo, .classinfo) property.
711  */
712 class TypeInfo_Class : TypeInfo
713 {
714     override string toString() { return info.name; }
715
716     override equals_t opEquals(Object o)
717     {
718         TypeInfo_Class c;
719         return this is o ||
720                 ((c = cast(TypeInfo_Class)o) !is null &&
721                  this.info.name == c.info.name);
722     }
723
724     override hash_t getHash(in void* p)
725     {
726         Object o = *cast(Object*)p;
727         return o ? o.toHash() : 0;
728     }
729
730     override equals_t equals(in void* p1, in void* p2)
731     {
732         Object o1 = *cast(Object*)p1;
733         Object o2 = *cast(Object*)p2;
734
735         return (o1 is o2) || (o1 && o1.opEquals(o2));
736     }
737
738     override int compare(in void* p1, in void* p2)
739     {
740         Object o1 = *cast(Object*)p1;
741         Object o2 = *cast(Object*)p2;
742         int c = 0;
743
744         // Regard null references as always being "less than"
745         if (o1 !is o2)
746         {
747             if (o1)
748             {
749                 if (!o2)
750                     c = 1;
751                 else
752                     c = o1.opCmp(o2);
753             }
754             else
755                 c = -1;
756         }
757         return c;
758     }
759
760     override size_t tsize()
761     {
762         return Object.sizeof;
763     }
764
765     override uint flags() { return 1; }
766
767     override OffsetTypeInfo[] offTi()
768     {
769         return m_offTi;
770     }
771
772     @property TypeInfo_Class info() { return this; }
773     @property TypeInfo typeinfo() { return this; }
774
775     byte[]      init;           /** class static initializer
776                                  * (init.length gives size in bytes of class)
777                                  */
778     string      name;           /// class name
779     void*[]     vtbl;           /// virtual function pointer table
780     Interface[] interfaces;     /// interfaces this class implements
781     TypeInfo_Class   base;           /// base class
782     void*       destructor;
783     void function(Object) classInvariant;
784     uint        m_flags;
785     //  1:                      // is IUnknown or is derived from IUnknown
786     //  2:                      // has no possible pointers into GC memory
787     //  4:                      // has offTi[] member
788     //  8:                      // has constructors
789     // 16:                      // has xgetMembers member
790     // 32:                      // has typeinfo member
791     void*       deallocator;
792     OffsetTypeInfo[] m_offTi;
793     void function(Object) defaultConstructor;   // default Constructor
794     const(MemberInfo[]) function(in char[]) xgetMembers;
795
796     /**
797      * Search all modules for TypeInfo_Class corresponding to classname.
798      * Returns: null if not found
799      */
800     static TypeInfo_Class find(in char[] classname)
801     {
802         foreach (m; ModuleInfo)
803         {
804           if (m)
805             //writefln("module %s, %d", m.name, m.localClasses.length);
806             foreach (c; m.localClasses)
807             {
808                 //writefln("\tclass %s", c.name);
809                 if (c.name == classname)
810                     return c;
811             }
812         }
813         return null;
814     }
815
816     /**
817      * Create instance of Object represented by 'this'.
818      */
819     Object create()
820     {
821         if (m_flags & 8 && !defaultConstructor)
822             return null;
823         Object o = _d_newclass(this);
824         if (m_flags & 8 && defaultConstructor)
825         {
826             defaultConstructor(o);
827         }
828         return o;
829     }
830
831     /**
832      * Search for all members with the name 'name'.
833      * If name[] is null, return all members.
834      */
835     const(MemberInfo[]) getMembers(in char[] name)
836     {
837         if (m_flags & 16 && xgetMembers)
838             return xgetMembers(name);
839         return null;
840     }
841 }
842
843 alias TypeInfo_Class ClassInfo;
844
845 class TypeInfo_Interface : TypeInfo
846 {
847     override string toString() { return info.name; }
848
849     override equals_t opEquals(Object o)
850     {
851         TypeInfo_Interface c;
852         return this is o ||
853                 ((c = cast(TypeInfo_Interface)o) !is null &&
854                  this.info.name == c.classinfo.name);
855     }
856
857     override hash_t getHash(in void* p)
858     {
859         Interface* pi = **cast(Interface ***)*cast(void**)p;
860         Object o = cast(Object)(*cast(void**)p - pi.offset);
861         assert(o);
862         return o.toHash();
863     }
864
865     override equals_t equals(in void* p1, in void* p2)
866     {
867         Interface* pi = **cast(Interface ***)*cast(void**)p1;
868         Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
869         pi = **cast(Interface ***)*cast(void**)p2;
870         Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
871
872         return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
873     }
874
875     override int compare(in void* p1, in void* p2)
876     {
877         Interface* pi = **cast(Interface ***)*cast(void**)p1;
878         Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
879         pi = **cast(Interface ***)*cast(void**)p2;
880         Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
881         int c = 0;
882
883         // Regard null references as always being "less than"
884         if (o1 != o2)
885         {
886             if (o1)
887             {
888                 if (!o2)
889                     c = 1;
890                 else
891                     c = o1.opCmp(o2);
892             }
893             else
894                 c = -1;
895         }
896         return c;
897     }
898
899     override size_t tsize()
900     {
901         return Object.sizeof;
902     }
903
904     override uint flags() { return 1; }
905
906     TypeInfo_Class info;
907 }
908
909 class TypeInfo_Struct : TypeInfo
910 {
911     override string toString() { return name; }
912
913     override equals_t opEquals(Object o)
914     {
915         TypeInfo_Struct s;
916         return this is o ||
917                 ((s = cast(TypeInfo_Struct)o) !is null &&
918                  this.name == s.name &&
919                  this.init.length == s.init.length);
920     }
921
922     override hash_t getHash(in void* p)
923     {
924         assert(p);
925         if (xtoHash)
926         {
927             debug(PRINTF) printf("getHash() using xtoHash\n");
928             return (*xtoHash)(p);
929         }
930         else
931         {
932             debug(PRINTF) printf("getHash() using default hash\n");
933             return hashOf(p, init.length);
934         }
935     }
936
937     override equals_t equals(in void* p1, in void* p2)
938     {
939         if (p1 == p2)
940             return true;
941         else if (!p1 || !p2)
942             return false;
943         else if (xopEquals)
944             return (*xopEquals)(p1, p2);
945         else
946             // BUG: relies on the GC not moving objects
947             return memcmp(p1, p2, init.length) == 0;
948     }
949
950     override int compare(in void* p1, in void* p2)
951     {
952         // Regard null references as always being "less than"
953         if (p1 != p2)
954         {
955             if (p1)
956             {
957                 if (!p2)
958                     return true;
959                 else if (xopCmp)
960                     return (*xopCmp)(p2, p1);
961                 else
962                     // BUG: relies on the GC not moving objects
963                     return memcmp(p1, p2, init.length);
964             }
965             else
966                 return -1;
967         }
968         return 0;
969     }
970
971     override size_t tsize()
972     {
973         return init.length;
974     }
975
976     override void[] init() { return m_init; }
977
978     override uint flags() { return m_flags; }
979
980     override size_t talign() { return m_align; }
981
982     override void destroy(void* p)
983     {
984         if (xdtor)
985             (*xdtor)(p);
986     }
987
988     override void postblit(void* p)
989     {
990         if (xpostblit)
991             (*xpostblit)(p);
992     }
993
994     string name;
995     void[] m_init;      // initializer; init.ptr == null if 0 initialize
996
997     hash_t   function(in void*)           xtoHash;
998     equals_t function(in void*, in void*) xopEquals;
999     int      function(in void*, in void*) xopCmp;
1000     char[]   function(in void*)           xtoString;
1001
1002     uint m_flags;
1003
1004     const(MemberInfo[]) function(in char[]) xgetMembers;
1005     void function(void*)                    xdtor;
1006     void function(void*)                    xpostblit;
1007
1008     uint m_align;
1009
1010     version (X86_64)
1011     {
1012         override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1013         {   arg1 = m_arg1;
1014             arg2 = m_arg2;
1015             return 0;
1016         }
1017         TypeInfo m_arg1;
1018         TypeInfo m_arg2;
1019     }
1020 }
1021
1022 class TypeInfo_Tuple : TypeInfo
1023 {
1024     TypeInfo[] elements;
1025
1026     override string toString()
1027     {
1028         string s = "(";
1029         foreach (i, element; elements)
1030         {
1031             if (i)
1032                 s ~= ',';
1033             s ~= element.toString();
1034         }
1035         s ~= ")";
1036         return s;
1037     }
1038
1039     override equals_t opEquals(Object o)
1040     {
1041         if (this is o)
1042             return true;
1043
1044         auto t = cast(TypeInfo_Tuple)o;
1045         if (t && elements.length == t.elements.length)
1046         {
1047             for (size_t i = 0; i < elements.length; i++)
1048             {
1049                 if (elements[i] != t.elements[i])
1050                     return false;
1051             }
1052             return true;
1053         }
1054         return false;
1055     }
1056
1057     override hash_t getHash(in void* p)
1058     {
1059         assert(0);
1060     }
1061
1062     override equals_t equals(in void* p1, in void* p2)
1063     {
1064         assert(0);
1065     }
1066
1067     override int compare(in void* p1, in void* p2)
1068     {
1069         assert(0);
1070     }
1071
1072     override size_t tsize()
1073     {
1074         assert(0);
1075     }
1076
1077     override void swap(void* p1, void* p2)
1078     {
1079         assert(0);
1080     }
1081
1082     override void destroy(void* p)
1083     {
1084         assert(0);
1085     }
1086
1087     override void postblit(void* p)
1088     {
1089         assert(0);
1090     }
1091
1092     override size_t talign()
1093     {
1094         assert(0);
1095     }
1096
1097     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1098     {
1099         assert(0);
1100     }
1101 }
1102
1103 class TypeInfo_Const : TypeInfo
1104 {
1105     override string toString()
1106     {
1107         return cast(string) ("const(" ~ base.toString() ~ ")");
1108     }
1109
1110     //override equals_t opEquals(Object o) { return base.opEquals(o); }
1111     override equals_t opEquals(Object o)
1112     {
1113         if (this is o)
1114             return true;
1115
1116         if (typeid(this) != typeid(o))
1117             return false;
1118
1119         auto t = cast(TypeInfo_Const)o;
1120         if (base.opEquals(t.base))
1121         {
1122             return true;
1123         }
1124         return false;
1125     }
1126
1127     override hash_t getHash(in void *p) { return base.getHash(p); }
1128     override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
1129     override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
1130     override size_t tsize() { return base.tsize(); }
1131     override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
1132
1133     override TypeInfo next() { return base.next(); }
1134     override uint flags() { return base.flags(); }
1135     override void[] init() { return base.init(); }
1136
1137     override size_t talign() { return base.talign(); }
1138
1139     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1140     {   return base.argTypes(arg1, arg2);
1141     }
1142
1143     TypeInfo base;
1144 }
1145
1146 class TypeInfo_Invariant : TypeInfo_Const
1147 {
1148     override string toString()
1149     {
1150         return cast(string) ("immutable(" ~ base.toString() ~ ")");
1151     }
1152 }
1153
1154 class TypeInfo_Shared : TypeInfo_Const
1155 {
1156     override string toString()
1157     {
1158         return cast(string) ("shared(" ~ base.toString() ~ ")");
1159     }
1160 }
1161
1162 class TypeInfo_Inout : TypeInfo_Const
1163 {
1164     override string toString()
1165     {
1166         return cast(string) ("inout(" ~ base.toString() ~ ")");
1167     }
1168 }
1169
1170 abstract class MemberInfo
1171 {
1172     string name();
1173 }
1174
1175 class MemberInfo_field : MemberInfo
1176 {
1177     this(string name, TypeInfo ti, size_t offset)
1178     {
1179         m_name = name;
1180         m_typeinfo = ti;
1181         m_offset = offset;
1182     }
1183
1184     override string name() { return m_name; }
1185     TypeInfo typeInfo() { return m_typeinfo; }
1186     size_t offset() { return m_offset; }
1187
1188     string   m_name;
1189     TypeInfo m_typeinfo;
1190     size_t   m_offset;
1191 }
1192
1193 class MemberInfo_function : MemberInfo
1194 {
1195     this(string name, TypeInfo ti, void* fp, uint flags)
1196     {
1197         m_name = name;
1198         m_typeinfo = ti;
1199         m_fp = fp;
1200         m_flags = flags;
1201     }
1202
1203     override string name() { return m_name; }
1204     TypeInfo typeInfo() { return m_typeinfo; }
1205     void* fp() { return m_fp; }
1206     uint flags() { return m_flags; }
1207
1208     string   m_name;
1209     TypeInfo m_typeinfo;
1210     void*    m_fp;
1211     uint     m_flags;
1212 }
1213
1214
1215 ///////////////////////////////////////////////////////////////////////////////
1216 // Throwable
1217 ///////////////////////////////////////////////////////////////////////////////
1218
1219
1220 class Throwable : Object
1221 {
1222     interface TraceInfo
1223     {
1224         int opApply(scope int delegate(ref char[]));
1225         int opApply(scope int delegate(ref size_t, ref char[]));
1226         string toString();
1227     }
1228
1229     string      msg;
1230     string      file;
1231     size_t      line;
1232     TraceInfo   info;
1233     Throwable   next;
1234
1235     this(string msg, Throwable next = null)
1236     {
1237         this.msg = msg;
1238         this.next = next;
1239         //this.info = _d_traceContext();
1240     }
1241
1242     this(string msg, string file, size_t line, Throwable next = null)
1243     {
1244         this(msg, next);
1245         this.file = file;
1246         this.line = line;
1247         //this.info = _d_traceContext();
1248     }
1249
1250     override string toString()
1251     {
1252         char[20] tmp = void;
1253         char[]   buf;
1254
1255         for (Throwable e = this; e !is null; e = e.next)
1256         {
1257             if (e.file)
1258             {
1259                buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg;
1260             }
1261             else
1262             {
1263                buf ~= e.classinfo.name ~ ": " ~ e.msg;
1264             }
1265             if (e.info)
1266             {
1267                 buf ~= "\n----------------";
1268                 foreach (t; e.info)
1269                     buf ~= "\n" ~ t;
1270             }
1271             if (e.next)
1272                 buf ~= "\n";
1273         }
1274         return cast(string) buf;
1275     }
1276 }
1277
1278
1279 alias Throwable.TraceInfo function(void* ptr = null) TraceHandler;
1280 private __gshared TraceHandler traceHandler = null;
1281
1282
1283 /**
1284  * Overrides the default trace hander with a user-supplied version.
1285  *
1286  * Params:
1287  *  h = The new trace handler.  Set to null to use the default handler.
1288  */
1289 extern (C) void  rt_setTraceHandler(TraceHandler h)
1290 {
1291     traceHandler = h;
1292 }
1293
1294 /**
1295  * Return the current trace handler
1296  */
1297 extern (C) TraceHandler rt_getTraceHandler()
1298 {
1299     return traceHandler;
1300 }
1301
1302 /**
1303  * This function will be called when an exception is constructed.  The
1304  * user-supplied trace handler will be called if one has been supplied,
1305  * otherwise no trace will be generated.
1306  *
1307  * Params:
1308  *  ptr = A pointer to the location from which to generate the trace, or null
1309  *        if the trace should be generated from within the trace handler
1310  *        itself.
1311  *
1312  * Returns:
1313  *  An object describing the current calling context or null if no handler is
1314  *  supplied.
1315  */
1316 extern (C) Throwable.TraceInfo _d_traceContext(void* ptr = null)
1317 {
1318     if (traceHandler is null)
1319         return null;
1320     return traceHandler(ptr);
1321 }
1322
1323
1324 class Exception : Throwable
1325 {
1326
1327     this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1328     {
1329         super(msg, file, line, next);
1330     }
1331     this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
1332     {
1333         super(msg, file, line, next);
1334     }
1335 }
1336
1337 unittest
1338 {
1339     {
1340         auto e = new Exception("msg");
1341         assert(e.file == __FILE__);
1342         assert(e.line == __LINE__ - 2);
1343         assert(e.next is null);
1344         assert(e.msg == "msg");
1345     }
1346
1347     {
1348         auto e = new Exception("msg", new Exception("It's an Excepton!"), "hello", 42);
1349         assert(e.file == "hello");
1350         assert(e.line == 42);
1351         assert(e.next !is null);
1352         assert(e.msg == "msg");
1353     }
1354
1355     {
1356         auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
1357         assert(e.file == "hello");
1358         assert(e.line == 42);
1359         assert(e.next !is null);
1360         assert(e.msg == "msg");
1361     }
1362 }
1363
1364
1365 class Error : Throwable
1366 {
1367     this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
1368     {
1369         super(msg, file, line, next);
1370         bypassedException = null;
1371     }
1372
1373     this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1374     {
1375         super(msg, file, line, next);
1376         bypassedException = null;
1377     }
1378
1379     /// The first Exception which was bypassed when this Error was thrown,
1380     /// or null if no Exceptions were pending.
1381     Throwable   bypassedException;
1382 }
1383
1384 unittest
1385 {
1386     {
1387         auto e = new Error("msg");
1388         assert(e.file == __FILE__);
1389         assert(e.line == __LINE__ - 2);
1390         assert(e.next is null);
1391         assert(e.msg == "msg");
1392         assert(e.bypassedException is null);
1393     }
1394
1395     {
1396         auto e = new Error("msg", new Exception("It's an Excepton!"), "hello", 42);
1397         assert(e.file == "hello");
1398         assert(e.line == 42);
1399         assert(e.next !is null);
1400         assert(e.msg == "msg");
1401         assert(e.bypassedException is null);
1402     }
1403
1404     {
1405         auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!"));
1406         assert(e.file == "hello");
1407         assert(e.line == 42);
1408         assert(e.next !is null);
1409         assert(e.msg == "msg");
1410         assert(e.bypassedException is null);
1411     }
1412 }
1413
1414
1415 ///////////////////////////////////////////////////////////////////////////////
1416 // ModuleInfo
1417 ///////////////////////////////////////////////////////////////////////////////
1418
1419
1420 enum
1421 {
1422     MIctorstart  = 1,   // we've started constructing it
1423     MIctordone   = 2,   // finished construction
1424     MIstandalone = 4,   // module ctor does not depend on other module
1425                         // ctors being done first
1426     MItlsctor    = 8,
1427     MItlsdtor    = 0x10,
1428     MIctor       = 0x20,
1429     MIdtor       = 0x40,
1430     MIxgetMembers = 0x80,
1431     MIictor      = 0x100,
1432     MIunitTest   = 0x200,
1433     MIimportedModules = 0x400,
1434     MIlocalClasses = 0x800,
1435     MInew        = 0x80000000        // it's the "new" layout
1436 }
1437
1438
1439 struct ModuleInfo
1440 {
1441     struct New
1442     {
1443         uint flags;
1444         uint index;                        // index into _moduleinfo_array[]
1445
1446         /* Order of appearance, depending on flags
1447          * tlsctor
1448          * tlsdtor
1449          * xgetMembers
1450          * ctor
1451          * dtor
1452          * ictor
1453          * importedModules
1454          * localClasses
1455          * name
1456          */
1457     }
1458     struct Old
1459     {
1460         string          name;
1461         ModuleInfo*[]    importedModules;
1462         TypeInfo_Class[]     localClasses;
1463         uint            flags;
1464
1465         void function() ctor;       // module shared static constructor (order dependent)
1466         void function() dtor;       // module shared static destructor
1467         void function() unitTest;   // module unit tests
1468
1469         void* xgetMembers;          // module getMembers() function
1470
1471         void function() ictor;      // module shared static constructor (order independent)
1472
1473         void function() tlsctor;        // module thread local static constructor (order dependent)
1474         void function() tlsdtor;        // module thread local static destructor
1475
1476         uint index;                        // index into _moduleinfo_array[]
1477
1478         void*[1] reserved;          // for future expansion
1479     }
1480
1481     union
1482     {
1483         New n;
1484         Old o;
1485     }
1486
1487     @property isNew() { return n.flags & MInew; }
1488
1489     @property uint index() { return isNew ? n.index : o.index; }
1490     @property void index(uint i) { if (isNew) n.index = i; else o.index = i; }
1491
1492     @property uint flags() { return isNew ? n.flags : o.flags; }
1493     @property void flags(uint f) { if (isNew) n.flags = f; else o.flags = f; }
1494
1495     @property void function() tlsctor()
1496     {
1497         if (isNew)
1498         {
1499             if (n.flags & MItlsctor)
1500             {
1501                 size_t off = New.sizeof;
1502                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1503             }
1504             return null;
1505         }
1506         else
1507             return o.tlsctor;
1508     }
1509
1510     @property void function() tlsdtor()
1511     {
1512         if (isNew)
1513         {
1514             if (n.flags & MItlsdtor)
1515             {
1516                 size_t off = New.sizeof;
1517                 if (n.flags & MItlsctor)
1518                     off += o.tlsctor.sizeof;
1519                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1520             }
1521             return null;
1522         }
1523         else
1524             return o.tlsdtor;
1525     }
1526
1527     @property void* xgetMembers()
1528     {
1529         if (isNew)
1530         {
1531             if (n.flags & MIxgetMembers)
1532             {
1533                 size_t off = New.sizeof;
1534                 if (n.flags & MItlsctor)
1535                     off += o.tlsctor.sizeof;
1536                 if (n.flags & MItlsdtor)
1537                     off += o.tlsdtor.sizeof;
1538                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1539             }
1540             return null;
1541         }
1542         return o.xgetMembers;
1543     }
1544
1545     @property void function() ctor()
1546     {
1547         if (isNew)
1548         {
1549             if (n.flags & MIctor)
1550             {
1551                 size_t off = New.sizeof;
1552                 if (n.flags & MItlsctor)
1553                     off += o.tlsctor.sizeof;
1554                 if (n.flags & MItlsdtor)
1555                     off += o.tlsdtor.sizeof;
1556                 if (n.flags & MIxgetMembers)
1557                     off += o.xgetMembers.sizeof;
1558                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1559             }
1560             return null;
1561         }
1562         return o.ctor;
1563     }
1564
1565     @property void function() dtor()
1566     {
1567         if (isNew)
1568         {
1569             if (n.flags & MIdtor)
1570             {
1571                 size_t off = New.sizeof;
1572                 if (n.flags & MItlsctor)
1573                     off += o.tlsctor.sizeof;
1574                 if (n.flags & MItlsdtor)
1575                     off += o.tlsdtor.sizeof;
1576                 if (n.flags & MIxgetMembers)
1577                     off += o.xgetMembers.sizeof;
1578                 if (n.flags & MIctor)
1579                     off += o.ctor.sizeof;
1580                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1581             }
1582             return null;
1583         }
1584         return o.ctor;
1585     }
1586
1587     @property void function() ictor()
1588     {
1589         if (isNew)
1590         {
1591             if (n.flags & MIictor)
1592             {
1593                 size_t off = New.sizeof;
1594                 if (n.flags & MItlsctor)
1595                     off += o.tlsctor.sizeof;
1596                 if (n.flags & MItlsdtor)
1597                     off += o.tlsdtor.sizeof;
1598                 if (n.flags & MIxgetMembers)
1599                     off += o.xgetMembers.sizeof;
1600                 if (n.flags & MIctor)
1601                     off += o.ctor.sizeof;
1602                 if (n.flags & MIdtor)
1603                     off += o.ctor.sizeof;
1604                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1605             }
1606             return null;
1607         }
1608         return o.ictor;
1609     }
1610
1611     @property void function() unitTest()
1612     {
1613         if (isNew)
1614         {
1615             if (n.flags & MIunitTest)
1616             {
1617                 size_t off = New.sizeof;
1618                 if (n.flags & MItlsctor)
1619                     off += o.tlsctor.sizeof;
1620                 if (n.flags & MItlsdtor)
1621                     off += o.tlsdtor.sizeof;
1622                 if (n.flags & MIxgetMembers)
1623                     off += o.xgetMembers.sizeof;
1624                 if (n.flags & MIctor)
1625                     off += o.ctor.sizeof;
1626                 if (n.flags & MIdtor)
1627                     off += o.ctor.sizeof;
1628                 if (n.flags & MIictor)
1629                     off += o.ictor.sizeof;
1630                 return *cast(typeof(return)*)(cast(void*)(&this) + off);
1631             }
1632             return null;
1633         }
1634         return o.unitTest;
1635     }
1636
1637     @property ModuleInfo*[] importedModules()
1638     {
1639         if (isNew)
1640         {
1641             if (n.flags & MIimportedModules)
1642             {
1643                 size_t off = New.sizeof;
1644                 if (n.flags & MItlsctor)
1645                     off += o.tlsctor.sizeof;
1646                 if (n.flags & MItlsdtor)
1647                     off += o.tlsdtor.sizeof;
1648                 if (n.flags & MIxgetMembers)
1649                     off += o.xgetMembers.sizeof;
1650                 if (n.flags & MIctor)
1651                     off += o.ctor.sizeof;
1652                 if (n.flags & MIdtor)
1653                     off += o.ctor.sizeof;
1654                 if (n.flags & MIictor)
1655                     off += o.ictor.sizeof;
1656                 if (n.flags & MIunitTest)
1657                     off += o.unitTest.sizeof;
1658                 auto plength = cast(size_t*)(cast(void*)(&this) + off);
1659                 ModuleInfo** pm = cast(ModuleInfo**)(plength + 1);
1660                 return pm[0 .. *plength];
1661             }
1662             return null;
1663         }
1664         return o.importedModules;
1665     }
1666
1667     @property TypeInfo_Class[] localClasses()
1668     {
1669         if (isNew)
1670         {
1671             if (n.flags & MIlocalClasses)
1672             {
1673                 size_t off = New.sizeof;
1674                 if (n.flags & MItlsctor)
1675                     off += o.tlsctor.sizeof;
1676                 if (n.flags & MItlsdtor)
1677                     off += o.tlsdtor.sizeof;
1678                 if (n.flags & MIxgetMembers)
1679                     off += o.xgetMembers.sizeof;
1680                 if (n.flags & MIctor)
1681                     off += o.ctor.sizeof;
1682                 if (n.flags & MIdtor)
1683                     off += o.ctor.sizeof;
1684                 if (n.flags & MIictor)
1685                     off += o.ictor.sizeof;
1686                 if (n.flags & MIunitTest)
1687                     off += o.unitTest.sizeof;
1688                 if (n.flags & MIimportedModules)
1689                 {
1690                     auto plength = cast(size_t*)(cast(void*)(&this) + off);
1691                     off += size_t.sizeof + *plength * plength.sizeof;
1692                 }
1693                 auto plength = cast(size_t*)(cast(void*)(&this) + off);
1694                 TypeInfo_Class* pt = cast(TypeInfo_Class*)(plength + 1);
1695                 return pt[0 .. *plength];
1696             }
1697             return null;
1698         }
1699         return o.localClasses;
1700     }
1701
1702     @property string name()
1703     {
1704         if (isNew)
1705         {
1706             size_t off = New.sizeof;
1707             if (n.flags & MItlsctor)
1708                 off += o.tlsctor.sizeof;
1709             if (n.flags & MItlsdtor)
1710                 off += o.tlsdtor.sizeof;
1711             if (n.flags & MIxgetMembers)
1712                 off += o.xgetMembers.sizeof;
1713             if (n.flags & MIctor)
1714                 off += o.ctor.sizeof;
1715             if (n.flags & MIdtor)
1716                 off += o.ctor.sizeof;
1717             if (n.flags & MIictor)
1718                 off += o.ictor.sizeof;
1719             if (n.flags & MIunitTest)
1720                 off += o.unitTest.sizeof;
1721             if (n.flags & MIimportedModules)
1722             {
1723                 auto plength = cast(size_t*)(cast(void*)(&this) + off);
1724                 off += size_t.sizeof + *plength * plength.sizeof;
1725             }
1726             if (n.flags & MIlocalClasses)
1727             {
1728                 auto plength = cast(size_t*)(cast(void*)(&this) + off);
1729                 off += size_t.sizeof + *plength * plength.sizeof;
1730             }
1731             auto p = cast(immutable(char)*)(cast(void*)(&this) + off);
1732             auto len = strlen(p);
1733             return p[0 .. len];
1734         }
1735         return o.name;
1736     }
1737
1738
1739     static int opApply(scope int delegate(ref ModuleInfo*) dg)
1740     {
1741         int ret = 0;
1742
1743         foreach (m; _moduleinfo_array)
1744         {
1745             // TODO: Should null ModuleInfo be allowed?
1746             if (m !is null)
1747             {
1748                 ret = dg(m);
1749                 if (ret)
1750                     break;
1751             }
1752         }
1753         return ret;
1754     }
1755 }
1756
1757
1758 // Windows: this gets initialized by minit.asm
1759 // Posix: this gets initialized in _moduleCtor()
1760 extern (C) __gshared ModuleInfo*[] _moduleinfo_array;
1761
1762
1763 version (linux)
1764 {
1765     // This linked list is created by a compiler generated function inserted
1766     // into the .ctor list by the compiler.
1767     struct ModuleReference
1768     {
1769         ModuleReference* next;
1770         ModuleInfo*      mod;
1771     }
1772
1773     extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
1774 }
1775
1776 version (FreeBSD)
1777 {
1778     // This linked list is created by a compiler generated function inserted
1779     // into the .ctor list by the compiler.
1780     struct ModuleReference
1781     {
1782         ModuleReference* next;
1783         ModuleInfo*      mod;
1784     }
1785
1786     extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
1787 }
1788
1789 version (Solaris)
1790 {
1791     // This linked list is created by a compiler generated function inserted
1792     // into the .ctor list by the compiler.
1793     struct ModuleReference
1794     {
1795         ModuleReference* next;
1796         ModuleInfo*      mod;
1797     }
1798
1799     extern (C) __gshared ModuleReference* _Dmodule_ref;   // start of linked list
1800 }
1801
1802 version (OSX)
1803 {
1804     extern (C)
1805     {
1806         extern __gshared void* _minfo_beg;
1807         extern __gshared void* _minfo_end;
1808     }
1809 }
1810
1811 __gshared ModuleInfo*[] _moduleinfo_dtors;
1812 __gshared size_t        _moduleinfo_dtors_i;
1813
1814 __gshared ModuleInfo*[] _moduleinfo_tlsdtors;
1815 __gshared size_t        _moduleinfo_tlsdtors_i;
1816
1817 // Register termination function pointers
1818 extern (C) int _fatexit(void*);
1819
1820 /**
1821  * Initialize the modules.
1822  */
1823
1824 extern (C) void _moduleCtor()
1825 {
1826     debug(PRINTF) printf("_moduleCtor()\n");
1827     version (linux)
1828     {
1829         int len = 0;
1830         ModuleReference *mr;
1831
1832         for (mr = _Dmodule_ref; mr; mr = mr.next)
1833             len++;
1834         _moduleinfo_array = new ModuleInfo*[len];
1835         len = 0;
1836         for (mr = _Dmodule_ref; mr; mr = mr.next)
1837         {   _moduleinfo_array[len] = mr.mod;
1838             len++;
1839         }
1840     }
1841
1842     version (FreeBSD)
1843     {
1844         int len = 0;
1845         ModuleReference *mr;
1846
1847         for (mr = _Dmodule_ref; mr; mr = mr.next)
1848             len++;
1849         _moduleinfo_array = new ModuleInfo*[len];
1850         len = 0;
1851         for (mr = _Dmodule_ref; mr; mr = mr.next)
1852         {   _moduleinfo_array[len] = mr.mod;
1853             len++;
1854         }
1855     }
1856
1857     version (Solaris)
1858     {
1859         int len = 0;
1860         ModuleReference *mr;
1861
1862         for (mr = _Dmodule_ref; mr; mr = mr.next)
1863             len++;
1864         _moduleinfo_array = new ModuleInfo*[len];
1865         len = 0;
1866         for (mr = _Dmodule_ref; mr; mr = mr.next)
1867         {   _moduleinfo_array[len] = mr.mod;
1868             len++;
1869         }
1870     }
1871
1872     version (OSX)
1873     {
1874         /* The ModuleInfo references are stored in the special segment
1875          * __minfodata, which is bracketed by the segments __minfo_beg
1876          * and __minfo_end. The variables _minfo_beg and _minfo_end
1877          * are of zero size and are in the two bracketing segments,
1878          * respectively.
1879          */
1880          size_t length = cast(ModuleInfo**)&_minfo_end - cast(ModuleInfo**)&_minfo_beg;
1881          _moduleinfo_array = (cast(ModuleInfo**)&_minfo_beg)[0 .. length];
1882          debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length);
1883
1884          debug foreach (m; _moduleinfo_array)
1885          {
1886              // TODO: Should null ModuleInfo be allowed?
1887              if (m !is null)
1888                 //printf("\t%p\n", m);
1889                 printf("\t%.*s\n", m.name);
1890          }
1891     }   
1892
1893     version (Windows)
1894     {
1895         // Ensure module destructors also get called on program termination
1896         //_fatexit(&_STD_moduleDtor);
1897     }
1898
1899     //_moduleinfo_dtors = new ModuleInfo*[_moduleinfo_array.length];
1900     //debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
1901     // this will determine the constructor/destructor order, and check for
1902     // cycles for both shared and TLS ctors
1903     _checkModCtors();
1904
1905     _moduleIndependentCtors();
1906     // now, call the module constructors in the designated order
1907     foreach(i; 0.._moduleinfo_dtors_i)
1908     {
1909         ModuleInfo *mi = _moduleinfo_dtors[i];
1910         if(mi.ctor)
1911             (*mi.ctor)();
1912     }
1913
1914     //_moduleCtor2(_moduleinfo_array, 0);
1915     // NOTE: _moduleTlsCtor is now called manually by dmain2
1916     //_moduleTlsCtor();
1917 }
1918
1919 extern (C) void _moduleIndependentCtors()
1920 {
1921     debug(PRINTF) printf("_moduleIndependentCtors()\n");
1922     foreach (m; _moduleinfo_array)
1923     {
1924         // TODO: Should null ModuleInfo be allowed?
1925         if (m && m.ictor)
1926         {
1927             (*m.ictor)();
1928         }
1929     }
1930 }
1931
1932 /********************************************
1933  * Check for cycles on module constructors, and establish an order for module
1934  * constructors.
1935  */
1936 extern(C) void _checkModCtors()
1937 {
1938     // Create an array of modules that will determine the order of construction
1939     // (and destruction in reverse).
1940     auto dtors = _moduleinfo_dtors = new ModuleInfo*[_moduleinfo_array.length];
1941     size_t dtoridx = 0;
1942
1943     // this pointer will identify the module where the cycle was detected.
1944     ModuleInfo *cycleModule;
1945
1946     // allocate some stack arrays that will be used throughout the process.
1947     ubyte* p = cast(ubyte *)alloca(_moduleinfo_array.length * ubyte.sizeof);
1948     auto reachable = p[0.._moduleinfo_array.length];
1949
1950     p = cast(ubyte *)alloca(_moduleinfo_array.length * ubyte.sizeof);
1951     auto flags = p[0.._moduleinfo_array.length];
1952
1953
1954     // find all the non-trivial dependencies (that is, dependencies that have a
1955     // ctor or dtor) of a given module.  Doing this, we can 'skip over' the
1956     // trivial modules to get at the non-trivial ones.
1957     size_t _findDependencies(ModuleInfo *current, bool orig = true)
1958     {
1959         auto idx = current.index;
1960         if(reachable[idx])
1961             return 0;
1962         size_t result = 0;
1963         reachable[idx] = 1;
1964         if(!orig && (flags[idx] & (MIctor | MIdtor)) && !(flags[idx] & MIstandalone))
1965             // non-trivial, stop here
1966             return result + 1;
1967         foreach(ModuleInfo *m; current.importedModules)
1968         {
1969             result += _findDependencies(m, false);
1970         }
1971         return result;
1972     }
1973
1974     void println(string msg[]...)
1975     {
1976         version(Windows)
1977             immutable ret = "\r\n";
1978         else
1979             immutable ret = "\n";
1980         foreach(m; msg)
1981         {
1982             // write message to stderr
1983             console(m);
1984         }
1985         console(ret);
1986     }
1987
1988     bool printCycle(ModuleInfo *current, ModuleInfo *target, bool orig = true)
1989     {
1990         if(reachable[current.index])
1991             // already visited
1992             return false;
1993         if(current is target)
1994             // found path
1995             return true;
1996         reachable[current.index] = 1;
1997         if(!orig && (flags[current.index] & (MIctor | MIdtor)) && !(flags[current.index] & MIstandalone))
1998             // don't go through modules with ctors/dtors that aren't
1999             // standalone.
2000             return false;
2001         // search connections from current to see if we can get to target
2002         foreach(m; current.importedModules)
2003         {
2004             if(printCycle(m, target, false))
2005             {
2006                 // found the path, print this module
2007                 if(orig)
2008                     println("imported from ", current.name, " containing module ctor/dtor");
2009                 else
2010                     println("   imported from (", current.name, ")");
2011                 return true;
2012             }
2013         }
2014         return false;
2015     }
2016
2017     // This function will determine the order of construction/destruction and
2018     // check for cycles.
2019     bool _checkModCtors2(ModuleInfo *current)
2020     {
2021         // we only get called if current has a dtor or a ctor, so no need to
2022         // check that.  First, determine what non-trivial elements are
2023         // reachable.
2024         reachable[] = 0;
2025         auto nmodules = _findDependencies(current);
2026
2027         // allocate the dependencies on the stack
2028         ModuleInfo **p = cast(ModuleInfo **)alloca(nmodules * (ModuleInfo*).sizeof);
2029         auto dependencies = p[0..nmodules];
2030         uint depidx = 0;
2031         // fill in the dependencies
2032         foreach(i, r; reachable)
2033         {
2034             if(r)
2035             {
2036                 ModuleInfo *m = _moduleinfo_array[i];
2037                 if(m !is current && (flags[i] & (MIctor | MIdtor)) && !(flags[i] & MIstandalone))
2038                 {
2039                     dependencies[depidx++] = m;
2040                 }
2041             }
2042         }
2043         assert(depidx == nmodules);
2044
2045         // ok, now perform cycle detection
2046         auto curidx = current.index;
2047         flags[curidx] |= MIctorstart;
2048         bool valid = true;
2049         foreach(m; dependencies)
2050         {
2051             auto mflags = flags[m.index];
2052             if(mflags & MIctorstart)
2053             {
2054                 // found a cycle, but we don't care if the MIstandalone flag is
2055                 // set, this is a guarantee that there are no cycles in this
2056                 // module (not sure what triggers it)
2057                 println("Cyclic dependency in module ", m.name);
2058                 cycleModule = m;
2059                 valid = false;
2060
2061                 // use the currently allocated dtor path to record the loop
2062                 // that contains module ctors/dtors only.
2063                 dtoridx = dtors.length;
2064             }
2065             else if(!(mflags & MIctordone))
2066             {
2067                 valid = _checkModCtors2(m);
2068             }
2069
2070
2071             if(!valid)
2072             {
2073                 // cycle detected, now, we must print in reverse order the
2074                 // module include cycle.  For this, we need to traverse the
2075                 // graph of trivial modules again, this time printing them.
2076                 reachable[] = 0;
2077                 printCycle(current, m);
2078
2079                 // record this as a module that was used in the loop.
2080                 dtors[--dtoridx] = current;
2081                 if(current is cycleModule)
2082                 {
2083                     // print the cycle
2084                     println("Cycle detected between modules with ctors/dtors:");
2085                     foreach(cm; dtors[dtoridx..$])
2086                     {
2087                         console(cm.name)(" -> ");
2088                     }
2089                     println(cycleModule.name);
2090                     throw new Exception("Aborting!");
2091                 }
2092                 return false;
2093             }
2094         }
2095         flags[curidx] = (flags[curidx] & ~MIctorstart) | MIctordone;
2096         // add this module to the construction order list
2097         dtors[dtoridx++] = current;
2098         return true;
2099     }
2100
2101     void _checkModCtors3()
2102     {
2103         foreach(m; _moduleinfo_array)
2104         {
2105             // TODO: Should null ModuleInfo be allowed?
2106             if (m is null) continue;
2107             auto flag = flags[m.index];
2108             if((flag & (MIctor | MIdtor)) && !(flag & MIctordone))
2109             {
2110                 if(flag & MIstandalone)
2111                 {
2112                     // no need to run a check on this one, but we do need to call its ctor/dtor
2113                     dtors[dtoridx++] = m;
2114                 }
2115                 else
2116                     _checkModCtors2(m);
2117             }
2118         }
2119     }
2120
2121     // ok, now we need to assign indexes, and also initialize the flags
2122     foreach(uint i, m; _moduleinfo_array)
2123     {
2124         // TODO: Should null ModuleInfo be allowed?
2125         if (m is null) continue;
2126         m.index = i;
2127         ubyte flag = m.flags & MIstandalone;
2128         if(m.dtor)
2129             flag |= MIdtor;
2130         if(m.ctor)
2131             flag |= MIctor;
2132         flags[i] = flag;
2133     }
2134
2135     // everything's all set up for shared ctors
2136     _checkModCtors3();
2137
2138     // store the number of dtors/ctors
2139     _moduleinfo_dtors_i = dtoridx;
2140
2141     // set up everything for tls ctors
2142     dtors = _moduleinfo_tlsdtors = new ModuleInfo*[_moduleinfo_array.length];
2143     dtoridx = 0;
2144     foreach(i, m; _moduleinfo_array)
2145     {
2146         // TODO: Should null ModuleInfo be allowed?
2147         if (m is null) continue;
2148         ubyte flag = m.flags & MIstandalone;
2149         if(m.tlsdtor)
2150             flag |= MIdtor;
2151         if(m.tlsctor)
2152             flag |= MIctor;
2153         flags[i] = flag;
2154     }
2155
2156     // ok, run it
2157     _checkModCtors3();
2158
2159     // store the number of dtors/ctors
2160     _moduleinfo_tlsdtors_i = dtoridx;
2161 }
2162
2163 /********************************************
2164  * Run static constructors for thread local global data.
2165  */
2166
2167 extern (C) void _moduleTlsCtor()
2168 {
2169     // call the module constructors in the correct order as determined by the
2170     // check routine.
2171     foreach(i; 0.._moduleinfo_tlsdtors_i)
2172     {
2173         ModuleInfo *mi = _moduleinfo_tlsdtors[i];
2174         if(mi.tlsctor)
2175             (*mi.tlsctor)();
2176     }
2177 }
2178
2179
2180 /**
2181  * Destruct the modules.
2182  */
2183
2184 // Starting the name with "_STD" means under Posix a pointer to the
2185 // function gets put in the .dtors segment.
2186
2187 extern (C) void _moduleDtor()
2188 {
2189     debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
2190
2191     // NOTE: _moduleTlsDtor is now called manually by dmain2
2192     //_moduleTlsDtor();
2193     for (auto i = _moduleinfo_dtors_i; i-- != 0;)
2194     {
2195         ModuleInfo* m = _moduleinfo_dtors[i];
2196
2197         debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name.length, m.name.ptr, m);
2198         if (m.dtor)
2199         {
2200             (*m.dtor)();
2201         }
2202     }
2203     debug(PRINTF) printf("_moduleDtor() done\n");
2204 }
2205
2206 extern (C) void _moduleTlsDtor()
2207 {
2208     debug(PRINTF) printf("_moduleTlsDtor(): %d modules\n", _moduleinfo_tlsdtors_i);
2209     version(none)
2210     {
2211         printf("_moduleinfo_tlsdtors = %d,%p\n", _moduleinfo_tlsdtors);
2212         foreach (i,m; _moduleinfo_tlsdtors[0..11])
2213             printf("[%d] = %p\n", i, m);
2214     }
2215
2216     for (auto i = _moduleinfo_tlsdtors_i; i-- != 0;)
2217     {
2218         ModuleInfo* m = _moduleinfo_tlsdtors[i];
2219
2220         debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name.length, m.name.ptr, m);
2221         if (m.tlsdtor)
2222         {
2223             (*m.tlsdtor)();
2224         }
2225     }
2226     debug(PRINTF) printf("_moduleTlsDtor() done\n");
2227 }
2228
2229 // Alias the TLS ctor and dtor using "rt_" prefixes, since these routines
2230 // must be called by core.thread.
2231
2232 extern (C) void rt_moduleTlsCtor()
2233 {
2234     _moduleTlsCtor();
2235 }
2236
2237 extern (C) void rt_moduleTlsDtor()
2238 {
2239     _moduleTlsDtor();
2240 }
2241
2242 ///////////////////////////////////////////////////////////////////////////////
2243 // Monitor
2244 ///////////////////////////////////////////////////////////////////////////////
2245
2246 alias Object.Monitor        IMonitor;
2247 alias void delegate(Object) DEvent;
2248
2249 // NOTE: The dtor callback feature is only supported for monitors that are not
2250 //       supplied by the user.  The assumption is that any object with a user-
2251 //       supplied monitor may have special storage or lifetime requirements and
2252 //       that as a result, storing references to local objects within Monitor
2253 //       may not be safe or desirable.  Thus, devt is only valid if impl is
2254 //       null.
2255 struct Monitor
2256 {
2257     IMonitor impl;
2258     /* internal */
2259     DEvent[] devt;
2260     size_t   refs;
2261     /* stuff */
2262 }
2263
2264 Monitor* getMonitor(Object h)
2265 {
2266     return cast(Monitor*) h.__monitor;
2267 }
2268
2269 void setMonitor(Object h, Monitor* m)
2270 {
2271     h.__monitor = m;
2272 }
2273
2274 void setSameMutex(shared Object ownee, shared Object owner)
2275 in
2276 {
2277     assert(ownee.__monitor is null);
2278 }
2279 body
2280 {
2281     auto m = cast(shared(Monitor)*) owner.__monitor;
2282
2283     if (m is null)
2284     {
2285         _d_monitor_create(cast(Object) owner);
2286         m = cast(shared(Monitor)*) owner.__monitor;
2287     }
2288    
2289     auto i = m.impl;
2290     if (i is null)
2291     {
2292         atomicOp!("+=")(m.refs, cast(size_t)1);
2293         ownee.__monitor = owner.__monitor;
2294         return;
2295     }
2296     // If m.impl is set (ie. if this is a user-created monitor), assume
2297     // the monitor is garbage collected and simply copy the reference.
2298     ownee.__monitor = owner.__monitor;
2299 }
2300
2301 extern (C) void _d_monitor_create(Object);
2302 extern (C) void _d_monitor_destroy(Object);
2303 extern (C) void _d_monitor_lock(Object);
2304 extern (C) int  _d_monitor_unlock(Object);
2305
2306 extern (C) void _d_monitordelete(Object h, bool det)
2307 {
2308     // det is true when the object is being destroyed deterministically (ie.
2309     // when it is explicitly deleted or is a scope object whose time is up).
2310     Monitor* m = getMonitor(h);
2311
2312     if (m !is null)
2313     {
2314         IMonitor i = m.impl;
2315         if (i is null)
2316         {
2317             auto s = cast(shared(Monitor)*) m;
2318             if(!atomicOp!("-=")(s.refs, cast(size_t) 1))
2319             {
2320                 _d_monitor_devt(m, h);
2321                 _d_monitor_destroy(h);
2322                 setMonitor(h, null);
2323             }
2324             return;
2325         }
2326         // NOTE: Since a monitor can be shared via setSameMutex it isn't safe
2327         //       to explicitly delete user-created monitors--there's no
2328         //       refcount and it may have multiple owners.
2329         /+
2330         if (det && (cast(void*) i) !is (cast(void*) h))
2331             delete i;
2332         +/
2333         setMonitor(h, null);
2334     }
2335 }
2336
2337 extern (C) void _d_monitorenter(Object h)
2338 {
2339     Monitor* m = getMonitor(h);
2340
2341     if (m is null)
2342     {
2343         _d_monitor_create(h);
2344         m = getMonitor(h);
2345     }
2346
2347     IMonitor i = m.impl;
2348
2349     if (i is null)
2350     {
2351         _d_monitor_lock(h);
2352         return;
2353     }
2354     i.lock();
2355 }
2356
2357 extern (C) void _d_monitorexit(Object h)
2358 {
2359     Monitor* m = getMonitor(h);
2360     IMonitor i = m.impl;
2361
2362     if (i is null)
2363     {
2364         _d_monitor_unlock(h);
2365         return;
2366     }
2367     i.unlock();
2368 }
2369
2370 extern (C) void _d_monitor_devt(Monitor* m, Object h)
2371 {
2372     if (m.devt.length)
2373     {
2374         DEvent[] devt;
2375
2376         synchronized (h)
2377         {
2378             devt = m.devt;
2379             m.devt = null;
2380         }
2381         foreach (v; devt)
2382         {
2383             if (v)
2384                 v(h);
2385         }
2386         free(devt.ptr);
2387     }
2388 }
2389
2390 extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
2391 {
2392     synchronized (h)
2393     {
2394         Monitor* m = getMonitor(h);
2395         assert(m.impl is null);
2396
2397         foreach (ref v; m.devt)
2398         {
2399             if (v is null || v == e)
2400             {
2401                 v = e;
2402                 return;
2403             }
2404         }
2405
2406         auto len = m.devt.length + 4; // grow by 4 elements
2407         auto pos = m.devt.length;     // insert position
2408         auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
2409         if (!p)
2410             onOutOfMemoryError();
2411         m.devt = (cast(DEvent*)p)[0 .. len];
2412         m.devt[pos+1 .. len] = null;
2413         m.devt[pos] = e;
2414     }
2415 }
2416
2417 extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
2418 {
2419     synchronized (h)
2420     {
2421         Monitor* m = getMonitor(h);
2422         assert(m.impl is null);
2423
2424         foreach (p, v; m.devt)
2425         {
2426             if (v == e)
2427             {
2428                 memmove(&m.devt[p],
2429                         &m.devt[p+1],
2430                         (m.devt.length - p - 1) * DEvent.sizeof);
2431                 m.devt[$ - 1] = null;
2432                 return;
2433             }
2434         }
2435     }
2436 }
2437
2438 extern (C)
2439 {
2440     // from druntime/src/compiler/dmd/aaA.d
2441
2442     size_t _aaLen(void* p);
2443     void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...);
2444     void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...);
2445     void* _aaIn(void* p, TypeInfo keyti);
2446     void _aaDel(void* p, TypeInfo keyti, ...);
2447     void[] _aaValues(void* p, size_t keysize, size_t valuesize);
2448     void[] _aaKeys(void* p, size_t keysize);
2449     void* _aaRehash(void** pp, TypeInfo keyti);
2450
2451     extern (D) typedef scope int delegate(void *) _dg_t;
2452     int _aaApply(void* aa, size_t keysize, _dg_t dg);
2453
2454     extern (D) typedef scope int delegate(void *, void *) _dg2_t;
2455     int _aaApply2(void* aa, size_t keysize, _dg2_t dg);
2456
2457     void* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...);
2458 }
2459
2460 struct AssociativeArray(Key, Value)
2461 {
2462     void* p;
2463
2464     size_t length() @property { return _aaLen(p); }
2465
2466     Value[Key] rehash() @property
2467     {
2468         auto p = _aaRehash(&p, typeid(Value[Key]));
2469         return *cast(Value[Key]*)(&p);
2470     }
2471
2472     Value[] values() @property
2473     {
2474         auto a = _aaValues(p, Key.sizeof, Value.sizeof);
2475         return *cast(Value[]*) &a;
2476     }
2477
2478     Key[] keys() @property
2479     {
2480         auto a = _aaKeys(p, Key.sizeof);
2481         return *cast(Key[]*) &a;
2482     }
2483
2484     int opApply(scope int delegate(ref Key, ref Value) dg)
2485     {
2486         return _aaApply2(p, Key.sizeof, cast(_dg2_t)dg);
2487     }
2488
2489     int opApply(scope int delegate(ref Value) dg)
2490     {
2491         return _aaApply(p, Key.sizeof, cast(_dg_t)dg);
2492     }
2493
2494     int delegate(int delegate(ref Key) dg) byKey()
2495     {
2496         // Discard the Value part and just do the Key
2497         int foo(int delegate(ref Key) dg)
2498         {
2499             int byKeydg(ref Key key, ref Value value)
2500             {
2501                 return dg(key);
2502             }
2503
2504         return _aaApply2(p, Key.sizeof, cast(_dg2_t)&byKeydg);
2505     }
2506
2507         return &foo;
2508     }
2509
2510     int delegate(int delegate(ref Value) dg) byValue()
2511     {
2512         return &opApply;
2513     }
2514
2515     Value get(Key key, lazy Value defaultValue)
2516     {
2517         auto p = key in *cast(Value[Key]*)(&p);
2518         return p ? *p : defaultValue;
2519     }
2520
2521     static if (is(typeof({ Value[Key] r; r[Key.init] = Value.init; }())))
2522         @property Value[Key] dup()
2523         {
2524             Value[Key] result;
2525             foreach (k, v; this)
2526             {
2527                 result[k] = v;
2528             }
2529             return result;
2530         }
2531 }
2532
2533 unittest
2534 {
2535     auto a = [ 1:"one", 2:"two", 3:"three" ];
2536     auto b = a.dup;
2537     assert(b == [ 1:"one", 2:"two", 3:"three" ]);
2538 }
2539
2540 void clear(T)(T obj) if (is(T == class))
2541 {
2542     if (!obj) return;
2543     auto ci = obj.classinfo;
2544     auto defaultCtor =
2545         cast(void function(Object)) ci.defaultConstructor;
2546     version(none) // enforce isn't available in druntime
2547         _enforce(defaultCtor || (ci.flags & 8) == 0);
2548     immutable size = ci.init.length;
2549
2550     auto ci2 = ci;
2551     do
2552     {
2553         auto dtor = cast(void function(Object))ci2.destructor;
2554         if (dtor)
2555             dtor(obj);
2556         ci2 = ci2.base;
2557     } while (ci2)
2558
2559     auto buf = (cast(void*) obj)[0 .. size];
2560     buf[] = ci.init;
2561     if (defaultCtor)
2562         defaultCtor(obj);
2563 }
2564
2565 version(unittest) unittest
2566 {
2567    {
2568        class A { string s = "A"; this() {} }
2569        auto a = new A;
2570        a.s = "asd";
2571        clear(a);
2572        assert(a.s == "A");
2573    }
2574    {
2575        static bool destroyed = false;
2576        class B
2577        {
2578            string s = "B";
2579            this() {}
2580            ~this()
2581            {
2582                destroyed = true;
2583            }
2584        }
2585        auto a = new B;
2586        a.s = "asd";
2587        clear(a);
2588        assert(destroyed);
2589        assert(a.s == "B");
2590    }
2591    {
2592        class C
2593        {
2594            string s;
2595            this()
2596            {
2597                s = "C";
2598            }
2599        }
2600        auto a = new C;
2601        a.s = "asd";
2602        clear(a);
2603        assert(a.s == "C");
2604    }
2605 }
2606
2607 void clear(T)(ref T obj) if (is(T == struct))
2608 {
2609     static if (is(typeof(obj.__dtor())))
2610     {
2611         obj.__dtor();
2612     }
2613     auto buf = (cast(ubyte*) &obj)[0 .. T.sizeof];
2614     auto init = cast(ubyte[])typeid(T).init();
2615     if(init.ptr is null) // null ptr means initialize to 0s
2616         buf[] = 0;
2617     else
2618         buf[] = init[];
2619 }
2620
2621 version(unittest) unittest
2622 {
2623    {
2624        struct A { string s = "A";  }
2625        A a;
2626        a.s = "asd";
2627        clear(a);
2628        assert(a.s == "A");
2629    }
2630    {
2631        static bool destroyed = false;
2632        struct B
2633        {
2634            string s = "B";
2635            ~this()
2636            {
2637                destroyed = true;
2638            }
2639        }
2640        B a;
2641        a.s = "asd";
2642        clear(a);
2643        assert(destroyed);
2644        assert(a.s == "B");
2645    }
2646 }
2647
2648 void clear(T : U[n], U, size_t n)(ref T obj)
2649 {
2650     obj = T.init;
2651 }
2652
2653 version(unittest) unittest
2654 {
2655     int[2] a;
2656     a[0] = 1;
2657     a[1] = 2;
2658     clear(a);
2659     assert(a == [ 0, 0 ]);
2660 }
2661
2662 void clear(T)(ref T obj)
2663     if (!is(T == struct) && !is(T == class) && !_isStaticArray!T)
2664 {
2665     obj = T.init;
2666 }
2667
2668 template _isStaticArray(T : U[N], U, size_t N)
2669 {
2670     enum bool _isStaticArray = true;
2671 }
2672
2673 template _isStaticArray(T)
2674 {
2675     enum bool _isStaticArray = false;
2676 }
2677
2678 version(unittest) unittest
2679 {
2680    {
2681        int a = 42;
2682        clear(a);
2683        assert(a == 0);
2684    }
2685    {
2686        float a = 42;
2687        clear(a);
2688        assert(isnan(a));
2689    }
2690 }
2691
2692 version (unittest)
2693 {
2694     bool isnan(float x)
2695     {
2696         return x != x;
2697     }
2698 }
2699
2700 /**
2701  * (Property) Get the current capacity of an array.  The capacity is the number
2702  * of elements that the array can grow to before the array must be
2703  * extended/reallocated.
2704  */
2705 @property size_t capacity(T)(T[] arr)
2706 {
2707     return _d_arraysetcapacity(typeid(T[]), 0, cast(void *)&arr);
2708 }
2709
2710 /**
2711  * Try to reserve capacity for an array.  The capacity is the number of
2712  * elements that the array can grow to before the array must be
2713  * extended/reallocated.
2714  *
2715  * The return value is the new capacity of the array (which may be larger than
2716  * the requested capacity).
2717  */
2718 size_t reserve(T)(ref T[] arr, size_t newcapacity)
2719 {
2720     return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void *)&arr);
2721 }
2722
2723 /**
2724  * Assume that it is safe to append to this array.  Appends made to this array
2725  * after calling this function may append in place, even if the array was a
2726  * slice of a larger array to begin with.
2727  *
2728  * Use this only when you are sure no elements are in use beyond the array in
2729  * the memory block.  If there are, those elements could be overwritten by
2730  * appending to this array.
2731  *
2732  * Calling this function, and then using references to data located after the
2733  * given array results in undefined behavior.
2734  */
2735 void assumeSafeAppend(T)(T[] arr)
2736 {
2737     _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
2738 }
2739
2740 version (unittest) unittest
2741 {
2742     {
2743         int[] arr;
2744         auto newcap = arr.reserve(2000);
2745         assert(newcap >= 2000);
2746         assert(newcap == arr.capacity);
2747         auto ptr = arr.ptr;
2748         foreach(i; 0..2000)
2749             arr ~= i;
2750         assert(ptr == arr.ptr);
2751         arr = arr[0..1];
2752         arr.assumeSafeAppend();
2753         arr ~= 5;
2754         assert(ptr == arr.ptr);
2755     }
2756 }
2757
2758
2759 version (none)
2760 {
2761     // enforce() copied from Phobos std.contracts for clear(), left out until
2762     // we decide whether to use it.
2763    
2764
2765     T _enforce(T, string file = __FILE__, int line = __LINE__)
2766         (T value, lazy const(char)[] msg = null)
2767     {
2768         if (!value) bailOut(file, line, msg);
2769         return value;
2770     }
2771
2772     T _enforce(T, string file = __FILE__, int line = __LINE__)
2773         (T value, scope void delegate() dg)
2774     {
2775         if (!value) dg();
2776         return value;
2777     }
2778
2779     T _enforce(T)(T value, lazy Exception ex)
2780     {
2781         if (!value) throw ex();
2782         return value;
2783     }
2784
2785     private void _bailOut(string file, int line, in char[] msg)
2786     {
2787         char[21] buf;
2788         throw new Exception(cast(string)(file ~ "(" ~ ulongToString(buf[], line) ~ "): " ~ (msg ? msg : "Enforcement failed")));
2789     }
2790 }
2791
2792
2793 /***************************************
2794  * Helper function used to see if two containers of different
2795  * types have the same contents in the same sequence.
2796  */
2797
2798 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
2799 {
2800     if (a1.length != a2.length)
2801         return false;
2802     foreach(i, a; a1)
2803     {
2804         if (a != a2[i])
2805             return false;
2806     }
2807     return true;
2808 }
Note: See TracBrowser for help on using the browser.