April 06, 2012
Le 06/04/2012 17:00, Andrei Alexandrescu a écrit :
> On 4/6/12 5:06 AM, Walter Bright wrote:
>> On 4/6/2012 2:41 AM, Johannes Pfau wrote:
>>> The last time custom attributes where discussed, a C# like model was
>>> proposed. Is there a good reason why we should deviate from the C#
>>> implementation?
>>
>> C# uses a runtime implementation, not a compile time one.
>
> Speaking of the distinction, it would be great if we arranged things
> such that attributes are a lowering to existing D (i.e. the compiler
> rewrites a nice attribute syntax into clunky D code you wouldn't want to
> write by hand).
>
> Lowerings have worked miracles for us in terms of keeping language
> semantics simple and reducing implementation bugs. We should use them
> wherever appropriate.
>
>
> Andrei

Again, I rise the need of AOP.

No need for runtime attribute or compiler magic if we have AOP that could interleave « clunky D code you wouldn't want to write by hand » without adding yet again another language feature.
April 06, 2012
On 04/06/2012 05:00 PM, Andrei Alexandrescu wrote:
> On 4/6/12 5:06 AM, Walter Bright wrote:
>> On 4/6/2012 2:41 AM, Johannes Pfau wrote:
>>> The last time custom attributes where discussed, a C# like model was
>>> proposed. Is there a good reason why we should deviate from the C#
>>> implementation?
>>
>> C# uses a runtime implementation, not a compile time one.
>
> Speaking of the distinction, it would be great if we arranged things
> such that attributes are a lowering to existing D (i.e. the compiler
> rewrites a nice attribute syntax into clunky D code you wouldn't want to
> write by hand).
>

What would that look like?

> Lowerings have worked miracles for us in terms of keeping language
> semantics simple and reducing implementation bugs.

What do you have in mind here?

All lowerings I am aware of are trivial ones and their implementation resulted in sloppy error handling (eg: foreach) for no clear benefit. Some of them (eg: with statement) have even made the implementation bug situation worse.

> We should use them
> wherever appropriate.
>
>
> Andrei

I don't think they are in this case. What will help reducing implementation bugs is that most of their implementation is already covered by the CTFE implementation.
April 06, 2012
Andrei Alexandrescu wrote:
> On 4/6/12 1:47 AM, Walter Bright wrote:
>> __traits(hasAttribute, x, foo)
>>
>> would return true, and:
>>
>> __traits(getAttribute, x, foo)
>>
>> would return the expression (bar+1). The expression would be
>> compile-time only, evaluated at the point of declaration.
>
> You also need means to enumerate attributes.

Minimalistically getAttribute*s* should be enough:

__traits(getAttributes, x)

would return all attributes of x.

The rest can be implemented as library templates in std.traits.
April 06, 2012
On Friday, 6 April 2012 at 15:16:37 UTC, Piotr Szturmaj wrote:
> __traits(getAttributes, x)

Note that my proposal from a couple weeks ago did it this way.

getAttributes returned a TypeTuple. You'd loop through it
with is(typeof()) to extract a specific one.

The key is the type name.

The value is whatever your thing evaluated to:

@attr(10+2) decl;

conceptually the same as

enum tmp = 10+2;
decl.annotations ~= tmp;


