diff --git a/source/compile.c b/source/compile.c index ecc391f..c1d583b 100644 --- a/source/compile.c +++ b/source/compile.c @@ -27,7 +27,10 @@ int compile_deinit(void) { static void dump_variable_to_assembler(void * data) { - variable_t * variable = (variable_t*)data; + symbol_t * variable = (symbol_t*)data; + if (variable->symbol_type != VARIABLE) { + return; + } append_instructions(ASMDIRMEM, variable->_id, ASMDIRIMM, type2size(variable->type)); @@ -44,7 +47,7 @@ void dump_variable_to_assembler(void * data) { static void dump_variables_to_assembler(void) { - tommy_hashtable_foreach(&variable_table, dump_variable_to_assembler); + tommy_hashtable_foreach(&symbol_table, dump_variable_to_assembler); } static diff --git a/source/compile.h b/source/compile.h index 7696c11..c6b09df 100644 --- a/source/compile.h +++ b/source/compile.h @@ -13,10 +13,6 @@ extern int compile(void); extern void append_label (int rel); -extern void append_fastcall_begin (int rel); -extern void append_fastcall_end (void); -extern void append_fastcall_arguments (int rel, int wid, int imm); - /* --- Token appending * The core problem is that we want an interface where we can append {instructoin} * tokens without modifying the counter as that gets old fast and error prone diff --git a/source/debug.h b/source/debug.h index 9deac89..eb3711d 100644 --- a/source/debug.h +++ b/source/debug.h @@ -18,7 +18,7 @@ void debug_printf(const char * const fmt, ...) { static void dump_variable(void * data) { - variable_t * variable = (variable_t*)data; + symbol_t * variable = (symbol_t*)data; if (variable->elements == 1) { printf("{ .name = '%s', .value = '%ld' }\n", variable->name, @@ -36,7 +36,7 @@ void dump_variable(void * data) { static void debug_dump_variables(void) { - tommy_hashtable_foreach(&variable_table, dump_variable); + tommy_hashtable_foreach(&symbol_table, dump_variable); } static diff --git a/source/eaxhla.c b/source/eaxhla.c index 1f3c7ec..bd72161 100644 --- a/source/eaxhla.c +++ b/source/eaxhla.c @@ -18,7 +18,8 @@ unsigned long long anon_variable_counter = 0; -tommy_hashtable variable_table; +static unsigned symbol_id = 0; +tommy_hashtable symbol_table; int has_encountered_error = 0; int is_program_found = 0; @@ -29,20 +30,20 @@ char * yyfilename = ""; int eaxhla_init(void) { - tommy_hashtable_init(&variable_table, 256); + tommy_hashtable_init(&symbol_table, 256); return 0; } static void free_variable(void * data) { - variable_t * variable = (variable_t*)data; + symbol_t * variable = (symbol_t*)data; free(variable->name); free(variable); } int eaxhla_deinit(void) { - tommy_hashtable_foreach(&variable_table, free_variable); - tommy_hashtable_done(&variable_table); + tommy_hashtable_foreach(&symbol_table, free_variable); + tommy_hashtable_done(&symbol_table); return 0; } @@ -50,31 +51,46 @@ int eaxhla_deinit(void) { static int table_compare_unsigned(const void * arg, const void * obj) { - return *(const unsigned *) arg != ((const variable_t*)obj)->_hash; + return *(const unsigned *) arg != ((const symbol_t*)obj)->_hash; } -void add_variable(variable_t variable) { - static unsigned vid = 0; +void add_variable(symbol_t variable) { if (get_variable(variable.name)) { // XXX: this should say the varname, but this function does not know it // in fact this source file should not be reporting errors, // it should be returning an error and the parser should check. - issue_error("variable declared twice"); + issue_error("symbol '%s' declared twice", variable.name); return; } - variable._id = vid++; + variable._id = symbol_id++; // XXX this is cursed - variable_t * heap_variable = malloc(sizeof(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(&variable_table, + tommy_hashtable_insert(&symbol_table, &heap_variable->_node, heap_variable, heap_variable->_hash ); } +void add_procedure(symbol_t procedure) { + procedure._id = symbol_id++; + // XXX this is cursed + 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. */ @@ -161,16 +177,36 @@ char * make_scoped_name(const char * const scope, char * name) { return r; } -variable_t * get_variable(const char * const name) { +static +void * symbol_lookup(const char * const name) { unsigned lookup_hash = tommy_strhash_u32(0, name); - variable_t * r = tommy_hashtable_search(&variable_table, - table_compare_unsigned, - &lookup_hash, - lookup_hash - ); + 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, ...) { diff --git a/source/eaxhla.h b/source/eaxhla.h index e6f83fc..52bd7c0 100644 --- a/source/eaxhla.h +++ b/source/eaxhla.h @@ -4,21 +4,35 @@ #define WORD_SIZE_IN_BYTES (64/8) +typedef enum { + VARIABLE, + FUNCTION, +} symbol_type_t; + typedef struct { - union { - long value; - void * array_value; - }; - unsigned long long elements; - char * name; - int type; - unsigned _id; - unsigned _hash; - tommy_node _node; -} variable_t; + symbol_type_t symbol_type; + union { + struct { // VARIABLE + int type; + unsigned long long elements; + union { + long value; + void * array_value; + }; + }; + struct { // FUNCTION + void * unused; + }; + }; + char * name; + unsigned _id; + unsigned _hash; + tommy_node _node; +} symbol_t; -extern tommy_hashtable variable_table; +extern tommy_hashtable symbol_table; +// Used for naming variables constructed from literals extern unsigned long long anon_variable_counter; typedef struct { @@ -43,8 +57,12 @@ extern char * make_scoped_name(const char * const scope, char * name); extern int can_fit(int type, long long value); extern int validate_array_size(int size); -extern void add_variable(variable_t variable); -extern variable_t * get_variable(const char * const name); +extern void add_variable(symbol_t variable); +extern symbol_t * get_variable(const char * const name); + +//extern void add_function(symbol_t function); +extern symbol_t * get_function(const char * const name); +extern void add_procedure(symbol_t procedure); extern int type2size(int type); diff --git a/source/eaxhla.y b/source/eaxhla.y index f957c0f..e0cc6d3 100644 --- a/source/eaxhla.y +++ b/source/eaxhla.y @@ -29,7 +29,7 @@ unsigned long long len; void * data; } blobval; - variable_t varval; + symbol_t varval; cpuregister_t regval; } @@ -127,10 +127,17 @@ system_specifier: UNIX { system_type = UNIX; } ; // XXX: end procedure thing -function: function_head declaration_section MYBEGIN code END_PROCEDURE { scope = NULL; } +function: function_head declaration_section MYBEGIN code END_PROCEDURE { + scope = NULL; + append_instructions(RETN); + } ; -function_head: function_specifier PROCEDURE IDENTIFIER { scope = $3; } +function_head: function_specifier PROCEDURE IDENTIFIER { + scope = $3; + symbol_t procedure; + add_procedure(procedure); + } ; function_specifier: %empty @@ -207,7 +214,7 @@ type: S8 { $$ = S8; } immediate: LITERAL { $$.type = IMM; $$.value = $1; } | IDENTIFIER { char * varname = make_scoped_name(scope, $1); - variable_t * variable = get_variable(varname); + symbol_t * variable = get_variable(varname); $$.type = REL; $$.value = variable->_id; free(varname); @@ -227,7 +234,7 @@ value: artimetric_block | LITERAL | IDENTIFIER { char * varname = make_scoped_name(scope, $1); - variable_t * var = get_variable(varname); + symbol_t * var = get_variable(varname); $$ = var->value; free(var); } @@ -292,9 +299,9 @@ machine_code: %empty ; call: FASTCALL IDENTIFIER arguments { - //append_fastcall_begin(/**/); - //append_fastcall_arguments(); - append_fastcall_end(); + // XXX + symbol_t * function = get_function($2); + append_instructions(CALL, REL, function->_id); free($2); } ;