Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tac.c 8.36 KiB
#include <stdlib.h>
#include <assert.h>

#include "mcc/tac.h"
#include "mcc/tac_string_builder.h"

// --------------------------------------------- Error Collector

// struct mcc_tac_error_collector *mcc_tac_new_error_collector() {
//     struct mcc_tac_error_collector *ec = malloc(sizeof(*ec));

//     if (ec == NULL) return NULL;

//     ec -> errors = mcc_create_dynamic_array(MCC_TAC_ERROR_SIZE);

//     return ec;
// }

// int mcc_tac_add_error(struct mcc_tac_error_collector *ec, struct mcc_tac_error *e) {
//     assert(ec);
//     assert(e);

//     return mcc_add_to_array(ec -> errors, e);
// }

// struct mcc_tac_error *mcc_tac_new_error(struct mcc_ast_source_location *sloc, enum mcc_tac_error_type error_type) {
//     struct mcc_tac_error *e = malloc(sizeof(*e));

//     e -> sloc = sloc;
//     e -> error_type = error_type;

//     return e;
// }

// --------------------------------------------- TAC Object

struct mcc_tac *mcc_tac_new(struct mcc_tac *prev_tac, struct mcc_symbol_table *st) {
    struct mcc_tac *tac = malloc(sizeof(*tac));

    if(!tac) {
        return NULL;
    }

    tac->prev = prev_tac;
    tac->next = NULL;

    if(prev_tac != NULL) {
        prev_tac->next = tac;
    }

    tac->tac_entries = mcc_create_dynamic_array(MCC_TAC_ENTRY_SIZE);
    tac->temporary_count = 0;
    tac->label_count = 0;

    tac->root_table = st;
    tac->current_symbol_table = st;
    tac->current_symbol_index = 0;

    return tac;
}

struct mcc_tac_entry *mcc_tac_new_entry(
        enum mcc_tac_operation tac_op,
        char *arg1,
        char *arg2,
        char *result
) {
    struct mcc_tac_entry *te = malloc(sizeof(*te));

    te->tac_op = tac_op;
    te->arg1 = arg1;
    te->arg2 = arg2;
    te->result = result;

    return te;
}

int mcc_tac_add_entry(struct mcc_tac *tac, struct mcc_tac_entry *te) {
    return mcc_add_to_array(tac->tac_entries, te);
}

int mcc_tac_create_and_add_new_entry(
        enum mcc_tac_operation tac_op,
        char *arg1,
        char *arg2,
        char *result,
        struct mcc_tac *tac) {
    struct mcc_tac_entry *te = mcc_tac_new_entry(tac_op, arg1, arg2, result);

    return mcc_tac_add_entry(tac, te);
}

int mcc_tac_create_and_add_new_entry_temp(
        enum mcc_tac_operation tac_op,
        char *arg1,
        char *arg2,
        struct mcc_tac *tac) {

    char *result = mcc_tac_new_temporary_string(tac);
    struct mcc_tac_entry *te = mcc_tac_new_entry(tac_op, arg1, arg2, result);

    return mcc_tac_add_entry(tac, te);
}


void mcc_tac_delete_entry(void *te) {
    struct mcc_tac_entry *tac_entry = (struct mcc_tac_entry *) te;

    free(tac_entry);
}

void mcc_tac_delete(struct mcc_tac *tac) {
    if(tac->next != NULL) {
        mcc_tac_delete(tac->next);
    }

    mcc_delete_array(tac->tac_entries, mcc_tac_delete_entry);

    free(tac);
}

enum mcc_tac_operation mcc_convert_ast_type_to_tac_literal(enum mcc_ast_data_type type) {
    switch(type) {
        case MCC_AST_DATA_TYPE_INT:
            return MCC_TAC_INT;
        case MCC_AST_DATA_TYPE_BOOL:
            return MCC_TAC_BOOL;
        case MCC_AST_DATA_TYPE_FLOAT:
            return MCC_TAC_FLOAT;
        case MCC_AST_DATA_TYPE_STRING:
            return MCC_TAC_STRING;
        default:
            break;
    }
    return MCC_TAC_UNKNOWN;
}

enum mcc_tac_operation mcc_convert_ast_type_to_tac_ident(enum mcc_ast_data_type type) {
    switch(type) {
        case MCC_AST_DATA_TYPE_INT:
            return MCC_TAC_IDENTIFIER_INT;
        case MCC_AST_DATA_TYPE_BOOL:
            return MCC_TAC_IDENTIFIER_BOOL;
        case MCC_AST_DATA_TYPE_FLOAT:
            return MCC_TAC_IDENTIFIER_FLOAT;
        case MCC_AST_DATA_TYPE_STRING:
            return MCC_TAC_IDENTIFIER_STRING;
        default:
            break;
    }
    return MCC_TAC_UNKNOWN;
}

enum mcc_tac_operation mcc_convert_ast_type_to_tac_param(enum mcc_ast_data_type type) {
    switch(type) {
        case MCC_AST_DATA_TYPE_INT:
            return MCC_TAC_PARAM_INT;
        case MCC_AST_DATA_TYPE_BOOL:
            return MCC_TAC_PARAM_BOOL;
        case MCC_AST_DATA_TYPE_FLOAT:
            return MCC_TAC_PARAM_FLOAT;
        case MCC_AST_DATA_TYPE_STRING:
            return MCC_TAC_PARAM_INT;
        default:
            break;
    }
    return MCC_TAC_UNKNOWN;
}

