Vczh Library++3.0之成功将源代码注释进指令列表
经过昨天的艰苦奋斗我终于在 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 );
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
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
最新的代码可以在 这里获得。