1+ #include "ast.h"
2+ #include <stdlib.h>
3+ #include <string.h>
4+ #include <stdio.h>
5+
6+ static void * ast_alloc (size_t size ) {
7+ void * ptr = malloc (size );
8+ if (!ptr ) {
9+ fprintf (stderr , "Out of memory\n" );
10+ exit (1 );
11+ }
12+ memset (ptr , 0 , size );
13+ return ptr ;
14+ }
15+
16+ Expr * expr_int (int64_t value , int line , int column ) {
17+ Expr * expr = ast_alloc (sizeof (Expr ));
18+ expr -> type = EXPR_INT ;
19+ expr -> line = line ;
20+ expr -> column = column ;
21+ expr -> as .int_value = value ;
22+ return expr ;
23+ }
24+
25+ Expr * expr_flt (double value , int line , int column ) {
26+ Expr * expr = ast_alloc (sizeof (Expr ));
27+ expr -> type = EXPR_FLT ;
28+ expr -> line = line ;
29+ expr -> column = column ;
30+ expr -> as .flt_value = value ;
31+ return expr ;
32+ }
33+
34+ Expr * expr_str (char * value , int line , int column ) {
35+ Expr * expr = ast_alloc (sizeof (Expr ));
36+ expr -> type = EXPR_STR ;
37+ expr -> line = line ;
38+ expr -> column = column ;
39+ expr -> as .str_value = value ;
40+ return expr ;
41+ }
42+
43+ Expr * expr_ident (char * name , int line , int column ) {
44+ Expr * expr = ast_alloc (sizeof (Expr ));
45+ expr -> type = EXPR_IDENT ;
46+ expr -> line = line ;
47+ expr -> column = column ;
48+ expr -> as .ident = name ;
49+ return expr ;
50+ }
51+
52+ Expr * expr_call (Expr * callee , int line , int column ) {
53+ Expr * expr = ast_alloc (sizeof (Expr ));
54+ expr -> type = EXPR_CALL ;
55+ expr -> line = line ;
56+ expr -> column = column ;
57+ expr -> as .call .callee = callee ;
58+ return expr ;
59+ }
60+
61+ void expr_list_add (ExprList * list , Expr * expr ) {
62+ if (list -> count + 1 > list -> capacity ) {
63+ size_t new_cap = list -> capacity == 0 ? 4 : list -> capacity * 2 ;
64+ list -> items = realloc (list -> items , new_cap * sizeof (Expr * ));
65+ if (!list -> items ) {
66+ fprintf (stderr , "Out of memory\n" );
67+ exit (1 );
68+ }
69+ list -> capacity = new_cap ;
70+ }
71+ list -> items [list -> count ++ ] = expr ;
72+ }
73+
74+ Stmt * stmt_block (int line , int column ) {
75+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
76+ stmt -> type = STMT_BLOCK ;
77+ stmt -> line = line ;
78+ stmt -> column = column ;
79+ return stmt ;
80+ }
81+
82+ Stmt * stmt_expr (Expr * expr , int line , int column ) {
83+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
84+ stmt -> type = STMT_EXPR ;
85+ stmt -> line = line ;
86+ stmt -> column = column ;
87+ stmt -> as .expr_stmt .expr = expr ;
88+ return stmt ;
89+ }
90+
91+ Stmt * stmt_assign (bool has_type , DeclType decl_type , char * name , Expr * value , int line , int column ) {
92+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
93+ stmt -> type = STMT_ASSIGN ;
94+ stmt -> line = line ;
95+ stmt -> column = column ;
96+ stmt -> as .assign .has_type = has_type ;
97+ stmt -> as .assign .decl_type = decl_type ;
98+ stmt -> as .assign .name = name ;
99+ stmt -> as .assign .value = value ;
100+ return stmt ;
101+ }
102+
103+ Stmt * stmt_decl (DeclType decl_type , char * name , int line , int column ) {
104+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
105+ stmt -> type = STMT_DECL ;
106+ stmt -> line = line ;
107+ stmt -> column = column ;
108+ stmt -> as .decl .decl_type = decl_type ;
109+ stmt -> as .decl .name = name ;
110+ return stmt ;
111+ }
112+
113+ Stmt * stmt_if (Expr * cond , Stmt * then_branch , int line , int column ) {
114+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
115+ stmt -> type = STMT_IF ;
116+ stmt -> line = line ;
117+ stmt -> column = column ;
118+ stmt -> as .if_stmt .condition = cond ;
119+ stmt -> as .if_stmt .then_branch = then_branch ;
120+ return stmt ;
121+ }
122+
123+ Stmt * stmt_while (Expr * cond , Stmt * body , int line , int column ) {
124+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
125+ stmt -> type = STMT_WHILE ;
126+ stmt -> line = line ;
127+ stmt -> column = column ;
128+ stmt -> as .while_stmt .condition = cond ;
129+ stmt -> as .while_stmt .body = body ;
130+ return stmt ;
131+ }
132+
133+ Stmt * stmt_for (char * counter , Expr * target , Stmt * body , int line , int column ) {
134+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
135+ stmt -> type = STMT_FOR ;
136+ stmt -> line = line ;
137+ stmt -> column = column ;
138+ stmt -> as .for_stmt .counter = counter ;
139+ stmt -> as .for_stmt .target = target ;
140+ stmt -> as .for_stmt .body = body ;
141+ return stmt ;
142+ }
143+
144+ Stmt * stmt_func (char * name , DeclType ret , Stmt * body , int line , int column ) {
145+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
146+ stmt -> type = STMT_FUNC ;
147+ stmt -> line = line ;
148+ stmt -> column = column ;
149+ stmt -> as .func_stmt .name = name ;
150+ stmt -> as .func_stmt .return_type = ret ;
151+ stmt -> as .func_stmt .body = body ;
152+ return stmt ;
153+ }
154+
155+ Stmt * stmt_return (Expr * value , int line , int column ) {
156+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
157+ stmt -> type = STMT_RETURN ;
158+ stmt -> line = line ;
159+ stmt -> column = column ;
160+ stmt -> as .return_stmt .value = value ;
161+ return stmt ;
162+ }
163+
164+ Stmt * stmt_break (Expr * value , int line , int column ) {
165+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
166+ stmt -> type = STMT_BREAK ;
167+ stmt -> line = line ;
168+ stmt -> column = column ;
169+ stmt -> as .break_stmt .value = value ;
170+ return stmt ;
171+ }
172+
173+ Stmt * stmt_continue (int line , int column ) {
174+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
175+ stmt -> type = STMT_CONTINUE ;
176+ stmt -> line = line ;
177+ stmt -> column = column ;
178+ return stmt ;
179+ }
180+
181+ Stmt * stmt_try (Stmt * try_block , char * catch_name , Stmt * catch_block , int line , int column ) {
182+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
183+ stmt -> type = STMT_TRY ;
184+ stmt -> line = line ;
185+ stmt -> column = column ;
186+ stmt -> as .try_stmt .try_block = try_block ;
187+ stmt -> as .try_stmt .catch_name = catch_name ;
188+ stmt -> as .try_stmt .catch_block = catch_block ;
189+ return stmt ;
190+ }
191+
192+ Stmt * stmt_goto (Expr * target , int line , int column ) {
193+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
194+ stmt -> type = STMT_GOTO ;
195+ stmt -> line = line ;
196+ stmt -> column = column ;
197+ stmt -> as .goto_stmt .target = target ;
198+ return stmt ;
199+ }
200+
201+ Stmt * stmt_gotopoint (Expr * target , int line , int column ) {
202+ Stmt * stmt = ast_alloc (sizeof (Stmt ));
203+ stmt -> type = STMT_GOTOPOINT ;
204+ stmt -> line = line ;
205+ stmt -> column = column ;
206+ stmt -> as .gotopoint_stmt .target = target ;
207+ return stmt ;
208+ }
209+
210+ void stmt_list_add (StmtList * list , Stmt * stmt ) {
211+ if (list -> count + 1 > list -> capacity ) {
212+ size_t new_cap = list -> capacity == 0 ? 4 : list -> capacity * 2 ;
213+ list -> items = realloc (list -> items , new_cap * sizeof (Stmt * ));
214+ if (!list -> items ) {
215+ fprintf (stderr , "Out of memory\n" );
216+ exit (1 );
217+ }
218+ list -> capacity = new_cap ;
219+ }
220+ list -> items [list -> count ++ ] = stmt ;
221+ }
222+
223+ void param_list_add (ParamList * list , Param param ) {
224+ if (list -> count + 1 > list -> capacity ) {
225+ size_t new_cap = list -> capacity == 0 ? 4 : list -> capacity * 2 ;
226+ list -> items = realloc (list -> items , new_cap * sizeof (Param ));
227+ if (!list -> items ) {
228+ fprintf (stderr , "Out of memory\n" );
229+ exit (1 );
230+ }
231+ list -> capacity = new_cap ;
232+ }
233+ list -> items [list -> count ++ ] = param ;
234+ }
235+
236+ static void free_expr_list (ExprList * list ) {
237+ for (size_t i = 0 ; i < list -> count ; i ++ ) {
238+ free_expr (list -> items [i ]);
239+ }
240+ free (list -> items );
241+ }
242+
243+ static void free_stmt_list (StmtList * list ) {
244+ for (size_t i = 0 ; i < list -> count ; i ++ ) {
245+ free_stmt (list -> items [i ]);
246+ }
247+ free (list -> items );
248+ }
249+
250+ void free_expr (Expr * expr ) {
251+ if (!expr ) return ;
252+ switch (expr -> type ) {
253+ case EXPR_STR :
254+ free (expr -> as .str_value );
255+ break ;
256+ case EXPR_IDENT :
257+ free (expr -> as .ident );
258+ break ;
259+ case EXPR_CALL :
260+ free_expr (expr -> as .call .callee );
261+ free_expr_list (& expr -> as .call .args );
262+ break ;
263+ default :
264+ break ;
265+ }
266+ free (expr );
267+ }
268+
269+ void free_stmt (Stmt * stmt ) {
270+ if (!stmt ) return ;
271+ switch (stmt -> type ) {
272+ case STMT_BLOCK :
273+ free_stmt_list (& stmt -> as .block );
274+ break ;
275+ case STMT_EXPR :
276+ free_expr (stmt -> as .expr_stmt .expr );
277+ break ;
278+ case STMT_ASSIGN :
279+ free (stmt -> as .assign .name );
280+ free_expr (stmt -> as .assign .value );
281+ break ;
282+ case STMT_DECL :
283+ free (stmt -> as .decl .name );
284+ break ;
285+ case STMT_IF :
286+ free_expr (stmt -> as .if_stmt .condition );
287+ free_stmt (stmt -> as .if_stmt .then_branch );
288+ free_expr_list (& stmt -> as .if_stmt .elif_conditions );
289+ free_stmt_list (& stmt -> as .if_stmt .elif_blocks );
290+ free_stmt (stmt -> as .if_stmt .else_branch );
291+ break ;
292+ case STMT_WHILE :
293+ free_expr (stmt -> as .while_stmt .condition );
294+ free_stmt (stmt -> as .while_stmt .body );
295+ break ;
296+ case STMT_FOR :
297+ free (stmt -> as .for_stmt .counter );
298+ free_expr (stmt -> as .for_stmt .target );
299+ free_stmt (stmt -> as .for_stmt .body );
300+ break ;
301+ case STMT_FUNC :
302+ free (stmt -> as .func_stmt .name );
303+ for (size_t i = 0 ; i < stmt -> as .func_stmt .params .count ; i ++ ) {
304+ free (stmt -> as .func_stmt .params .items [i ].name );
305+ free_expr (stmt -> as .func_stmt .params .items [i ].default_value );
306+ }
307+ free (stmt -> as .func_stmt .params .items );
308+ free_stmt (stmt -> as .func_stmt .body );
309+ break ;
310+ case STMT_RETURN :
311+ free_expr (stmt -> as .return_stmt .value );
312+ break ;
313+ case STMT_BREAK :
314+ free_expr (stmt -> as .break_stmt .value );
315+ break ;
316+ case STMT_TRY :
317+ free_stmt (stmt -> as .try_stmt .try_block );
318+ free (stmt -> as .try_stmt .catch_name );
319+ free_stmt (stmt -> as .try_stmt .catch_block );
320+ break ;
321+ case STMT_GOTO :
322+ free_expr (stmt -> as .goto_stmt .target );
323+ break ;
324+ case STMT_GOTOPOINT :
325+ free_expr (stmt -> as .gotopoint_stmt .target );
326+ break ;
327+ default :
328+ break ;
329+ }
330+ free (stmt );
331+ }
0 commit comments