1 
2 module dquery.attribute;
3 
4 import std.typetuple;
5 
6 struct DQueryAttribute(alias Attribute)
7 {
8 
9 	/++
10 	 + Property that returns the value of the attribute.
11 	 ++/
12 	@property
13 	alias attribute = Attribute;
14 
15 	/++
16 	 + Proprety that returns true if the attribute is a type.
17 	 ++/
18 	@property
19 	enum isType = !is(typeof(Attribute));
20 
21 	/++
22 	 + Property that returns true if the attribute is an expression.
23 	 ++/
24 	@property
25 	enum isExpression = is(typeof(Attribute));
26 
27 	// Determine how to get the type.
28 	static if(isExpression)
29 	{
30 		/++
31 		 + Property that returns the type of the attribute.
32 		 ++/
33 		@property
34 		alias type = typeof(Attribute);
35 
36 		/++
37 		 + Property that returns the value of the attributes.
38 		 + Only defined for attributes that can produce a value.
39 		 ++/
40 		@property
41 		alias get = Attribute;
42 
43 		/++
44 		 + Property that returns the value of the attribute if it's an expression,
45 		 + else a default value if the attribute if a type.
46 		 ++/
47 		@property
48 		alias getOrElse(alias Default) = Attribute;
49 
50 		/++
51 		 + Property that returns the value of the attribute if it's an expression,
52 		 + else throws an exception (at runtime) if it's a type.
53 		 ++/
54 		@property
55 		static type getOrThrow(ExcType = Exception)(string message)
56 		{
57 			return Attribute;
58 		}
59 	}
60 	else
61 	{
62 		/++
63 		 + Property that returns the type of the attribute.
64 		 ++/
65 		@property
66 		alias type = Attribute;
67 
68 		/++
69 		 + Property that returns the value of the attribute if it's an expression,
70 		 + else a default value if the attribute if a type.
71 		 ++/
72 		@property
73 		alias getOrElse(alias Default) = Default;
74 
75 		/++
76 		 + Property that returns the value of the attribute if it's an expression,
77 		 + else throws an exception (at runtime) if it's a type.
78 		 ++/
79 		@property
80 		static type getOrThrow(ExcType = Exception)(string message)
81 		{
82 			throw new ExcType(message);
83 		}
84 	}
85 
86 	/++
87 	 + Property that returns true if a given type matches the attribute's
88 	 + type exactly.
89 	 ++/
90 	@property
91 	enum isTypeOf(Type) = is(type == Type);
92 
93 	/++
94 	 + Property that returns true if a given type can be assigned to a
95 	 + variable of the attribute's type.
96 	 ++/
97 	@property
98 	enum isTypeAssignableTo(Type) = __traits(compiles, {
99 		type t1 = void;
100 		Type t2 = t1;
101 	});
102 
103 	/++
104 	 + Property that returns true if a given type can be assigned from a
105 	 + variable of the attribute's type.
106 	 ++/
107 	@property
108 	enum isTypeAssignableFrom(Type) = __traits(compiles, {
109 		Type t1 = void;
110 		type t2 = t1;
111 	});
112 
113 	@property
114 	static auto opCall()
115 	{
116 		DQueryAttribute!(Attribute) attribute = void;
117 		return attribute;
118 	}
119 
120 	/++
121 	 + Queries the type of the attribute.
122 	 ++/
123 	@property
124 	static auto query()()
125 	{
126 		import dquery.d;
127 		return query!type;
128 	}
129 
130 	static string toString()
131 	{
132 		return Attribute.stringof;
133 	}
134 
135 }