]> de.git.xonotic.org Git - xonotic/gmqcc.git/blob - test/ast-test.c
use the correct STORE instruction, make pawn a local
[xonotic/gmqcc.git] / test / ast-test.c
1 #include "gmqcc.h"
2 #include "ast.h"
3
4 /* NOTE: it's a test - I'll abort() on epic-failure */
5
6 #ifdef assert
7 #   undef assert
8 #endif
9 /* (note: 'do {} while(0)' forces the need for a semicolon after assert() */
10 #define assert(x) do { if ( !(x) ) { printf("Assertion failed: %s\n", #x); abort(); } } while(0)
11
12 VECTOR_MAKE(ast_value*, globals);
13 VECTOR_MAKE(ast_value*, fields);
14 VECTOR_MAKE(ast_function*, functions);
15
16 uint32_t    opts_flags[1 + (COUNT_FLAGS / 32)];
17 uint32_t    opts_warn [1 + (COUNT_WARNINGS / 32)];
18
19 uint32_t    opts_O        = 1;
20 const char *opts_output   = "progs.dat";
21 int         opts_standard = COMPILER_GMQCC;
22 bool        opts_debug    = false;
23 bool        opts_memchk   = false;
24
25 #include "ast-macros.h"
26
27 int main()
28 {
29     size_t i;
30
31     ir_builder     *ir;
32
33     TESTVARS();
34
35     DEFVAR(vi);
36     DEFVAR(vx);
37     DEFVAR(f0);
38     DEFVAR(f1);
39     DEFVAR(f5);
40     DEFVAR(sHello);
41     DEFVAR(print);
42     DEFVAR(ftos);
43     DEFVAR(spawn);
44
45     DEFVAR(mema);
46     DEFVAR(pawn);
47
48     /* opts_debug = true; */
49
50 BUILTIN(print, TYPE_VOID, -1);
51 PARAM(TYPE_STRING, text);
52 ENDBUILTIN();
53
54 BUILTIN(ftos, TYPE_STRING, -2);
55 PARAM(TYPE_FLOAT, value);
56 ENDBUILTIN();
57
58 BUILTIN(spawn, TYPE_ENTITY, -3);
59 ENDBUILTIN();
60
61     TESTINIT();
62 VAR(TYPE_FLOAT, f0);
63 VAR(TYPE_FLOAT, f1);
64 VAR(TYPE_FLOAT, f5);
65 VAR(TYPE_STRING, sHello);
66
67 FIELD(TYPE_FLOAT, mema);
68
69 MKCONSTFLOAT(f0, 0.0);
70 MKCONSTFLOAT(f1, 1.0);
71 MKCONSTFLOAT(f5, 5.0);
72 MKCONSTSTRING(sHello, "Hello, World\n");
73
74 FUNCTION(foo, TYPE_VOID);
75 ENDFUNCTION(foo);
76
77 FUNCTION(main, TYPE_VOID);
78
79     VAR(TYPE_FLOAT, vi);
80     VAR(TYPE_FLOAT, vx);
81     VAR(TYPE_ENTITY, pawn);
82
83     MKLOCAL(vi);
84     MKLOCAL(vx);
85     MKLOCAL(pawn);
86
87     STATE(ASSIGN(STORE_F, vi, f0));
88     WHILE(BIN(LT, vi, f5));
89         STATE(ASSIGN(STORE_F, vx, BIN(MUL_F, vi, f5)));
90         STATE(ASSIGN(STORE_F, vi, BIN(ADD_F, vi, f1)));
91     ENDWHILE();
92
93     CALL(print)
94     CALLPARAM(sHello)
95     ENDCALL();
96
97     CALL(spawn)
98     ENDCALLWITH(newent, STATE(ASSIGN(STORE_ENT, pawn, newent)));
99
100     STATE(ASSIGN(STOREP_F, ENTFIELD(pawn, mema), f5));
101     CALL(ftos)
102     CALLPARAM(ENTFIELD(pawn, mema))
103     ENDCALLWITH(output, STATE(ASSIGN(STORE_F, vi, output)));
104
105     CALL(print)
106     CALLPARAM(vi)
107     ENDCALL();
108
109 ENDFUNCTION(main);
110
111     ir = ir_builder_new("ast_test");
112     assert(ir);
113
114     /* gen fields */
115     for (i = 0; i < fields_elements; ++i) {
116         if (!ast_global_codegen(fields_data[i], ir)) {
117             assert(!"failed to generate field");
118         }
119     }
120     /* gen globals */
121     for (i = 0; i < globals_elements; ++i) {
122         if (!ast_global_codegen(globals_data[i], ir)) {
123             assert(!"failed to generate global");
124         }
125     }
126
127     /* gen functions */
128     for (i = 0; i < functions_elements; ++i) {
129         if (!ast_function_codegen(functions_data[i], ir)) {
130             assert(!"failed to generate function");
131         }
132         if (!ir_function_finalize(functions_data[i]->ir_func))
133             assert(!"finalize on function failed...");
134     }
135
136
137     /* dump */
138     ir_builder_dump(ir, printf);
139
140     /* Now create a file */
141     if (!ir_builder_generate(ir, "test_ast.dat"))
142         printf("*** failed to generate code\n");
143
144     /* ir cleanup */
145     ir_builder_delete(ir);
146
147     /* cleanup */
148     /* Functions must be deleted FIRST since their expressions
149      * reference global variables.
150      */
151     for (i = 0; i < functions_elements; ++i) {
152         ast_function_delete(functions_data[i]);
153     }
154     if (functions_data)
155         mem_d(functions_data);
156
157     /* We must delete not only globals, but also the functions'
158      * ast_values (their type and name), that's why we added them to the globals vector.
159      */
160     for (i = 0; i < globals_elements; ++i) {
161         ast_value_delete(globals_data[i]);
162     }
163     if (globals_data)
164         mem_d(globals_data);
165     return 0;
166 }