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