Skip to content

Commit

Permalink
Add documentation for UDA.
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-carlborg committed Jan 4, 2013
1 parent 77da903 commit bddbdf1
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 0 deletions.
111 changes: 111 additions & 0 deletions attribute.dd
Expand Up @@ -632,6 +632,117 @@ $(P
they can still provide $(SINGLEQUOTE base class functionality.) they can still provide $(SINGLEQUOTE base class functionality.)
) )


$(SECTION2 $(LNAME2 uda, User Defined Attributes),

$(P
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.
)

$(P
Grammatically, a UDA is a StorageClass:
)

$(GRAMMAR
$(GNAME StorageClass):
$(GLINK UserDefinedAttribute)

$(GNAME UserDefinedAttribute):
@(ArgumentList)
@CallExpression
)
$(P
And looks like:
)

---
@(3) int a;
@("string", 7) int b;

enum Foo;
@Foo int c;

struct Bar
{
int x;
}

@Bar(3) int d;
---

$(P
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")
}
---

$(P
UDA's can be extracted into an expression tuple using __traits:
)

---
@('c') string s;
pragma(msg, __traits(getAttributes, s)); // prints tuple('c')
---
)

$(P
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); // prints tuple(3, 4, 7, (SSS))
pragma(msg, TP[2]); // prints 7
---

$(P
Of course the tuple types can be used to declare things:
)

---
TP[3] a; // a is declared as an SSS
---

$(P
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")
---

$(P
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.
)

$(P
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.
)
)

) )


Macros: Macros:
Expand Down
33 changes: 33 additions & 0 deletions traits.dd
Expand Up @@ -35,6 +35,7 @@ $(GNAME TraitsKeyword):
$(GBLINK isLazy) $(GBLINK isLazy)
$(GBLINK hasMember) $(GBLINK hasMember)
$(GBLINK identifier) $(GBLINK identifier)
$(GBLINK getAttributes)
$(GBLINK getMember) $(GBLINK getMember)
$(GBLINK getOverloads) $(GBLINK getOverloads)
$(GBLINK getProtection) $(GBLINK getProtection)
Expand Down Expand Up @@ -306,6 +307,38 @@ $(H2 $(GNAME identifier))
for that symbol as a string literal. for that symbol as a string literal.
) )


$(SECTION2 $(GNAME getAttributes),
$(P
Takes one argument, a symbol. Returns a tuple of all attached user defined attributes.
If no UDA's exist it will return an empty tuple.
)

$(P
For more information, see: $(DDSUBLINK attribute, uda, User Defined Attributes)
)

---
@(3) int a;
@("string", 7) int b;

enum Foo;
@Foo int c;

pragma(msg, __traits(getAttributes, a));
pragma(msg, __traits(getAttributes, b));
pragma(msg, __traits(getAttributes, c));
---

$(P
Prints:
)

$(CONSOLE
tuple(3)
tuple("string", 7)
tuple((Foo))
)
)


$(H2 $(GNAME getMember)) $(H2 $(GNAME getMember))


Expand Down

0 comments on commit bddbdf1

Please sign in to comment.