Thread overview
[dmd-internals] Type-checked arrays?
Jun 14, 2011
Michel Fortin
Jun 14, 2011
Don Clugston
Jun 14, 2011
Michel Fortin
Jun 15, 2011
Michel Fortin
Jun 15, 2011
mrmocool at gmx.de
June 13, 2011
I've been looking at how to implement named arguments and one approach that comes to mind is to replace the array of expressions which holds arguments with an array of Argument (a new type) which would contain the expression as well as the name of the argument, and possibly later the

But here comes the problem. Everywhere in DMD, the Array struct holds raw pointers which then get casted to whatever you need in a given context. Having to cast every time you extract an element from an array prevents the compiler from doing proper type checking. This in turn makes it extremely perilous to refractor code in a way that changes the type contained in the array.

The standard C++ way to deal with that is to use a template parametrized on the type of content. I can understand that Walter likes that the compiler can compile even on the oldest C++ compiler, but at the same time I feel the lack of type-checking is holding us back.

I'd like to ask this: would it make sense to transform Array into a template and getting rid of all these casts? And if templates are still out bounds, couldn't we do the same using macros? What do you think?

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



June 14, 2011
On 14 June 2011 04:23, Michel Fortin <michel.fortin at michelf.com> wrote:
> I've been looking at how to implement named arguments and one approach that comes to mind is to replace the array of expressions which holds arguments with an array of Argument (a new type) which would contain the expression as well as the name of the argument, and possibly later the
>
> But here comes the problem. Everywhere in DMD, the Array struct holds raw pointers which then get casted to whatever you need in a given context. Having to cast every time you extract an element from an array prevents the compiler from doing proper type checking. This in turn makes it extremely perilous to refractor code in a way that changes the type contained in the array.
>
> The standard C++ way to deal with that is to use a template parametrized on the type of content. I can understand that Walter likes that the compiler can compile even on the oldest C++ compiler, but at the same time I feel the lack of type-checking is holding us back.

There have been a huge number of bugs(mostly ICE, but a couple of wrong-code bugs)  because of the lack of type checking. For example, there's still one in there, related to tuples.

BTW named arguments for functions has very much in common with named arguments for struct initializers, which was finally implemented in the last release. That uses two Arrays, one with the argument and the other with the name.

>
> I'd like to ask this: would it make sense to transform Array into a template and getting rid of all these casts? And if templates are still out bounds, couldn't we do the same using macros? What do you think?
>
> --
> Michel Fortin
> michel.fortin at michelf.com
> http://michelf.com/
>
>
>
> _______________________________________________
> dmd-internals mailing list
> dmd-internals at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-internals
>
June 14, 2011
Le 2011-06-14 ? 4:27, Don Clugston a ?crit :

> BTW named arguments for functions has very much in common with named

> arguments for struct initializers, which was finally implemented in the last release. That uses two Arrays, one with the argument and the other with the name.

It's not a bad idea, but I fear this might become complicated once tuples get expanded in the argument list. That said, how exactly tuples should interact with named argument is an open question.


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



June 15, 2011
Le 2011-06-13 ? 22:23, Michel Fortin a ?crit :

> I'd like to ask this: would it make sense to transform Array into a template and getting rid of all these casts? And if templates are still out bounds, couldn't we do the same using macros? What do you think?

Various options depending on what's allowed:

What we have currently:

	// in arraytypes.h
	struct Expressions : Array {}

	// elsewhere
	Expressions exps = ...;
	Expression *e = (Expression *)exps->data[i];
        exps->data[i] = (void *)e;

With macros or templates:

	// in arraytypes.h
	typedef ArrayOf(Expression) Expressions; // with macros
	typedef Array< Expression > Expressions; // with templates

	// elsewhere
	Expressions exps = ...;
	Expression *e = exps->tdata()[i];
        exps->tdata()[i] = e;

(Note: I could use reference return and operator[] instead to make things tidier, but it seems DMD avoids those C++ features...)

I counted 789 instances of array->data[i] that'd need to be updated.

I'd rename the current Array struct to ArrayBase. Renaming it will make all of its existing uses through the code an error, pointing out each variable that needs to be migrated to the new type. Also, making its 'data' member protected will make all accesses of untyped data an error, making it easy to migrate those lines of code. Typed arrays would be implemented on top of ArrayBase:

Proposed macro implementation would be implemented like this:

	#define ArrayOf(TYPE) struct Array_##TYPE : ArrayBase \
	{ \
	    // return typed data \
	    TYPE **tdata() { return (TYPE **)data; } \
	}

Proposed template implementation (just a little cleaner):

	template < class TYPE >
	struct Array : ArrayBase
	{
	    // return typed data
	    TYPE **tdata() { return (TYPE **)data; }
	}

What do you think? Is this change worth it? Walter, would you agree with such a change?


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



June 15, 2011
Am 15.06.2011, 14:15 Uhr, schrieb Michel Fortin <michel.fortin at michelf.com>:
> (Note: I could use reference return and operator[] instead to make things tidier, but it seems DMD avoids those C++ features...)
...
> What do you think? Is this change worth it? Walter, would you agree with such a change?

Definitely worth it.
But if we do all that work anyway, we should really do it properly, i.e.
with operator[]!