www.digitalmars.com         C & C++   DMDScript  

D - ICE simple repro case

reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
// 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
parent reply "Walter" <walter digitalmars.com> writes:
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
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
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
parent reply Pavel Minayev <evilone omen.ru> writes:
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
parent reply Burton Radons <loth users.sourceforge.net> writes:
Pavel Minayev wrote:
 On Mon, 17 Jun 2002 23:30:19 -0700 "Sean L. Palmer" <seanpalmer earthlink.net> 
 wrote:
 
 
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:

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.
Jun 18 2002
parent reply Pavel Minayev <evilone omen.ru> writes:
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
next sibling parent reply Burton Radons <loth users.sourceforge.net> writes:
Pavel Minayev wrote:
 On Tue, 18 Jun 2002 01:53:00 -0700 Burton Radons <loth users.sourceforge.net> 
 wrote:
 
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???

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. ;-)
    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 ...

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.
Jun 18 2002
parent Pavel Minayev <evilone omen.ru> writes:
On Tue, 18 Jun 2002 07:14:46 -0700 Burton Radons <loth users.sourceforge.net> 
wrote:

 Hey, and how are you going to call the constructor???

Not desirable for serialisation. But if you inflict an interface on

It is a question... not calling constructor may result in very subtle errors due to initialization not performed in base classes.
Jun 18 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"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
parent Pavel Minayev <evilone omen.ru> writes:
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