经过昨天的艰苦奋斗我终于在
Vczh Library++ 3.0里完成这么一个功能了。假设我现在用代码组装了一个语法树:
1 BasicProgramNode program;
2 program.DefineStructure(L"Complex")
3 .Member(L"r", t_int())
4 .Member(L"i", t_int());
5 program.DefineFunction(L"main").ReturnType(t_int()).Statement(
6 s_var(t_type(L"Complex"), L"a")
7 <<s_var(t_type(L"Complex"), L"b")
8 <<s_var(t_type(L"Complex"), L"c")
9 <<s_expr(e_name(L"a").Member(L"r").Assign(e_prim(1)))
10 <<s_expr(e_name(L"a").Member(L"i").Assign(e_prim(2)))
11 <<s_expr(e_name(L"b").Member(L"r").Assign(e_prim(3)))
12 <<s_expr(e_name(L"b").Member(L"i").Assign(e_prim(4)))
13 <<s_var(t_type(L"Complex"), L"x", e_name(L"a"))
14 <<s_var(t_type(L"Complex"), L"y")
15 <<s_expr(e_name(L"y").Assign(e_name(L"b")))
16 <<s_expr(e_name(L"c").Member(L"r").Assign(
17 e_name(L"x").Member(L"r") + e_name(L"y").Member(L"r")
18 ))
19 <<s_expr(e_name(L"c").Member(L"i").Assign(
20 e_name(L"x").Member(L"i") + e_name(L"y").Member(L"i")
21 ))
22 <<s_expr(e_result().Assign(
23 e_name(L"c").Member(L"r")*e_prim(100) + e_name(L"c").Member(L"i")
24 ))
25 );
于是最近写的N个函数终于可以发挥作用了。首先我会拿这个program编译成指令集先跑一次,如果答案跟测试用例给出的一致那就继续往下走。接下来就将这个program还原成一个NativeX语言的字符串,然后调用NativeX的语法分析器再编译一次,这样每一个语法树的节点都有一个指向记号的属性了。这样语法树生成指令集的时候,每一个指令原本属于哪颗语法树也就都记录下来了。这个时候,将指令集输出成文本文件的时候,就可以根据位置信息使用NativeX的源代码打上注释,然后再跑一次。这样还可以通过丰富的测试用例来测试NativeX的语法分析器,而且还不会被语法分析器影响。因为program编译了一次,program->NativeX->newProgram又编译了一次,哇哈哈。结果如下:
(窥孔优化在这个时候就可以大展身手了,不过我还没做……)
1 /*NativeX Code*/
2 unit nativex_program_generated;
3 structure Complex
4 {
5 int32 r;
6 int32 i;
7 }
8
9 function int32 main()
10 {
11 variable Complex a;
12 variable Complex b;
13 variable Complex c;
14 (a.r=1);
15 (a.i=2);
16 (b.r=3);
17 (b.i=4);
18 variable Complex x = a;
19 variable Complex y;
20 (y=b);
21 (c.r=(x.r+y.r));
22 (c.i=(x.i+y.i));
23 (result=((c.r*100)+c.i));
24 }
25
26
27 /*Assembly*/
28 .data
29 .label
30 0: instruction 3
31 .code
32 // unit nativex_program_generated;
33 0: stack_reserve 0
34 1: stack_reserve 0
35 2: ret 0
36 // function int32 main()
37 3: stack_reserve 40
38 // (a.r=1);
39 4: push s8 1
40 5: convert s32 s8
41 6: stack_offset -8
42 7: push s32 0
43 8: add s32
44 9: write s32
45 // (a.i=2);
46 10: push s8 2
47 11: convert s32 s8
48 12: stack_offset -8
49 13: push s32 4
50 14: add s32
51 15: write s32
52 // (b.r=3);
53 16: push s8 3
54 17: convert s32 s8
55 18: stack_offset -16
56 19: push s32 0
57 20: add s32
58 21: write s32
59 // (b.i=4);
60 22: push s8 4
61 23: convert s32 s8
62 24: stack_offset -16
63 25: push s32 4
64 26: add s32
65 27: write s32
66 // variable Complex x = a;
67 28: stack_offset -8
68 29: stack_offset -32
69 30: copymem 8
70 // (y=b);
71 31: stack_offset -16
72 32: stack_offset -40
73 33: copymem 8
74 // (c.r=(x.r+y.r));
75 34: stack_offset -40
76 35: push s32 0
77 36: add s32
78 37: read s32
79 38: stack_offset -32
80 39: push s32 0
81 40: add s32
82 41: read s32
83 42: add s32
84 43: stack_offset -24
85 44: push s32 0
86 45: add s32
87 46: write s32
88 // (c.i=(x.i+y.i));
89 47: stack_offset -40
90 48: push s32 4
91 49: add s32
92 50: read s32
93 51: stack_offset -32
94 52: push s32 4
95 53: add s32
96 54: read s32
97 55: add s32
98 56: stack_offset -24
99 57: push s32 4
100 58: add s32
101 59: write s32
102 // (result=((c.r*100)+c.i));
103 60: stack_offset -24
104 61: push s32 4
105 62: add s32
106 63: read s32
107 64: push s8 100
108 65: convert s32 s8
109 66: stack_offset -24
110 67: push s32 0
111 68: add s32
112 69: read s32
113 70: mul s32
114 71: add s32
115 72: resptr
116 73: write s32
117 // function int32 main()
118 74: stack_reserve -40
119 75: ret 0
120
最新的代码可以在
这里获得。
posted on 2010-06-04 19:49
陈梓瀚(vczh) 阅读(2758)
评论(1) 编辑 收藏 引用 所属分类:
VL++3.0开发纪事