User Defined Attributes
Walter Bright
newshound2 at digitalmars.com
Mon Nov 5 23:55:49 PST 2012
References:
http://www.digitalmars.com/d/archives/digitalmars/D/Custom_attributes_again_163042.html
http://www.digitalmars.com/d/archives/digitalmars/D/custom_attribute_proposal_yeah_another_one_163246.html
Inspired by a gallon of coffee, I decided to get it implemented. It's simple,
based on what D already does (CTFE and heterogeneous tuples), easy to implement,
easy to understand, and doesn't break anything. It should do everything asked
for in the above references (except it's not a type constructor).
You can download it here and try it out:
http://ftp.digitalmars.com/dmd2beta.zip
As a bonus, that beta also can generate Win64 executables, and you can even
symbolically debug them with VS! (Thanks to Rainer Schütze for his invaluable
help with that).
Here's the rather skimpy and lame spec I banged out:
=====================================================
User Defined Attributes
-----------------------
User Defined Attributes (UDA) are compile time expressions that can be attached
to a declaration. These attributes can then be queried, extracted, and manipulated
at compile time. There is no runtime component to them.
Grammatically, a UDA is a StorageClass:
StorageClass:
UserDefinedAttribute
UserDefinedAttribute:
[ ArgumentList ]
And looks like:
[ 3 ] int a;
[ "string", 7 ]: int b;
If there are multiple UDAs in scope for a declaration, they are concatenated:
[ 1 ] {
[ 2 ] int a; // has UDA's [1,2]
[ "string" ] int b; // has UDA's [1,"string"]
}
UDA's can be extracted into an expression tuple using __traits:
[ 'c' ] string s;
pragma(msg, __traits(getAttributes, s));
prints:
tuple('c')
If there are no user defined attributes for the symbol, an empty tuple is returned.
The expression tuple can be turned into a manipulatable tuple:
template Tuple(T...) {
alias T Tuple;
}
enum EEE = 7;
["hello"] struct SSS { }
[3] { [4][EEE][SSS] int foo; }
alias Tuple!(__traits(getAttributes, foo)) TP;
pragma(msg, TP);
pragma(msg, TP[2]);
prints:
tuple(3,4,7,(SSS))
7
and of course the tuple types can be used to declare things:
TP[3] a; // a is declared as an SSS
The attribute of the type name is not the same as the attribute of the variable:
pragma(msg, __traits(getAttributes, typeof(a));
prints:
tuple("hello")
Of course, the real value of UDA's is to be able to create user defined types with
specific values. Having attribute values of basic types does not scale.
The attribute tuples can be manipulated like any other tuple, and
can be passed as the argument list to a template.
Whether the attributes are values or types is up to the user, and whether later
attributes accumulate or override earlier ones is also up to how the user
interprets them.
More information about the Digitalmars-d-announce
mailing list