Mercurial > projects > ldc
annotate lphobos/internal/objectimpl.d @ 89:ccca1c13e13a trunk
[svn r93] a few fixes, some phobos additions.
some very rough groundwork for moduleinfo and classinfo support
author | lindquist |
---|---|
date | Wed, 07 Nov 2007 02:45:47 +0100 |
parents | fd32135dca3e |
children | 5b5194b25f33 |
rev | line source |
---|---|
1 | 1 |
2 /** | |
3 * Part of the D programming language runtime library. | |
4 * Forms the symbols available to all D programs. Includes | |
5 * Object, which is the root of the class object hierarchy. | |
6 * | |
7 * This module is implicitly imported. | |
8 * Macros: | |
9 * WIKI = Phobos/Object | |
10 */ | |
11 | |
12 /* | |
13 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com | |
14 * Written by Walter Bright | |
15 * | |
16 * This software is provided 'as-is', without any express or implied | |
17 * warranty. In no event will the authors be held liable for any damages | |
18 * arising from the use of this software. | |
19 * | |
20 * Permission is granted to anyone to use this software for any purpose, | |
21 * including commercial applications, and to alter it and redistribute it | |
22 * freely, in both source and binary form, subject to the following | |
23 * restrictions: | |
24 * | |
25 * o The origin of this software must not be misrepresented; you must not | |
26 * claim that you wrote the original software. If you use this software | |
27 * in a product, an acknowledgment in the product documentation would be | |
28 * appreciated but is not required. | |
29 * o Altered source versions must be plainly marked as such, and must not | |
30 * be misrepresented as being the original software. | |
31 * o This notice may not be removed or altered from any source | |
32 * distribution. | |
33 */ | |
34 | |
89 | 35 /* |
36 * This copy is modified to work with LLVMDC by Tomas Lindquist Olsen 2007 | |
37 */ | |
1 | 38 |
39 module object; | |
40 | |
89 | 41 import std.outofmemory; |
1 | 42 |
52 | 43 /** |
44 * An unsigned integral type large enough to span the memory space. Use for | |
45 * array indices and pointer offsets for maximal portability to | |
46 * architectures that have different memory address ranges. This is | |
47 * analogous to C's size_t. | |
48 */ | |
49 alias typeof(int.sizeof) size_t; | |
50 | |
51 /** | |
52 * A signed integral type large enough to span the memory space. Use for | |
53 * pointer differences and for size_t differences for maximal portability to | |
54 * architectures that have different memory address ranges. This is | |
55 * analogous to C's ptrdiff_t. | |
56 */ | |
57 alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; | |
58 | |
59 alias size_t hash_t; | |
60 | |
1 | 61 extern (C) |
62 { /// C's printf function. | |
63 int printf(char *, ...); | |
52 | 64 void trace_term(); |
1 | 65 |
66 int memcmp(void *, void *, size_t); | |
67 void* memcpy(void *, void *, size_t); | |
68 void* calloc(size_t, size_t); | |
69 void* realloc(void*, size_t); | |
70 void free(void*); | |
71 | |
72 //Object _d_newclass(ClassInfo ci); | |
73 } | |
74 | |
75 /// Standard boolean type. | |
76 alias bool bit; | |
77 | |
52 | 78 alias char[] string; |
79 alias wchar[] wstring; | |
80 alias dchar[] dstring; | |
1 | 81 |
82 /+ | |
52 | 83 |
1 | 84 /* ************************* |
85 * Internal struct pointed to by the hidden .monitor member. | |
86 */ | |
87 struct Monitor | |
88 { | |
89 void delegate(Object)[] delegates; | |
90 | |
91 /* More stuff goes here defined by internal/monitor.c */ | |
92 } | |
52 | 93 |
1 | 94 +/ |
95 | |
96 /****************** | |
97 * All D class objects inherit from Object. | |
98 */ | |
99 class Object | |
100 { | |
101 void print() | |
102 { | |
103 char[] s = toString(); | |
104 printf("%.*s\n", s.length, s.ptr); | |
105 } | |
106 | |
107 /** | |
108 * Convert Object to a human readable string. | |
109 */ | |
110 char[] toString() | |
111 { | |
112 //return this.classinfo.name; | |
52 | 113 return "object.Object (no classinfo yet)"; |
1 | 114 } |
115 | |
116 /** | |
117 * Compute hash function for Object. | |
118 */ | |
119 hash_t toHash() | |
120 { | |
121 // BUG: this prevents a compacting GC from working, needs to be fixed | |
52 | 122 return cast(hash_t)cast(void *)this; |
1 | 123 } |
124 | |
125 /** | |
126 * Compare with another Object obj. | |
127 * Returns: | |
128 * $(TABLE | |
129 * $(TR $(TD this < obj) $(TD < 0)) | |
130 * $(TR $(TD this == obj) $(TD 0)) | |
131 * $(TR $(TD this > obj) $(TD > 0)) | |
132 * ) | |
133 */ | |
134 int opCmp(Object o) | |
135 { | |
136 // BUG: this prevents a compacting GC from working, needs to be fixed | |
137 //return cast(int)cast(void *)this - cast(int)cast(void *)o; | |
138 | |
139 //throw new Error("need opCmp for class " ~ this.classinfo.name); | |
52 | 140 throw new Error("need opCmp for class unknown object.Object (no classinfo yet)"); |
1 | 141 } |
142 | |
143 /** | |
144 * Returns !=0 if this object does have the same contents as obj. | |
145 */ | |
146 int opEquals(Object o) | |
147 { | |
148 return cast(int)(this is o); | |
149 } | |
150 | |
151 /* ** | |
152 * Call delegate dg, passing this to it, when this object gets destroyed. | |
153 * Use extreme caution, as the list of delegates is stored in a place | |
154 * not known to the gc. Thus, if any objects pointed to by one of these | |
155 * delegates gets freed by the gc, calling the delegate will cause a | |
156 * crash. | |
157 * This is only for use by library developers, as it will need to be | |
158 * redone if weak pointers are added or a moving gc is developed. | |
159 */ | |
160 final void notifyRegister(void delegate(Object) dg) | |
161 { | |
52 | 162 /+ |
1 | 163 //printf("notifyRegister(dg = %llx, o = %p)\n", dg, this); |
52 | 164 synchronized (this) |
1 | 165 { |
166 Monitor* m = cast(Monitor*)(cast(void**)this)[1]; | |
167 foreach (inout x; m.delegates) | |
168 { | |
169 if (!x || x == dg) | |
170 { x = dg; | |
171 return; | |
172 } | |
173 } | |
174 | |
175 // Increase size of delegates[] | |
176 auto len = m.delegates.length; | |
177 auto startlen = len; | |
178 if (len == 0) | |
179 { | |
180 len = 4; | |
181 auto p = calloc((void delegate(Object)).sizeof, len); | |
182 if (!p) | |
183 _d_OutOfMemory(); | |
184 m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; | |
185 } | |
186 else | |
187 { | |
188 len += len + 4; | |
189 auto p = realloc(m.delegates.ptr, (void delegate(Object)).sizeof * len); | |
190 if (!p) | |
191 _d_OutOfMemory(); | |
192 m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; | |
193 m.delegates[startlen .. len] = null; | |
194 } | |
195 m.delegates[startlen] = dg; | |
52 | 196 } |
197 +/ | |
1 | 198 } |
199 | |
200 /* ** | |
201 * Remove delegate dg from the notify list. | |
202 * This is only for use by library developers, as it will need to be | |
203 * redone if weak pointers are added or a moving gc is developed. | |
204 */ | |
205 final void notifyUnRegister(void delegate(Object) dg) | |
206 { | |
52 | 207 /+ |
208 synchronized (this) | |
1 | 209 { |
210 Monitor* m = cast(Monitor*)(cast(void**)this)[1]; | |
211 foreach (inout x; m.delegates) | |
212 { | |
213 if (x == dg) | |
214 x = null; | |
215 } | |
52 | 216 } |
217 +/ | |
1 | 218 } |
219 | |
220 /****** | |
221 * Create instance of class specified by classname. | |
222 * The class must either have no constructors or have | |
223 * a default constructor. | |
224 * Returns: | |
225 * null if failed | |
226 */ | |
52 | 227 static Object factory(char[] classname) |
1 | 228 { |
52 | 229 /+ |
42 | 230 auto ci = ClassInfo.find(classname); |
1 | 231 if (ci) |
232 { | |
233 return ci.create(); | |
42 | 234 } |
52 | 235 +/ |
1 | 236 return null; |
52 | 237 } |
1 | 238 } |
239 | |
240 /+ | |
241 extern (C) void _d_notify_release(Object o) | |
242 { | |
243 //printf("_d_notify_release(o = %p)\n", o); | |
244 Monitor* m = cast(Monitor*)(cast(void**)o)[1]; | |
245 if (m.delegates.length) | |
246 { | |
247 auto dgs = m.delegates; | |
248 synchronized (o) | |
249 { | |
250 dgs = m.delegates; | |
251 m.delegates = null; | |
252 } | |
253 | |
254 foreach (dg; dgs) | |
255 { | |
256 if (dg) | |
257 { //printf("calling dg = %llx (%p)\n", dg, o); | |
258 dg(o); | |
259 } | |
260 } | |
261 | |
262 free(dgs.ptr); | |
263 } | |
264 } | |
265 | |
89 | 266 +/ |
267 | |
1 | 268 /** |
269 * Information about an interface. | |
270 * A pointer to this appears as the first entry in the interface's vtbl[]. | |
271 */ | |
272 struct Interface | |
273 { | |
274 ClassInfo classinfo; /// .classinfo for this interface (not for containing class) | |
275 void *[] vtbl; | |
276 int offset; /// offset to Interface 'this' from Object 'this' | |
277 } | |
278 | |
279 import std.moduleinit; | |
89 | 280 |
1 | 281 /** |
282 * Runtime type information about a class. Can be retrieved for any class type | |
283 * or instance by using the .classinfo property. | |
284 * A pointer to this appears as the first entry in the class's vtbl[]. | |
285 */ | |
286 class ClassInfo : Object | |
287 { | |
288 byte[] init; /** class static initializer | |
289 * (init.length gives size in bytes of class) | |
290 */ | |
291 char[] name; /// class name | |
292 void *[] vtbl; /// virtual function pointer table | |
293 Interface[] interfaces; /// interfaces this class implements | |
294 ClassInfo base; /// base class | |
295 void *destructor; | |
89 | 296 void function(Object) classInvariant; |
1 | 297 uint flags; |
298 // 1: // IUnknown | |
299 // 2: // has no possible pointers into GC memory | |
300 // 4: // has offTi[] member | |
301 // 8: // has constructors | |
302 void *deallocator; | |
303 OffsetTypeInfo[] offTi; | |
304 void function(Object) defaultConstructor; // default Constructor | |
305 | |
306 /************* | |
307 * Search all modules for ClassInfo corresponding to classname. | |
308 * Returns: null if not found | |
309 */ | |
310 static ClassInfo find(char[] classname) | |
311 { | |
89 | 312 /+foreach (m; ModuleInfo.modules()) |
1 | 313 { |
314 //writefln("module %s, %d", m.name, m.localClasses.length); | |
315 foreach (c; m.localClasses) | |
316 { | |
317 //writefln("\tclass %s", c.name); | |
318 if (c.name == classname) | |
319 return c; | |
320 } | |
89 | 321 }+/ |
1 | 322 return null; |
323 } | |
324 | |
325 /******************** | |
326 * Create instance of Object represented by 'this'. | |
327 */ | |
328 Object create() | |
329 { | |
89 | 330 /+if (flags & 8 && !defaultConstructor) |
1 | 331 return null; |
332 Object o = _d_newclass(this); | |
333 if (flags & 8 && defaultConstructor) | |
334 { | |
335 defaultConstructor(o); | |
336 } | |
337 return o; | |
89 | 338 +/ |
339 return null; | |
1 | 340 } |
341 } | |
342 | |
89 | 343 //private import std.string; |
1 | 344 |
52 | 345 |
1 | 346 /** |
347 * Array of pairs giving the offset and type information for each | |
348 * member in an aggregate. | |
349 */ | |
350 struct OffsetTypeInfo | |
351 { | |
352 size_t offset; /// Offset of member from start of object | |
353 TypeInfo ti; /// TypeInfo for this member | |
354 } | |
355 | |
52 | 356 private int string_cmp(char[] s1, char[] s2) |
357 { | |
358 auto len = s1.length; | |
359 if (s2.length < len) | |
360 len = s2.length; | |
361 int result = memcmp(s1.ptr, s2.ptr, len); | |
362 if (result == 0) | |
363 result = cast(int)(cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length); | |
364 return result; | |
365 } | |
366 | |
1 | 367 /** |
368 * Runtime type information about a type. | |
369 * Can be retrieved for any type using a | |
370 * <a href="../expression.html#typeidexpression">TypeidExpression</a>. | |
371 */ | |
372 class TypeInfo | |
373 { | |
374 hash_t toHash() | |
375 { hash_t hash; | |
376 | |
377 foreach (char c; this.toString()) | |
378 hash = hash * 9 + c; | |
379 return hash; | |
380 } | |
381 | |
382 int opCmp(Object o) | |
383 { | |
384 if (this is o) | |
385 return 0; | |
386 TypeInfo ti = cast(TypeInfo)o; | |
387 if (ti is null) | |
388 return 1; | |
52 | 389 return string_cmp(this.toString(), ti.toString()); |
1 | 390 } |
391 | |
392 int opEquals(Object o) | |
393 { | |
394 /* TypeInfo instances are singletons, but duplicates can exist | |
395 * across DLL's. Therefore, comparing for a name match is | |
396 * sufficient. | |
397 */ | |
398 if (this is o) | |
399 return 1; | |
400 TypeInfo ti = cast(TypeInfo)o; | |
401 return cast(int)(ti && this.toString() == ti.toString()); | |
402 } | |
403 | |
404 /// Returns a hash of the instance of a type. | |
405 hash_t getHash(void *p) { return cast(uint)p; } | |
406 | |
407 /// Compares two instances for equality. | |
408 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); } | |
409 | |
410 /// Compares two instances for <, ==, or >. | |
411 int compare(void *p1, void *p2) { return 0; } | |
412 | |
413 /// Returns size of the type. | |
414 size_t tsize() { return 0; } | |
415 | |
416 /// Swaps two instances of the type. | |
417 void swap(void *p1, void *p2) | |
418 { | |
419 size_t n = tsize(); | |
420 for (size_t i = 0; i < n; i++) | |
421 { byte t; | |
422 | |
423 t = (cast(byte *)p1)[i]; | |
424 (cast(byte *)p1)[i] = (cast(byte *)p2)[i]; | |
425 (cast(byte *)p2)[i] = t; | |
426 } | |
427 } | |
428 | |
429 /// Get TypeInfo for 'next' type, as defined by what kind of type this is, | |
430 /// null if none. | |
431 TypeInfo next() { return null; } | |
432 | |
433 /// Return default initializer, null if default initialize to 0 | |
434 void[] init() { return null; } | |
435 | |
436 /// Get flags for type: 1 means GC should scan for pointers | |
437 uint flags() { return 0; } | |
438 | |
439 /// Get type information on the contents of the type; null if not available | |
440 OffsetTypeInfo[] offTi() { return null; } | |
441 } | |
442 | |
443 class TypeInfo_Typedef : TypeInfo | |
444 { | |
445 char[] toString() { return name; } | |
446 | |
447 int opEquals(Object o) | |
448 { TypeInfo_Typedef c; | |
449 | |
450 return cast(int) | |
451 (this is o || | |
452 ((c = cast(TypeInfo_Typedef)o) !is null && | |
453 this.name == c.name && | |
454 this.base == c.base)); | |
455 } | |
456 | |
457 hash_t getHash(void *p) { return base.getHash(p); } | |
458 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
459 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
460 size_t tsize() { return base.tsize(); } | |
461 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
462 | |
54
28e99b04a132
[svn r58] Fixed cond expression resulting in a non-basic type.
lindquist
parents:
52
diff
changeset
|
463 TypeInfo next() { return base; } |
1 | 464 uint flags() { return base.flags(); } |
465 void[] init() { return m_init.length ? m_init : base.init(); } | |
466 | |
467 TypeInfo base; | |
468 char[] name; | |
469 void[] m_init; | |
470 } | |
471 | |
472 class TypeInfo_Enum : TypeInfo_Typedef | |
473 { | |
474 } | |
475 | |
476 class TypeInfo_Pointer : TypeInfo | |
477 { | |
478 char[] toString() { return m_next.toString() ~ "*"; } | |
479 | |
480 int opEquals(Object o) | |
481 { TypeInfo_Pointer c; | |
482 | |
483 return this is o || | |
484 ((c = cast(TypeInfo_Pointer)o) !is null && | |
485 this.m_next == c.m_next); | |
486 } | |
487 | |
488 hash_t getHash(void *p) | |
489 { | |
490 return cast(uint)*cast(void* *)p; | |
491 } | |
492 | |
493 int equals(void *p1, void *p2) | |
494 { | |
495 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); | |
496 } | |
497 | |
498 int compare(void *p1, void *p2) | |
499 { | |
500 if (*cast(void* *)p1 < *cast(void* *)p2) | |
501 return -1; | |
502 else if (*cast(void* *)p1 > *cast(void* *)p2) | |
503 return 1; | |
504 else | |
505 return 0; | |
506 } | |
507 | |
508 size_t tsize() | |
509 { | |
510 return (void*).sizeof; | |
511 } | |
512 | |
513 void swap(void *p1, void *p2) | |
514 { void* tmp; | |
515 tmp = *cast(void**)p1; | |
516 *cast(void**)p1 = *cast(void**)p2; | |
517 *cast(void**)p2 = tmp; | |
518 } | |
519 | |
520 TypeInfo next() { return m_next; } | |
521 uint flags() { return 1; } | |
522 | |
523 TypeInfo m_next; | |
524 } | |
525 | |
526 class TypeInfo_Array : TypeInfo | |
527 { | |
528 char[] toString() { return value.toString() ~ "[]"; } | |
529 | |
530 int opEquals(Object o) | |
531 { TypeInfo_Array c; | |
532 | |
533 return cast(int) | |
534 (this is o || | |
535 ((c = cast(TypeInfo_Array)o) !is null && | |
536 this.value == c.value)); | |
537 } | |
538 | |
539 hash_t getHash(void *p) | |
540 { size_t sz = value.tsize(); | |
541 hash_t hash = 0; | |
542 void[] a = *cast(void[]*)p; | |
543 for (size_t i = 0; i < a.length; i++) | |
544 hash += value.getHash(a.ptr + i * sz); | |
545 return hash; | |
546 } | |
547 | |
548 int equals(void *p1, void *p2) | |
549 { | |
550 void[] a1 = *cast(void[]*)p1; | |
551 void[] a2 = *cast(void[]*)p2; | |
552 if (a1.length != a2.length) | |
553 return 0; | |
554 size_t sz = value.tsize(); | |
555 for (size_t i = 0; i < a1.length; i++) | |
556 { | |
557 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
558 return 0; | |
559 } | |
560 return 1; | |
561 } | |
562 | |
563 int compare(void *p1, void *p2) | |
564 { | |
565 void[] a1 = *cast(void[]*)p1; | |
566 void[] a2 = *cast(void[]*)p2; | |
567 size_t sz = value.tsize(); | |
568 size_t len = a1.length; | |
569 | |
570 if (a2.length < len) | |
571 len = a2.length; | |
572 for (size_t u = 0; u < len; u++) | |
573 { | |
574 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
575 if (result) | |
576 return result; | |
577 } | |
578 return cast(int)a1.length - cast(int)a2.length; | |
579 } | |
580 | |
581 size_t tsize() | |
582 { | |
583 return (void[]).sizeof; | |
584 } | |
585 | |
586 void swap(void *p1, void *p2) | |
587 { void[] tmp; | |
588 tmp = *cast(void[]*)p1; | |
589 *cast(void[]*)p1 = *cast(void[]*)p2; | |
590 *cast(void[]*)p2 = tmp; | |
591 } | |
592 | |
593 TypeInfo value; | |
594 | |
595 TypeInfo next() | |
596 { | |
597 return value; | |
598 } | |
599 | |
600 uint flags() { return 1; } | |
601 } | |
602 | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
603 private const char[10] digits = "0123456789"; /// 0..9 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
604 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
605 private char[] lengthToString(uint u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
606 { char[uint.sizeof * 3] buffer = void; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
607 int ndigits; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
608 char[] result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
609 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
610 ndigits = 0; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
611 if (u < 10) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
612 // Avoid storage allocation for simple stuff |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
613 result = digits[u .. u + 1]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
614 else |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
615 { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
616 while (u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
617 { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
618 uint c = (u % 10) + '0'; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
619 u /= 10; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
620 ndigits++; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
621 buffer[buffer.length - ndigits] = cast(char)c; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
622 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
623 result = new char[ndigits]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
624 result[] = buffer[buffer.length - ndigits .. buffer.length]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
625 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
626 return result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
627 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
628 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
629 private char[] lengthToString(ulong u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
630 { char[ulong.sizeof * 3] buffer; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
631 int ndigits; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
632 char[] result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
633 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
634 if (u < 0x1_0000_0000) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
635 return lengthToString(cast(uint)u); |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
636 ndigits = 0; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
637 while (u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
638 { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
639 char c = cast(char)((u % 10) + '0'); |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
640 u /= 10; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
641 ndigits++; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
642 buffer[buffer.length - ndigits] = c; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
643 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
644 result = new char[ndigits]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
645 result[] = buffer[buffer.length - ndigits .. buffer.length]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
646 return result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
647 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
648 |
1 | 649 class TypeInfo_StaticArray : TypeInfo |
650 { | |
651 char[] toString() | |
652 { | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
653 return value.toString() ~ "[" ~ lengthToString(len) ~ "]"; |
1 | 654 } |
655 | |
656 int opEquals(Object o) | |
657 { TypeInfo_StaticArray c; | |
658 | |
659 return cast(int) | |
660 (this is o || | |
661 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
662 this.len == c.len && | |
663 this.value == c.value)); | |
664 } | |
665 | |
666 hash_t getHash(void *p) | |
667 { size_t sz = value.tsize(); | |
668 hash_t hash = 0; | |
669 for (size_t i = 0; i < len; i++) | |
670 hash += value.getHash(p + i * sz); | |
671 return hash; | |
672 } | |
673 | |
674 int equals(void *p1, void *p2) | |
675 { | |
676 size_t sz = value.tsize(); | |
677 | |
678 for (size_t u = 0; u < len; u++) | |
679 { | |
680 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
681 return 0; | |
682 } | |
683 return 1; | |
684 } | |
685 | |
686 int compare(void *p1, void *p2) | |
687 { | |
688 size_t sz = value.tsize(); | |
689 | |
690 for (size_t u = 0; u < len; u++) | |
691 { | |
692 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
693 if (result) | |
694 return result; | |
695 } | |
696 return 0; | |
697 } | |
698 | |
699 size_t tsize() | |
700 { | |
701 return len * value.tsize(); | |
702 } | |
703 | |
704 void swap(void *p1, void *p2) | |
705 { void* tmp; | |
706 size_t sz = value.tsize(); | |
707 ubyte[16] buffer; | |
708 void* pbuffer; | |
709 | |
710 if (sz < buffer.sizeof) | |
711 tmp = buffer.ptr; | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
712 else { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
713 if (value.flags() & 1) |
1 | 714 tmp = pbuffer = (new void[sz]).ptr; |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
715 else |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
716 tmp = pbuffer = (new byte[sz]).ptr; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
717 } |
1 | 718 |
719 for (size_t u = 0; u < len; u += sz) | |
720 { size_t o = u * sz; | |
721 memcpy(tmp, p1 + o, sz); | |
722 memcpy(p1 + o, p2 + o, sz); | |
723 memcpy(p2 + o, tmp, sz); | |
724 } | |
725 if (pbuffer) | |
726 delete pbuffer; | |
727 } | |
728 | |
729 void[] init() { return value.init(); } | |
730 TypeInfo next() { return value; } | |
731 uint flags() { return value.flags(); } | |
732 | |
733 TypeInfo value; | |
734 size_t len; | |
735 } | |
736 | |
737 class TypeInfo_AssociativeArray : TypeInfo | |
738 { | |
739 char[] toString() | |
740 { | |
741 return value.toString() ~ "[" ~ key.toString() ~ "]"; | |
742 } | |
743 | |
744 int opEquals(Object o) | |
745 { TypeInfo_AssociativeArray c; | |
746 | |
747 return this is o || | |
748 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
749 this.key == c.key && | |
750 this.value == c.value); | |
751 } | |
752 | |
753 // BUG: need to add the rest of the functions | |
754 | |
755 size_t tsize() | |
756 { | |
757 return (char[int]).sizeof; | |
758 } | |
759 | |
760 TypeInfo next() { return value; } | |
761 uint flags() { return 1; } | |
762 | |
763 TypeInfo value; | |
764 TypeInfo key; | |
765 } | |
766 | |
767 class TypeInfo_Function : TypeInfo | |
768 { | |
769 char[] toString() | |
770 { | |
771 return next.toString() ~ "()"; | |
772 } | |
773 | |
774 int opEquals(Object o) | |
775 { TypeInfo_Function c; | |
776 | |
777 return this is o || | |
778 ((c = cast(TypeInfo_Function)o) !is null && | |
779 this.next == c.next); | |
780 } | |
781 | |
782 // BUG: need to add the rest of the functions | |
783 | |
784 size_t tsize() | |
785 { | |
786 return 0; // no size for functions | |
787 } | |
788 | |
789 TypeInfo next; | |
790 } | |
791 | |
792 class TypeInfo_Delegate : TypeInfo | |
793 { | |
794 char[] toString() | |
795 { | |
796 return next.toString() ~ " delegate()"; | |
797 } | |
798 | |
799 int opEquals(Object o) | |
800 { TypeInfo_Delegate c; | |
801 | |
802 return this is o || | |
803 ((c = cast(TypeInfo_Delegate)o) !is null && | |
804 this.next == c.next); | |
805 } | |
806 | |
807 // BUG: need to add the rest of the functions | |
808 | |
809 size_t tsize() | |
810 { alias int delegate() dg; | |
811 return dg.sizeof; | |
812 } | |
813 | |
814 uint flags() { return 1; } | |
815 | |
816 TypeInfo next; | |
817 } | |
818 | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
819 /+ |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
820 |
1 | 821 class TypeInfo_Class : TypeInfo |
822 { | |
823 char[] toString() { return info.name; } | |
824 | |
825 int opEquals(Object o) | |
826 { TypeInfo_Class c; | |
827 | |
828 return this is o || | |
829 ((c = cast(TypeInfo_Class)o) !is null && | |
830 this.info.name == c.classinfo.name); | |
831 } | |
832 | |
833 hash_t getHash(void *p) | |
834 { | |
835 Object o = *cast(Object*)p; | |
836 assert(o); | |
837 return o.toHash(); | |
838 } | |
839 | |
840 int equals(void *p1, void *p2) | |
841 { | |
842 Object o1 = *cast(Object*)p1; | |
843 Object o2 = *cast(Object*)p2; | |
844 | |
845 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
846 } | |
847 | |
848 int compare(void *p1, void *p2) | |
849 { | |
850 Object o1 = *cast(Object*)p1; | |
851 Object o2 = *cast(Object*)p2; | |
852 int c = 0; | |
853 | |
854 // Regard null references as always being "less than" | |
855 if (o1 !is o2) | |
856 { | |
857 if (o1) | |
858 { if (!o2) | |
859 c = 1; | |
860 else | |
861 c = o1.opCmp(o2); | |
862 } | |
863 else | |
864 c = -1; | |
865 } | |
866 return c; | |
867 } | |
868 | |
869 size_t tsize() | |
870 { | |
871 return Object.sizeof; | |
872 } | |
873 | |
874 uint flags() { return 1; } | |
875 | |
876 OffsetTypeInfo[] offTi() | |
877 { | |
878 return (info.flags & 4) ? info.offTi : null; | |
879 } | |
880 | |
881 ClassInfo info; | |
882 } | |
883 | |
884 class TypeInfo_Interface : TypeInfo | |
885 { | |
886 char[] toString() { return info.name; } | |
887 | |
888 int opEquals(Object o) | |
889 { TypeInfo_Interface c; | |
890 | |
891 return this is o || | |
892 ((c = cast(TypeInfo_Interface)o) !is null && | |
893 this.info.name == c.classinfo.name); | |
894 } | |
895 | |
896 hash_t getHash(void *p) | |
897 { | |
898 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
899 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
900 assert(o); | |
901 return o.toHash(); | |
902 } | |
903 | |
904 int equals(void *p1, void *p2) | |
905 { | |
906 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
907 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
908 pi = **cast(Interface ***)*cast(void**)p2; | |
909 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
910 | |
911 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
912 } | |
913 | |
914 int compare(void *p1, void *p2) | |
915 { | |
916 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
917 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
918 pi = **cast(Interface ***)*cast(void**)p2; | |
919 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
920 int c = 0; | |
921 | |
922 // Regard null references as always being "less than" | |
923 if (o1 != o2) | |
924 { | |
925 if (o1) | |
926 { if (!o2) | |
927 c = 1; | |
928 else | |
929 c = o1.opCmp(o2); | |
930 } | |
931 else | |
932 c = -1; | |
933 } | |
934 return c; | |
935 } | |
936 | |
937 size_t tsize() | |
938 { | |
939 return Object.sizeof; | |
940 } | |
941 | |
942 uint flags() { return 1; } | |
943 | |
944 ClassInfo info; | |
945 } | |
946 | |
72 | 947 +/ |
948 | |
1 | 949 class TypeInfo_Struct : TypeInfo |
950 { | |
951 char[] toString() { return name; } | |
952 | |
953 int opEquals(Object o) | |
954 { TypeInfo_Struct s; | |
955 | |
956 return this is o || | |
957 ((s = cast(TypeInfo_Struct)o) !is null && | |
958 this.name == s.name && | |
959 this.init.length == s.init.length); | |
960 } | |
961 | |
962 hash_t getHash(void *p) | |
963 { hash_t h; | |
964 | |
965 assert(p); | |
966 if (xtoHash) | |
967 { //printf("getHash() using xtoHash\n"); | |
968 h = (*xtoHash)(p); | |
969 } | |
970 else | |
971 { | |
972 //printf("getHash() using default hash\n"); | |
973 // A sorry hash algorithm. | |
974 // Should use the one for strings. | |
975 // BUG: relies on the GC not moving objects | |
976 for (size_t i = 0; i < init.length; i++) | |
977 { h = h * 9 + *cast(ubyte*)p; | |
978 p++; | |
979 } | |
980 } | |
981 return h; | |
982 } | |
983 | |
73 | 984 int equals(void *p1, void *p2) |
1 | 985 { int c; |
986 | |
987 if (p1 == p2) | |
988 c = 1; | |
989 else if (!p1 || !p2) | |
990 c = 0; | |
991 else if (xopEquals) | |
992 c = (*xopEquals)(p1, p2); | |
993 else | |
994 // BUG: relies on the GC not moving objects | |
995 c = (memcmp(p1, p2, init.length) == 0); | |
996 return c; | |
997 } | |
998 | |
72 | 999 int compare(void *p1, void *p2) |
1 | 1000 { |
1001 int c = 0; | |
1002 | |
1003 // Regard null references as always being "less than" | |
1004 if (p1 != p2) | |
1005 { | |
1006 if (p1) | |
1007 { if (!p2) | |
1008 c = 1; | |
1009 else if (xopCmp) | |
1010 c = (*xopCmp)(p1, p2); | |
1011 else | |
1012 // BUG: relies on the GC not moving objects | |
1013 c = memcmp(p1, p2, init.length); | |
1014 } | |
1015 else | |
1016 c = -1; | |
1017 } | |
1018 return c; | |
1019 } | |
1020 | |
1021 size_t tsize() | |
1022 { | |
1023 return init.length; | |
1024 } | |
1025 | |
1026 void[] init() { return m_init; } | |
1027 | |
1028 uint flags() { return m_flags; } | |
1029 | |
1030 char[] name; | |
1031 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
1032 | |
1033 hash_t function(void*) xtoHash; | |
1034 int function(void*,void*) xopEquals; | |
1035 int function(void*,void*) xopCmp; | |
1036 char[] function(void*) xtoString; | |
1037 | |
1038 uint m_flags; | |
1039 } | |
1040 | |
72 | 1041 /+ |
1042 | |
1 | 1043 class TypeInfo_Tuple : TypeInfo |
1044 { | |
1045 TypeInfo[] elements; | |
1046 | |
1047 char[] toString() | |
1048 { | |
1049 char[] s; | |
1050 s = "("; | |
1051 foreach (i, element; elements) | |
1052 { | |
1053 if (i) | |
1054 s ~= ','; | |
1055 s ~= element.toString(); | |
1056 } | |
1057 s ~= ")"; | |
1058 return s; | |
1059 } | |
1060 | |
1061 int opEquals(Object o) | |
1062 { | |
1063 if (this is o) | |
1064 return 1; | |
1065 | |
1066 auto t = cast(TypeInfo_Tuple)o; | |
1067 if (t && elements.length == t.elements.length) | |
1068 { | |
1069 for (size_t i = 0; i < elements.length; i++) | |
1070 { | |
1071 if (elements[i] != t.elements[i]) | |
1072 return 0; | |
1073 } | |
1074 return 1; | |
1075 } | |
1076 return 0; | |
1077 } | |
1078 | |
1079 hash_t getHash(void *p) | |
1080 { | |
1081 assert(0); | |
1082 } | |
1083 | |
1084 int equals(void *p1, void *p2) | |
1085 { | |
1086 assert(0); | |
1087 } | |
1088 | |
1089 int compare(void *p1, void *p2) | |
1090 { | |
1091 assert(0); | |
1092 } | |
1093 | |
1094 size_t tsize() | |
1095 { | |
1096 assert(0); | |
1097 } | |
1098 | |
1099 void swap(void *p1, void *p2) | |
1100 { | |
1101 assert(0); | |
1102 } | |
1103 } | |
52 | 1104 |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
1105 +/ |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
1106 |
52 | 1107 class TypeInfo_Const : TypeInfo |
1108 { | |
1109 char[] toString() { return "const " ~ base.toString(); } | |
1110 | |
1111 int opEquals(Object o) { return base.opEquals(o); } | |
1112 hash_t getHash(void *p) { return base.getHash(p); } | |
1113 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
1114 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
1115 size_t tsize() { return base.tsize(); } | |
1116 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
1117 | |
1118 TypeInfo next() { return base.next(); } | |
1119 uint flags() { return base.flags(); } | |
1120 void[] init() { return base.init(); } | |
1121 | |
1122 TypeInfo base; | |
1123 } | |
1124 | |
1125 class TypeInfo_Invariant : TypeInfo_Const | |
1126 { | |
1127 char[] toString() { return "invariant " ~ base.toString(); } | |
1128 } | |
1129 | |
1 | 1130 /** |
1131 * All recoverable exceptions should be derived from class Exception. | |
1132 */ | |
1133 class Exception : Object | |
1134 { | |
1135 char[] msg; | |
1136 | |
1137 /** | |
1138 * Constructor; msg is a descriptive message for the exception. | |
1139 */ | |
1140 this(char[] msg) | |
1141 { | |
1142 this.msg = msg; | |
1143 } | |
1144 | |
86
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1145 void print() |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1146 { |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1147 char[] s = toString(); |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1148 printf("%.*s\n", s.length, s.ptr); |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1149 } |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1150 |
1 | 1151 char[] toString() { return msg; } |
1152 } | |
1153 | |
1154 /** | |
1155 * All irrecoverable exceptions should be derived from class Error. | |
1156 */ | |
1157 class Error : Exception | |
1158 { | |
1159 Error next; | |
1160 | |
1161 /** | |
1162 * Constructor; msg is a descriptive message for the exception. | |
1163 */ | |
1164 this(char[] msg) | |
1165 { | |
1166 super(msg); | |
1167 } | |
1168 | |
1169 this(char[] msg, Error next) | |
1170 { | |
1171 super(msg); | |
1172 this.next = next; | |
1173 } | |
1174 } | |
1175 | |
1176 //extern (C) int nullext = 0; | |
52 | 1177 |