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