由于
Vczh Library++3.0的托管語(yǔ)言ManagedX被設(shè)計(jì)成編譯到本地語(yǔ)言NativeX,因此山寨一個(gè)mscorlib.dll是必不可少的。不過(guò)我的mscorlib.dll只包含最低限度的代碼。譬如說(shuō)string,譬如說(shuō)數(shù)組,譬如說(shuō)函數(shù)類型等等這些本不能用托管語(yǔ)言自己來(lái)實(shí)現(xiàn)的類(C++是唯一的一個(gè)所有東西都可以用類庫(kù)來(lái)彌補(bǔ)的語(yǔ)言)。因此花費(fèi)了數(shù)日,用ManagedX實(shí)現(xiàn)了它的聲明和一些代碼,然后external一些函數(shù)。最終,ManagedX寫的mscorlib會(huì)被編譯成NativeX,而external的幾個(gè)函數(shù)自然會(huì)用NativeX自己來(lái)寫。譬如說(shuō)如何比較兩個(gè)string的大小,這個(gè)托管語(yǔ)言自己顯然是搞不定的。
因此這里就比較麻煩了,需要做一些工程上的麻煩事情。首先,若干個(gè)ManagedX文件被編譯成一個(gè)單獨(dú)的NativeX文件,然后這個(gè)生成的NativeX文件跟另一個(gè)手寫的NativeX文件再一起被編譯成一個(gè)assembly。這就跟把C#編譯成C差不多。
第一個(gè)版本的ManagedX還需要做出一點(diǎn)折衷,譬如說(shuō)數(shù)組的維度不能超過(guò)10。這里的維度指的是a[,,,,,,,,,],而不是a[][][][][][][][][][]。譬如說(shuō)函數(shù)類型的參數(shù)數(shù)量不能超過(guò)10(但是函數(shù)的參數(shù)數(shù)量卻可以,這里只針對(duì)函數(shù)類型)。主要是因?yàn)椋瑸榱俗孧anagedX可以被編譯成NativeX,那么勢(shì)必不可能運(yùn)行的時(shí)候才動(dòng)態(tài)生成某個(gè)類(模板除外,因?yàn)槲业腘ativeX==C+template)。因此一維、二維乃至十維的數(shù)組當(dāng)然是10個(gè)不同的類(你可以使用一個(gè)二維的十維數(shù)組的數(shù)組去模擬一個(gè)十二維的數(shù)組,這毫無(wú)問(wèn)題)。不過(guò)為了避免我真的將一批相似的類重復(fù)寫10次,我使用了一年多前開發(fā)的
Fpmacro來(lái)做。Fpmacro是一個(gè)語(yǔ)法不同的類似C語(yǔ)言宏的擴(kuò)展,但是沒(méi)有C語(yǔ)言的宏的所有陷阱,而且其實(shí)是一門函數(shù)是語(yǔ)言,帶有類似lambda表達(dá)式的東西,每一個(gè)函數(shù)都被設(shè)計(jì)成一個(gè)返回字符串的函數(shù),參數(shù)可以是數(shù)組、字符串或者另一個(gè)函數(shù)。而且語(yǔ)法經(jīng)過(guò)了優(yōu)化,完全沒(méi)有多余的東西。這里給一個(gè)例子,譬如說(shuō)聲明10個(gè)Array的Fpmacro代碼:
1 $$include:Common.fpm
2
3 $$define $DIMENTION_FIELD_NAME($element) dimSize$element
4 $$define $DIMENTION_PARAMETER_NAME($element) _$element
5 $$define $DIMENTION_PARAMETER_DEFINITION($element) int $DIMENTION_PARAMETER_NAME($element)
6 $$define $DIMENTION_PARAMETER_NAME_IN_ARRAY($element) indices[$element]
7
8 $$define $DIMENTION_FIELD($element) $$begin
9 private int $DIMENTION_FIELD_NAME($element);
10 $( )
11 $$end
12
13 $$define $DIMENTION_FIELD_SETTER($element) $$begin
14 $DIMENTION_FIELD_NAME($element) = $DIMENTION_PARAMETER_NAME($element);
15 $( )
16 $$end
17
18 $$define $DIMENTION_SIZE_CASE($element) $$begin
19 case $element:
20 return $DIMENTION_FIELD_NAME($element);
21 $( )
22 $$end
23
24 $$define $DIMENTION_CHECK($element) $$begin
25 if($DIMENTION_PARAMETER_NAME($element)<0 || $DIMENTION_PARAMETER_NAME($element)>=$DIMENTION_FIELD_NAME($element))
26 throw new ArgumentOutOfRangeException($(")$DIMENTION_PARAMETER_NAME($element)$("));
27 $( )
28 $$end
29
30 $$define $DIMENTION_SUMMERS($elements) $$begin
31 $$define $DIMENTION_SUMMER($index) $$begin
32 sum*=$DIMENTION_FIELD_NAME($sub($sub($elements,1),$index));
33 index+=sum*$DIMENTION_PARAMETER_NAME($sub($sub($elements,2),$index));
34 $( )
35 $$end
36 $loop($sub($elements,1),0,$DIMENTION_SUMMER)
37 $$end
38
39 $$define $ARRAY_IMPLEMENTATION($elements) $$begin
40 $( )
41 generic<inout T>
42 public sealed class Array$elements : Array
43 {
44 $( )
45 public constructor($loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ), Array<T> src=null, bool copy=true)
46 {
47 $loop($elements,0,$DIMENTION_FIELD_SETTER)
48 Initialize(this.Length, src, copy);
49 }
50 $( )
51 $loop($elements,0,$DIMENTION_FIELD)
52 public override int GetDimCount()
53 {
54 return $elements;
55 }
56 $( )
57 public override int GetDimSize(int dim)
58 {
59 switch(dim)
60 {
61 $loop($elements,0,$DIMENTION_SIZE_CASE)
62 default:
63 throw new ArgumentOutOfRangeException("dim");
64 }
65 }
66 $( )
67 public override int Length
68 {
69 get
70 {
71 return $loopsep($elements,0,$DIMENTION_FIELD_NAME,$(*));
72 }
73 }
74 $( )
75 public override int GetStartIndexFromIndices(params int[] indices)
76 {
77 if(indices.Length!=$elements)
78 {
79 throw new ArgumentOutOfRangeException("indices");
80 }
81 return GetStartIndex[$loopsep($elements,0,$DIMENTION_PARAMETER_NAME_IN_ARRAY,$(,))];
82 }
83 $( )
84 public int GetStartIndex($loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ))
85 {
86 $loop($elements,0,$DIMENTION_CHECK)
87 int index=$DIMENTION_PARAMETER_NAME($sub($elements,1));
88 int sum=1;
89 $DIMENTION_SUMMERS($elements)
90 return index;
91 }
92 $( )
93 public override T GetElement(params int[] indices)
94 {
95 return Get(GetStartIndexFromIndices(indices));
96 }
97 $( )
98 public override void SetElement(T value, params int[] indices)
99 {
100 Set(value, GetStartIndexFromIndices(indices));
101 }
102 $( )
103 public T operator get[]($loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ))
104 {
105 return Get($loopsep($elements,0,$DIMENTION_PARAMETER_NAME,$(,) ));
106 }
107 $( )
108 public T operator set[](T value, $loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ))
109 {
110 return Set(value, $loopsep($elements,0,$DIMENTION_PARAMETER_NAME,$(,) ));
111 }
112 $( )
113 }
114 $$end
115
116 namespace System
117 {
118 generic<inout T>
119 public abstract class Array : IEnumerable<T>
120 {
121 protected intptr gchandle=0;
122 protected external void Initialize(int size, Array<T> src, bool copy);
123 public external T Get(int position);
124 public external void Set(T value, int position);
125 $( )
126 public external void CopyTo(intptr pointer, int fromStart, int length);
127 public external void CopyTo(Array<T> array, int fromStart, int length, int toStart);
128 $( )
129 public abstract int GetDimCount();
130 public abstract int GetDimSize(int dim);
131 public abstract int Length{get;}
132 public abstract int GetStartIndexFromIndices(params int[] indices);
133 public abstract T GetElement(params int[] indices);
134 public abstract void SetElement(T value, params int[] indices);
135 $( )
136 private class Enumerator : IEnumerator
137 {
138 private Array<T> array;
139 private int index;
140 $( )
141 public constructor(Array<T> array)
142 {
143 this.array=array;
144 this.index=-1;
145 }
146 $( )
147 public bool MoveNext()
148 {
149 if(index==array.Length-1)
150 {
151 return false;
152 }
153 else
154 {
155 index++;
156 return true;
157 }
158 }
159 $( )
160 public T Current
161 {
162 get
163 {
164 return array.Get(index);
165 }
166 }
167 $( )
168 object IEnumerator::Current
169 {
170 get
171 {
172 return array.Get(index);
173 }
174 }
175 }
176 $( )
177 IEnumerator<T> IEnumerable<T>::GetEnumerator()
178 {
179 return new Enumerator(this);
180 }
181 $( )
182 IEnumerator IEnumerable::GetEnumerator()
183 {
184 return new Enumerator(this);
185 }
186 $( )
187 }
188 $( )
189 generic<inout T>
190 public class ReadonlyArray
191 {
192 private T[] items;
193 $( )
194 public constructor(T[] items)
195 {
196 this.items=items;
197 }
198 $( )
199 public int Length
200 {
201 get
202 {
203 return this.items.Length;
204 }
205 }
206 $( )
207 public T operator get[](int index)
208 {
209 return this.items[index];
210 }
211 }
212 $loop($MAX_ELEMENT_COUNT(),1,$ARRAY_IMPLEMENTATION)
213 }
會(huì)被擴(kuò)展成(太長(zhǎng)cppblog編輯器性能太爛導(dǎo)致響應(yīng)速度無(wú)法忍受,
下載代碼并打開UnitTest\Binary\ScriptCoreLibrary\System.CoreManaged\Array.txt自行閱讀)
山寨mscorlib.dll的ManagedX部分基本完成,剩下的十幾個(gè)函數(shù)寫的NativeX則等到編譯成NativeX的部分完成之后再寫。到了這里,一共實(shí)現(xiàn)了:
Array<T>
Array1<T> .. Array10<T>
Attribute
AttributeUsageAttribute
AutoGeneratedAttribute
NotInstantiableAttribute
StructBaseAttribute
DefaultValueAttribute
VariadicParameterAttribute
EnumItemBase
EnumItemManager
Exception
IndexOutOfRangeException
ArgumentOutOfRangeException
WrongFormatException
TypeConversionException
NotImplementedException
Delegate
DelegateTarget
MethodDelegate
BroadcastDelegate
Function<R> .. Function<R, T0 .. T9>
Procedure, Procedure<T0> .. Procedure<T0 .. T9>
Event, Event<T0> .. Event<T0 .. T9>
IEnumerator
IEnumerable
IEnumerator<T>
IEnumerable<T>
SInt8 .. SInt64
UInt8 .. UInt64
Single, Double, Char, Bool, Void
Object
String
Type
從明天開始就要做ManagedX的語(yǔ)義分析器了。接下來(lái)的路還很長(zhǎng)。語(yǔ)義分析結(jié)束之后,要把ManagedX展開變成一份更長(zhǎng)但是包含的東西更少的ManagedX(譬如沒(méi)有l(wèi)ambda expression,因?yàn)楸恢貙懗闪艘粋€(gè)內(nèi)部類),最后編譯成NativeX。