Skip to content

Commit a16a97d

Browse files
gh-1, gh-4: Build interpreter.
1 parent 931fd71 commit a16a97d

14 files changed

Lines changed: 4046 additions & 47 deletions

File tree

src/ast.c

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
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

Comments
 (0)