1. 程式人生 > >Vczh Library++3.0完成了NativeX語言的所有泛型語法

Vczh Library++3.0完成了NativeX語言的所有泛型語法

    如上一篇文章所說,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