Mercurial > projects > ldc
annotate lphobos/internal/objectimpl.d @ 86:fd32135dca3e trunk
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
Lots of bugfixes.
Added support for special foreach on strings.
Added std.array, std.utf, std.ctype and std.uni to phobos.
Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author | lindquist |
---|---|
date | Sat, 03 Nov 2007 14:44:58 +0100 |
parents | b706170e24a9 |
children | ccca1c13e13a |
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 | |
72 | 940 +/ |
941 | |
1 | 942 class TypeInfo_Struct : TypeInfo |
943 { | |
944 char[] toString() { return name; } | |
945 | |
946 int opEquals(Object o) | |
947 { TypeInfo_Struct s; | |
948 | |
949 return this is o || | |
950 ((s = cast(TypeInfo_Struct)o) !is null && | |
951 this.name == s.name && | |
952 this.init.length == s.init.length); | |
953 } | |
954 | |
955 hash_t getHash(void *p) | |
956 { hash_t h; | |
957 | |
958 assert(p); | |
959 if (xtoHash) | |
960 { //printf("getHash() using xtoHash\n"); | |
961 h = (*xtoHash)(p); | |
962 } | |
963 else | |
964 { | |
965 //printf("getHash() using default hash\n"); | |
966 // A sorry hash algorithm. | |
967 // Should use the one for strings. | |
968 // BUG: relies on the GC not moving objects | |
969 for (size_t i = 0; i < init.length; i++) | |
970 { h = h * 9 + *cast(ubyte*)p; | |
971 p++; | |
972 } | |
973 } | |
974 return h; | |
975 } | |
976 | |
73 | 977 int equals(void *p1, void *p2) |
1 | 978 { int c; |
979 | |
980 if (p1 == p2) | |
981 c = 1; | |
982 else if (!p1 || !p2) | |
983 c = 0; | |
984 else if (xopEquals) | |
985 c = (*xopEquals)(p1, p2); | |
986 else | |
987 // BUG: relies on the GC not moving objects | |
988 c = (memcmp(p1, p2, init.length) == 0); | |
989 return c; | |
990 } | |
991 | |
72 | 992 int compare(void *p1, void *p2) |
1 | 993 { |
994 int c = 0; | |
995 | |
996 // Regard null references as always being "less than" | |
997 if (p1 != p2) | |
998 { | |
999 if (p1) | |
1000 { if (!p2) | |
1001 c = 1; | |
1002 else if (xopCmp) | |
1003 c = (*xopCmp)(p1, p2); | |
1004 else | |
1005 // BUG: relies on the GC not moving objects | |
1006 c = memcmp(p1, p2, init.length); | |
1007 } | |
1008 else | |
1009 c = -1; | |
1010 } | |
1011 return c; | |
1012 } | |
1013 | |
1014 size_t tsize() | |
1015 { | |
1016 return init.length; | |
1017 } | |
1018 | |
1019 void[] init() { return m_init; } | |
1020 | |
1021 uint flags() { return m_flags; } | |
1022 | |
1023 char[] name; | |
1024 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
1025 | |
1026 hash_t function(void*) xtoHash; | |
1027 int function(void*,void*) xopEquals; | |
1028 int function(void*,void*) xopCmp; | |
1029 char[] function(void*) xtoString; | |
1030 | |
1031 uint m_flags; | |
1032 } | |
1033 | |
72 | 1034 /+ |
1035 | |
1 | 1036 class TypeInfo_Tuple : TypeInfo |
1037 { | |
1038 TypeInfo[] elements; | |
1039 | |
1040 char[] toString() | |
1041 { | |
1042 char[] s; | |
1043 s = "("; | |
1044 foreach (i, element; elements) | |
1045 { | |
1046 if (i) | |
1047 s ~= ','; | |
1048 s ~= element.toString(); | |
1049 } | |
1050 s ~= ")"; | |
1051 return s; | |
1052 } | |
1053 | |
1054 int opEquals(Object o) | |
1055 { | |
1056 if (this is o) | |
1057 return 1; | |
1058 | |
1059 auto t = cast(TypeInfo_Tuple)o; | |
1060 if (t && elements.length == t.elements.length) | |
1061 { | |
1062 for (size_t i = 0; i < elements.length; i++) | |
1063 { | |
1064 if (elements[i] != t.elements[i]) | |
1065 return 0; | |
1066 } | |
1067 return 1; | |
1068 } | |
1069 return 0; | |
1070 } | |
1071 | |
1072 hash_t getHash(void *p) | |
1073 { | |
1074 assert(0); | |
1075 } | |
1076 | |
1077 int equals(void *p1, void *p2) | |
1078 { | |
1079 assert(0); | |
1080 } | |
1081 | |
1082 int compare(void *p1, void *p2) | |
1083 { | |
1084 assert(0); | |
1085 } | |
1086 | |
1087 size_t tsize() | |
1088 { | |
1089 assert(0); | |
1090 } | |
1091 | |
1092 void swap(void *p1, void *p2) | |
1093 { | |
1094 assert(0); | |
1095 } | |
1096 } | |
52 | 1097 |
58
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
1098 +/ |
2c3cd3596187
[svn r62] Added support for TypeInfo _Array, _Function, _Pointer, _Delegate, _Enum
lindquist
parents:
54
diff
changeset
|
1099 |
52 | 1100 class TypeInfo_Const : TypeInfo |
1101 { | |
1102 char[] toString() { return "const " ~ base.toString(); } | |
1103 | |
1104 int opEquals(Object o) { return base.opEquals(o); } | |
1105 hash_t getHash(void *p) { return base.getHash(p); } | |
1106 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
1107 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
1108 size_t tsize() { return base.tsize(); } | |
1109 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
1110 | |
1111 TypeInfo next() { return base.next(); } | |
1112 uint flags() { return base.flags(); } | |
1113 void[] init() { return base.init(); } | |
1114 | |
1115 TypeInfo base; | |
1116 } | |
1117 | |
1118 class TypeInfo_Invariant : TypeInfo_Const | |
1119 { | |
1120 char[] toString() { return "invariant " ~ base.toString(); } | |
1121 } | |
1122 | |
1 | 1123 /** |
1124 * All recoverable exceptions should be derived from class Exception. | |
1125 */ | |
1126 class Exception : Object | |
1127 { | |
1128 char[] msg; | |
1129 | |
1130 /** | |
1131 * Constructor; msg is a descriptive message for the exception. | |
1132 */ | |
1133 this(char[] msg) | |
1134 { | |
1135 this.msg = msg; | |
1136 } | |
1137 | |
86
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1138 void print() |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1139 { |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1140 char[] s = toString(); |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1141 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
|
1142 } |
fd32135dca3e
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
lindquist
parents:
73
diff
changeset
|
1143 |
1 | 1144 char[] toString() { return msg; } |
1145 } | |
1146 | |
1147 /** | |
1148 * All irrecoverable exceptions should be derived from class Error. | |
1149 */ | |
1150 class Error : Exception | |
1151 { | |
1152 Error next; | |
1153 | |
1154 /** | |
1155 * Constructor; msg is a descriptive message for the exception. | |
1156 */ | |
1157 this(char[] msg) | |
1158 { | |
1159 super(msg); | |
1160 } | |
1161 | |
1162 this(char[] msg, Error next) | |
1163 { | |
1164 super(msg); | |
1165 this.next = next; | |
1166 } | |
1167 } | |
1168 | |
1169 //extern (C) int nullext = 0; | |
52 | 1170 |