//-------------------------------------------------------------------------------------
-// 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
}
#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
+
+
+
+
+//-------------------------------------------------------------------------------
+// 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
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,
//-------------------------------------------------------------------------------------
-// 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]);
}
}
// 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];
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;
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;
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
(*(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;
}
}
-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) {
#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
#ifndef ONYXPARSER_H
#define ONYXPARSER_H
-#define BH_NO_STRING
#include "bh.h"
#include "onyxlex.h"
// 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;
#ifndef ONYXWASM_H
#define ONYXWASM_H
-#define BH_NO_STRING
#include "bh.h"
#include "onyxparser.h"
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;
-
-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
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();
}
-#define BH_NO_STRING
// #define BH_DEBUG
#define BH_DEFINE
#include "bh.h"
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.
};
#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
}
#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;
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)) {
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);
}
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);
}
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);
}
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) {
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;
}
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;
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,
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++;
}
}
void onyx_parser_free(OnyxParser* parser) {
- bh_hash_free(parser->identifiers);
+ bh_table_free(parser->identifiers);
}
OnyxAstNode* onyx_parse(OnyxParser *parser) {
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;
}
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);
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 }));
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 }));
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;
}
*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
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++;
}
.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);
.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);
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);
}
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)++;
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) {
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) {
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);
}
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);
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);
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);
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);
}