1. 程式人生 > >Vczh Library++3.0之山寨mscorlib.dll

Vczh Library++3.0之山寨mscorlib.dll

    由於Vczh Library++3.0的託管語言ManagedX被設計成編譯到本地語言NativeX,因此山寨一個mscorlib.dll是必不可少的。不過我的mscorlib.dll只包含最低限度的程式碼。譬如說string,譬如說陣列,譬如說函式型別等等這些本不能用託管語言自己來實現的類(C++是唯一的一個所有東西都可以用類庫來彌補的語言)。因此花費了數日,用ManagedX實現了它的宣告和一些程式碼,然後external一些函式。最終,ManagedX寫的mscorlib會被編譯成NativeX,而external的幾個函式自然會用NativeX自己來寫。譬如說如何比較兩個string的大小,這個託管語言自己顯然是搞不定的。

    因此這裡就比較麻煩了,需要做一些工程上的麻煩事情。首先,若干個ManagedX檔案被編譯成一個單獨的NativeX檔案,然後這個生成的NativeX檔案跟另一個手寫的NativeX檔案再一起被編譯成一個assembly。這就跟把C#編譯成C差不多。

    第一個版本的ManagedX還需要做出一點折衷,譬如說陣列的維度不能超過10。這裡的維度指的是a[,,,,,,,,,],而不是a[][][][][][][][][][]。譬如說函式型別的引數數量不能超過10(但是函式的引數數量卻可以,這裡只針對函式型別)。主要是因為,為了讓ManagedX可以被編譯成NativeX,那麼勢必不可能執行的時候才動態生成某個類(模板除外,因為我的NativeX==C+template)。因此一維、二維乃至十維的陣列當然是10個不同的類(你可以使用一個二維的十維陣列的陣列去模擬一個十二維的陣列,這毫無問題)。不過為了避免我真的將一批相似的類重複寫10次,我使用了一年多前開發的
Fpmacro
來做。Fpmacro是一個語法不同的類似C語言巨集的擴充套件,但是沒有C語言的巨集的所有陷阱,而且其實是一門函式是語言,帶有類似lambda表示式的東西,每一個函式都被設計成一個返回字串的函式,引數可以是陣列、字串或者另一個函式。而且語法經過了優化,完全沒有多餘的東西。這裡給一個例子,譬如說宣告10個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 privateint $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 thrownew 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 publicsealedclass Array$elements : Array
 43     {
 44 $( )
 45 public constructor($loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ), Array<T> src=nullbool 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 publicoverrideint GetDimCount()
 53         {
 54 return $elements;
 55         }
 56 $( )
 57 publicoverrideint GetDimSize(int dim)
 58         {
 59 switch(dim)
 60             {
 61 $loop($elements,0,$DIMENTION_SIZE_CASE)
 62 default:
 63 thrownew ArgumentOutOfRangeException("dim");
 64             }
 65         }
 66 $( )
 67 publicoverrideint Length
 68         {
 69 get 70             {
 71 return $loopsep($elements,0,$DIMENTION_FIELD_NAME,$(*));
 72             }
 73         }
 74 $( )
 75 publicoverrideint GetStartIndexFromIndices(paramsint[] indices)
 76         {
 77 if(indices.Length!=$elements)
 78             {
 79 thrownew ArgumentOutOfRangeException("indices");
 80             }
 81 return GetStartIndex[$loopsep($elements,0,$DIMENTION_PARAMETER_NAME_IN_ARRAY,$(,))];
 82         }
 83 $( )
 84 publicint 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 publicoverride T GetElement(paramsint[] indices)
 94         {
 95 return Get(GetStartIndexFromIndices(indices));
 96         }
 97 $( )
 98 publicoverridevoid SetElement(T value, paramsint[] indices)
 99         {
100             Set(value, GetStartIndexFromIndices(indices));
101         }
102 $( )
103 public T operatorget[]($loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ))
104         {
105 return Get($loopsep($elements,0,$DIMENTION_PARAMETER_NAME,$(,) ));
106         }
107 $( )
108 public T operatorset[](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 publicabstractclass 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 publicabstractint GetDimCount();
130 publicabstractint GetDimSize(int dim);
131 publicabstractint Length{get;}
132 publicabstractint GetStartIndexFromIndices(paramsint[] indices);
133 publicabstract T GetElement(paramsint[] indices);
134 publicabstractvoid SetElement(T value, paramsint[] indices);
135 $( )
136 privateclass Enumerator : IEnumerator
137         {
138 private Array<T> array;
139 privateint index;
140 $( )
141 public constructor(Array<T> array)
142             {
143 this.array=array;
144 this.index=-1;
145             }
146 $( )
147 publicbool MoveNext()
148             {
149 if(index==array.Length-1)
150                 {
151 returnfalse;
152                 }
153 else154                 {
155                     index++;
156 returntrue;
157                 }
158             }
159 $( )
160 public T Current
161             {
162 get163                 {
164 return array.Get(index);
165                 }
166             }
167 $( )
168 object IEnumerator::Current
169             {
170 get171                 {
172 return array.Get(index);
173                 }
174             }
175         }
176 $( )
177         IEnumerator<T> IEnumerable<T>::GetEnumerator()
178         {
179 returnnew Enumerator(this);
180         }
181 $( )
182         IEnumerator IEnumerable::GetEnumerator()
183         {
184 returnnew Enumerator(this);
185         }
186 $( )
187     }
188 $( )
189     generic<inout T>190 publicclass ReadonlyArray
191     {
192 private T[] items;
193 $( )
194 public constructor(T[] items)
195         {
196 this.items=items;
197         }
198 $( )
199 publicint Length
200         {
201 get202             {
203 returnthis.items.Length;
204             }
205         }
206 $( )
207 public T operatorget[](int index)
208         {
209 returnthis.items[index];
210         }
211     }
212 $loop($MAX_ELEMENT_COUNT(),1,$ARRAY_IMPLEMENTATION)
213 }
    會被擴充套件成(太長cppblog編輯器效能太爛導致響應速度無法忍受,下載程式碼並開啟UnitTest\Binary\ScriptCoreLibrary\System.CoreManaged\Array.txt自行閱讀)

    山寨mscorlib.dll的ManagedX部分基本完成,剩下的十幾個函式寫的NativeX則等到編譯成NativeX的部分完成之後再寫。到了這裡,一共實現了:
    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的語義分析器了。接下來的路還很長。語義分析結束之後,要把ManagedX展開變成一份更長但是包含的東西更少的ManagedX(譬如沒有lambda expression,因為被重寫成了一個內部類),最後編譯成NativeX。