Vczh Library++3.0完成了NativeX語言的所有泛型語法
阿新 • • 發佈:2018-12-27
如上一篇文章所說,Vczh Library++3.0的NativeX語言實現了計劃的所有泛型語法。讓我們來看一個簡單的例子:我們為型別寫一個Equals函式。我們可以為普通型別,譬如int32寫一個Equals函式。我們有Vector<T>型別,只要T型別擁有一個Equals函式,那麼Vector<T>顯然也可以有Equals函式。問題來了,我們在VectorEquals<T>函式裡面怎麼知道T的Equals函式究竟是那一個呢?在這裡我們用concept和instance,其實也就是haskell的type class在C語言上僅有的一種形式,來表達。
首先我們定義一個叫Eq的concept,裡面包含Equals和NotEquals兩個函式的原型。這兩個函式規定了引數的型別和返回值型別:
1 concept T : Eq
2 {
3 Equals = function bool(T, T);
4 NotEquals = function bool(T, T);
5 }
其次,我們為int32實現這兩個函式。實現的方法很直接,首先我們寫IntEquals和IntNotEquals兩個函式,其次將int32、Eq和這兩個函式繫結起來:
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));
因為繫結在Eq上的T的Equals和NotEquals函式的引數是T,因此IntEquals和IntNotEquals的引數必然就是int32了。接下來我們宣告一個Vector<T>型別,然後實現這兩個函式:
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)));
我們看得出來這跟普通的函式沒什麼區別,而且在給Vector<T>繫結Eq的時候,我們還可以規定T必須也存在一個到Eq的繫結。因此我們不僅可以有Vector<int32>,還能有Vector<Vector<int32>>。而且在VectorEquals內部使用Eq<W>::Equals函式的時候,如果函式宣告沒有where W:Eq的標記那麼就無法通過編譯。因此所有呼叫VectorEquals<W>函式的W都需要有一個到Eq的繫結。如此下去,只要你漏綁定了什麼,都會得到編譯錯誤的提示。
最後就剩下main函數了:
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 else12 (result = 0s32);
13 }
我們可以main函式和VectorEquals函式看到一個Equals函式是如何被呼叫的。當然這個程式碼編譯成二進位制程式碼之後,虛擬機器將會在適當的時候搜尋、展開並例項化這些具體的函式。我們可以看看編譯器在執行完這些程式碼之後究竟產生了什麼資料結構:
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 461 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 461 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 81 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 00 90 36: jumpfalse 411 91 37: push s32 1 92 38: resptr
93 39: write s32
94 40: jump 441 95 41: push s32 0 96 42: resptr
97 43: write s32
98 44: stack_reserve -16 99 45: ret 0100 46: stack_reserve 0101 47: stack_offset 20102 48: read s32
103 49: stack_offset 16104 50: read s32
105 51: eq s32
106 52: resptr
107 53: write u8
108 54: stack_reserve 0109 55: ret 8110 56: stack_reserve 0111 57: stack_offset 20112 58: read s32
113 59: stack_offset 16114 60: read s32
115 61: ne s32
116 62: resptr
117 63: write u8
118 64: stack_reserve 0119 65: ret 8120 66: stack_reserve 2121 67: stack_offset 0[Linear]
122 68: push s32 0123 69: add s32
124 70: readmem 1[Linear]
125 71: stack_offset 16126 72: push s32 0127 73: add s32
128 74: readmem 1[Linear]
129 75: stack_offset -1130 76: generic_instance_callfunc 1131 77: stack_offset 0[Linear]
132 78: push s32 1[Linear]
133 79: add s32
134 80: readmem 1[Linear]
135 81: stack_offset 16136 82: push s32 1[Linear]
137 83: add s32
138 84: readmem 1[Linear]
139 85: stack_offset -2140 86: generic_instance_callfunc 1141 87: stack_offset -2142 88: read u8
143 89: convert u32 u8
144 90: stack_offset -1145 91: read u8
146 92: convert u32 u8
147 93: and u32
148 94: push u32 0149 95: ne u32
150 96: resptr
151 97: write u8
152 98: stack_reserve -2153 99: ret 2[Linear]
154 100: stack_reserve 0155 101: stack_reserve 1156 102: stack_offset 0[Linear]
157 103: readmem 3[Linear]
158 104: stack_offset 16159 105: readmem 3[Linear]
160 106: stack_top 2[Linear]
161 107: generic_callfunc 0162 108: push s8 1163 109: xor u8
164 110: resptr
165 111: write u8
166 112: stack_reserve 0167 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 =1177 Instruction =66178 Length =34179 UniqueName = [assembly_generated]::[VectorEquals]
180 }
181 Function Entries[1] = {
182 Name = VectorNotEquals
183 Arguments =1184 Instruction =100185 Length =14186 UniqueName = [assembly_generated]::[VectorNotEquals]
187 }
188 Targets[0] = {
189 AssemblyName = assembly_generated
190 SymbolName = VectorEquals
191 Argument[0] = {0} : 1*T0 +0192 }
193 Linears[0] =2*T0 +16194 Linears[1] =1*T0 +0195 Linears[2] =4*T0 +0196 Linears[3] =2*T0 +0197 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 =0207 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 =1223 Functions[0] = {
224 FunctionName = Equals
225 AssemblyName = assembly_generated
226 SymbolName = VectorEquals
227 Argument[0] = {0} : 1*T0 +0228 }
229 Functions[1] = {
230 FunctionName = NotEquals
231 AssemblyName = assembly_generated
232 SymbolName = VectorNotEquals
233 Argument[0] = {0} : 1*T0 +0234 }
235 }
236 Instance Targets[0] = {
237 AssemblyName = assembly_generated
238 SymbolName = Eq
239 FunctionName = Equals
240 Argument = [assembly_generated]::[Vector] : 8 {
241 s32 : 4242 }
243 }
244 Instance Targets[1] = {
245 AssemblyName = assembly_generated
246 SymbolName = Eq
247 FunctionName = Equals
248 Argument = {0} : 1*T0 +0249 }
250 251 -----------------------------------------------252 Assembly Name Map
253 -----------------------------------------------254 assembly_generated =1255 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 =66281 Count =34282 Assembly =1283 Generic Argument Count =1284 Unique Entry ID = [assembly_generated]::[VectorEquals]
285 assembly_generated.VectorNotEquals
286 Instruction =100287 Count =14288 Assembly =1289 Generic Argument Count =1290 Unique Entry ID = [assembly_generated]::[VectorNotEquals]
291 292 -----------------------------------------------29
首先我們定義一個叫Eq的concept,裡面包含Equals和NotEquals兩個函式的原型。這兩個函式規定了引數的型別和返回值型別:
1
2 {
3 Equals = function bool(T, T);
4 NotEquals = function bool(T, T);
5 }
其次,我們為int32實現這兩個函式。實現的方法很直接,首先我們寫IntEquals和IntNotEquals兩個函式,其次將int32、Eq和這兩個函式繫結起來:
1 instance int32 : Eq
2 {
3 Equals = IntEquals;
4 NotEquals = IntNotEquals;
5 }
6 7 function bool IntEquals(int32 a, int32 b)
9 10 function bool IntNotEquals(int32 a, int32 b)
11 (result = (a != b));
因為繫結在Eq上的T的Equals和NotEquals函式的引數是T,因此IntEquals和IntNotEquals的引數必然就是int32了。接下來我們宣告一個Vector<T>型別,然後實現這兩個函式:
1 generic<U> 2 structure Vector
3 {
4 U X;
5 U Y;
6 }
7 8 generic
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)));
我們看得出來這跟普通的函式沒什麼區別,而且在給Vector<T>繫結Eq的時候,我們還可以規定T必須也存在一個到Eq的繫結。因此我們不僅可以有Vector<int32>,還能有Vector<Vector<int32>>。而且在VectorEquals內部使用Eq<W>::Equals函式的時候,如果函式宣告沒有where W:Eq的標記那麼就無法通過編譯。因此所有呼叫VectorEquals<W>函式的W都需要有一個到Eq的繫結。如此下去,只要你漏綁定了什麼,都會得到編譯錯誤的提示。
最後就剩下main函數了:
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 else12 (result = 0s32);
13 }
我們可以main函式和VectorEquals函式看到一個Equals函式是如何被呼叫的。當然這個程式碼編譯成二進位制程式碼之後,虛擬機器將會在適當的時候搜尋、展開並例項化這些具體的函式。我們可以看看編譯器在執行完這些程式碼之後究竟產生了什麼資料結構:
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 461 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 461 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 81 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 00 90 36: jumpfalse 411 91 37: push s32 1 92 38: resptr
93 39: write s32
94 40: jump 441 95 41: push s32 0 96 42: resptr
97 43: write s32
98 44: stack_reserve -16 99 45: ret 0100 46: stack_reserve 0101 47: stack_offset 20102 48: read s32
103 49: stack_offset 16104 50: read s32
105 51: eq s32
106 52: resptr
107 53: write u8
108 54: stack_reserve 0109 55: ret 8110 56: stack_reserve 0111 57: stack_offset 20112 58: read s32
113 59: stack_offset 16114 60: read s32
115 61: ne s32
116 62: resptr
117 63: write u8
118 64: stack_reserve 0119 65: ret 8120 66: stack_reserve 2121 67: stack_offset 0[Linear]
122 68: push s32 0123 69: add s32
124 70: readmem 1[Linear]
125 71: stack_offset 16126 72: push s32 0127 73: add s32
128 74: readmem 1[Linear]
129 75: stack_offset -1130 76: generic_instance_callfunc 1131 77: stack_offset 0[Linear]
132 78: push s32 1[Linear]
133 79: add s32
134 80: readmem 1[Linear]
135 81: stack_offset 16136 82: push s32 1[Linear]
137 83: add s32
138 84: readmem 1[Linear]
139 85: stack_offset -2140 86: generic_instance_callfunc 1141 87: stack_offset -2142 88: read u8
143 89: convert u32 u8
144 90: stack_offset -1145 91: read u8
146 92: convert u32 u8
147 93: and u32
148 94: push u32 0149 95: ne u32
150 96: resptr
151 97: write u8
152 98: stack_reserve -2153 99: ret 2[Linear]
154 100: stack_reserve 0155 101: stack_reserve 1156 102: stack_offset 0[Linear]
157 103: readmem 3[Linear]
158 104: stack_offset 16159 105: readmem 3[Linear]
160 106: stack_top 2[Linear]
161 107: generic_callfunc 0162 108: push s8 1163 109: xor u8
164 110: resptr
165 111: write u8
166 112: stack_reserve 0167 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 =1177 Instruction =66178 Length =34179 UniqueName = [assembly_generated]::[VectorEquals]
180 }
181 Function Entries[1] = {
182 Name = VectorNotEquals
183 Arguments =1184 Instruction =100185 Length =14186 UniqueName = [assembly_generated]::[VectorNotEquals]
187 }
188 Targets[0] = {
189 AssemblyName = assembly_generated
190 SymbolName = VectorEquals
191 Argument[0] = {0} : 1*T0 +0192 }
193 Linears[0] =2*T0 +16194 Linears[1] =1*T0 +0195 Linears[2] =4*T0 +0196 Linears[3] =2*T0 +0197 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 =0207 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 =1223 Functions[0] = {
224 FunctionName = Equals
225 AssemblyName = assembly_generated
226 SymbolName = VectorEquals
227 Argument[0] = {0} : 1*T0 +0228 }
229 Functions[1] = {
230 FunctionName = NotEquals
231 AssemblyName = assembly_generated
232 SymbolName = VectorNotEquals
233 Argument[0] = {0} : 1*T0 +0234 }
235 }
236 Instance Targets[0] = {
237 AssemblyName = assembly_generated
238 SymbolName = Eq
239 FunctionName = Equals
240 Argument = [assembly_generated]::[Vector] : 8 {
241 s32 : 4242 }
243 }
244 Instance Targets[1] = {
245 AssemblyName = assembly_generated
246 SymbolName = Eq
247 FunctionName = Equals
248 Argument = {0} : 1*T0 +0249 }
250 251 -----------------------------------------------252 Assembly Name Map
253 -----------------------------------------------254 assembly_generated =1255 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 =66281 Count =34282 Assembly =1283 Generic Argument Count =1284 Unique Entry ID = [assembly_generated]::[VectorEquals]
285 assembly_generated.VectorNotEquals
286 Instruction =100287 Count =14288 Assembly =1289 Generic Argument Count =1290 Unique Entry ID = [assembly_generated]::[VectorNotEquals]
291 292 -----------------------------------------------29