#include "eaxhla.h" /* This source file is responsible for holding data * that belongs neither to the scanner nor the parser. * It also facades "implementation details" such as * the storage of variables. */ #include #include #include #include "eaxhla.tab.h" #include "debug.h" #include "assembler.h" #include "compile.h" unsigned long long anon_variable_counter = 0; static unsigned symbol_id = 1; tommy_hashtable symbol_table; int has_encountered_error = 0; int is_program_found = 0; char * scope = NULL; void empty_out_scope(void) { free(scope); scope = NULL; } char * yyfilename = ""; int eaxhla_init(void) { tommy_hashtable_init(&symbol_table, 256); return 0; } static void free_symbol(void * data) { symbol_t * variable = (symbol_t*)data; free(variable->name); free(variable); } int eaxhla_deinit(void) { tommy_hashtable_foreach(&symbol_table, free_symbol); tommy_hashtable_done(&symbol_table); return 0; } static int table_compare_unsigned(const void * arg, const void * obj) { return *(const unsigned *) arg != ((const symbol_t*)obj)->_hash; } void add_variable(symbol_t variable) { if (get_variable(variable.name)) { issue_error("symbol '%s' redeclared as new variable", variable.name); return; } variable._id = symbol_id++; variable.symbol_type = VARIABLE; symbol_t * heap_variable = malloc(sizeof(variable)); memcpy(heap_variable, &variable, sizeof(variable)); heap_variable->_hash = tommy_strhash_u32(0, heap_variable->name); tommy_hashtable_insert(&symbol_table, &heap_variable->_node, heap_variable, heap_variable->_hash ); } void add_procedure(symbol_t procedure) { if (get_function(procedure.name)) { issue_error("symbol '%s' redeclared as new function", procedure.name); return; } procedure._id = symbol_id++; procedure.symbol_type = FUNCTION; symbol_t * heap_procedure = malloc(sizeof(procedure)); memcpy(heap_procedure, &procedure, sizeof(procedure)); heap_procedure->_hash = tommy_strhash_u32(0, heap_procedure->name); tommy_hashtable_insert(&symbol_table, &heap_procedure->_node, heap_procedure, heap_procedure->_hash ); // append_instructions(ASMDIRMEM, procedure._id); } /* Are these literals ugly? yes. * However it would be much more painful to calculate the values inline. */ int can_fit(const int type, const long long value) { unsigned long long max = 0; long long min = 0; switch (type) { case U8: { max = 255; } break; case U16: { max = 65535; } break; case U32: { max = 4294967295; } break; case U64: { max = 9223372036854775807; } break; case S8: { min = -128; max = 127; } break; case S16: { min = -256; max = 255; } break; case S32: { min = -65536; max = 65535; } break; case S64: { min = -4294967296; max = 4294967295; } break; } return value > 0 ? (unsigned long long)value <= max : value >= min; } int type2size(const int type) { switch (type) { case U8: case S8: return D8; case U16: case S16: return D16; case U32: case S32: return D32; case U64: case S64: return D64; } issue_error("internal error"); return -1; } int validate_array_size(const int size) { if (size < 1) { issue_error("cannot create an array of size '%d', because its less than 1", size); return 1; } return 0; } char * make_scoped_name(const char * const scope, char * name) { if (!scope) { return name; } char * r; const long scl = strlen(scope); const long nml = strlen(name); r = malloc(2 + scl + 1 + nml + 1); r[0] = '_'; r[1] = '_'; memcpy(r + 2, scope, scl); r[2 + scl] = '_'; memcpy(r + 2 + scl + 1, name, nml); r[2 + scl + 1 + nml] = '\0'; free(name); return r; } static void * symbol_lookup(const char * const name) { unsigned lookup_hash = tommy_strhash_u32(0, name); void * r = tommy_hashtable_search(&symbol_table, table_compare_unsigned, &lookup_hash, lookup_hash ); return r; } symbol_t * get_variable(const char * const name) { symbol_t *r = symbol_lookup(name); if (r && r->symbol_type != VARIABLE) { issue_error("the symbol '%s' is not a variable", name); return NULL; } return r; } symbol_t * get_function(const char * const name) { symbol_t * r = symbol_lookup(name); if (r && r->symbol_type != FUNCTION) { issue_error("the symbol '%s' is not a function", name); return NULL; } return r; } void issue_warning(const char * const format, ...) { extern char * yyfilename; extern int yylineno; va_list args; va_start(args, format); char * msg; const int ignore = vasprintf(&msg, format, args); (void)ignore; fprintf(stderr, "\033[1m%s:%d:\033[0m \033[35mWarning\033[0m: %s.\n", yyfilename, yylineno, msg ); free(msg); } void issue_error(const char * const format, ...) { extern char * yyfilename; extern int yylineno; has_encountered_error = 1; va_list args; va_start(args, format); char * msg; const int ignore = vasprintf(&msg, format, args); (void)ignore; fprintf(stderr, "\033[1m%s:%d:\033[0m \033[31mError\033[0m: %s.\n", yyfilename, yylineno, msg ); free(msg); } int system_type = #if defined(__unix__) UNIX #elif defined(_WIN64) WIN64 #else #error Your system was not recognized. 0 #endif ;