enum mcc_tac_operation mcc_convert_ast_type_to_tac_unary(enum mcc_ast_data_type type) {
    switch(type) {
        case MCC_AST_DATA_TYPE_INT:
            return MCC_TAC_MINUS_INT_UN;
        case MCC_AST_DATA_TYPE_BOOL:
            return MCC_TAC_PARAM_BOOL;
        case MCC_TAC_MINUS_FLOAT_UN:
            return MCC_TAC_NOT;
        default:
            break;
    }
    return MCC_TAC_UNKNOWN;
}


enum mcc_tac_operation
mcc_convert_ast_type_to_tac_binary(enum mcc_ast_binary_op binary_op, enum mcc_ast_data_type type) {
    switch(binary_op) {
        case MCC_AST_BINARY_OP_ADD:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_PLUS_INT
                   : MCC_TAC_PLUS_FLOAT;
        case MCC_AST_BINARY_OP_SUB:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_MINUS_INT_BIN
                   : MCC_TAC_MINUS_FLOAT_BIN;
        case MCC_AST_BINARY_OP_MUL:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_MUL_INT
                   : MCC_TAC_MUL_FLOAT;
        case MCC_AST_BINARY_OP_DIV:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_DIV_INT
                   : MCC_TAC_DIV_FLOAT;

        case MCC_AST_BINARY_OP_LESS:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_LT
                   : MCC_TAC_LT_FLOAT;
        case MCC_AST_BINARY_OP_GREATER:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_GT
                   : MCC_TAC_GT_FLOAT;
        case MCC_AST_BINARY_OP_LESS_EQUALS:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_LTEQ
                   : MCC_TAC_LTEQ_FLOAT;
        case MCC_AST_BINARY_OP_GREATER_EQUALS:
            return (type == MCC_AST_DATA_TYPE_INT)
                   ? MCC_TAC_GTEQ
                   : MCC_TAC_GTEQ_FLOAT;

        case MCC_AST_BINARY_OP_EQUALS:
            if(type == MCC_AST_DATA_TYPE_BOOL) {
                return MCC_TAC_EQ_BOOL;
            } else if(type == MCC_AST_DATA_TYPE_INT) {
                return MCC_TAC_EQ;
            } else {
                return MCC_TAC_EQ_FLOAT;
            }
        case MCC_AST_BINARY_OP_NOT_EQUALS:
            if(type == MCC_AST_DATA_TYPE_BOOL) {
                return MCC_TAC_NEQ_BOOL;
            } else if(type == MCC_AST_DATA_TYPE_INT) {
                return MCC_TAC_NEQ;
            } else {
                return MCC_TAC_NEQ_FLOAT;
            }
        case MCC_AST_BINARY_OP_AND:
            return MCC_TAC_AND;
        case MCC_AST_BINARY_OP_OR:
            return MCC_TAC_OR;
        default:
            break;
    }
    return MCC_TAC_UNKNOWN;
}

enum mcc_tac_operation mcc_convert_ast_type_to_tac_load(enum mcc_ast_data_type type) {
    switch(type) {
        case MCC_AST_DATA_TYPE_BOOL:
            return MCC_TAC_LOAD_BOOL;
        case MCC_AST_DATA_TYPE_INT:
            return MCC_TAC_LOAD_INT;
        case MCC_AST_DATA_TYPE_FLOAT:
            return MCC_TAC_LOAD_FLOAT;
        case MCC_AST_DATA_TYPE_STRING:
            return MCC_TAC_LOAD_STRING;
        default:
            break;
    }
    return MCC_TAC_UNKNOWN;

}

enum mcc_tac_operation mcc_convert_ast_type_to_tac_store(enum mcc_ast_data_type type) {
    switch(type) {
        case MCC_AST_DATA_TYPE_BOOL:
            return MCC_TAC_STORE_BOOL;
        case MCC_AST_DATA_TYPE_INT:
            return MCC_TAC_STORE_INT;
        case MCC_AST_DATA_TYPE_FLOAT:
            return MCC_TAC_STORE_FLOAT;
        case MCC_AST_DATA_TYPE_STRING:
            return MCC_TAC_STORE_STRING;
        default:
            return MCC_TAC_UNKNOWN;
    }


}

void mcc_tac_enter_next_deeper_scope(struct mcc_tac *tac) {
    struct mcc_symbol_table *next_curr = tac->current_symbol_table->inner_tables->arr[tac->current_symbol_index];

    tac->current_symbol_table = next_curr;
    tac->current_symbol_index = 0;
}

void mcc_tac_exit_to_outer_scope(struct mcc_tac *tac, int tac_st_index) {
    struct mcc_symbol_table *root = tac->current_symbol_table->parent;

    tac->current_symbol_table = root;
    tac->current_symbol_index = tac_st_index;
}

void mcc_tac_jump_to_next_inner_st(struct mcc_tac *tac) {

}

void mcc_tac_jump_to_prev_inner_st(struct mcc_tac *tac) {

}