Newer
Older

Clemens Paumgarten
committed
#include <stdlib.h>

Clemens Paumgarten
committed
#include <mcc/ast.h>
#include "mcc/symbol_table_validate.h"
#include "mcc/symbol_table_print.h"
#include "mcc/utils.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 = mcc_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 = mcc_convert_ast_type_to_tac_literal(literal->type);
char *arg1 = malloc((size_t ) mcc_get_number_of_digits(tac->temporary_count) + 2);
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 = mcc_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((size_t ) 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 = mcc_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 = mcc_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 = mcc_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 = mcc_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;
}
}
void 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);
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;

Clemens Paumgarten
committed
mcc_tac_enter_next_deeper_scope(tac);
mcc_tac_parse_statement(statement -> if_stmt, tac);

Clemens Paumgarten
committed
// go back to previous scope
mcc_tac_exit_to_outer_scope(tac, current_scope_index);

Clemens Paumgarten
committed

Clemens Paumgarten
committed
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;

Clemens Paumgarten
committed
mcc_tac_enter_next_deeper_scope(tac);
mcc_tac_parse_statement(statement -> else_stmt, tac);

Clemens Paumgarten
committed
//go back to previous scope
mcc_tac_exit_to_outer_scope(tac, current_scope_index);

Clemens Paumgarten
committed
tac -> current_symbol_index++;

Clemens Paumgarten
committed
} break;
case MCC_AST_STATEMENT_TYPE_EXPRESSION:
mcc_tac_parse_expression(statement -> expression, tac);
break;
case MCC_AST_STATEMENT_TYPE_WHILE: {
mcc_tac_parse_expression(statement -> while_condition, tac);

Clemens Paumgarten
committed
char *last_temp = tac -> last_temporary;

Clemens Paumgarten
committed
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);

Clemens Paumgarten
committed
int current_scope_index = tac -> current_symbol_index;
mcc_tac_enter_next_deeper_scope(tac);

Clemens Paumgarten
committed
mcc_tac_parse_statement(statement -> if_stmt, tac);

Clemens Paumgarten
committed
//go back to previous scope
mcc_tac_exit_to_outer_scope(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;

Clemens Paumgarten
committed
enum mcc_ast_data_type assignment_type = mcc_symbol_table_get_symbol(
tac->current_symbol_table,
result,
true) -> data_type;

Clemens Paumgarten
committed
enum mcc_tac_operation tac_op = mcc_convert_ast_type_to_tac_literal(assignment_type);
if (a -> type == MCC_AST_ASSIGNMENT_TYPE_ARRAY) {
mcc_tac_parse_expression(a -> array_ass.index, tac);

Clemens Paumgarten
committed
char *arg2 = tac -> last_temporary;

Clemens Paumgarten
committed
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);

Clemens Paumgarten
committed
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: {// get expression type
// enum mcc_ast_data_type return_type = mcc_symbol_table_get_expression_return_type(
// statement -> expression,
// tac -> current_symbol_table
// );
//
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);
mcc_tac_create_and_add_new_entry(MCC_TAC_RETURN, arg1, NULL, result, tac);
} break;
}
}
// -------------------------------- parse function
void parse_params(struct mcc_ast_parameter *parameter, struct mcc_tac *tac) {
// parse params from right to left
for (int i = parameter -> parameters -> size - 1; i >= 0; i--) {
struct mcc_ast_declaration *param_decl = (struct mcc_ast_declaration *) parameter -> parameters -> arr[i];
}
}
int mcc_tac_parse_function(struct mcc_ast_function *f, struct mcc_tac *tac) {
assert(f);
assert(tac);
parse_params(f -> parameter, tac);
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) {
struct mcc_tac *tac = mcc_tac_new(NULL, st);
struct mcc_ast_function *f = NULL;
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");
tac -> current_symbol_table = t;
tac -> current_symbol_index = 0;
if (t != NULL) {
mcc_tac_parse_function(f, tac);
}
}
}