D - ICE simple repro case
- Sean L. Palmer (25/25) Jun 15 2002 // This smaller snippet should repro the bug:
- Walter (4/4) Jun 17 2002 Thanks for boiling this down for me. The trouble is that in the semantic
- Sean L. Palmer (57/61) Jun 17 2002 So it typecasts to the wrong type? Shame. ;)
- Pavel Minayev (25/25) Jun 18 2002 On Mon=2C 17 Jun 2002 23=3A30=3A19 -0700 =22Sean L=2E Palmer=22 =3Cseanp...
- Burton Radons (16/35) Jun 18 2002 This'll be necessarily for serialisation (constructing an object with
- Pavel Minayev (18/18) Jun 18 2002 On Tue=2C 18 Jun 2002 01=3A53=3A00 -0700 Burton Radons =3Cloth=40users=2...
- Burton Radons (40/61) Jun 18 2002 Not desirable for serialisation. But if you inflict an interface on
- Pavel Minayev (4/7) Jun 18 2002 It is a question... not calling constructor may result in very subtle
- Walter (4/8) Jun 18 2002 Ah, you noticed! That makes for a much more efficient way to verify a cl...
- Pavel Minayev (17/17) Jun 18 2002 On Tue=2C 18 Jun 2002 10=3A04=3A34 -0700 =22Walter=22 =3Cwalter=40digita...
// This smaller snippet should repro the bug: import intrinsic; public: // VECTOR alias float[2] vector2; // POINT typedef vector2 point2; // POINT TO POINT DISTANCE float distance(point2 a, point2 b) { point2 d = b[] - a[]; return sqrt(d[0]*d[0]+d[1]*d[1]); } // SPHERE struct sphere2 { point2 center; float radius; } alias sphere2 circle; // SPHERE TO SPHERE DISTANCE float distance(sphere2 a, sphere2 b) { return distance(a.center, b.center) - (a.radius + b.radius); }
Jun 15 2002
Thanks for boiling this down for me. The trouble is that in the semantic analyzer, it doesn't always check for typedefs before working on the type. (That's why making it an alias works as a workaround.) I need to find and correct all those trouble spots. -Walter
Jun 17 2002
So it typecasts to the wrong type? Shame. ;) Casts do turn out to be (occasionally) necessary. It's always fastest to do your own RTTI. Speaking of RTTI have you got a concept of "pointer to constructor" function kind of like a memory allocator. In fact this may be better modeled as an object allocator. Kind of like operator new and delete rolled into one. It's also a bit like the Factory pattern in GoF. This pointer could be stored in the vtable of a class and other code could access it thru the vtable. Calling it with a void returns an object of that class. Calling it with an object of that class takes the object back, deallocates it, and returns void. Perhaps one could define a function which were called when the object is merely referenced; A value-producer. C++'s equivalent would be user-defined conversion operators. I would be ok if I could just convert to one specific type which is my value when used as a rvalue in any ordinary expression. And operator = when assigned as an lvalue, perhaps for just one type (and it could specify the type required). With those two I can write such: class mallocator { foo this() { return new foo; } void this(foo r) { delete r; } } void main() { mallocator mymallocator; foo myfoo = mymallocator; // get a new foo from the mallocator myfoo.dosomething(); mymallocator = myfoo; // give myfoo back to mallocator for deletion } With that syntax you can also almost make a smart pointer or iterator or some kind of "object call forwarding" object. Nah. You won't go for the operator overloading (at least not for v1.0) but some kind of standard concept of allocator wouldn't be bad. Because you could obtain an allocator from the vtable. In a standard way. That would have to be good, right? Vtable should also have some kind of linker id attribute and human-readable name. Maybe instead of operator overloading we can come up with What if the language defined that, at time of a scope exiting, all objects created during that scope are destroyed *except* those explicitly made "long lived" by the code (by declaring "new foo x" instead of "foo x") This would apply to result objects obtained from called functions, all temporaries, everything it knows about that hasn't been "new"ed somehow. That simplifies alot of things at runtime and is easy to enforce at compile time. Of course the allocator (new in this case) manages those kind of objects so when the allocator itself goes out of scope and is destroyed all its objects will be too. The standard allocator runs before main and destroys everything at termination of main and in the meantime can free unused objects if it runs out of memory. It would be nice if we could get the compiler to just tell the mallocator what was being referred to when, by whom. That and auto-streaming I guess. Maybe I was right and you should go beta before we talk your ear off and think of all kinds of wacky stuff for D 2.0 ;) Sean "Walter" <walter digitalmars.com> wrote in message news:aem07p$pb1$1 digitaldaemon.com...Thanks for boiling this down for me. The trouble is that in the semantic analyzer, it doesn't always check for typedefs before working on the type. (That's why making it an alias works as a workaround.) I need to find and correct all those trouble spots. -Walter
Jun 17 2002
On Mon=2C 17 Jun 2002 23=3A30=3A19 -0700 =22Sean L=2E Palmer=22 =3Cseanpalmer=40earthlink=2Enet=3E wrote=3A =3E Speaking of RTTI have you got a concept of =22pointer to constructor=22 function =3E kind of like a memory allocator=2E In fact this may be better modeled as an =3E object allocator=2E Kind of like operator new and delete rolled into one=2E =3E It's also a bit like the Factory pattern in GoF=2E This pointer could be =3E stored in the vtable of a class and other code could access it thru the =3E vtable=2E Calling it with a void returns an object of that class=2E Calling it =3E with an object of that class takes the object back=2C deallocates it=2C and =3E returns void=2E I already asked Walter of something like this=2C and he said it's a great idea=2C but it has to wait till he implements other important things=2E=2E=2E By the way=2C I'd suggest a simpler approach=2E Since we already have class ClassInfo=2C why don't add a method to it which creates the object of that class=3F And we could still use delete to destroy that object=3A =09Object spawn=28ClassInfo ci=29 =09{ =09=09Object obj =3D ci=2EnewInstance=28=29=3B =09=09=2E=2E=2E =09=09return obj=3B =09} =09Object obj =3D spawn=28NPC=2EClassInfo=29=3B =09=2E=2E=2E =09delete obj=3B
Jun 18 2002
Pavel Minayev wrote:On Mon, 17 Jun 2002 23:30:19 -0700 "Sean L. Palmer" <seanpalmer earthlink.net> wrote:This'll be necessarily for serialisation (constructing an object with just its class and not calling any constructors), so it's definitely going to come around sometime. But to be honest, it can be done using: Object spawn(ClassInfo ci) { return (Object) (void *) ci.init.dup; } ClassInfo classof(Object object) { return (ClassInfo) **(void ***) object; } The only way it won't work is that delete'ing it will destroy the universe. Wait, no it won't. Isn't that odd? I'm guessing it's at least ignoring my rabid call for destruction.Speaking of RTTI have you got a concept of "pointer to constructor" function kind of like a memory allocator. In fact this may be better modeled as an object allocator. Kind of like operator new and delete rolled into one. It's also a bit like the Factory pattern in GoF. This pointer could be stored in the vtable of a class and other code could access it thru the vtable. Calling it with a void returns an object of that class. Calling it with an object of that class takes the object back, deallocates it, and returns void.I already asked Walter of something like this, and he said it's a great idea, but it has to wait till he implements other important things... By the way, I'd suggest a simpler approach. Since we already have class ClassInfo, why don't add a method to it which creates the object of that class? And we could still use delete to destroy that object:
Jun 18 2002
On Tue=2C 18 Jun 2002 01=3A53=3A00 -0700 Burton Radons =3Cloth=40users=2Esourceforge=2Enet=3E wrote=3A =3E But to be honest=2C it can be done using=3A =3E =3E Object spawn=28ClassInfo ci=29 =3E { =3E return =28Object=29 =28void *=29 ci=2Einit=2Edup=3B =3E } Hey=2C and how are you going to call the constructor=3F=3F=3F =3E ClassInfo classof=28Object object=29 =3E { =3E return =28ClassInfo=29 **=28void ***=29 object=3B =3E } Well actually every object has =2Eclassinfo property =28and it can also be applied to class name=29=3A =09if =28stream=2Eclassinfo =3D=3D File=2Eclassinfo=29=09=2F=2F stream is File =09=09=2E=2E=2E
Jun 18 2002
Pavel Minayev wrote:On Tue, 18 Jun 2002 01:53:00 -0700 Burton Radons <loth users.sourceforge.net> wrote:Not desirable for serialisation. But if you inflict an interface on compliant objects you could have a non-argument constructor as the first method: /* Return whether the interface is in the class */ Interface *implements(ClassInfo classinfo, ClassInfo inter) { Interface [] interlist = classinfo.interfaces; for (int c = 0; c < interlist.length; c ++) if (interlist [c].classinfo == inter) return &interlist [c]; return null; } Object spawn(ClassInfo ci) { Interface *inter; Object object; object = (Object) (void *) ci.init.dup; inter = implements(ci, IConstructor.classinfo); if (inter != null) { void (*method) (Object); method = (void (*) (Object)) inter.vtbl [0]; method ((Object) ((void *) object + inter.offset)); /* 'Tis not ours to question why... */ } return object; } interface IConstructor { void construct(); } Otherwise since all classes need constructors it's a fairly safe assumption that the first method is the first constructor which takes no arguments, but that's dependent on coding style. Otherwise you'll have to wait for introspection. I'm sorry I can't bend reality to my whim. ;-)But to be honest, it can be done using: Object spawn(ClassInfo ci) { return (Object) (void *) ci.init.dup; }Hey, and how are you going to call the constructor???Oh! Well, it's, uh, my style to take apart an implementation before trying for an easy method. :-) This should be mentioned somewhere in the standard. Thanks.ClassInfo classof(Object object) { return (ClassInfo) **(void ***) object; }Well actually every object has .classinfo property (and it can also be applied to class name): if (stream.classinfo == File.classinfo) // stream is File ...
Jun 18 2002
On Tue, 18 Jun 2002 07:14:46 -0700 Burton Radons <loth users.sourceforge.net> wrote:It is a question... not calling constructor may result in very subtle errors due to initialization not performed in base classes.Hey, and how are you going to call the constructor???Not desirable for serialisation. But if you inflict an interface on
Jun 18 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374256701879745 news.digitalmars.com...Well actually every object has .classinfo property (and it can also be applied to class name): if (stream.classinfo == File.classinfo) // stream is File ...Ah, you noticed! That makes for a much more efficient way to verify a class type than using C++'s RTTI.
Jun 18 2002
On Tue=2C 18 Jun 2002 10=3A04=3A34 -0700 =22Walter=22 =3Cwalter=40digitalmars=2Ecom=3E wrote=3A =3E =22Pavel Minayev=22 =3Cevilone=40omen=2Eru=3E wrote in message =3E news=3ACFN374256701879745=40news=2Edigitalmars=2Ecom=2E=2E=2E =3E=3EWell actually every object has =2Eclassinfo property =28and it can also =3E=3Ebe applied to class name=29=3A =3E=3E =3E=3Eif =28stream=2Eclassinfo =3D=3D File=2Eclassinfo=29 =2F=2F stream is File =3E=3E=2E=2E=2E =3E =3E Ah=2C you noticed! That makes for a much more efficient way to verify a class =3E type than using C++'s RTTI=2E Yes=2C also there is a cast we can rely on=3A =09if =28cast=28File=29 stream=29 =2E=2E=2E Now if we only had function like isBase=28=29 for ClassInfo =28since one can't perform a run-time cast using ClassInfo=29=2E=2E=2E
Jun 18 2002