Newer
Older

Clemens Paumgarten
committed
#include <stdlib.h>

Clemens Paumgarten
committed
#include <mcc/ast.h>

Clemens Paumgarten
committed
#include "tac_string_builder.h"

Clemens Paumgarten
committed
#include "symbol_table_validate.h"
// -------------------------------- parse expression
void mcc_tac_parse_expression(struct mcc_ast_expression *expression, struct mcc_tac *tac) {
assert(expression);
assert(tac);
switch (expression -> type) {
case MCC_AST_EXPRESSION_TYPE_IDENTIFIER: {
struct mcc_ast_identifier *identifier = expression->identifier;
enum mcc_ast_data_type type = mcc_symbol_table_get_expression_return_type(expression,tac->current_symbol_table);
enum mcc_tac_operation op = convert_ast_type_to_tac_ident(type);
char *arg1 = identifier->i_value;
mcc_tac_create_and_add_new_entry_temp(op,arg1,NULL,tac);

Clemens Paumgarten
committed
} break;
case MCC_AST_EXPRESSION_TYPE_LITERAL : {
struct mcc_ast_literal *literal = expression->literal;
enum mcc_tac_operation op = convert_ast_type_to_tac_literal(literal->type);
char *arg1;
switch (op)
{
case MCC_TAC_BOOL :
arg1 = literal->b_value ? "true" : "false";
break;
case MCC_TAC_INT :
sprintf(arg1, "%d", literal->i_value);
break;
case MCC_TAC_FLOAT :
sprintf(arg1, "%f", literal->f_value);
break;
case MCC_TAC_STRING :
arg1= literal->s_value;
break;
default:
break;
}
mcc_tac_create_and_add_new_entry_temp(op,arg1,NULL,tac);
} break;
case MCC_AST_EXPRESSION_TYPE_CALL_EXPRESSION : {
int arg_size;
if(expression->argument) {
arg_size = expression->argument->expressions->size;
struct mcc_ast_expression *parameter = expression->argument->expressions->arr[i];
enum mcc_ast_data_type type = mcc_symbol_table_get_expression_return_type(parameter,
tac->current_symbol_table);
enum mcc_tac_operation op = convert_ast_type_to_tac_param(type);
mcc_tac_parse_expression(parameter, tac);
mcc_tac_create_and_add_new_entry(op, arg1, NULL, NULL, tac);
char *arg1 = malloc(mcc_get_number_of_digits(tac->temporary_count) + 2);
sprintf(arg1, "$%d", arg_size);
char *result = expression->function_name->i_value;
mcc_tac_create_and_add_new_entry(MCC_TAC_CALL, arg1, NULL, result, tac);
enum mcc_ast_data_type type = mcc_symbol_table_get_expression_return_type(expression,
tac->current_symbol_table);
enum mcc_tac_operation op = convert_ast_type_to_tac_ident(type);
char *arg1 = mcc_tac_new_return_function_name(result);
mcc_tac_create_and_add_new_entry_temp(op, arg1, NULL, tac);
}
} break;
case MCC_AST_EXPRESSION_TYPE_UNARY_OP : {
enum mcc_ast_data_type type = mcc_symbol_table_get_expression_return_type(expression,
tac->current_symbol_table);
enum mcc_tac_operation op = convert_ast_type_to_tac_unary(type);
mcc_tac_parse_expression(expression->unary_expression, tac);
mcc_tac_create_and_add_new_entry_temp(op, arg1, NULL, tac);
} break;
case MCC_AST_EXPRESSION_TYPE_BINARY_OP : {
enum mcc_ast_data_type type = mcc_symbol_table_get_expression_return_type(expression,
tac->current_symbol_table);
enum mcc_tac_operation op = convert_ast_type_to_tac_binary(expression->op, type);
mcc_tac_parse_expression(expression->lhs, tac);
mcc_tac_parse_expression(expression->rhs, tac);
mcc_tac_create_and_add_new_entry_temp(op, arg1, arg2, tac);
case MCC_AST_EXPRESSION_TYPE_PARENTH :
mcc_tac_parse_expression(expression->expression,tac);
case MCC_AST_EXPRESSION_TYPE_BRACKET : {
enum mcc_ast_data_type type = mcc_symbol_table_get_expression_return_type(expression,
tac->current_symbol_table);
enum mcc_tac_operation op = convert_ast_type_to_tac_load(type);
struct mcc_ast_identifier *ident = expression->bracket_identifier;
char *arg1 = ident->i_value;
mcc_tac_parse_expression(expression->bracket_expression, tac);
mcc_tac_create_and_add_new_entry_temp(op, arg1, arg2, tac);
} break;
void mcc_tac_parse_statement_list(struct mcc_ast_statement_list *stl, struct mcc_tac *tac) {
assert(stl);
assert(tac);
while (stl != NULL) {
mcc_tac_parse_statement(stl -> statement, tac);
stl = stl -> next;
}
}
struct mcc_tac *mcc_tac_parse_statement(struct mcc_ast_statement *statement, struct mcc_tac *tac) {
switch (statement -> type) {
case MCC_AST_STATEMENT_TYPE_COMPOUND:
mcc_tac_parse_statement_list(statement -> statement_list, tac);

Clemens Paumgarten
committed
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
break;
case MCC_AST_STATEMENT_TYPE_IF: {
// evaluate if expression
mcc_tac_parse_expression(statement -> while_condition, tac);
char *last_temp = tac -> last_temporary;
// now do that jump / jumpfalse stuff here
char *if_label = mcc_tac_new_label_string(tac);
mcc_tac_create_and_add_new_entry(MCC_TAC_JMP_FALSE, last_temp, NULL, if_label, tac);
//scope go to deeper scope and save current index
int current_scope_index = tac -> current_symbol_index;
mcc_tac_enter_next_deeper_scope(tac);
mcc_tac_parse_statement(statement -> if_stmt, tac);
//go back to previous scope
mcc_tac_exit_to_outer_scoper(tac, current_scope_index);
tac -> current_symbol_index++;
char *else_label= mcc_tac_new_label_string(tac);
mcc_tac_create_and_add_new_entry(MCC_TAC_JMP, NULL, NULL, else_label, tac);
if (statement -> else_stmt != NULL) {
// jump last label
current_scope_index = tac -> current_symbol_index;
mcc_tac_enter_next_deeper_scope(tac);
mcc_tac_parse_statement(statement -> else_stmt, tac);
//go back to previous scope
mcc_tac_exit_to_outer_scoper(tac, current_scope_index);
tac -> current_symbol_index++;
}
} break;
case MCC_AST_STATEMENT_TYPE_EXPRESSION:

Clemens Paumgarten
committed
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
mcc_tac_parse_expression(statement -> expression, tac);
break;
case MCC_AST_STATEMENT_TYPE_WHILE: {
mcc_tac_parse_expression(statement -> while_condition, tac);
char *last_temp = tac -> last_temporary;
char *while_label = mcc_tac_new_label_string(tac);
mcc_tac_create_and_add_new_entry(MCC_TAC_JMP_FALSE, last_temp, NULL, while_label, tac);
int current_scope_index = tac -> current_symbol_index;
mcc_tac_enter_next_deeper_scope(tac);
mcc_tac_parse_statement(statement -> if_stmt, tac);
//go back to previous scope
mcc_tac_exit_to_outer_scoper(tac, current_scope_index);
tac -> current_symbol_index++;
} break;
case MCC_AST_STATEMENT_TYPE_DECL: {
// Check nicht ganz um was es da geht
// struct mCc_ast_literal *array_size = statement->declaration->array_size;
// if (array_size) {
// builder->current_variable_count += atoi(array_size->value);
// create_and_add_line(builder, MCC_TAC_OPERATION_ARRAY_DECLARATION,
// array_size->value, NULL,
// statement->declaration->identifier->name);
// }
// break;
// }
} break;
case MCC_AST_STATEMENT_TYPE_ASSGN_ARR:
case MCC_AST_STATEMENT_TYPE_ASSGN: {
// get type
struct mcc_ast_assignment *a = statement -> assignment;
char *result = statement -> assignment -> identifier ->i_value;
enum mcc_ast_data_type assignment_type =
mcc_symbol_table_get_symbol(
tac->current_symbol_table,
result,
true) -> data_type;
enum mcc_tac_operation tac_op = convert_ast_type_to_tac_operation(assignment_type);
if (a -> type == MCC_AST_ASSIGNMENT_TYPE_ARRAY) {
mcc_tac_parse_expression(a -> array_ass.index, tac);
char *arg2 = tac -> last_temporary;
mcc_tac_parse_expression(a -> array_ass.rhs, tac);
char *arg1 = tac -> last_temporary;
mcc_tac_create_and_add_new_entry(tac_op, arg1, arg2, result, tac);
} else {
// evaluate expression
mcc_tac_parse_expression(a -> normal_ass.rhs, tac);
char *arg1 = tac -> last_temporary;
mcc_tac_create_and_add_new_entry(tac_op, arg1, NULL, result, tac);
}
} break;
case MCC_AST_STATEMENT_TYPE_RETURN: {
// TODO: get symbol table name from a seperate variable (tac -> root_table)
// get expression type
enum mcc_ast_data_type return_type = mcc_symbol_table_get_expression_return_type(
statement -> expression,
tac -> current_symbol_table
);
enum mcc_tac_operation tac_op = convert_ast_type_to_tac_operation(return_type);
mcc_tac_parse_expression(statement -> expression, tac);
char *arg1 = tac -> last_temporary;
char *result = mcc_tac_new_return_function_name(tac -> current_symbol_table -> sym_table_name);

Clemens Paumgarten
committed
mcc_tac_create_and_add_new_entry(MCC_TAC_RETURN, arg1, NULL, result, tac);
} break;
}
// -------------------------------- parse function
int mcc_tac_parse_function(struct mcc_ast_function *f, struct mcc_tac *tac) {
assert(f);
assert(tac);
// TODO: do something with params
if (f->statement != NULL) {
mcc_tac_parse_statement(f -> statement, tac);
// start parsing program
struct mcc_tac *mcc_tac_build(struct mcc_ast_program *program, struct mcc_symbol_table *st) {

Clemens Paumgarten
committed
struct mcc_tac *tac = mcc_tac_new(NULL, st);
struct mcc_ast_function *f = NULL;
// look for main an start parsing program
for (int i = 0; i < program -> function_def -> size; i++) {
f = program -> function_def -> arr[i];
if (strcmp(f -> identifier -> i_value, "main") == 0) {
struct mcc_symbol_table *t = mcc_symbol_table_get_inner_table_by_name(st, "main");
if (t != NULL) {

Clemens Paumgarten
committed
mcc_tac_parse_function(f, tac);