Thread overview
ICE simple repro case
Jun 15, 2002
Sean L. Palmer
Jun 18, 2002
Walter
Jun 18, 2002
Sean L. Palmer
Jun 18, 2002
Pavel Minayev
Jun 18, 2002
Burton Radons
Jun 18, 2002
Pavel Minayev
Jun 18, 2002
Burton Radons
Jun 18, 2002
Pavel Minayev
Jun 18, 2002
Walter
Jun 18, 2002
Pavel Minayev
June 15, 2002
// 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);
}



June 18, 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


June 18, 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



June 18, 2002
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:

	Object spawn(ClassInfo ci)
	{
		Object obj = ci.newInstance();
		...
		return obj;
	}

	Object obj = spawn(NPC.ClassInfo);
	...
	delete obj;





June 18, 2002
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.

June 18, 2002
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???

>     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
		...
June 18, 2002
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.

June 18, 2002
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.

June 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.


June 18, 2002
On Tue, 18 Jun 2002 10:04:34 -0700 "Walter" <walter@digitalmars.com> wrote:

> "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.

Yes, also there is a cast we can rely on:

	if (cast(File) stream) ...

Now if we only had function like isBase() for ClassInfo (since one
can't perform a run-time cast using ClassInfo)...