Mercurial > projects > ldc
annotate lphobos/internal/objectimpl.d @ 58:2c3cd3596187 trunk
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
Added initial support for CatExp aka 'a ~ b'
Fixed global constant static arrays initialized with string literals
Fixed casting any dynamic array to void*
Fixed new expression with temporary storage
Fixed alias declarations in function scope
Fixed relational comparisons of pointers
author | lindquist |
---|---|
date | Thu, 25 Oct 2007 09:02:55 +0200 |
parents | 28e99b04a132 |
children | d7e764e62462 |
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 | |
469 class TypeInfo_Pointer : TypeInfo | |
470 { | |
471 char[] toString() { return m_next.toString() ~ "*"; } | |
472 | |
473 int opEquals(Object o) | |
474 { TypeInfo_Pointer c; | |
475 | |
476 return this is o || | |
477 ((c = cast(TypeInfo_Pointer)o) !is null && | |
478 this.m_next == c.m_next); | |
479 } | |
480 | |
481 hash_t getHash(void *p) | |
482 { | |
483 return cast(uint)*cast(void* *)p; | |
484 } | |
485 | |
486 int equals(void *p1, void *p2) | |
487 { | |
488 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); | |
489 } | |
490 | |
491 int compare(void *p1, void *p2) | |
492 { | |
493 if (*cast(void* *)p1 < *cast(void* *)p2) | |
494 return -1; | |
495 else if (*cast(void* *)p1 > *cast(void* *)p2) | |
496 return 1; | |
497 else | |
498 return 0; | |
499 } | |
500 | |
501 size_t tsize() | |
502 { | |
503 return (void*).sizeof; | |
504 } | |
505 | |
506 void swap(void *p1, void *p2) | |
507 { void* tmp; | |
508 tmp = *cast(void**)p1; | |
509 *cast(void**)p1 = *cast(void**)p2; | |
510 *cast(void**)p2 = tmp; | |
511 } | |
512 | |
513 TypeInfo next() { return m_next; } | |
514 uint flags() { return 1; } | |
515 | |
516 TypeInfo m_next; | |
517 } | |
518 | |
519 class TypeInfo_Array : TypeInfo | |
520 { | |
521 char[] toString() { return value.toString() ~ "[]"; } | |
522 | |
523 int opEquals(Object o) | |
524 { TypeInfo_Array c; | |
525 | |
526 return cast(int) | |
527 (this is o || | |
528 ((c = cast(TypeInfo_Array)o) !is null && | |
529 this.value == c.value)); | |
530 } | |
531 | |
532 hash_t getHash(void *p) | |
533 { size_t sz = value.tsize(); | |
534 hash_t hash = 0; | |
535 void[] a = *cast(void[]*)p; | |
536 for (size_t i = 0; i < a.length; i++) | |
537 hash += value.getHash(a.ptr + i * sz); | |
538 return hash; | |
539 } | |
540 | |
541 int equals(void *p1, void *p2) | |
542 { | |
543 void[] a1 = *cast(void[]*)p1; | |
544 void[] a2 = *cast(void[]*)p2; | |
545 if (a1.length != a2.length) | |
546 return 0; | |
547 size_t sz = value.tsize(); | |
548 for (size_t i = 0; i < a1.length; i++) | |
549 { | |
550 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
551 return 0; | |
552 } | |
553 return 1; | |
554 } | |
555 | |
556 int compare(void *p1, void *p2) | |
557 { | |
558 void[] a1 = *cast(void[]*)p1; | |
559 void[] a2 = *cast(void[]*)p2; | |
560 size_t sz = value.tsize(); | |
561 size_t len = a1.length; | |
562 | |
563 if (a2.length < len) | |
564 len = a2.length; | |
565 for (size_t u = 0; u < len; u++) | |
566 { | |
567 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
568 if (result) | |
569 return result; | |
570 } | |
571 return cast(int)a1.length - cast(int)a2.length; | |
572 } | |
573 | |
574 size_t tsize() | |
575 { | |
576 return (void[]).sizeof; | |
577 } | |
578 | |
579 void swap(void *p1, void *p2) | |
580 { void[] tmp; | |
581 tmp = *cast(void[]*)p1; | |
582 *cast(void[]*)p1 = *cast(void[]*)p2; | |
583 *cast(void[]*)p2 = tmp; | |
584 } | |
585 | |
586 TypeInfo value; | |
587 | |
588 TypeInfo next() | |
589 { | |
590 return value; | |
591 } | |
592 | |
593 uint flags() { return 1; } | |
594 } | |
595 | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
596 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
|
597 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
598 private char[] lengthToString(uint u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
599 { char[uint.sizeof * 3] buffer = void; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
600 int ndigits; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
601 char[] result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
602 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
603 ndigits = 0; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
604 if (u < 10) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
605 // Avoid storage allocation for simple stuff |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
606 result = digits[u .. u + 1]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
607 else |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
608 { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
609 while (u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
610 { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
611 uint c = (u % 10) + '0'; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
612 u /= 10; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
613 ndigits++; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
614 buffer[buffer.length - ndigits] = cast(char)c; |
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 result = new char[ndigits]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
617 result[] = buffer[buffer.length - ndigits .. buffer.length]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
618 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
619 return result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
620 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
621 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
622 private char[] lengthToString(ulong u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
623 { char[ulong.sizeof * 3] buffer; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
624 int ndigits; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
625 char[] result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
626 |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
627 if (u < 0x1_0000_0000) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
628 return lengthToString(cast(uint)u); |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
629 ndigits = 0; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
630 while (u) |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
631 { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
632 char c = cast(char)((u % 10) + '0'); |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
633 u /= 10; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
634 ndigits++; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
635 buffer[buffer.length - ndigits] = c; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
636 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
637 result = new char[ndigits]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
638 result[] = buffer[buffer.length - ndigits .. buffer.length]; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
639 return result; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
640 } |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
641 |
1 | 642 class TypeInfo_StaticArray : TypeInfo |
643 { | |
644 char[] toString() | |
645 { | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
646 return value.toString() ~ "[" ~ lengthToString(len) ~ "]"; |
1 | 647 } |
648 | |
649 int opEquals(Object o) | |
650 { TypeInfo_StaticArray c; | |
651 | |
652 return cast(int) | |
653 (this is o || | |
654 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
655 this.len == c.len && | |
656 this.value == c.value)); | |
657 } | |
658 | |
659 hash_t getHash(void *p) | |
660 { size_t sz = value.tsize(); | |
661 hash_t hash = 0; | |
662 for (size_t i = 0; i < len; i++) | |
663 hash += value.getHash(p + i * sz); | |
664 return hash; | |
665 } | |
666 | |
667 int equals(void *p1, void *p2) | |
668 { | |
669 size_t sz = value.tsize(); | |
670 | |
671 for (size_t u = 0; u < len; u++) | |
672 { | |
673 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
674 return 0; | |
675 } | |
676 return 1; | |
677 } | |
678 | |
679 int compare(void *p1, void *p2) | |
680 { | |
681 size_t sz = value.tsize(); | |
682 | |
683 for (size_t u = 0; u < len; u++) | |
684 { | |
685 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
686 if (result) | |
687 return result; | |
688 } | |
689 return 0; | |
690 } | |
691 | |
692 size_t tsize() | |
693 { | |
694 return len * value.tsize(); | |
695 } | |
696 | |
697 void swap(void *p1, void *p2) | |
698 { void* tmp; | |
699 size_t sz = value.tsize(); | |
700 ubyte[16] buffer; | |
701 void* pbuffer; | |
702 | |
703 if (sz < buffer.sizeof) | |
704 tmp = buffer.ptr; | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
705 else { |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
706 if (value.flags() & 1) |
1 | 707 tmp = pbuffer = (new void[sz]).ptr; |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
708 else |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
709 tmp = pbuffer = (new byte[sz]).ptr; |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
710 } |
1 | 711 |
712 for (size_t u = 0; u < len; u += sz) | |
713 { size_t o = u * sz; | |
714 memcpy(tmp, p1 + o, sz); | |
715 memcpy(p1 + o, p2 + o, sz); | |
716 memcpy(p2 + o, tmp, sz); | |
717 } | |
718 if (pbuffer) | |
719 delete pbuffer; | |
720 } | |
721 | |
722 void[] init() { return value.init(); } | |
723 TypeInfo next() { return value; } | |
724 uint flags() { return value.flags(); } | |
725 | |
726 TypeInfo value; | |
727 size_t len; | |
728 } | |
729 | |
730 class TypeInfo_AssociativeArray : TypeInfo | |
731 { | |
732 char[] toString() | |
733 { | |
734 return value.toString() ~ "[" ~ key.toString() ~ "]"; | |
735 } | |
736 | |
737 int opEquals(Object o) | |
738 { TypeInfo_AssociativeArray c; | |
739 | |
740 return this is o || | |
741 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
742 this.key == c.key && | |
743 this.value == c.value); | |
744 } | |
745 | |
746 // BUG: need to add the rest of the functions | |
747 | |
748 size_t tsize() | |
749 { | |
750 return (char[int]).sizeof; | |
751 } | |
752 | |
753 TypeInfo next() { return value; } | |
754 uint flags() { return 1; } | |
755 | |
756 TypeInfo value; | |
757 TypeInfo key; | |
758 } | |
759 | |
760 class TypeInfo_Function : TypeInfo | |
761 { | |
762 char[] toString() | |
763 { | |
764 return next.toString() ~ "()"; | |
765 } | |
766 | |
767 int opEquals(Object o) | |
768 { TypeInfo_Function c; | |
769 | |
770 return this is o || | |
771 ((c = cast(TypeInfo_Function)o) !is null && | |
772 this.next == c.next); | |
773 } | |
774 | |
775 // BUG: need to add the rest of the functions | |
776 | |
777 size_t tsize() | |
778 { | |
779 return 0; // no size for functions | |
780 } | |
781 | |
782 TypeInfo next; | |
783 } | |
784 | |
785 class TypeInfo_Delegate : TypeInfo | |
786 { | |
787 char[] toString() | |
788 { | |
789 return next.toString() ~ " delegate()"; | |
790 } | |
791 | |
792 int opEquals(Object o) | |
793 { TypeInfo_Delegate c; | |
794 | |
795 return this is o || | |
796 ((c = cast(TypeInfo_Delegate)o) !is null && | |
797 this.next == c.next); | |
798 } | |
799 | |
800 // BUG: need to add the rest of the functions | |
801 | |
802 size_t tsize() | |
803 { alias int delegate() dg; | |
804 return dg.sizeof; | |
805 } | |
806 | |
807 uint flags() { return 1; } | |
808 | |
809 TypeInfo next; | |
810 } | |
811 | |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
812 /+ |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
813 |
1 | 814 class TypeInfo_Class : TypeInfo |
815 { | |
816 char[] toString() { return info.name; } | |
817 | |
818 int opEquals(Object o) | |
819 { TypeInfo_Class c; | |
820 | |
821 return this is o || | |
822 ((c = cast(TypeInfo_Class)o) !is null && | |
823 this.info.name == c.classinfo.name); | |
824 } | |
825 | |
826 hash_t getHash(void *p) | |
827 { | |
828 Object o = *cast(Object*)p; | |
829 assert(o); | |
830 return o.toHash(); | |
831 } | |
832 | |
833 int equals(void *p1, void *p2) | |
834 { | |
835 Object o1 = *cast(Object*)p1; | |
836 Object o2 = *cast(Object*)p2; | |
837 | |
838 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
839 } | |
840 | |
841 int compare(void *p1, void *p2) | |
842 { | |
843 Object o1 = *cast(Object*)p1; | |
844 Object o2 = *cast(Object*)p2; | |
845 int c = 0; | |
846 | |
847 // Regard null references as always being "less than" | |
848 if (o1 !is o2) | |
849 { | |
850 if (o1) | |
851 { if (!o2) | |
852 c = 1; | |
853 else | |
854 c = o1.opCmp(o2); | |
855 } | |
856 else | |
857 c = -1; | |
858 } | |
859 return c; | |
860 } | |
861 | |
862 size_t tsize() | |
863 { | |
864 return Object.sizeof; | |
865 } | |
866 | |
867 uint flags() { return 1; } | |
868 | |
869 OffsetTypeInfo[] offTi() | |
870 { | |
871 return (info.flags & 4) ? info.offTi : null; | |
872 } | |
873 | |
874 ClassInfo info; | |
875 } | |
876 | |
877 class TypeInfo_Interface : TypeInfo | |
878 { | |
879 char[] toString() { return info.name; } | |
880 | |
881 int opEquals(Object o) | |
882 { TypeInfo_Interface c; | |
883 | |
884 return this is o || | |
885 ((c = cast(TypeInfo_Interface)o) !is null && | |
886 this.info.name == c.classinfo.name); | |
887 } | |
888 | |
889 hash_t getHash(void *p) | |
890 { | |
891 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
892 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
893 assert(o); | |
894 return o.toHash(); | |
895 } | |
896 | |
897 int equals(void *p1, void *p2) | |
898 { | |
899 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
900 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
901 pi = **cast(Interface ***)*cast(void**)p2; | |
902 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
903 | |
904 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
905 } | |
906 | |
907 int compare(void *p1, void *p2) | |
908 { | |
909 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
910 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
911 pi = **cast(Interface ***)*cast(void**)p2; | |
912 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
913 int c = 0; | |
914 | |
915 // Regard null references as always being "less than" | |
916 if (o1 != o2) | |
917 { | |
918 if (o1) | |
919 { if (!o2) | |
920 c = 1; | |
921 else | |
922 c = o1.opCmp(o2); | |
923 } | |
924 else | |
925 c = -1; | |
926 } | |
927 return c; | |
928 } | |
929 | |
930 size_t tsize() | |
931 { | |
932 return Object.sizeof; | |
933 } | |
934 | |
935 uint flags() { return 1; } | |
936 | |
937 ClassInfo info; | |
938 } | |
939 | |
940 class TypeInfo_Struct : TypeInfo | |
941 { | |
942 char[] toString() { return name; } | |
943 | |
944 int opEquals(Object o) | |
945 { TypeInfo_Struct s; | |
946 | |
947 return this is o || | |
948 ((s = cast(TypeInfo_Struct)o) !is null && | |
949 this.name == s.name && | |
950 this.init.length == s.init.length); | |
951 } | |
952 | |
953 hash_t getHash(void *p) | |
954 { hash_t h; | |
955 | |
956 assert(p); | |
957 if (xtoHash) | |
958 { //printf("getHash() using xtoHash\n"); | |
959 h = (*xtoHash)(p); | |
960 } | |
961 else | |
962 { | |
963 //printf("getHash() using default hash\n"); | |
964 // A sorry hash algorithm. | |
965 // Should use the one for strings. | |
966 // BUG: relies on the GC not moving objects | |
967 for (size_t i = 0; i < init.length; i++) | |
968 { h = h * 9 + *cast(ubyte*)p; | |
969 p++; | |
970 } | |
971 } | |
972 return h; | |
973 } | |
974 | |
975 int equals(void *p2, void *p1) | |
976 { int c; | |
977 | |
978 if (p1 == p2) | |
979 c = 1; | |
980 else if (!p1 || !p2) | |
981 c = 0; | |
982 else if (xopEquals) | |
983 c = (*xopEquals)(p1, p2); | |
984 else | |
985 // BUG: relies on the GC not moving objects | |
986 c = (memcmp(p1, p2, init.length) == 0); | |
987 return c; | |
988 } | |
989 | |
990 int compare(void *p2, void *p1) | |
991 { | |
992 int c = 0; | |
993 | |
994 // Regard null references as always being "less than" | |
995 if (p1 != p2) | |
996 { | |
997 if (p1) | |
998 { if (!p2) | |
999 c = 1; | |
1000 else if (xopCmp) | |
1001 c = (*xopCmp)(p1, p2); | |
1002 else | |
1003 // BUG: relies on the GC not moving objects | |
1004 c = memcmp(p1, p2, init.length); | |
1005 } | |
1006 else | |
1007 c = -1; | |
1008 } | |
1009 return c; | |
1010 } | |
1011 | |
1012 size_t tsize() | |
1013 { | |
1014 return init.length; | |
1015 } | |
1016 | |
1017 void[] init() { return m_init; } | |
1018 | |
1019 uint flags() { return m_flags; } | |
1020 | |
1021 char[] name; | |
1022 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
1023 | |
1024 hash_t function(void*) xtoHash; | |
1025 int function(void*,void*) xopEquals; | |
1026 int function(void*,void*) xopCmp; | |
1027 char[] function(void*) xtoString; | |
1028 | |
1029 uint m_flags; | |
1030 } | |
1031 | |
1032 class TypeInfo_Tuple : TypeInfo | |
1033 { | |
1034 TypeInfo[] elements; | |
1035 | |
1036 char[] toString() | |
1037 { | |
1038 char[] s; | |
1039 s = "("; | |
1040 foreach (i, element; elements) | |
1041 { | |
1042 if (i) | |
1043 s ~= ','; | |
1044 s ~= element.toString(); | |
1045 } | |
1046 s ~= ")"; | |
1047 return s; | |
1048 } | |
1049 | |
1050 int opEquals(Object o) | |
1051 { | |
1052 if (this is o) | |
1053 return 1; | |
1054 | |
1055 auto t = cast(TypeInfo_Tuple)o; | |
1056 if (t && elements.length == t.elements.length) | |
1057 { | |
1058 for (size_t i = 0; i < elements.length; i++) | |
1059 { | |
1060 if (elements[i] != t.elements[i]) | |
1061 return 0; | |
1062 } | |
1063 return 1; | |
1064 } | |
1065 return 0; | |
1066 } | |
1067 | |
1068 hash_t getHash(void *p) | |
1069 { | |
1070 assert(0); | |
1071 } | |
1072 | |
1073 int equals(void *p1, void *p2) | |
1074 { | |
1075 assert(0); | |
1076 } | |
1077 | |
1078 int compare(void *p1, void *p2) | |
1079 { | |
1080 assert(0); | |
1081 } | |
1082 | |
1083 size_t tsize() | |
1084 { | |
1085 assert(0); | |
1086 } | |
1087 | |
1088 void swap(void *p1, void *p2) | |
1089 { | |
1090 assert(0); | |
1091 } | |
1092 } | |
52 | 1093 |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
1094 +/ |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
1095 |
52 | 1096 class TypeInfo_Const : TypeInfo |
1097 { | |
1098 char[] toString() { return "const " ~ base.toString(); } | |
1099 | |
1100 int opEquals(Object o) { return base.opEquals(o); } | |
1101 hash_t getHash(void *p) { return base.getHash(p); } | |
1102 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
1103 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
1104 size_t tsize() { return base.tsize(); } | |
1105 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
1106 | |
1107 TypeInfo next() { return base.next(); } | |
1108 uint flags() { return base.flags(); } | |
1109 void[] init() { return base.init(); } | |
1110 | |
1111 TypeInfo base; | |
1112 } | |
1113 | |
1114 class TypeInfo_Invariant : TypeInfo_Const | |
1115 { | |
1116 char[] toString() { return "invariant " ~ base.toString(); } | |
1117 } | |
1118 | |
1 | 1119 /** |
1120 * All recoverable exceptions should be derived from class Exception. | |
1121 */ | |
1122 class Exception : Object | |
1123 { | |
1124 char[] msg; | |
1125 | |
1126 /** | |
1127 * Constructor; msg is a descriptive message for the exception. | |
1128 */ | |
1129 this(char[] msg) | |
1130 { | |
1131 this.msg = msg; | |
1132 } | |
1133 | |
1134 char[] toString() { return msg; } | |
1135 } | |
1136 | |
1137 /** | |
1138 * All irrecoverable exceptions should be derived from class Error. | |
1139 */ | |
1140 class Error : Exception | |
1141 { | |
1142 Error next; | |
1143 | |
1144 /** | |
1145 * Constructor; msg is a descriptive message for the exception. | |
1146 */ | |
1147 this(char[] msg) | |
1148 { | |
1149 super(msg); | |
1150 } | |
1151 | |
1152 this(char[] msg, Error next) | |
1153 { | |
1154 super(msg); | |
1155 this.next = next; | |
1156 } | |
1157 } | |
1158 | |
1159 //extern (C) int nullext = 0; | |
52 | 1160 |