由于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 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
42 public sealed class Array$elements : Array
43 {
44 $( )
45 public constructor($loopsep($elements,0,$DIMENTION_PARAMETER_DEFINITION,$(,) ), Array 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