April 06, 2012
On Fri, 06 Apr 2012 11:00:25 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 4/6/12 5:06 AM, Walter Bright wrote:
>> On 4/6/2012 2:41 AM, Johannes Pfau wrote:
>>> The last time custom attributes where discussed, a C# like model was
>>> proposed. Is there a good reason why we should deviate from the C#
>>> implementation?
>>
>> C# uses a runtime implementation, not a compile time one.
>
> Speaking of the distinction, it would be great if we arranged things such that attributes are a lowering to existing D (i.e. the compiler rewrites a nice attribute syntax into clunky D code you wouldn't want to write by hand).
>
> Lowerings have worked miracles for us in terms of keeping language semantics simple and reducing implementation bugs. We should use them wherever appropriate.

I don't think that applies here.  We have no low-level mechanism to affect the compiler internals, which is where attribute metadata belongs.

-Steve
April 06, 2012
On 4/6/12 10:09 AM, Timon Gehr wrote:
>> Speaking of the distinction, it would be great if we arranged things
>> such that attributes are a lowering to existing D (i.e. the compiler
>> rewrites a nice attribute syntax into clunky D code you wouldn't want to
>> write by hand).
>>
>
> What would that look like?

Essentially we want to associate with any symbol (be it a type, function, method, or whatnot) some extra information in the form of a tuple of key/value pairs. The value can be anything CTFE. How would one do that "by hand", albeit ugly and verbose? Once we get the desired functionality, we work back on a syntax for it. And we're done.

>> Lowerings have worked miracles for us in terms of keeping language
>> semantics simple and reducing implementation bugs.
>
> What do you have in mind here?

All: foreach, scope, operator overloading - wherever we used lowerings it's been an unqualified success. I am only sorry we didn't use them more often and more systematically.

> All lowerings I am aware of are trivial ones and their implementation
> resulted in sloppy error handling (eg: foreach) for no clear benefit.

Defining foreach as a lowering clarifies to both the library author and the user what the expectations are.

> Some of them (eg: with statement) have even made the implementation bug
> situation worse.

"with" is not implemented via a lowering.


Andrei

April 06, 2012
On 04/06/2012 09:15 PM, Andrei Alexandrescu wrote:
> On 4/6/12 10:09 AM, Timon Gehr wrote:
>>> Speaking of the distinction, it would be great if we arranged things
>>> such that attributes are a lowering to existing D (i.e. the compiler
>>> rewrites a nice attribute syntax into clunky D code you wouldn't want to
>>> write by hand).
>>>
>>
>> What would that look like?
>
> Essentially we want to associate with any symbol (be it a type,
> function, method, or whatnot) some extra information in the form of a
> tuple of key/value pairs. The value can be anything CTFE. How would one
> do that "by hand", albeit ugly and verbose? Once we get the desired
> functionality, we work back on a syntax for it. And we're done.
>

There is no existing in-language solution whose only bad property is its ugliness, because it cannot be allowed to introduce additional symbols.

>>> Lowerings have worked miracles for us in terms of keeping language
>>> semantics simple and reducing implementation bugs.
>>
>> What do you have in mind here?
>
> All: foreach, scope, operator overloading - wherever we used lowerings
> it's been an unqualified success. I am only sorry we didn't use them
> more often and more systematically.
>

I think they have been applied where they were appropriate. What other existing language features would you rather have specified as a lowering?

>> All lowerings I am aware of are trivial ones and their implementation
>> resulted in sloppy error handling (eg: foreach) for no clear benefit.
>
> Defining foreach as a lowering clarifies to both the library author and
> the user what the expectations are.
>

Agreed, using lowering custom overloading of language constructs is good. These usages have slipped my mind because they are so different from what we are discussing here.

I was thinking about foreach over built in arrays. For example:

foreach(double i,x; (int[]).init){}
Error: cannot implicitly convert expression (i) of type double to ulong

i.e. using lowering for implementation without any additional checks is not a good thing.

Anyway, how does the argument apply to the custom attribute case? The specification of how custom attributes work is certainly simpler and more clear than the specification of how the 'code that is too ugly to be written by hand' is generated and getting it right should be comparably difficult for both. The solution that uses a lowering would need additional compiler support for hiding additionally generated symbols. This makes the lowering even harder to follow for someone who wants to get started on custom attributes. It just seems kludgy to me.
April 06, 2012
On 4/6/12 2:47 PM, Timon Gehr wrote:
> There is no existing in-language solution whose only bad property is its
> ugliness, because it cannot be allowed to introduce additional symbols.

You can always assume fresh variables even though indeed there's no support for them. Just use __ as prefix and then combine with a cookie and the existing symbol name. There will be no clashes.

>> All: foreach, scope, operator overloading - wherever we used lowerings
>> it's been an unqualified success. I am only sorry we didn't use them
>> more often and more systematically.

I forgot the new lambda syntax ("=>") was defined as a lowering and as a consequence is came virtually bug free.

> I think they have been applied where they were appropriate. What other
> existing language features would you rather have specified as a lowering?

Some array and associative array literals and operations. All object copying.

> Anyway, how does the argument apply to the custom attribute case? The
> specification of how custom attributes work is certainly simpler and
> more clear than the specification of how the 'code that is too ugly to
> be written by hand' is generated and getting it right should be
> comparably difficult for both. The solution that uses a lowering would
> need additional compiler support for hiding additionally generated
> symbols. This makes the lowering even harder to follow for someone who
> wants to get started on custom attributes. It just seems kludgy to me.

Expressing attributes in terms of what they do within attribute-less D is crucial to keeping both definition and implementation simple. Hidden symbols are a non-issue.


Andrei
April 06, 2012
Le 06/04/2012 12:28, Walter Bright a écrit :
> On 4/6/2012 3:23 AM, Manu wrote:
>> What about:
>>
>> struct editor
>> {
>> this(string name, EditType, Colour = Colour.Default, string
>> description = null)
>> {
>> //...
>> }
>>
>> blah blah blah
>> }
>>
>> @attr(editor("thing",...blah...))
>
> Are you really changing the arguments for every declaration? Or is it
> one set that is repeated everywhere?
>
>
>> I don't see the advantage over:
>> @editor(...)
>>
>> ?
>
> Name collisions with other @ attributes.
>

That isn't a good argument IMO. We have type int and user defined types. I cannot do struct int {}. Same for @safe or @property or any other language defined property.
April 07, 2012
On 2012-04-06 15:48, Adam D. Ruppe wrote:
> On Friday, 6 April 2012 at 12:52:27 UTC, Jacob Carlborg wrote:
>> Just as we have today with keywords and symbols, I don't see the problem.
>
> Things like safe aren't keywords though. They are just
> magic identifiers.
>
> Think of the implementation:
>
> switch(tok.ident) {
> case Id::safe:
> case Id::property:
> // etc for built ins
> default:
> // handle user ones here
> }
>
> If you were to define a struct safe {}, which is perfectly
> legal D, and try to use it, you won't get what you expect.
>
> It will trigger the case safe before it goes to the default.
> So, the user defined one will just be quietly hidden.

I mean that "int" is a keyword and "int" is in the same "scope" as the rest of the symbols. So if we allow custom attributes, like "@foo", it's the same "problem" as with regular identifiers. Regular identifiers can conflict with keywords.

-- 
/Jacob Carlborg