From: Brendan Hansen Date: Thu, 18 Jun 2020 00:09:13 +0000 (-0500) Subject: Lots of small changes; initial function calling X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=cc8dd5abb0c874b9015dcbf63dd11f5ac233637a;p=onyx.git Lots of small changes; initial function calling --- diff --git a/include/bh.h b/include/bh.h index 9d6ea6d0..687b51ab 100644 --- a/include/bh.h +++ b/include/bh.h @@ -535,12 +535,12 @@ void bh__arr_deleten(void **arr, i32 elemsize, i32 index, i32 numelems); //------------------------------------------------------------------------------------- -// HASH TABLE FUNCTIONS +// STRING HASH TABLE FUNCTIONS //------------------------------------------------------------------------------------- -#ifndef BH_NO_HASHTABLE +#ifndef BH_NO_TABLE #ifdef BH_DEFINE -u64 bh__hash_function(const char* str, i32 len, i32 mod) { +u64 bh__table_hash_function(const char* str, i32 len, i32 mod) { u64 hash = 5381; i32 c, l = 0; if (len == 0) len = ((u32) 1 << 31) - 1; // TODO: Verify this is right @@ -553,62 +553,62 @@ u64 bh__hash_function(const char* str, i32 len, i32 mod) { } #endif -typedef struct bh_hash_iterator { +typedef struct bh_table_iterator { ptr *tab, *endtab; i32 elemsize, arrlen; ptr entry; -} bh_hash_iterator; +} bh_table_iterator; -typedef struct bh__hash { +typedef struct bh__table { bh_allocator allocator; - u64 hash_size; // NOTE: u64 since padding will make it 8-bytes no matter what + u64 table_size; // NOTE: u64 since padding will make it 8-bytes no matter what ptr arrs[]; -} bh__hash; - -#define bh_hash(T) T* - -#ifdef BH_HASH_SIZE_SAFE - #define bh_hash_init(allocator_, tab, hs) bh__hash_init(allocator_, (bh__hash **)&(tab), hs) - #define bh_hash_free(tab) bh__hash_free((bh__hash **)&(tab)) - #define bh_hash_put(T, tab, key, value) (assert(sizeof(T) == sizeof(*(tab))), (*((T *) bh__hash_put((bh__hash *) tab, sizeof(T), key)) = (T) value)) - #define bh_hash_has(T, tab, key) (assert(sizeof(T) == sizeof(*(tab))), (bh__hash_has((bh__hash *) tab, sizeof(T), key))) - #define bh_hash_get(T, tab, key) (assert(sizeof(T) == sizeof(*(tab))), (*((T *) bh__hash_get((bh__hash *) tab, sizeof(T), key)))) - #define bh_hash_delete(T, tab, key) (assert(sizeof(T) == sizeof(*(tab))), bh__hash_delete((bh__hash *) tab, sizeof(T), key)) - #define bh_hash_clear(tab) (bh__hash_clear((bh__hash *) tab)) - - #define bh_hash_iter_setup(T, tab) (assert(sizeof(T) == sizeof(*(tab))), bh__hash_iter_setup((bh__hash *) tab, sizeof(T))) - #define bh_hash_iter_key(it) ((char *)(bh_pointer_add(it.entry, it.elemsize + sizeof(u16)))) - #define bh_hash_iter_value(T, it) (*(T *)it.entry) +} bh__table; + +#define bh_table(T) T* + +#ifdef BH_TABLE_SIZE_SAFE + #define bh_table_init(allocator_, tab, hs) bh__table_init(allocator_, (bh__table **)&(tab), hs) + #define bh_table_free(tab) bh__table_free((bh__table **)&(tab)) + #define bh_table_put(T, tab, key, value) (assert(sizeof(T) == sizeof(*(tab))), (*((T *) bh__table_put((bh__table *) tab, sizeof(T), key)) = (T) value)) + #define bh_table_has(T, tab, key) (assert(sizeof(T) == sizeof(*(tab))), (bh__table_has((bh__table *) tab, sizeof(T), key))) + #define bh_table_get(T, tab, key) (assert(sizeof(T) == sizeof(*(tab))), (*((T *) bh__table_get((bh__table *) tab, sizeof(T), key)))) + #define bh_table_delete(T, tab, key) (assert(sizeof(T) == sizeof(*(tab))), bh__table_delete((bh__table *) tab, sizeof(T), key)) + #define bh_table_clear(tab) (bh__table_clear((bh__table *) tab)) + + #define bh_table_iter_setup(T, tab) (assert(sizeof(T) == sizeof(*(tab))), bh__table_iter_setup((bh__table *) tab, sizeof(T))) + #define bh_table_iter_key(it) ((char *)(bh_pointer_add(it.entry, it.elemsize + sizeof(u16)))) + #define bh_table_iter_value(T, it) (*(T *)it.entry) #else - #define bh_hash_init(allocator_, tab, hs) bh__hash_init(allocator_, (bh__hash **)&(tab), hs) - #define bh_hash_free(tab) bh__hash_free((bh__hash **)&(tab)) - #define bh_hash_put(T, tab, key, value) (*((T *) bh__hash_put((bh__hash *) tab, sizeof(T), key)) = value) - #define bh_hash_has(T, tab, key) (bh__hash_has((bh__hash *) tab, sizeof(T), key)) - #define bh_hash_get(T, tab, key) (*((T *) bh__hash_get((bh__hash *) tab, sizeof(T), key))) - #define bh_hash_delete(T, tab, key) (bh__hash_delete((bh__hash *) tab, sizeof(T), key)) - #define bh_hash_clear(tab) (bh__hash_clear((bh__hash *) tab)) - - #define bh_hash_iter_setup(T, tab) (bh__hash_iter_setup((bh__hash *) tab, sizeof(T))) - #define bh_hash_iter_key(it) ((char *)(bh_pointer_add(it.entry, it.elemsize + sizeof(u16)))) - #define bh_hash_iter_value(T, it) (*(T *)it.entry) + #define bh_table_init(allocator_, tab, hs) bh__table_init(allocator_, (bh__table **)&(tab), hs) + #define bh_table_free(tab) bh__table_free((bh__table **)&(tab)) + #define bh_table_put(T, tab, key, value) (*((T *) bh__table_put((bh__table *) tab, sizeof(T), key)) = value) + #define bh_table_has(T, tab, key) (bh__table_has((bh__table *) tab, sizeof(T), key)) + #define bh_table_get(T, tab, key) (*((T *) bh__table_get((bh__table *) tab, sizeof(T), key))) + #define bh_table_delete(T, tab, key) (bh__table_delete((bh__table *) tab, sizeof(T), key)) + #define bh_table_clear(tab) (bh__table_clear((bh__table *) tab)) + + #define bh_table_iter_setup(T, tab) (bh__table_iter_setup((bh__table *) tab, sizeof(T))) + #define bh_table_iter_key(it) ((char *)(bh_pointer_add(it.entry, it.elemsize + sizeof(u16)))) + #define bh_table_iter_value(T, it) (*(T *)it.entry) #endif -#define bh_hash_each_start(T, table) { \ - bh_hash_iterator it = bh_hash_iter_setup(T, (table)); \ - while (bh_hash_iter_next(&it)) { \ - const char* key = bh_hash_iter_key(it); \ - T value = bh_hash_iter_value(T, it); -#define bh_hash_each_end } } - -b32 bh__hash_init(bh_allocator allocator, bh__hash **table, i32 hash_size); -b32 bh__hash_free(bh__hash **table); -ptr bh__hash_put(bh__hash *table, i32 elemsize, char *key); -b32 bh__hash_has(bh__hash *table, i32 elemsize, char *key); -ptr bh__hash_get(bh__hash *table, i32 elemsize, char *key); -void bh__hash_delete(bh__hash *table, i32 elemsize, char *key); -void bh__hash_clear(bh__hash *table); -bh_hash_iterator bh__hash_iter_setup(bh__hash *table, i32 elemsize); -b32 bh_hash_iter_next(bh_hash_iterator* it); +#define bh_table_each_start(T, table) { \ + bh_table_iterator it = bh_table_iter_setup(T, (table)); \ + while (bh_table_iter_next(&it)) { \ + const char* key = bh_table_iter_key(it); \ + T value = bh_table_iter_value(T, it); +#define bh_table_each_end } } + +b32 bh__table_init(bh_allocator allocator, bh__table **table, i32 table_size); +b32 bh__table_free(bh__table **table); +ptr bh__table_put(bh__table *table, i32 elemsize, char *key); +b32 bh__table_has(bh__table *table, i32 elemsize, char *key); +ptr bh__table_get(bh__table *table, i32 elemsize, char *key); +void bh__table_delete(bh__table *table, i32 elemsize, char *key); +void bh__table_clear(bh__table *table); +bh_table_iterator bh__table_iter_setup(bh__table *table, i32 elemsize); +b32 bh_table_iter_next(bh_table_iterator* it); #endif @@ -616,6 +616,59 @@ b32 bh_hash_iter_next(bh_hash_iterator* it); + + + + +//------------------------------------------------------------------------------- +// IMAP (integer to integer map) +//------------------------------------------------------------------------------- +#ifndef BH_NO_IMAP + +typedef u64 bh_imap_key_t; + +typedef struct bh__imap_entry { + bh_imap_key_t key, value; +} bh__imap_entry; + +typedef struct bh_imap { + bh_allocator allocator; + bh_arr(bh__imap_entry) keys; +} bh_imap; + + +void bh_imap_init(bh_imap* imap, bh_allocator alloc); +void bh_imap_free(bh_imap* imap); +void bh_imap_put(bh_imap* imap, bh_imap_key_t key, bh_imap_key_t value); +b32 bh_imap_has(bh_imap* imap, bh_imap_key_t key); +bh_imap_key_t bh_imap_get(bh_imap* imap, bh_imap_key_t key); +void bh_imap_delete(bh_imap* imap, bh_imap_key_t key); + +#ifdef BH_DEFINE +#endif // BH_DEFINE + + +#endif + + + + + + + + + + + + + + + + + + + + //------------------------------------------------------------------------------- // OTHER COMMON DATA STRUCTURES @@ -1608,6 +1661,7 @@ void bh__arr_insertn(void **arr, i32 elemsize, i32 index, i32 numelems) { bh__arr* arrptr = bh__arrhead(*arr); if (!bh__arr_grow(bh_arr_allocator(arr), arr, elemsize, arrptr->length + numelems)) return; // Fail case + arrptr = bh__arrhead(*arr); memmove( (char *)(*arr) + elemsize * (index + numelems), (char *)(*arr) + elemsize * index, @@ -1633,26 +1687,26 @@ void bh__arr_insertn(void **arr, i32 elemsize, i32 index, i32 numelems) { //------------------------------------------------------------------------------------- -// HASHTABLE IMPLEMENTATION +// TABLE IMPLEMENTATION //------------------------------------------------------------------------------------- -#ifndef BH_NO_HASHTABLE +#ifndef BH_NO_TABLE -b32 bh__hash_init(bh_allocator allocator, bh__hash **table, i32 hash_size) { - *table = bh_alloc(allocator, sizeof(bh__hash) + sizeof(ptr) * hash_size); +b32 bh__table_init(bh_allocator allocator, bh__table **table, i32 table_size) { + *table = bh_alloc(allocator, sizeof(bh__table) + sizeof(ptr) * table_size); if (*table == NULL) return 0; (*table)->allocator = allocator; - (*table)->hash_size = hash_size; + (*table)->table_size = table_size; - for (i32 i = 0; i < hash_size; i++) { + for (i32 i = 0; i < table_size; i++) { (*table)->arrs[i] = NULL; } return 1; } -b32 bh__hash_free(bh__hash **table) { - for (i32 i = 0; i < (*table)->hash_size; i++) { +b32 bh__table_free(bh__table **table) { + for (i32 i = 0; i < (*table)->table_size; i++) { if ((*table)->arrs[i] != NULL) { bh_arr_free((*table)->arrs[i]); } @@ -1663,10 +1717,10 @@ b32 bh__hash_free(bh__hash **table) { } // Assumes NULL terminated string for key -ptr bh__hash_put(bh__hash *table, i32 elemsize, char *key) { +ptr bh__table_put(bh__table *table, i32 elemsize, char *key) { elemsize += (elemsize & 1); - u64 index = bh__hash_function(key, 0, table->hash_size); + u64 index = bh__table_hash_function(key, 0, table->table_size); u8 arr_was_new = 0; ptr arrptr = table->arrs[index]; @@ -1716,10 +1770,10 @@ found_matching: return bh_pointer_add(arrptr, -(sizeof(u16) + elemsize)); } -b32 bh__hash_has(bh__hash *table, i32 elemsize, char *key) { +b32 bh__table_has(bh__table *table, i32 elemsize, char *key) { elemsize += (elemsize & 1); - u64 index = bh__hash_function(key, 0, table->hash_size); + u64 index = bh__table_hash_function(key, 0, table->table_size); ptr arrptr = table->arrs[index]; if (arrptr == NULL) return 0; @@ -1739,10 +1793,10 @@ b32 bh__hash_has(bh__hash *table, i32 elemsize, char *key) { return 0; } -ptr bh__hash_get(bh__hash *table, i32 elemsize, char *key) { +ptr bh__table_get(bh__table *table, i32 elemsize, char *key) { elemsize += (elemsize & 1); - u64 index = bh__hash_function(key, 0, table->hash_size); + u64 index = bh__table_hash_function(key, 0, table->table_size); ptr arrptr = table->arrs[index]; if (arrptr == NULL) return 0; @@ -1764,10 +1818,10 @@ ptr bh__hash_get(bh__hash *table, i32 elemsize, char *key) { return NULL; } -void bh__hash_delete(bh__hash *table, i32 elemsize, char *key) { +void bh__table_delete(bh__table *table, i32 elemsize, char *key) { elemsize += (elemsize & 1); - u64 index = bh__hash_function(key, 0, table->hash_size); + u64 index = bh__table_hash_function(key, 0, table->table_size); ptr arrptr = table->arrs[index], walker; if (arrptr == NULL) return; // Didn't exist @@ -1801,8 +1855,8 @@ found_matching: (*(u64 *) arrptr)--; } -void bh__hash_clear(bh__hash *table) { - for (i32 i = 0; i < table->hash_size; i++) { +void bh__table_clear(bh__table *table) { + for (i32 i = 0; i < table->table_size; i++) { if (table->arrs[i] != NULL) { // NOTE: Set length property to 0 *((u64 *) table->arrs[i]) = 0; @@ -1811,19 +1865,19 @@ void bh__hash_clear(bh__hash *table) { } } -bh_hash_iterator bh__hash_iter_setup(bh__hash *table, i32 elemsize) { +bh_table_iterator bh__table_iter_setup(bh__table *table, i32 elemsize) { elemsize += (elemsize & 1); - bh_hash_iterator it = { + bh_table_iterator it = { .tab = table->arrs, - .endtab = table->arrs + table->hash_size, + .endtab = table->arrs + table->table_size, .elemsize = elemsize, .entry = NULL }; return it; } -b32 bh_hash_iter_next(bh_hash_iterator* it) { +b32 bh_table_iter_next(bh_table_iterator* it) { if (it->tab == NULL) return 0; if (it->entry != NULL) { @@ -1858,6 +1912,88 @@ step_to_next: #endif // ifndef BH_NO_HASHTABLE + + +//------------------------------------------------------------------------------------- +// IMAP IMPLEMENTATION +//------------------------------------------------------------------------------------- +#ifndef BH_NO_IMAP +void bh_imap_init(bh_imap* imap, bh_allocator alloc) { + imap->allocator = alloc; + imap->keys = NULL; + + bh_arr_new(alloc, imap->keys, 4); +} + +void bh_imap_free(bh_imap* imap) { + bh_arr_free(imap->keys); + imap->keys = NULL; +} + +b32 bh__imap_get_index(bh_imap* imap, bh_imap_key_t key, i32* pos) { + i32 low = 0; + i32 high = bh_arr_length(imap->keys); + i32 middle = 0; + bh__imap_entry tmp; + + while (high > low) { + middle = (high + low) / 2; + tmp = imap->keys[middle]; + + if (tmp.key == key) { + if (pos) *pos = middle; + return 1; + } else if (tmp.key < key) { + low = middle + 1; + middle++; + } else if (tmp.key > key) { + high = middle; + } + } + + if (pos) *pos = middle; + return 0; +} + +void bh_imap_put(bh_imap* imap, bh_imap_key_t key, bh_imap_key_t value) { + i32 middle = 0; + b32 found_existing = bh__imap_get_index(imap, key, &middle); + + if (found_existing) { + imap->keys[middle].value = value; + } else { + bh_arr_insertn(imap->keys, middle, 1); + imap->keys[middle].key = key; + imap->keys[middle].value = value; + } +} + +b32 bh_imap_has(bh_imap* imap, bh_imap_key_t key) { + return bh__imap_get_index(imap, key, NULL); +} + +bh_imap_key_t bh_imap_get(bh_imap* imap, bh_imap_key_t key) { + i32 middle = 0; + b32 found_existing = bh__imap_get_index(imap, key, &middle); + + if (found_existing) { + return imap->keys[middle].value; + } else { + return 0; + } +} + +void bh_imap_delete(bh_imap* imap, bh_imap_key_t key) { + i32 middle = 0; + b32 found_existing = bh__imap_get_index(imap, key, &middle); + + if (found_existing) { + bh_arr_deleten(imap->keys, middle, 1); + } +} + +#endif // ifndef BH_NO_IMAP + #endif // ifdef BH_DEFINE #endif // ifndef BH_H diff --git a/include/onyxparser.h b/include/onyxparser.h index 631fc092..47786d40 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -1,7 +1,6 @@ #ifndef ONYXPARSER_H #define ONYXPARSER_H -#define BH_NO_STRING #include "bh.h" #include "onyxlex.h" @@ -27,7 +26,7 @@ typedef struct OnyxParser { // NOTE: A table of the current identifiers in the current scope. // If the identifier doesn't at the time of parsing, it is an error. // Cleared at the end of a block. - bh_hash(OnyxAstNode*) identifiers; + bh_table(OnyxAstNode*) identifiers; OnyxAstNodeScope *curr_scope; OnyxMessages *msgs; diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 4f7cf685..52e0c74a 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -1,7 +1,6 @@ #ifndef ONYXWASM_H #define ONYXWASM_H -#define BH_NO_STRING #include "bh.h" #include "onyxparser.h" @@ -266,20 +265,22 @@ typedef struct OnyxWasmModule { bh_allocator allocator; // NOTE: Mapping to local indicies currently in scope. - bh_hash(i32) local_map; + bh_table(i32) local_map; // NOTE: Used internally as a map from strings that represent function types, // 0x7f 0x7f : 0x7f ( (i32, i32) -> i32 ) // to the function type index if it has been created. - bh_hash(i32) type_map; + bh_table(i32) type_map; i32 next_type_idx; // NOTE: This have to be pointers because the type is variadic in size bh_arr(WasmFuncType*) functypes; bh_arr(WasmFunc) funcs; + // NOTE: Maps from ast node pointers to the function index + bh_imap func_map; i32 next_func_idx; - bh_hash(WasmExport) exports; + bh_table(WasmExport) exports; i32 export_count; } OnyxWasmModule; diff --git a/onyx b/onyx index 54fb7e20..cbaebf60 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/minimal.onyx b/progs/minimal.onyx index 79fa4857..e19b7ed2 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -1,13 +1,12 @@ - -export add :: proc (a i32, b i32) -> i32 { - return a + b; +foo :: proc () -> i32 { + return 10 as i32; } -export foo :: proc (foo i32, bar i32) -> i32 { - return 10 as i32; +add :: proc (a i32, b i32) -> i32 { + return a + b; } -export diff_square :: proc (a i32, b i32) -> i32 { +diff_square :: proc (a i32, b i32) -> i32 { // Typechecked c := a - b; // Mutable d :: a + b; // Constant @@ -15,6 +14,12 @@ export diff_square :: proc (a i32, b i32) -> i32 { return (c * d) as i32; } +export do_stuff :: proc () -> i32 { + res := diff_square((2 + 3) as i32, (4 + 5) as i32); + res = res + foo(); + return res; +} + export main :: proc () { - add(2, 3); + output :: do_stuff(); } diff --git a/src/onyx.c b/src/onyx.c index c55a7b31..5a07b655 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -1,4 +1,3 @@ -#define BH_NO_STRING // #define BH_DEBUG #define BH_DEFINE #include "bh.h" @@ -52,9 +51,9 @@ int main(int argc, char *argv[]) { onyx_message_print(&msgs); goto main_exit; } else { - // onyx_ast_print(program, 0); - bh_printf("\nNo errors.\n"); - } + onyx_ast_print(program, 0); + bh_printf("\nNo errors.\n"); + } // NOTE: 4th: Generate a WASM module from the parse tree and // write it to a file. diff --git a/src/onyxlex.c b/src/onyxlex.c index 0a4c3035..9e9a0104 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -57,8 +57,8 @@ static const char* onyx_token_type_names[] = { }; #ifndef LITERAL_TOKEN -#define LITERAL_TOKEN(token, token_type) \ - if (token_lit(tokenizer, &tk, token, token_type)) goto token_parsed; +#define LITERAL_TOKEN(token, word, token_type) \ + if (token_lit(tokenizer, &tk, token, word, token_type)) goto token_parsed; #endif #ifndef INCREMENT_CURR_TOKEN @@ -71,9 +71,12 @@ static const char* onyx_token_type_names[] = { } #endif -static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, OnyxTokenType type) { +static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_word, OnyxTokenType type) { i64 len = chars_match(tokenizer->curr, lit); if (len > 0) { + if (is_word && char_is_alphanum(*(tokenizer->curr + len)) || charset_contains("_$", *(tokenizer->curr + len))) + return 0; + tk->type = type; tk->token = tokenizer->curr; tk->length = len; @@ -131,45 +134,45 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { goto token_parsed; } - LITERAL_TOKEN("struct", TOKEN_TYPE_KEYWORD_STRUCT); - LITERAL_TOKEN("export", TOKEN_TYPE_KEYWORD_EXPORT); - LITERAL_TOKEN("use", TOKEN_TYPE_KEYWORD_USE); - LITERAL_TOKEN("if", TOKEN_TYPE_KEYWORD_IF); - LITERAL_TOKEN("else", TOKEN_TYPE_KEYWORD_ELSE); - LITERAL_TOKEN("foreign", TOKEN_TYPE_KEYWORD_FOREIGN); - LITERAL_TOKEN("for", TOKEN_TYPE_KEYWORD_FOR); - LITERAL_TOKEN("return", TOKEN_TYPE_KEYWORD_RETURN); - LITERAL_TOKEN("do", TOKEN_TYPE_KEYWORD_DO); - LITERAL_TOKEN("proc", TOKEN_TYPE_KEYWORD_PROC); - LITERAL_TOKEN("global", TOKEN_TYPE_KEYWORD_GLOBAL); - LITERAL_TOKEN("as", TOKEN_TYPE_KEYWORD_CAST); - LITERAL_TOKEN("->", TOKEN_TYPE_RIGHT_ARROW); - LITERAL_TOKEN("<-", TOKEN_TYPE_RIGHT_ARROW); - LITERAL_TOKEN("<=", TOKEN_TYPE_SYM_LESS_EQUAL); - LITERAL_TOKEN(">=", TOKEN_TYPE_SYM_GREATER_EQUAL); - LITERAL_TOKEN("(", TOKEN_TYPE_OPEN_PAREN); - LITERAL_TOKEN(")", TOKEN_TYPE_CLOSE_PAREN); - LITERAL_TOKEN("{", TOKEN_TYPE_OPEN_BRACE); - LITERAL_TOKEN("}", TOKEN_TYPE_CLOSE_BRACE); - LITERAL_TOKEN("[", TOKEN_TYPE_OPEN_BRACKET); - LITERAL_TOKEN("]", TOKEN_TYPE_CLOSE_BRACKET); - LITERAL_TOKEN("+", TOKEN_TYPE_SYM_PLUS); - LITERAL_TOKEN("-", TOKEN_TYPE_SYM_MINUS); - LITERAL_TOKEN("*", TOKEN_TYPE_SYM_STAR); - LITERAL_TOKEN(".", TOKEN_TYPE_SYM_DOT); - LITERAL_TOKEN("%", TOKEN_TYPE_SYM_PERCENT); - LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); - LITERAL_TOKEN("\\", TOKEN_TYPE_SYM_BSLASH); - LITERAL_TOKEN(":", TOKEN_TYPE_SYM_COLON); - LITERAL_TOKEN(";", TOKEN_TYPE_SYM_SEMICOLON); - LITERAL_TOKEN(",", TOKEN_TYPE_SYM_COMMA); - LITERAL_TOKEN(">", TOKEN_TYPE_SYM_GREATER); - LITERAL_TOKEN("<", TOKEN_TYPE_SYM_LESS); - LITERAL_TOKEN("=", TOKEN_TYPE_SYM_EQUALS); - LITERAL_TOKEN("~", TOKEN_TYPE_SYM_TILDE); - LITERAL_TOKEN("!", TOKEN_TYPE_SYM_BANG); - LITERAL_TOKEN("^", TOKEN_TYPE_SYM_CARET); - LITERAL_TOKEN("&", TOKEN_TYPE_SYM_AMPERSAND); + LITERAL_TOKEN("struct", 1, TOKEN_TYPE_KEYWORD_STRUCT); + LITERAL_TOKEN("export", 1, TOKEN_TYPE_KEYWORD_EXPORT); + LITERAL_TOKEN("use", 1, TOKEN_TYPE_KEYWORD_USE); + LITERAL_TOKEN("if", 1, TOKEN_TYPE_KEYWORD_IF); + LITERAL_TOKEN("else", 1, TOKEN_TYPE_KEYWORD_ELSE); + LITERAL_TOKEN("foreign", 1, TOKEN_TYPE_KEYWORD_FOREIGN); + LITERAL_TOKEN("for", 1, TOKEN_TYPE_KEYWORD_FOR); + LITERAL_TOKEN("return", 1, TOKEN_TYPE_KEYWORD_RETURN); + LITERAL_TOKEN("do", 1, TOKEN_TYPE_KEYWORD_DO); + LITERAL_TOKEN("proc", 1, TOKEN_TYPE_KEYWORD_PROC); + LITERAL_TOKEN("global", 1, TOKEN_TYPE_KEYWORD_GLOBAL); + LITERAL_TOKEN("as", 1, TOKEN_TYPE_KEYWORD_CAST); + LITERAL_TOKEN("->", 0, TOKEN_TYPE_RIGHT_ARROW); + LITERAL_TOKEN("<-", 0, TOKEN_TYPE_RIGHT_ARROW); + LITERAL_TOKEN("<=", 0, TOKEN_TYPE_SYM_LESS_EQUAL); + LITERAL_TOKEN(">=", 0, TOKEN_TYPE_SYM_GREATER_EQUAL); + LITERAL_TOKEN("(", 0, TOKEN_TYPE_OPEN_PAREN); + LITERAL_TOKEN(")", 0, TOKEN_TYPE_CLOSE_PAREN); + LITERAL_TOKEN("{", 0, TOKEN_TYPE_OPEN_BRACE); + LITERAL_TOKEN("}", 0, TOKEN_TYPE_CLOSE_BRACE); + LITERAL_TOKEN("[", 0, TOKEN_TYPE_OPEN_BRACKET); + LITERAL_TOKEN("]", 0, TOKEN_TYPE_CLOSE_BRACKET); + LITERAL_TOKEN("+", 0, TOKEN_TYPE_SYM_PLUS); + LITERAL_TOKEN("-", 0, TOKEN_TYPE_SYM_MINUS); + LITERAL_TOKEN("*", 0, TOKEN_TYPE_SYM_STAR); + LITERAL_TOKEN(".", 0, TOKEN_TYPE_SYM_DOT); + LITERAL_TOKEN("%", 0, TOKEN_TYPE_SYM_PERCENT); + LITERAL_TOKEN("/", 0, TOKEN_TYPE_SYM_FSLASH); + LITERAL_TOKEN("\\", 0, TOKEN_TYPE_SYM_BSLASH); + LITERAL_TOKEN(":", 0, TOKEN_TYPE_SYM_COLON); + LITERAL_TOKEN(";", 0, TOKEN_TYPE_SYM_SEMICOLON); + LITERAL_TOKEN(",", 0, TOKEN_TYPE_SYM_COMMA); + LITERAL_TOKEN(">", 0, TOKEN_TYPE_SYM_GREATER); + LITERAL_TOKEN("<", 0, TOKEN_TYPE_SYM_LESS); + LITERAL_TOKEN("=", 0, TOKEN_TYPE_SYM_EQUALS); + LITERAL_TOKEN("~", 0, TOKEN_TYPE_SYM_TILDE); + LITERAL_TOKEN("!", 0, TOKEN_TYPE_SYM_BANG); + LITERAL_TOKEN("^", 0, TOKEN_TYPE_SYM_CARET); + LITERAL_TOKEN("&", 0, TOKEN_TYPE_SYM_AMPERSAND); // Symbols if (char_is_alpha(*tk.token)) { diff --git a/src/onyxparser.c b/src/onyxparser.c index dff9dbba..b2fa3684 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -153,8 +153,8 @@ static OnyxAstNode* lookup_identifier(OnyxParser* parser, OnyxToken* token) { OnyxAstNode* ident = NULL; onyx_token_null_toggle(*token); - if (bh_hash_has(OnyxAstNode*, parser->identifiers, token->token)) { - ident = bh_hash_get(OnyxAstNode*, parser->identifiers, token->token); + if (bh_table_has(OnyxAstNode*, parser->identifiers, token->token)) { + ident = bh_table_get(OnyxAstNode*, parser->identifiers, token->token); } onyx_token_null_toggle(*token); @@ -170,11 +170,11 @@ static void insert_identifier(OnyxParser* parser, OnyxAstNode* ident, b32 is_loc } onyx_token_null_toggle(*local->token); - if (bh_hash_has(OnyxAstNode*, parser->identifiers, local->token->token)) { - local->shadowed = bh_hash_get(OnyxAstNode*, parser->identifiers, local->token->token); + if (bh_table_has(OnyxAstNode*, parser->identifiers, local->token->token)) { + local->shadowed = bh_table_get(OnyxAstNode*, parser->identifiers, local->token->token); } - bh_hash_put(OnyxAstNodeLocal*, parser->identifiers, local->token->token, local); + bh_table_put(OnyxAstNodeLocal*, parser->identifiers, local->token->token, local); onyx_token_null_toggle(*local->token); } @@ -183,9 +183,9 @@ static void remove_identifier(OnyxParser* parser, OnyxAstNode* ident) { onyx_token_null_toggle(*local->token); if (local->shadowed) { - bh_hash_put(OnyxAstNode*, parser->identifiers, local->token->token, local->shadowed); + bh_table_put(OnyxAstNode*, parser->identifiers, local->token->token, local->shadowed); } else { - bh_hash_delete(OnyxAstNode*, parser->identifiers, local->token->token); + bh_table_delete(OnyxAstNode*, parser->identifiers, local->token->token); } onyx_token_null_toggle(*local->token); } @@ -221,6 +221,10 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) { OnyxAstNodeCall* call_node = (OnyxAstNodeCall *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CALL); call_node->callee = sym_node; + // NOTE: Return type is stored on function definition's type + // This may have to change if we want multiple returns + call_node->type = sym_node->type; + OnyxAstNode** prev = &call_node->arguments; OnyxAstNode* curr = NULL; while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) { @@ -301,6 +305,11 @@ static OnyxAstNode* parse_bin_op(OnyxParser* parser, OnyxAstNode* left) { bin_op->left = left; bin_op->right = right; bin_op->type = left->type; + + if ((left->flags & ONYX_AST_FLAG_COMPTIME) != 0 && (right->flags & ONYX_AST_FLAG_COMPTIME) != 0) { + bin_op->flags |= ONYX_AST_FLAG_COMPTIME; + } + return bin_op; } @@ -561,10 +570,10 @@ static OnyxTypeInfo* parse_type(OnyxParser* parser) { onyx_token_null_toggle(*symbol); - if (!bh_hash_has(OnyxAstNode*, parser->identifiers, symbol->token)) { + if (!bh_table_has(OnyxAstNode*, parser->identifiers, symbol->token)) { onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->token); } else { - OnyxAstNode* type_info_node = bh_hash_get(OnyxAstNode*, parser->identifiers, symbol->token); + OnyxAstNode* type_info_node = bh_table_get(OnyxAstNode*, parser->identifiers, symbol->token); if (type_info_node->kind == ONYX_AST_NODE_KIND_TYPE) { type_info = type_info_node->type; @@ -676,8 +685,8 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { onyx_token_null_toggle(*symbol); - if (!bh_hash_has(OnyxAstNode *, parser->identifiers, symbol->token)) { - bh_hash_put(OnyxAstNode *, parser->identifiers, symbol->token, (OnyxAstNode *) func_def); + if (!bh_table_has(OnyxAstNode *, parser->identifiers, symbol->token)) { + bh_table_put(OnyxAstNode *, parser->identifiers, symbol->token, (OnyxAstNode *) func_def); } else { onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, @@ -735,13 +744,13 @@ OnyxAstNode* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind) {\ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs) { OnyxParser parser; - bh_hash_init(bh_heap_allocator(), parser.identifiers, 61); + bh_table_init(bh_heap_allocator(), parser.identifiers, 61); OnyxTypeInfo* it = &builtin_types[0]; while (it->kind != 0xffffffff) { OnyxAstNode* tmp = onyx_ast_node_new(alloc, ONYX_AST_NODE_KIND_TYPE); tmp->type = it; - bh_hash_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp); + bh_table_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp); it++; } @@ -756,7 +765,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, Onyx } void onyx_parser_free(OnyxParser* parser) { - bh_hash_free(parser->identifiers); + bh_table_free(parser->identifiers); } OnyxAstNode* onyx_parse(OnyxParser *parser) { diff --git a/src/onyxutils.c b/src/onyxutils.c index ba50b4ee..74aecf9d 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -98,6 +98,9 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { case ONYX_AST_NODE_KIND_LITERAL: { bh_printf("%b", node->token->token, node->token->length); + if (node->next) { + onyx_ast_print(node->next, indent); + } break; } @@ -110,6 +113,16 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { break; } + case ONYX_AST_NODE_KIND_CALL: { + OnyxAstNodeCall* call = &node->as_call; + bh_printf("%b", call->callee->token->token, call->callee->token->length); + onyx_ast_print(call->arguments, indent + 1); + if (call->next) { + onyx_ast_print(call->next, indent); + } + break; + } + default: { onyx_ast_print(node->left, indent + 1); onyx_ast_print(node->right, indent + 1); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 2dcff896..e30fae20 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -249,7 +249,7 @@ static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval) { if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) { onyx_token_null_toggle(*lval->token); - i32 localidx = bh_hash_get(i32, mod->local_map, lval->token->token); + i32 localidx = bh_table_get(i32, mod->local_map, lval->token->token); onyx_token_null_toggle(*lval->token); bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_SET, localidx })); @@ -339,7 +339,7 @@ static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* case ONYX_AST_NODE_KIND_PARAM: { onyx_token_null_toggle(*expr->token); - i32 localidx = bh_hash_get(i32, mod->local_map, expr->token->token); + i32 localidx = bh_table_get(i32, mod->local_map, expr->token->token); onyx_token_null_toggle(*expr->token); bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_GET, localidx })); @@ -360,7 +360,14 @@ static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* case ONYX_AST_NODE_KIND_CALL: { - DEBUG_HERE; + OnyxAstNodeCall* call = &expr->as_call; + forll (OnyxAstNode, arg, call->arguments, next) { + process_expression(mod, func, arg); + } + + i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) call->callee); + bh_arr_push(func->code, ((WasmInstruction){ WI_CALL, func_idx })); + break; } @@ -442,8 +449,8 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* *t = '\0'; i32 type_idx = 0; - if (bh_hash_has(i32, mod->type_map, type_repr_buf)) { - type_idx = bh_hash_get(i32, mod->type_map, type_repr_buf); + if (bh_table_has(i32, mod->type_map, type_repr_buf)) { + type_idx = bh_table_get(i32, mod->type_map, type_repr_buf); } else { // NOTE: Make a new type // TODO: Ensure that this isn't going to break things because of alignment @@ -456,7 +463,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* bh_arr_push(mod->functypes, type); - bh_hash_put(i32, mod->type_map, type_repr_buf, mod->next_type_idx); + bh_table_put(i32, mod->type_map, type_repr_buf, mod->next_type_idx); type_idx = mod->next_type_idx; mod->next_type_idx++; } @@ -472,6 +479,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* .code = NULL, }; i32 func_idx = mod->next_func_idx++; + bh_imap_put(&mod->func_map, (u64) fd, func_idx); if (fd->flags & ONYX_AST_FLAG_EXPORTED) { onyx_token_null_toggle(*fd->token); @@ -480,7 +488,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* .kind = WASM_EXPORT_FUNCTION, .idx = func_idx, }; - bh_hash_put(WasmExport, mod->exports, fd->token->token, wasm_export); + bh_table_put(WasmExport, mod->exports, fd->token->token, wasm_export); mod->export_count++; onyx_token_null_toggle(*fd->token); @@ -493,7 +501,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* i32 localidx = 0; forll (OnyxAstNodeParam, param, fd->params, next) { onyx_token_null_toggle(*param->token); - bh_hash_put(i32, mod->local_map, param->token->token, localidx++); + bh_table_put(i32, mod->local_map, param->token->token, localidx++); onyx_token_null_toggle(*param->token); } @@ -506,7 +514,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* forll (OnyxAstNodeLocal, local, fd->body->scope->last_local, prev_local) { if (onyx_type_to_wasm_type(local->type) == local_types[ti]) { onyx_token_null_toggle(*local->token); - bh_hash_put(i32, mod->local_map, local->token->token, localidx++); + bh_table_put(i32, mod->local_map, local->token->token, localidx++); onyx_token_null_toggle(*local->token); (*count)++; @@ -522,7 +530,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* bh_arr_push(mod->funcs, wasm_func); // NOTE: Clear the local map on exit of generating this function - bh_hash_clear(mod->local_map); + bh_table_clear(mod->local_map); } OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program) { @@ -543,9 +551,11 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra bh_arr_new(alloc, module.functypes, 4); bh_arr_new(alloc, module.funcs, 4); - bh_hash_init(bh_heap_allocator(), module.local_map, 61); - bh_hash_init(bh_heap_allocator(), module.type_map, 61); - bh_hash_init(bh_heap_allocator(), module.exports, 61); + bh_table_init(bh_heap_allocator(), module.local_map, 61); + bh_table_init(bh_heap_allocator(), module.type_map, 61); + bh_table_init(bh_heap_allocator(), module.exports, 61); + + bh_imap_init(&module.func_map, bh_heap_allocator()); OnyxAstNode* walker = program; while (walker) { @@ -565,9 +575,9 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra void onyx_wasm_module_free(OnyxWasmModule* module) { bh_arr_free(module->functypes); bh_arr_free(module->funcs); - bh_hash_free(module->local_map); - bh_hash_free(module->type_map); - bh_hash_free(module->exports); + bh_table_free(module->local_map); + bh_table_free(module->type_map); + bh_table_free(module->exports); } @@ -690,7 +700,7 @@ static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) { bh_buffer_append(&vec_buff, leb, leb_len); i32 key_len = 0; - bh_hash_each_start(WasmExport, module->exports); + bh_table_each_start(WasmExport, module->exports); key_len = strlen(key); leb = uint_to_uleb128((u64) key_len, &leb_len); bh_buffer_append(&vec_buff, leb, leb_len); @@ -699,7 +709,7 @@ static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) { bh_buffer_write_byte(&vec_buff, (u8) (value.kind)); leb = uint_to_uleb128((u64) value.idx, &leb_len); bh_buffer_append(&vec_buff, leb, leb_len); - bh_hash_each_end; + bh_table_each_end; leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len); bh_buffer_append(buff, leb, leb_len); @@ -714,14 +724,14 @@ static i32 output_startsection(OnyxWasmModule* module, bh_buffer* buff) { i32 prev_len = buff->length; i32 start_idx = -1; - bh_hash_each_start(WasmExport, module->exports) { + bh_table_each_start(WasmExport, module->exports) { if (value.kind == WASM_EXPORT_FUNCTION) { if (strncmp("main", key, 5) == 0) { start_idx = value.idx; break; } } - } bh_hash_each_end; + } bh_table_each_end; if (start_idx != -1) { bh_buffer_write_byte(buff, WASM_SECTION_ID_START); @@ -799,6 +809,12 @@ static void output_instruction(WasmInstruction* instr, bh_buffer* buff) { bh_buffer_write_byte(buff, 0); // TODO: Actually output the literal break; + case WI_CALL: + bh_buffer_write_byte(buff, (u8) instr->type); + leb = uint_to_uleb128((u64) instr->data.i1, &leb_len); + bh_buffer_append(buff, leb, leb_len); + break; + default: bh_buffer_write_byte(buff, (u8) instr->type); }