如
上一篇文章所說(shuō),
Vczh Library++3.0的NativeX語(yǔ)言實(shí)現(xiàn)了
計(jì)劃的所有泛型語(yǔ)法。讓我們來(lái)看一個(gè)簡(jiǎn)單的例子:我們?yōu)轭愋蛯?xiě)一個(gè)Equals函數(shù)。我們可以為普通類型,譬如int32寫(xiě)一個(gè)Equals函數(shù)。我們有Vector<T>類型,只要T類型擁有一個(gè)Equals函數(shù),那么Vector<T>顯然也可以有Equals函數(shù)。問(wèn)題來(lái)了,我們?cè)赩ectorEquals<T>函數(shù)里面怎么知道T的Equals函數(shù)究竟是那一個(gè)呢?在這里我們用concept和instance,其實(shí)也就是haskell的type class在C語(yǔ)言上僅有的一種形式,來(lái)表達(dá)。
首先我們定義一個(gè)叫Eq的concept,里面包含Equals和NotEquals兩個(gè)函數(shù)的原型。這兩個(gè)函數(shù)規(guī)定了參數(shù)的類型和返回值類型:
1 concept T : Eq
2 {
3 Equals = function bool(T, T);
4 NotEquals = function bool(T, T);
5 }
其次,我們?yōu)閕nt32實(shí)現(xiàn)這兩個(gè)函數(shù)。實(shí)現(xiàn)的方法很直接,首先我們寫(xiě)IntEquals和IntNotEquals兩個(gè)函數(shù),其次將int32、Eq和這兩個(gè)函數(shù)綁定起來(lái):
1 instance int32 : Eq
2 {
3 Equals = IntEquals;
4 NotEquals = IntNotEquals;
5 }
6
7 function bool IntEquals(int32 a, int32 b)
8 (result = (a == b));
9
10 function bool IntNotEquals(int32 a, int32 b)
11 (result = (a != b));
因?yàn)榻壎ㄔ贓q上的T的Equals和NotEquals函數(shù)的參數(shù)是T,因此IntEquals和IntNotEquals的參數(shù)必然就是int32了。接下來(lái)我們聲明一個(gè)Vector<T>類型,然后實(shí)現(xiàn)這兩個(gè)函數(shù):
1 generic<U>
2 structure Vector
3 {
4 U X;
5 U Y;
6 }
7
8 generic<V> where
9 V : Eq
10 instance Vector : Eq
11 {
12 Equals = VectorEquals<V>;
13 NotEquals = VectorNotEquals<V>;
14 }
15
16 generic<W> where
17 W : Eq
18 function bool VectorEquals(Vector<W> a, Vector<W> b)
19 {
20 variable bool x_equals = Eq<W>::Equals(a.X, b.X);
21 variable bool y_equals = Eq<W>::Equals(a.Y, b.Y);
22 (result = (x_equals && y_equals));
23 }
24
25 generic<W> where
26 W : Eq
27 function bool VectorNotEquals(Vector<W> a, Vector<W> b)
28 (result = ( ! VectorEquals<W>(a, b)));
我們看得出來(lái)這跟普通的函數(shù)沒(méi)什么區(qū)別,而且在給Vector<T>綁定Eq的時(shí)候,我們還可以規(guī)定T必須也存在一個(gè)到Eq的綁定。因此我們不僅可以有Vector<int32>,還能有Vector<Vector<int32>>。而且在VectorEquals內(nèi)部使用Eq<W>::Equals函數(shù)的時(shí)候,如果函數(shù)聲明沒(méi)有where W:Eq的標(biāo)記那么就無(wú)法通過(guò)編譯。因此所有調(diào)用VectorEquals<W>函數(shù)的W都需要有一個(gè)到Eq的綁定。如此下去,只要你漏綁定了什么,都會(huì)得到編譯錯(cuò)誤的提示。
最后就剩下main函數(shù)了:
1 function int32 main1()
2 {
3 variable Vector<int32> v1;
4 variable Vector<int32> v2;
5 (v1.X = 0s32);
6 (v1.Y = 1s32);
7 (v2.X = 2s32);
8 (v2.Y = 3s32);
9 if(Eq<Vector<int32>>::Equals(v1, v2))
10 (result = 1s32);
11 else
12 (result = 0s32);
13 }
我們可以main函數(shù)和VectorEquals函數(shù)看到一個(gè)Equals函數(shù)是如何被調(diào)用的。當(dāng)然這個(gè)代碼編譯成二進(jìn)制代碼之后,虛擬機(jī)將會(huì)在適當(dāng)?shù)臅r(shí)候搜索、展開(kāi)并實(shí)例化這些具體的函數(shù)。我們可以看看編譯器在執(zhí)行完這些代碼之后究竟產(chǎn)生了什么數(shù)據(jù)結(jié)構(gòu):
1 -----------------------------------------------
2 Loaded Assemblies[0]
3 -----------------------------------------------
4 .data
5 .label
6 .code
7 0: stack_reserve 2
8 1: stack_offset 24
9 2: push s32 0
10 3: add s32
11 4: readmem 4
12 5: stack_offset 16
13 6: push s32 0
14 7: add s32
15 8: readmem 4
16 9: stack_offset -1
17 10: call 46 1
18 11: stack_offset 24
19 12: push s32 4
20 13: add s32
21 14: readmem 4
22 15: stack_offset 16
23 16: push s32 4
24 17: add s32
25 18: readmem 4
26 19: stack_offset -2
27 20: call 46 1
28 21: stack_offset -2
29 22: read u8
30 23: convert u32 u8
31 24: stack_offset -1
32 25: read u8
33 26: convert u32 u8
34 27: and u32
35 28: push u32 0
36 29: ne u32
37 30: resptr
38 31: write u8
39 32: stack_reserve -2
40 33: ret 16
41
42 -----------------------------------------------
43 Loaded Assemblies[1]
44 -----------------------------------------------
45 .data
46 .label
47 0: instruction 3
48 1: instruction 8
49 2: instruction 46
50 3: instruction 56
51 4: instruction 66
52 5: instruction 100
53 .code
54 0: stack_reserve 0
55 1: stack_reserve 0
56 2: ret 0
57 3: stack_reserve 0
58 4: resptr
59 5: call 8 1
60 6: stack_reserve 0
61 7: ret 0
62 8: stack_reserve 16
63 9: push s32 0
64 10: stack_offset -8
65 11: push s32 0
66 12: add s32
67 13: write s32
68 14: push s32 1
69 15: stack_offset -8
70 16: push s32 4
71 17: add s32
72 18: write s32
73 19: push s32 2
74 20: stack_offset -16
75 21: push s32 0
76 22: add s32
77 23: write s32
78 24: push s32 3
79 25: stack_offset -16
80 26: push s32 4
81 27: add s32
82 28: write s32
83 29: stack_reserve 1
84 30: stack_offset -16
85 31: readmem 8
86 32: stack_offset -8
87 33: readmem 8
88 34: stack_top 16
89 35: call 0 0
90 36: jumpfalse 41 1
91 37: push s32 1
92 38: resptr
93 39: write s32
94 40: jump 44 1
95 41: push s32 0
96 42: resptr
97 43: write s32
98 44: stack_reserve -16
99 45: ret 0
100 46: stack_reserve 0
101 47: stack_offset 20
102 48: read s32
103 49: stack_offset 16
104 50: read s32
105 51: eq s32
106 52: resptr
107 53: write u8
108 54: stack_reserve 0
109 55: ret 8
110 56: stack_reserve 0
111 57: stack_offset 20
112 58: read s32
113 59: stack_offset 16
114 60: read s32
115 61: ne s32
116 62: resptr
117 63: write u8
118 64: stack_reserve 0
119 65: ret 8
120 66: stack_reserve 2
121 67: stack_offset 0[Linear]
122 68: push s32 0
123 69: add s32
124 70: readmem 1[Linear]
125 71: stack_offset 16
126 72: push s32 0
127 73: add s32
128 74: readmem 1[Linear]
129 75: stack_offset -1
130 76: generic_instance_callfunc 1
131 77: stack_offset 0[Linear]
132 78: push s32 1[Linear]
133 79: add s32
134 80: readmem 1[Linear]
135 81: stack_offset 16
136 82: push s32 1[Linear]
137 83: add s32
138 84: readmem 1[Linear]
139 85: stack_offset -2
140 86: generic_instance_callfunc 1
141 87: stack_offset -2
142 88: read u8
143 89: convert u32 u8
144 90: stack_offset -1
145 91: read u8
146 92: convert u32 u8
147 93: and u32
148 94: push u32 0
149 95: ne u32
150 96: resptr
151 97: write u8
152 98: stack_reserve -2
153 99: ret 2[Linear]
154 100: stack_reserve 0
155 101: stack_reserve 1
156 102: stack_offset 0[Linear]
157 103: readmem 3[Linear]
158 104: stack_offset 16
159 105: readmem 3[Linear]
160 106: stack_top 2[Linear]
161 107: generic_callfunc 0
162 108: push s8 1
163 109: xor u8
164 110: resptr
165 111: write u8
166 112: stack_reserve 0
167 113: ret 2[Linear]
168 .exports
169 Assembly Name: assembly_generated
170 Exports[0] = (3, main)
171 Exports[1] = (8, main1)
172 Exports[2] = (46, IntEquals)
173 Exports[3] = (56, IntNotEquals)
174 Function Entries[0] = {
175 Name = VectorEquals
176 Arguments = 1
177 Instruction = 66
178 Length = 34
179 UniqueName = [assembly_generated]::[VectorEquals]
180 }
181 Function Entries[1] = {
182 Name = VectorNotEquals
183 Arguments = 1
184 Instruction = 100
185 Length = 14
186 UniqueName = [assembly_generated]::[VectorNotEquals]
187 }
188 Targets[0] = {
189 AssemblyName = assembly_generated
190 SymbolName = VectorEquals
191 Argument[0] = {0} : 1*T0 + 0
192 }
193 Linears[0] = 2*T0 + 16
194 Linears[1] = 1*T0 + 0
195 Linears[2] = 4*T0 + 0
196 Linears[3] = 2*T0 + 0
197 Concepts[0] = {
198 Name = Eq
199 Functions[0] = Equals
200 Functions[1] = NotEquals
201 }
202 Instances[0] = {
203 ConcpetAssemblyName = assembly_generated
204 ConceptSymbolName = Eq
205 TypeUniqueName = s32
206 Arguments = 0
207 Functions[0] = {
208 FunctionName = Equals
209 AssemblyName = assembly_generated
210 SymbolName = IntEquals
211 }
212 Functions[1] = {
213 FunctionName = NotEquals
214 AssemblyName = assembly_generated
215 SymbolName = IntNotEquals
216 }
217 }
218 Instances[1] = {
219 ConcpetAssemblyName = assembly_generated
220 ConceptSymbolName = Eq
221 TypeUniqueName = [assembly_generated]::[Vector]
222 Arguments = 1
223 Functions[0] = {
224 FunctionName = Equals
225 AssemblyName = assembly_generated
226 SymbolName = VectorEquals
227 Argument[0] = {0} : 1*T0 + 0
228 }
229 Functions[1] = {
230 FunctionName = NotEquals
231 AssemblyName = assembly_generated
232 SymbolName = VectorNotEquals
233 Argument[0] = {0} : 1*T0 + 0
234 }
235 }
236 Instance Targets[0] = {
237 AssemblyName = assembly_generated
238 SymbolName = Eq
239 FunctionName = Equals
240 Argument = [assembly_generated]::[Vector] : 8 {
241 s32 : 4
242 }
243 }
244 Instance Targets[1] = {
245 AssemblyName = assembly_generated
246 SymbolName = Eq
247 FunctionName = Equals
248 Argument = {0} : 1*T0 + 0
249 }
250
251 -----------------------------------------------
252 Assembly Name Map
253 -----------------------------------------------
254 assembly_generated = 1
255
256 -----------------------------------------------
257 Function Pointer Map
258 -----------------------------------------------
259 0 = Assemblies[-1].Instructions[-1]
260 1 = Assemblies[1].Instructions[3]
261 2 = Assemblies[1].Instructions[8]
262 3 = Assemblies[1].Instructions[46]
263 4 = Assemblies[1].Instructions[56]
264 5 = Assemblies[1].Instructions[66]
265 6 = Assemblies[1].Instructions[100]
266 7 = Assemblies[0].Instructions[0]
267
268 -----------------------------------------------
269 Loaded Symbol Names
270 -----------------------------------------------
271 assembly_generated.IntEquals
272 assembly_generated.IntNotEquals
273 assembly_generated.main
274 assembly_generated.main1
275
276 -----------------------------------------------
277 Generic Function Entry Map
278 -----------------------------------------------
279 assembly_generated.VectorEquals
280 Instruction = 66
281 Count = 34
282 Assembly = 1
283 Generic Argument Count = 1
284 Unique Entry ID = [assembly_generated]::[VectorEquals]
285 assembly_generated.VectorNotEquals
286 Instruction = 100
287 Count = 14
288 Assembly = 1
289 Generic Argument Count = 1
290 Unique Entry ID = [assembly_generated]::[VectorNotEquals]
291
292 -----------------------------------------------
293 Generic Variable Entry Map
294 -----------------------------------------------
295
296 -----------------------------------------------
297 Instanciated Generic Function Map
298 -----------------------------------------------
299 [assembly_generated]::[VectorEquals]<s32> = 7
300
301 -----------------------------------------------
302 Instanciated Generic Variable Map
303 -----------------------------------------------
304
305 -----------------------------------------------
306 Cached Generic Target List
307 -----------------------------------------------
308 Assembly Name = assembly_generated
309 Symbol Name = VectorEquals
310 Arguments = {
311 Argument[0] = {
312 Name = s32
313 Size = 4
314 }
315 }
316
317 -----------------------------------------------
318 Generic Concept Map
319 -----------------------------------------------
320 assembly_generated.Eq
321
322 -----------------------------------------------
323 Generic Instance Map
324 -----------------------------------------------
325 assembly_generated.Eq<[assembly_generated]::[Vector]>
326 Generic Argument Count = 1
327 Resource Index = 1
328 Function Equals = 0
329 Function NotEquals = 1
330 assembly_generated.Eq<s32>
331 Generic Argument Count = 0
332 Resource Index = 0
333 Function Equals = 0
334 Function NotEquals = 1
335
336
Assembly[0]是專門(mén)用來(lái)保存模板函數(shù)的展開(kāi)結(jié)果的,當(dāng)然這里面只有一個(gè)模板函數(shù)被使用了:VectorEquals<int32>。其他的Assembly都是代碼編譯出來(lái)的。
接下來(lái)只需要測(cè)試一下,然后就可以著手開(kāi)發(fā)最后一個(gè)語(yǔ)法了:異常處理。