annotate d2/qtd/Attribute.d @ 346:2691dd58d7e1

fixed QSlitter.getRange
author Max Samukha <maxter@spambox.com>
date Fri, 14 May 2010 13:15:24 +0300
parents 719604a71da0
children 970332a88b72
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
345
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
1 /*********************************************************
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
2 Copyright: QtD Team, 2010
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
3 Authors: Max Samukha
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
4 License: Boost Software License 1.0
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
5 *********************************************************/
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
6 module qtd.Attribute;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
7
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
8 import
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
9 lds.meta.compiletime,
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
10 std.traits,
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
11 std.conv,
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
12 std.typetuple;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
13
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
14 enum standardNamespace = "qtd";
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
15
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
16 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
17 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
18 enum AttributeOptions
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
19 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
20 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
21 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
22 none,
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
23
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
24 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
25 Allows multiple attributes of the same category to be associated with the symbol.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
26 */
346
2691dd58d7e1 fixed QSlitter.getRange
Max Samukha <maxter@spambox.com>
parents: 345
diff changeset
27 allowMultiple = 0x0000_0001,
2691dd58d7e1 fixed QSlitter.getRange
Max Samukha <maxter@spambox.com>
parents: 345
diff changeset
28
2691dd58d7e1 fixed QSlitter.getRange
Max Samukha <maxter@spambox.com>
parents: 345
diff changeset
29 /* internal */ inner = 0x0000_0002
345
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
30 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
31
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
32 private template attributeId(alias symbol, uint index = 0)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
33 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
34 enum attributeId = standardNamespace ~ "_attr_" ~ uniqueId!symbol ~ "_" ~ to!string(index);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
35 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
36
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
37 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
38 Attributes allow to associate arbitrary compile-time data
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
39 with a declaration and optionaly make that data available at run-time.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
40
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
41 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
42 class A
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
43 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
44 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
45 mixin Attribute!(C, "someAttribute", "B");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
46 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
47
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
48 The example above associates the string "B" with class A under the attribute category "someAttribute".
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
49 Multiple data can be associated with an attribute category for a single declaration:
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
50
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
51 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
52 class A
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
53 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
54 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
55 mixin Attribute!(C, "someAttribute", "B");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
56 mixin Attribute!(C, "someAttribute", AttributeOptions.allowMultiple, "C");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
57 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
58
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
59 Attributes of an attribute category can be accessed at compile-time:
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
60
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
61 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
62 alias GetAttributes!(C, "someAttribute") attrs;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
63 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
64
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
65 GetAttribute returns a compile time tuple, which contains "someAttribute" category attributes in the form
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
66 of TypeTupleWrapper instances. The first element of the tuple wrapped in the TypeTupleWrapper
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
67 contains the attribute category name, other elements contain the attrubute data.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
68
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
69 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
70 alias attrs[0] attr0;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
71 alias attrs[1] attr1;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
72
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
73 static assert(attrs0.tuple[0] == "someAttribute" && attrs0.tuple[1] == "B");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
74 static assert(attrs1.tuple[0] == "someAttribute" && attrs1.tuple[1] == "C");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
75 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
76
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
77 Attributes can be inserted inside the body of a declaration.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
78 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
79 class A
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
80 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
81 mixin Attribute!("someAttribute", "B");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
82 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
83 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
84
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
85 Attributes can be made available at run time by means of the declaration's meta-object
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
86 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
87 // prints category names of all attributes associated with class A
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
88 auto a = new A;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
89 foreach (attr; a.metaObject.attributes)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
90 writeln(attr.name);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
91 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
92
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
93 Attributes can be specialized
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
94
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
95 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
96 mixin template DbFieldAttribute(alias prop, string columnName)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
97 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
98 mixin Attribute!(prop, "DbFieldAttribute", columnName);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
99 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
100
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
101 class A
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
102 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
103 int value;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
104 mixin DbFieldAttribute!(value, "Value");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
105
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
106 int anotherValue;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
107 mixin DbFieldAttribute!(anotherValue, "Value2");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
108 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
109
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
110 assert(GetAttributes!(A.value, "DbFieldAttribute")[0].tuple[1] == "Value");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
111 assert(GetAttributes!(A.anotherValue, "DbFieldAttribute")[0].tuple[1] == "Value2");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
112 ----
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
113
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
114 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
115 mixin template Attribute(alias symbol, string attrClass, A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
116 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
117 mixin Attribute!(symbol, attrClass, AttributeOptions.none, A);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
118 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
119
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
120 /// ditto
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
121 mixin template Attribute(alias symbol, string attrClass, AttributeOptions opts, A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
122 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
123 mixin AttributeImpl!(symbol, attrClass, opts, 0, A);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
124 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
125
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
126
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
127 /// ditto
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
128 // TODO: probably make this an overload of Attribute
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
129 mixin template InnerAttribute(string attrClass, AttributeOptions opts, A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
130 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
131 // BUG: needs to be generalized to accept any parent
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
132 mixin Attribute!(typeof(this), attrClass, opts | AttributeOptions.inner, A);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
133 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
134
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
135 // ditto
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
136 mixin template InnerAttribute(string attrClass, A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
137 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
138 // BUG: needs to be generalized to accept any parent
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
139 mixin InnerAttribute!(attrClass, AttributeOptions.none, A);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
140 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
141
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
142 private mixin template AttributeImpl(alias symbol, string attrClass, AttributeOptions opts, size_t index, A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
143 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
144 private enum attrId = attributeId!(symbol, index) ~ (opts & AttributeOptions.inner ? "_inner" : "");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
145
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
146 static if (is(typeof(mixin(attrId))))
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
147 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
148 mixin ("alias " ~ attrId ~ " attr;");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
149 static if (!(opts & AttributeOptions.allowMultiple))
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
150 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
151 static assert (attr[0] != attrClass, "Multiple " ~ attrClass ~ " attributes are not allowed for "
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
152 ~ __traits(parent, symbol).stringof ~ "." ~ stringOf!symbol);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
153 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
154
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
155 mixin AttributeImpl!(symbol, attrClass, opts, index + 1, A);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
156 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
157 else
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
158 mixin ("alias TypeTuple!(attrClass, A) " ~ attrId ~ ";");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
159 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
160
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
161 private string stringOfFunction(alias symbol)()
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
162 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
163 auto ptrType = typeof(&symbol).stringof;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
164 auto paramList = ParameterTypeTuple!(symbol).stringof;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
165
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
166 string result = ReturnType!(symbol).stringof ~ " " ~ __traits(identifier, symbol) ~ paramList;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
167
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
168 if (ptrType[$ - 1] != ')')
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
169 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
170 for (size_t i = ptrType.length - 2;; --i)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
171 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
172 if (ptrType[i] == ')')
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
173 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
174 result ~= ptrType[i + 1..$];
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
175 break;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
176 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
177 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
178 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
179
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
180 return result;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
181 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
182
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
183 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
184 String of any symbol, including functions
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
185 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
186 template stringOf(alias symbol)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
187 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
188 static if (isFunction!symbol)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
189 enum stringOf = stringOfFunction!symbol;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
190 else
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
191 enum stringOf = symbol.stringof;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
192 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
193
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
194 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
195 Returns the string uniquely identifying the
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
196 symbol in its container.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
197 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
198 template uniqueName(alias symbol)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
199 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
200 enum uniqueName = stringOf!symbol;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
201 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
202
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
203 // TODO: works only for simple types. implement
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
204 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
205 *
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
206 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
207 string uniqueIdImpl(string symbol)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
208 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
209 char[] r = symbol.dup;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
210 foreach (i, c; symbol)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
211 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
212 if (c == '(' || c == ')' || c == ' ')
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
213 r[i] = '_';
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
214 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
215
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
216 return cast(immutable)r;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
217 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
218
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
219 template uniqueId(alias symbol)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
220 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
221 enum uniqueId = uniqueIdImpl(stringOf!symbol);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
222 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
223
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
224 version (QtdUnittest)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
225 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
226 unittest
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
227 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
228 static class C
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
229 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
230 void foo() const {};
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
231 bool bar(int) { return true; };
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
232 int x;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
233 static assert (stringOf!foo == "void foo() const");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
234 static assert (uniqueName!foo == "void foo() const");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
235 static assert (stringOf!bar == "bool bar(int)");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
236 static assert (uniqueName!bar == "bool bar(int)");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
237 static assert (stringOf!x == "x");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
238 static assert (uniqueName!x == "x");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
239 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
240
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
241 static assert (stringOf!(C.foo) == "void foo() const");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
242 static assert (uniqueName!(C.foo) == "void foo() const");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
243 static assert (stringOf!(C.bar) == "bool bar(int)");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
244 static assert (uniqueName!(C.bar) == "bool bar(int)");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
245
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
246 static assert (stringOf!(C.x) == "x");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
247 static assert (uniqueName!(C.x) == "x");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
248 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
249 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
250
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
251 template truePred(A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
252 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
253 enum truePred = true;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
254 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
255
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
256 template attrCategoryPred(string name)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
257 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
258 template attrCategoryPred(A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
259 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
260 enum attrCategoryPred = A[0] == name;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
261 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
262 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
263
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
264 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
265 Returns a compile-time tuple of attributes that
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
266 match pred.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
267 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
268 template GetAttributes(alias symbol, alias pred = truePred)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
269 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
270 alias GetAttributesImpl!(symbol, 0, pred).result GetAttributes;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
271 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
272
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
273 /**
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
274 Returns a compile-time tuple of attributes
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
275 matching the specified attribute category.
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
276 */
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
277 template GetAttributes(alias symbol, string attrCategory)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
278 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
279 alias GetAttributes!(symbol, attrCategoryPred!attrCategory) GetAttributes;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
280 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
281
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
282
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
283 template GetAttributesImpl(alias symbol, size_t index, alias pred)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
284 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
285 //pragma(msg, mixin("symbol." ~ attributeId!(symbol, index) ~ "_inner").stringof);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
286 static if (is(typeof(mixin("__traits(parent, symbol)." ~ attributeId!(symbol, index)))))
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
287 mixin ("alias lds.meta.compiletime.Alias!(__traits(parent, symbol))." ~ attributeId!(symbol, index) ~ " attr;");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
288 else static if (is(typeof(mixin("symbol." ~ attributeId!(symbol, index) ~ "_inner"))))
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
289 mixin ("alias symbol." ~ attributeId!(symbol, index) ~ "_inner attr;");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
290
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
291 static if (is(typeof(attr)))
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
292 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
293 alias GetAttributesImpl!(symbol, index + 1, pred).result next;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
294
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
295 static if (pred!attr)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
296 alias TypeTuple!(TypeTupleWrapper!attr, next) result;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
297 else
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
298 alias next result;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
299 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
300 else
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
301 alias TypeTuple!() result;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
302 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
303
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
304 version (QtdUnittest)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
305 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
306 mixin template MyAttribute(alias symbol, A...)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
307 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
308 mixin Attribute!(symbol, "MyAttribute", AttributeOptions.allowMultiple, A);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
309 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
310
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
311 mixin template ClassInfo(string name, alias value)
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
312 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
313 mixin InnerAttribute!("ClassInfo", AttributeOptions.allowMultiple, name, value);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
314 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
315
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
316 unittest
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
317 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
318 static class C
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
319 {
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
320 // inner C attributes
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
321 mixin InnerAttribute!("Inner", 33); // generic
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
322 mixin ClassInfo!("version", 123);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
323 mixin ClassInfo!("author", "James Bond");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
324
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
325
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
326 void foo() {};
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
327 // foo attributes
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
328 mixin Attribute!(foo, "SomeAttribute", 42);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
329 mixin MyAttribute!(foo, 1, 2);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
330 mixin MyAttribute!(foo, 3, 4);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
331
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
332 alias GetAttributes!(typeof(this), "Inner") innerAttrs;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
333 static assert(innerAttrs[0].tuple[0] == "Inner");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
334 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
335 // outer C attribute
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
336 mixin MyAttribute!(C, 24);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
337
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
338 alias GetAttributes!(C, "Inner") innerAttrs;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
339 static assert(innerAttrs[0].tuple[0] == "Inner" && innerAttrs[0].tuple[1] == 33);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
340
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
341 alias GetAttributes!(C, "ClassInfo") ciAttrs;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
342 static assert(ciAttrs[0].tuple[1] == "version" && ciAttrs[0].tuple[2] == 123);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
343
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
344 alias GetAttributes!(C.foo, "SomeAttribute") someAttr;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
345 static assert(someAttr.length == 1);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
346 static assert(someAttr[0].tuple[0] == "SomeAttribute");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
347
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
348 alias GetAttributes!(C.foo, "MyAttribute") myAttrs;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
349
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
350 //COMPILER BUG: cannot 'alias myAttrs[0].tuple myAttrs_0';
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
351 static assert(myAttrs[0].tuple[0] == "MyAttribute");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
352 static assert(myAttrs[0].tuple[1] == 1 && myAttrs[0].tuple[2] == 2);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
353
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
354 static assert(myAttrs[1].tuple[0] == "MyAttribute");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
355 static assert(myAttrs[1].tuple[1] == 3 && myAttrs[1].tuple[2] == 4);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
356
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
357 /+ BUG: Fails: local declarations cannot be accessed as parent.localDecl
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
358 alias GetAttributes!(C, "MyAttribute") myAttrs2;
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
359 static assert(myAttrs2[0].tuple[0] == "MyAttribute");
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
360 static assert(myAttrs2[0].tuple[1] == 24);
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
361 +/
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
362 }
719604a71da0 added attribute exercise
Max Samukha <maxter@spambox.com>
parents:
diff changeset
363 }