OBJ_FILES=\
- build/onyxlex.o \
- build/onyxparser.o \
- build/onyxsempass.o \
- build/onyxsymres.o \
- build/onyxtypecheck.o \
- build/onyxmsgs.o \
- build/onyxutils.o \
- build/onyxwasm.o \
- build/onyx.o
+ build/onyxlex.o \
+ build/onyxparser.o \
+ build/onyxsempass.o \
+ build/onyxsymres.o \
+ build/onyxtypecheck.o \
+ build/onyxmsgs.o \
+ build/onyxutils.o \
+ build/onyxwasm.o \
+ build/onyx.o
CC=gcc
INCLUDES=-I./include
TARGET=./onyx
build/%.o: src/%.c include/bh.h
- $(CC) $(FLAGS) -c $< -o $@ $(INCLUDES)
+ $(CC) $(FLAGS) -c $< -o $@ $(INCLUDES)
$(TARGET): $(OBJ_FILES)
- $(CC) $(FLAGS) $(OBJ_FILES) -o $@ $(LIBS)
+ $(CC) $(FLAGS) $(OBJ_FILES) -o $@ $(LIBS)
install: $(TARGET)
- cp $(TARGET) /usr/bin/
+ cp $(TARGET) /usr/bin/
clean:
- rm -f $(OBJ_FILES) 2>&1 >/dev/null
+ rm -f $(OBJ_FILES) 2>&1 >/dev/null
all: onyx
The state of the hash implementation right now:
- (allocator + 1021 ptrs = 8192 bytes (HUGE))
- +---------------------------------------------------------
-table ----> | allocator | ptr | ptr | ptr | ptr | ptr | ptr | ptr ...
- +-------------||------------------------------------------
- \/
- +--------------+------------------------------------------------------
- | Array header | key (64-bytes) | value | key (64-bytes) | value | ...
- +--------------+------------------------------------------------------
+ (allocator + 1021 ptrs = 8192 bytes (HUGE))
+ +---------------------------------------------------------
+table ----> | allocator | ptr | ptr | ptr | ptr | ptr | ptr | ptr ...
+ +-------------||------------------------------------------
+ \/
+ +--------------+------------------------------------------------------
+ | Array header | key (64-bytes) | value | key (64-bytes) | value | ...
+ +--------------+------------------------------------------------------
There are a couple of issues with this implementation:
* The table of pointers is absolutely huge.
- It takes up about 2 pages of memory and we are randomly accessing it
- so it will not be cache efficient.
+ It takes up about 2 pages of memory and we are randomly accessing it
+ so it will not be cache efficient.
* The keys are always the same size.
- They are normally way too large, but also they would cut off if you
- needed a large key.
+ They are normally way too large, but also they would cut off if you
+ needed a large key.
THIS WORKED VERY WELL!
Attempt 1 to fix these issues:
- (user defined number of ptrs)
- +-----------------------------------------------------------
-table ----> | allocator | hash size | ptr | ptr | ptr | ptr | ptr | ...
- +-------------------------||--------------------------------
- \/
- +--------------+------------------------------------------------------------------------
- | Array header | length | value | key_length | key (null terminated) | v | kl | k | ...
- +--------------+------------------------------------------------------------------------
+ (user defined number of ptrs)
+ +-----------------------------------------------------------
+table ----> | allocator | hash size | ptr | ptr | ptr | ptr | ptr | ...
+ +-------------------------||--------------------------------
+ \/
+ +--------------+------------------------------------------------------------------------
+ | Array header | length | value | key_length | key (null terminated) | v | kl | k | ...
+ +--------------+------------------------------------------------------------------------
GOOD:
* This implementation would allow for any size of key.
- Initial thoughts:
- - Alignment is going to be very important.
- - Alignment will need to be by hand.
- - Aligning to 8 bytes should be sufficient.
- - The array would just be considered as a u8 array, since each element
- wouldn't be the same size.
- - Random access into the array would not be allowed for the same reason.
- - Random access will not be needed however.
+ Initial thoughts:
+ - Alignment is going to be very important.
+ - Alignment will need to be by hand.
+ - Aligning to 8 bytes should be sufficient.
+ - The array would just be considered as a u8 array, since each element
+ wouldn't be the same size.
+ - Random access into the array would not be allowed for the same reason.
+ - Random access will not be needed however.
* This implementation still allows for easy iterator traversal, which is
- important for the immediate use case.
+ important for the immediate use case.
BAD:
* The fact that the number of pointers is user defined, the hashing algorithm could
- be drastically slowed / crippled if they choose a bad number of pointers.
+ be drastically slowed / crippled if they choose a bad number of pointers.
* This implementation still takes a very large number of allocations.
SOURCE_FILE = TOP_LEVEL_STATEMENT ; SOURCE_FILE | ~
TOP_LEVEL_STATEMENT
- = COMMENT -- Should comments not be passed to the parser? Depends if I need to look at them. Probably not
- | USE_DECLARATION
- | EXPORT_DECLARATION
- | FOREIGN_DECLARATION
- | TOP_LEVEL_DECLARATION
+ = COMMENT -- Should comments not be passed to the parser? Depends if I need to look at them. Probably not
+ | USE_DECLARATION
+ | EXPORT_DECLARATION
+ | FOREIGN_DECLARATION
+ | TOP_LEVEL_DECLARATION
COMMENT = TOKEN_TYPE_COMMENT
TOP_LEVEL_DECLARATION = TOKEN_TYPE_SYMBOL :: TOP_LEVEL_VALUE
TOP_LEVEL_VALUE
- = FUNCTION_DECLARATION
- | STRUCT_DECLARATION
+ = FUNCTION_DECLARATION
+ | STRUCT_DECLARATION
FUNCTION_DECLARATION = proc FUNCTION_TYPE BLOCK
STATEMENTS = STATEMENT ; STATEMENTS | }
STATEMENT
- = ASSIGNMENT_STATEMENT
- | IF_STATEMENT
- | FOR_STATEMENT
- | RETURN_STATEMENT
- | EXPRESSION
+ = ASSIGNMENT_STATEMENT
+ | IF_STATEMENT
+ | FOR_STATEMENT
+ | RETURN_STATEMENT
+ | EXPRESSION
ASSIGNMENT_STATEMENT = TOKEN_TYPE_SYMBOL = EXPRESSION
IF_STATEMENT
- = if EXPRESSION BLOCK ELSE_IF_STATEMENT ELSE_STATEMENT
+ = if EXPRESSION BLOCK ELSE_IF_STATEMENT ELSE_STATEMENT
ELSEIF_STATEMENT = elseif EXPRESSION BLOCK ELSEIF_STATEMENT | ~
-- Remove abiguity in implementation
EXPRESSION
- = EXPRESSION + EXPRESSION
- | EXPRESSION - EXPRESSION
- | EXPRESSION * EXPRESSION
- | EXPRESSION / EXPRESSION
- | EXPRESSION % EXPRESSION
- | do BLOCK
- | FUNCTION_CALL -- This could have some abiguity with just the symbol
- | ( EXPRESSION )
- | TOKEN_TYPE_SYMBOL
+ = EXPRESSION + EXPRESSION
+ | EXPRESSION - EXPRESSION
+ | EXPRESSION * EXPRESSION
+ | EXPRESSION / EXPRESSION
+ | EXPRESSION % EXPRESSION
+ | do BLOCK
+ | FUNCTION_CALL -- This could have some abiguity with just the symbol
+ | ( EXPRESSION )
+ | TOKEN_TYPE_SYMBOL
FUNCTION_CALL = TOKEN_TYPE_SYMBOL ( EXPRESSION_LIST )
-----------------------------
WHAT:
- ONYX is a low-ish level programming language designed for use with
- Web-Assembly 32-bit (WASM). It features some advanced features such
- as comptime code execution and JS literals for external functions.
+ ONYX is a low-ish level programming language designed for use with
+ Web-Assembly 32-bit (WASM). It features some advanced features such
+ as comptime code execution and JS literals for external functions.
WHY:
- ONYX was made to help me learn about compiler design.
+ ONYX was made to help me learn about compiler design.
END GOAL:
- ONYX will be used to make a simple-ish game for the browser that leverages
- WASM and WebGL for a performant experience. Language design will reflect the
- needs of the game programming.
+ ONYX will be used to make a simple-ish game for the browser that leverages
+ WASM and WebGL for a performant experience. Language design will reflect the
+ needs of the game programming.
FEATURES:
- - Strong type system
- - functions (no anonymous functions)
- - Structs and enums
- - Control structures
- if, for, switch
- - pointers
- - inferred typing
- - Smart package loading
- - defer
- ? polymorphic functions
+ - Strong type system
+ - functions (no anonymous functions)
+ - Structs and enums
+ - Control structures
+ if, for, switch
+ - pointers
+ - inferred typing
+ - Smart package loading
+ - defer
+ ? polymorphic functions
HOW:
- Currently there is a multi-phase development process since implementing everything
- at once would be overwhelming and unsatisfying. The current progress of each stage:
-
- Stage 1 (MVP):
- [X] Can declare procedures
- [X] Procedures have params and returns of the following types:
- - i32, u32
- - i64, u64
- - f32, f64
- [X] Procedures have locals of the same set of types
- [X] Locals are declared in the following way
- local : (type) ((= or :) initial value);
-
- if : is used, the value is unmodifiable
- if type is specified, that is assumed to be the correct type
- if type is not specified, the type of initial value is used as the type
-
- [X] Five basic math operations are legal:
- + - * / %
- [X] Math operations are sign aware and only operate on operands of the same type
- [X] All casts are explicit using this syntax:
- X as T
-
- casts X to type T
-
- [X] Curly braces are required for all bodies of blocks
- [X] Numeric literals are parsed
- [X] Numeric literals have the minimum type detected
+ Currently there is a multi-phase development process since implementing everything
+ at once would be overwhelming and unsatisfying. The current progress of each stage:
+
+ Stage 1 (MVP):
+ [X] Can declare procedures
+ [X] Procedures have params and returns of the following types:
+ - i32, u32
+ - i64, u64
+ - f32, f64
+ [X] Procedures have locals of the same set of types
+ [X] Locals are declared in the following way
+ local : (type) ((= or :) initial value);
+
+ if : is used, the value is unmodifiable
+ if type is specified, that is assumed to be the correct type
+ if type is not specified, the type of initial value is used as the type
+
+ [X] Five basic math operations are legal:
+ + - * / %
+ [X] Math operations are sign aware and only operate on operands of the same type
+ [X] All casts are explicit using this syntax:
+ X as T
+
+ casts X to type T
+
+ [X] Curly braces are required for all bodies of blocks
+ [X] Numeric literals are parsed
+ [X] Numeric literals have the minimum type detected
[X] Foreign imports (functions only)
- [X] Comparison operators
- [X] Proper boolean type
- [X] Conditional branching works as expected
- XX] Simple while loop is functioning as expected
- [ ] break and continue semantics
- [X] Function calling works for the builtin types
- [X] Function return values are type checked
-
- Stage 2:
- [X] Order of symbol declaration is irrelevant
- Either:
- make a graph of symbol dependencies and produce a schedule on the graph
- that would allow for all symbols to be resolved
-
- OR
-
- Do as many passes on the parse tree as needed to resolve all symbols.
- This could be slow but it would be easier than creating a graph
- scheduling algorithm.
+ [X] Comparison operators
+ [X] Proper boolean type
+ [X] Conditional branching works as expected
+ XX] Simple while loop is functioning as expected
+ [ ] break and continue semantics
+ [X] Function calling works for the builtin types
+ [X] Function return values are type checked
+
+ Stage 2:
+ [X] Order of symbol declaration is irrelevant
+ Either:
+ make a graph of symbol dependencies and produce a schedule on the graph
+ that would allow for all symbols to be resolved
+
+ OR
+
+ Do as many passes on the parse tree as needed to resolve all symbols.
+ This could be slow but it would be easier than creating a graph
+ scheduling algorithm.
[X] Consequence of the above, recursion works
[ ] Output 'drop' instruction for functions whose return value isn't used
- [ ] Devise and implement a simple set of implicit type casting rules.
- - Numeric literals always type cast to whatever type is needed (very flexible).
+ [ ] Devise and implement a simple set of implicit type casting rules.
+ - Numeric literals always type cast to whatever type is needed (very flexible).
- [ ] Strings should work as pointers to data.
- - Literals should be placed in data section with pointers to the start.
- - Should strings be null-terminated or a length at the start of the string?
+ [ ] Strings should work as pointers to data.
+ - Literals should be placed in data section with pointers to the start.
+ - Should strings be null-terminated or a length at the start of the string?
- [ ] Start work on evaluating compile time known values.
- - An expression marked COMPTIME will be reduced to its value in the parse tree.
+ [ ] Start work on evaluating compile time known values.
+ - An expression marked COMPTIME will be reduced to its value in the parse tree.
Type checking at parse time:\r
- Why couldn't this work?\r
- * Every variable is of known type or the type must be known by immediate assignment\r
- * This requires that functions are declared in a particular order like C\r
- * This also requires immediate evaluation of external symbols (C #include style)\r
- - Don't like this at all\r
- - Want a proper module system <<<<\r
+ Why couldn't this work?\r
+ * Every variable is of known type or the type must be known by immediate assignment\r
+ * This requires that functions are declared in a particular order like C\r
+ * This also requires immediate evaluation of external symbols (C #include style)\r
+ - Don't like this at all\r
+ - Want a proper module system <<<<\r
\r
- /* foo.onyx */\r
- foo :: proc (a i32) -> f32 {\r
- return a as f32;\r
- }\r
+ /* foo.onyx */\r
+ foo :: proc (a i32) -> f32 {\r
+ return a as f32;\r
+ }\r
\r
\r
- /* main.onyx */\r
- use "foo";\r
+ /* main.onyx */\r
+ use "foo";\r
\r
- export main :: proc () -> void {\r
- a := 2.0f + foo(5);\r
- }\r
+ export main :: proc () -> void {\r
+ a := 2.0f + foo(5);\r
+ }\r
\r
- foo(5) would have a left node of SYMBOL:foo\r
- This will be resolved in a later stage between the parsing and semantic pass\r
- Type checking and resolving would have to occur afterwards\r
+ foo(5) would have a left node of SYMBOL:foo\r
+ This will be resolved in a later stage between the parsing and semantic pass\r
+ Type checking and resolving would have to occur afterwards\r
\r
Creating an IR:\r
// Better character functions
//-------------------------------------------------------------------------------------
inline b32 char_is_alpha(const char a) {
- return ('a' <= a && a <= 'z') || ('A' <= a && a <= 'Z');
+ return ('a' <= a && a <= 'z') || ('A' <= a && a <= 'Z');
}
inline char charset_contains(const char* charset, char ch) {
- while (*charset) {
- if (*charset == ch) return ch;
- charset++;
- }
+ while (*charset) {
+ if (*charset == ch) return ch;
+ charset++;
+ }
- return 0;
+ return 0;
}
inline b32 char_is_num(const char a) {
- return ('0' <= a && a <= '9');
+ return ('0' <= a && a <= '9');
}
inline b32 char_is_alphanum(const char a) {
- return char_is_alpha(a) || char_is_num(a);
+ return char_is_alpha(a) || char_is_num(a);
}
inline b32 char_is_whitespace(const char a) {
- return charset_contains(" \t\r\n", a);
+ return charset_contains(" \t\r\n", a);
}
inline b32 char_in_range(const char lo, const char hi, const char a) {
- return lo <= a <= hi;
+ return lo <= a <= hi;
}
inline i64 chars_match(char* ptr1, char* ptr2) {
- i64 len = 0;
- while (*ptr2 != '\0' && *ptr1 == *ptr2) ptr1++, ptr2++, len++;
- return *ptr2 == '\0' ? len : 0;
+ i64 len = 0;
+ while (*ptr2 != '\0' && *ptr1 == *ptr2) ptr1++, ptr2++, len++;
+ return *ptr2 == '\0' ? len : 0;
}
//-------------------------------------------------------------------------------------
// Better math functions
//-------------------------------------------------------------------------------------
-#define bh_max(a, b) ((a) > (b) ? (a) : (b))
-#define bh_min(a, b) ((a) < (b) ? (a) : (b))
-#define bh_clamp(v, a, b) (bh_min((b), bh_max((a), (v))))
-#define bh_abs(x) ((x) < 0 ? -(x) : (x))
+#define bh_max(a, b) ((a) > (b) ? (a) : (b))
+#define bh_min(a, b) ((a) < (b) ? (a) : (b))
+#define bh_clamp(v, a, b) (bh_min((b), bh_max((a), (v))))
+#define bh_abs(x) ((x) < 0 ? -(x) : (x))
//-------------------------------------------------------------------------------------
// Helpful macros
//-------------------------------------------------------------------------------------
-#define bh_offset_of(Type, elem) ((isize)&(((Type)*) 0)->elem)
-#define bh_align_of(Type) bh_offset_of(struct { char c; Type member; }, member)
-#define bh_swap(Type, a, b) do { Type tmp = (a); (a) = (b); (b) = tmp; } while(0)
+#define bh_offset_of(Type, elem) ((isize)&(((Type)*) 0)->elem)
+#define bh_align_of(Type) bh_offset_of(struct { char c; Type member; }, member)
+#define bh_swap(Type, a, b) do { Type tmp = (a); (a) = (b); (b) = tmp; } while(0)
-#define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm))
-#define BH_BIT(x) (1 << (x))
-#define BH_MASK_SET(var, set, mask) ((set) ? (var) |= (mask) : (var) &= ~(mask))
+#define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm))
+#define BH_BIT(x) (1 << (x))
+#define BH_MASK_SET(var, set, mask) ((set) ? (var) |= (mask) : (var) &= ~(mask))
-#define fori(var, lo, hi) for (i64 var = (lo); var <= (hi); var++)
-#define forll(T, var, start, step) for (T* var = (start); var != NULL; var = var->step)
+#define fori(var, lo, hi) for (i64 var = (lo); var <= (hi); var++)
+#define forll(T, var, start, step) for (T* var = (start); var != NULL; var = var->step)
#ifdef BH_DEBUG
- #define DEBUG_HERE __asm("int $3")
+ #define DEBUG_HERE __asm("int $3")
#else
- #define DEBUG_HERE
+ #define DEBUG_HERE
#endif
//-------------------------------------------------------------------------------------
typedef enum bh_allocator_actions {
- bh_allocator_action_alloc,
- bh_allocator_action_free,
- bh_allocator_action_resize,
+ bh_allocator_action_alloc,
+ bh_allocator_action_free,
+ bh_allocator_action_resize,
} bh_allocator_actions;
#define BH_ALLOCATOR_PROC(name) \
ptr name(ptr data, bh_allocator_actions action, \
- isize size, isize alignment, \
- void* prev_memory, \
- u64 flags)
+ isize size, isize alignment, \
+ void* prev_memory, \
+ u64 flags)
typedef BH_ALLOCATOR_PROC(bh__allocator_proc); // NOTE: so bh__allocator_proc can be used instead of that type
typedef struct bh_allocator {
- bh__allocator_proc* proc; // Procedure that can handle bh_allocator_actions
- ptr data; // Pointer to the other data for the allocator
+ bh__allocator_proc* proc; // Procedure that can handle bh_allocator_actions
+ ptr data; // Pointer to the other data for the allocator
} bh_allocator;
typedef enum bh_allocator_flags {
- bh_allocator_flag_clear = 1 // Sets all memory to be 0
+ bh_allocator_flag_clear = 1 // Sets all memory to be 0
} bh_allocator_flags;
ptr bh_alloc(bh_allocator a, isize size);
ptr bh_resize_aligned(bh_allocator a, ptr data, isize new_size, isize alignment);
void bh_free(bh_allocator a, ptr data);
-#define bh_alloc_item(allocator_, T) (T *) bh_alloc(allocator_, sizeof(T))
-#define bh_alloc_array(allocator_, T, n) (T *) bh_alloc(allocator_, sizeof(T) * (n))
+#define bh_alloc_item(allocator_, T) (T *) bh_alloc(allocator_, sizeof(T))
+#define bh_alloc_array(allocator_, T, n) (T *) bh_alloc(allocator_, sizeof(T) * (n))
// NOTE: This should get optimized out since alignment should be a power of two
-#define bh__align(x, alignment) ((((x) / alignment) + 1) * alignment)
+#define bh__align(x, alignment) ((((x) / alignment) + 1) * alignment)
// ARENA ALLOCATOR
typedef struct bh_arena {
- bh_allocator backing;
- ptr first_arena, current_arena;
- isize size, arena_size; // in bytes
+ bh_allocator backing;
+ ptr first_arena, current_arena;
+ isize size, arena_size; // in bytes
} bh_arena;
typedef struct bh__arena_internal {
- ptr next_arena;
- void* data; // Not actually a pointer, just used for the offset
+ ptr next_arena;
+ void* data; // Not actually a pointer, just used for the offset
} bh__arena_internal;
void bh_arena_init(bh_arena* alloc, bh_allocator backing, isize arena_size);
// SCRATCH ALLOCATOR
typedef struct bh_scratch {
- bh_allocator backing;
- ptr memory, end, curr;
+ bh_allocator backing;
+ ptr memory, end, curr;
} bh_scratch;
void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size);
#ifndef BH_NO_FILE
typedef enum bh_file_error {
- BH_FILE_ERROR_NONE,
- BH_FILE_ERROR_INVALID,
- BH_FILE_ERROR_BAD_FD,
+ BH_FILE_ERROR_NONE,
+ BH_FILE_ERROR_INVALID,
+ BH_FILE_ERROR_BAD_FD,
} bh_file_error;
typedef enum bh_file_mode {
- BH_FILE_MODE_READ = 1 << 0,
- BH_FILE_MODE_WRITE = 1 << 1,
- BH_FILE_MODE_APPEND = 1 << 2,
- BH_FILE_MODE_RW = 1 << 3,
+ BH_FILE_MODE_READ = 1 << 0,
+ BH_FILE_MODE_WRITE = 1 << 1,
+ BH_FILE_MODE_APPEND = 1 << 2,
+ BH_FILE_MODE_RW = 1 << 3,
- BH_FILE_MODE_MODES = BH_FILE_MODE_READ | BH_FILE_MODE_WRITE | BH_FILE_MODE_APPEND | BH_FILE_MODE_RW
+ BH_FILE_MODE_MODES = BH_FILE_MODE_READ | BH_FILE_MODE_WRITE | BH_FILE_MODE_APPEND | BH_FILE_MODE_RW
} bh_file_mode;
typedef enum bh_file_whence {
- BH_FILE_WHENCE_BEGIN = SEEK_SET,
- BH_FILE_WHENCE_CURRENT = SEEK_CUR,
- BH_FILE_WHENCE_END = SEEK_END,
+ BH_FILE_WHENCE_BEGIN = SEEK_SET,
+ BH_FILE_WHENCE_CURRENT = SEEK_CUR,
+ BH_FILE_WHENCE_END = SEEK_END,
} bh_file_whence;
typedef int bh_file_descriptor;
typedef struct bh_file {
- bh_file_descriptor fd;
- char const* filename;
+ bh_file_descriptor fd;
+ char const* filename;
} bh_file;
typedef enum bh_file_standard {
- BH_FILE_STANDARD_INPUT,
- BH_FILE_STANDARD_OUTPUT,
- BH_FILE_STANDARD_ERROR
+ BH_FILE_STANDARD_INPUT,
+ BH_FILE_STANDARD_OUTPUT,
+ BH_FILE_STANDARD_ERROR
} bh_file_standard;
typedef struct bh_file_contents {
- bh_allocator allocator;
- const char *filename;
- isize length;
- void* data;
+ bh_allocator allocator;
+ const char *filename;
+ isize length;
+ void* data;
} bh_file_contents;
bh_file_error bh_file_get_standard(bh_file* file, bh_file_standard stand);
i64 bh_file_size(bh_file* file);
#define bh_file_read_contents(allocator_, x) _Generic((x), \
- bh_file*: bh_file_read_contents_bh_file, \
- const char*: bh_file_read_contents_direct, \
- char*: bh_file_read_contents_direct)((allocator_), x)
+ bh_file*: bh_file_read_contents_bh_file, \
+ const char*: bh_file_read_contents_direct, \
+ char*: bh_file_read_contents_direct)((allocator_), x)
bh_file_contents bh_file_read_contents_bh_file(bh_allocator alloc, bh_file* file);
bh_file_contents bh_file_read_contents_direct(bh_allocator alloc, const char* filename);
//-------------------------------------------------------------------------------------
// Barebones implementation of printf. Does not support all format options
// Currently supports:
-// %c - chars
-// %_(u)d - ints where _ is:
-// nothing - decimal
-// o - octal
-// x - hexadecimal
-// %_(u)l - longs where _ is:
-// nothing - decimal
-// o - octal
-// x - hexadecimal
-// %f - floating points
-// %s - null terminated strings
-// %p - pointers
-// %% - literal %
+// %c - chars
+// %_(u)d - ints where _ is:
+// nothing - decimal
+// o - octal
+// x - hexadecimal
+// %_(u)l - longs where _ is:
+// nothing - decimal
+// o - octal
+// x - hexadecimal
+// %f - floating points
+// %s - null terminated strings
+// %p - pointers
+// %% - literal %
typedef struct bh__print_format {
- u32 base;
+ u32 base;
} bh__print_format;
isize bh_printf(char const *fmt, ...);
#ifdef BH_DEFINE
void* bh__debug_malloc(size_t size, const char* file, u64 line) {
- void* p = malloc(size);
- bh_printf("[DEBUG] %p = malloc(%d) at %s:%d\n", p, size, file, line);
- return p;
+ void* p = malloc(size);
+ bh_printf("[DEBUG] %p = malloc(%d) at %s:%d\n", p, size, file, line);
+ return p;
}
void* bh__debug_aligned_alloc(size_t alignment, size_t size, const char* file, u64 line) {
- void* p = aligned_alloc(alignment, size);
- bh_printf("[DEBUG] %p = aligned_alloc(%d, %d) at %s:%d\n", p, alignment, size, file, line);
- return p;
+ void* p = aligned_alloc(alignment, size);
+ bh_printf("[DEBUG] %p = aligned_alloc(%d, %d) at %s:%d\n", p, alignment, size, file, line);
+ return p;
}
void bh__debug_free(void* ptr, const char* file, u64 line) {
- bh_printf("[DEBUG] free(%p) at %s:%d\n", ptr, file, line);
- free(ptr);
+ bh_printf("[DEBUG] free(%p) at %s:%d\n", ptr, file, line);
+ free(ptr);
}
void* bh__debug_realloc(void* ptr, size_t size, const char* file, u64 line) {
- void* p = realloc(ptr, size);
- bh_printf("[DEBUG] %p = realloc(%p, %d) at %s:%d\n", p, ptr, size, file, line);
- return p;
+ void* p = realloc(ptr, size);
+ bh_printf("[DEBUG] %p = realloc(%p, %d) at %s:%d\n", p, ptr, size, file, line);
+ return p;
}
#endif
-#define malloc(size) (bh__debug_malloc(size, __FILE__, __LINE__))
-#define aligned_alloc(alignment, size) (bh__debug_aligned_alloc(alignment, size, __FILE__, __LINE__))
-#define free(ptr) (bh__debug_free(ptr, __FILE__, __LINE__))
-#define realloc(ptr, size) (bh__debug_realloc(ptr, size, __FILE__, __LINE__))
+#define malloc(size) (bh__debug_malloc(size, __FILE__, __LINE__))
+#define aligned_alloc(alignment, size) (bh__debug_aligned_alloc(alignment, size, __FILE__, __LINE__))
+#define free(ptr) (bh__debug_free(ptr, __FILE__, __LINE__))
+#define realloc(ptr, size) (bh__debug_realloc(ptr, size, __FILE__, __LINE__))
#endif
//-------------------------------------------------------------------------------------
typedef struct bh_buffer {
- bh_allocator allocator;
- i32 length, capacity;
- u8* data;
+ bh_allocator allocator;
+ i32 length, capacity;
+ u8* data;
} bh_buffer;
#ifndef BH_BUFFER_GROW_FORMULA
-#define BH_BUFFER_GROW_FORMULA(x) ((x) > 0 ? ((x) << 1) : 16)
+#define BH_BUFFER_GROW_FORMULA(x) ((x) > 0 ? ((x) << 1) : 16)
#endif
void bh_buffer_init(bh_buffer* buffer, bh_allocator alloc, i32 length);
#ifndef BH_NO_ARRAY
typedef struct bh__arr {
- bh_allocator allocator;
- i32 length, capacity;
+ bh_allocator allocator;
+ i32 length, capacity;
} bh__arr;
#ifndef BH_ARR_GROW_FORMULA
-#define BH_ARR_GROW_FORMULA(x) ((x) > 0 ? ((x) << 1) : 4)
+#define BH_ARR_GROW_FORMULA(x) ((x) > 0 ? ((x) << 1) : 4)
#endif
-#define bh_arr(T) T*
-#define bh__arrhead(arr) (((bh__arr *)(arr)) - 1)
+#define bh_arr(T) T*
+#define bh__arrhead(arr) (((bh__arr *)(arr)) - 1)
-#define bh_arr_allocator(arr) (arr ? bh__arrhead(arr)->allocator : bh_heap_allocator())
-#define bh_arr_length(arr) (arr ? bh__arrhead(arr)->length : 0)
-#define bh_arr_capacity(arr) (arr ? bh__arrhead(arr)->capacity : 0)
-#define bh_arr_size(arr) (arr ? bh__arrhead(arr)->capacity * sizeof(*(arr)) : 0)
-#define bh_arr_valid(arr, i) (arr ? (i32)(i) < bh__arrhead(arr)->length : 0)
+#define bh_arr_allocator(arr) (arr ? bh__arrhead(arr)->allocator : bh_heap_allocator())
+#define bh_arr_length(arr) (arr ? bh__arrhead(arr)->length : 0)
+#define bh_arr_capacity(arr) (arr ? bh__arrhead(arr)->capacity : 0)
+#define bh_arr_size(arr) (arr ? bh__arrhead(arr)->capacity * sizeof(*(arr)) : 0)
+#define bh_arr_valid(arr, i) (arr ? (i32)(i) < bh__arrhead(arr)->length : 0)
-#define bh_arr_pop(arr) ((arr)[--bh__arrhead(arr)->length])
-#define bh_arr_last(arr) ((arr)[bh__arrhead(arr)->length - 1])
-#define bh_arr_end(arr, i) ((i) >= &(arr)[bh_arr_length(arr)])
+#define bh_arr_pop(arr) ((arr)[--bh__arrhead(arr)->length])
+#define bh_arr_last(arr) ((arr)[bh__arrhead(arr)->length - 1])
+#define bh_arr_end(arr, i) ((i) >= &(arr)[bh_arr_length(arr)])
-#define bh_arr_new(allocator_, arr, cap) (bh__arr_grow((allocator_), (void**) &(arr), sizeof(*(arr)), cap))
-#define bh_arr_free(arr) (bh__arr_free((void**) &(arr)))
-#define bh_arr_copy(allocator_, arr) (bh__arr_copy((allocator_), (arr), sizeof(*(arr))))
+#define bh_arr_new(allocator_, arr, cap) (bh__arr_grow((allocator_), (void**) &(arr), sizeof(*(arr)), cap))
+#define bh_arr_free(arr) (bh__arr_free((void**) &(arr)))
+#define bh_arr_copy(allocator_, arr) (bh__arr_copy((allocator_), (arr), sizeof(*(arr))))
-#define bh_arr_grow(arr, cap) (bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), cap))
-#define bh_arr_shrink(arr, cap) (bh__arr_shrink((void **) &(arr), sizeof(*(arr)), cap))
-#define bh_arr_set_length(arr, n) ( \
- bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), n), \
- bh__arrhead(arr)->length = n)
+#define bh_arr_grow(arr, cap) (bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), cap))
+#define bh_arr_shrink(arr, cap) (bh__arr_shrink((void **) &(arr), sizeof(*(arr)), cap))
+#define bh_arr_set_length(arr, n) ( \
+ bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), n), \
+ bh__arrhead(arr)->length = n)
-#define bh_arr_insertn(arr, i, n) (bh__arr_insertn((void **) &(arr), sizeof(*(arr)), i, n))
+#define bh_arr_insertn(arr, i, n) (bh__arr_insertn((void **) &(arr), sizeof(*(arr)), i, n))
-#define bh_arr_insert_end(arr, n) ( \
- bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), bh_arr_length(arr) + n), \
- bh__arrhead(arr)->length += n)
+#define bh_arr_insert_end(arr, n) ( \
+ bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), bh_arr_length(arr) + n), \
+ bh__arrhead(arr)->length += n)
-#define bh_arr_push(arr, value) ( \
- bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), bh_arr_length(arr) + 1), \
- arr[bh__arrhead(arr)->length++] = value)
+#define bh_arr_push(arr, value) ( \
+ bh__arr_grow(bh_arr_allocator(arr), (void **) &(arr), sizeof(*(arr)), bh_arr_length(arr) + 1), \
+ arr[bh__arrhead(arr)->length++] = value)
-#define bh_arr_is_empty(arr) (arr ? bh__arrhead(arr)->length == 0 : 1)
-#define bh_arr_clear(arr) (arr ? (bh__arrhead(arr)->length = 0) : 0)
+#define bh_arr_is_empty(arr) (arr ? bh__arrhead(arr)->length == 0 : 1)
+#define bh_arr_clear(arr) (arr ? (bh__arrhead(arr)->length = 0) : 0)
-#define bh_arr_deleten(arr, i, n) (bh__arr_deleten((void **) &(arr), sizeof(*(arr)), i, n))
-#define bh_arr_fastdelete(arr, i) (arr[i] = arr[--bh__arrhead(arr)->length])
+#define bh_arr_deleten(arr, i, n) (bh__arr_deleten((void **) &(arr), sizeof(*(arr)), i, n))
+#define bh_arr_fastdelete(arr, i) (arr[i] = arr[--bh__arrhead(arr)->length])
-#define bh_arr_each(T, var, arr) for (T* var = (arr); !bh_arr_end((arr), var); var++)
+#define bh_arr_each(T, var, arr) for (T* var = (arr); !bh_arr_end((arr), var); var++)
b32 bh__arr_grow(bh_allocator alloc, void** arr, i32 elemsize, i32 cap);
b32 bh__arr_shrink(void** arr, i32 elemsize, i32 cap);
#ifdef BH_DEFINE
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
+ u64 hash = 5381;
+ i32 c, l = 0;
+ if (len == 0) len = ((u32) 1 << 31) - 1; // TODO: Verify this is right
- while ((c = *str++) && l++ < len) {
- hash = (hash << 5) + hash + c;
- }
+ while ((c = *str++) && l++ < len) {
+ hash = (hash << 5) + hash + c;
+ }
- return hash % mod;
+ return hash % mod;
}
#endif
typedef struct bh_table_iterator {
- ptr *tab, *endtab;
- i32 elemsize, arrlen;
- ptr entry;
+ ptr *tab, *endtab;
+ i32 elemsize, arrlen;
+ ptr entry;
} bh_table_iterator;
typedef struct bh__table {
- bh_allocator allocator;
- u64 table_size; // NOTE: u64 since padding will make it 8-bytes no matter what
- ptr arrs[];
+ bh_allocator allocator;
+ u64 table_size; // NOTE: u64 since padding will make it 8-bytes no matter what
+ ptr arrs[];
} bh__table;
-#define bh_table(T) T*
+#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)
+ #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_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)) = (T) 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)
+ #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)) = (T) 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_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 } }
+ 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);
// CUSTOM ALLOCATORS IMPLEMENTATION
//-------------------------------------------------------------------------------------
ptr bh_alloc(bh_allocator a, isize size) {
- return bh_alloc_aligned(a, size, 16);
+ return bh_alloc_aligned(a, size, 16);
}
ptr bh_alloc_aligned(bh_allocator a, isize size, isize alignment) {
- return a.proc(a.data, bh_allocator_action_alloc, size, alignment, NULL, 0);
+ return a.proc(a.data, bh_allocator_action_alloc, size, alignment, NULL, 0);
}
ptr bh_resize(bh_allocator a, ptr data, isize new_size) {
- return bh_resize_aligned(a, data, new_size, 16);
+ return bh_resize_aligned(a, data, new_size, 16);
}
ptr bh_resize_aligned(bh_allocator a, ptr data, isize new_size, isize alignment) {
- return a.proc(a.data, bh_allocator_action_resize, new_size, alignment, data, 0);
+ return a.proc(a.data, bh_allocator_action_resize, new_size, alignment, data, 0);
}
void bh_free(bh_allocator a, ptr data) {
- if (data != NULL) a.proc(a.data, bh_allocator_action_free, 0, 0, data, 0);
+ if (data != NULL) a.proc(a.data, bh_allocator_action_free, 0, 0, data, 0);
}
// HEAP ALLOCATOR IMPLEMENTATION
bh_allocator bh_heap_allocator(void) {
- return (bh_allocator) {
- .proc = bh_heap_allocator_proc,
- .data = NULL
- };
+ return (bh_allocator) {
+ .proc = bh_heap_allocator_proc,
+ .data = NULL
+ };
}
BH_ALLOCATOR_PROC(bh_heap_allocator_proc) {
- ptr retval = NULL;
+ ptr retval = NULL;
- switch (action) {
- case bh_allocator_action_alloc: {
- retval = aligned_alloc(alignment, size);
+ switch (action) {
+ case bh_allocator_action_alloc: {
+ retval = aligned_alloc(alignment, size);
- if (flags & bh_allocator_flag_clear && retval != NULL) {
- memset(retval, 0, size);
- }
- } break;
+ if (flags & bh_allocator_flag_clear && retval != NULL) {
+ memset(retval, 0, size);
+ }
+ } break;
- case bh_allocator_action_resize: {
- // TODO: Maybe replace with better custom function
- retval = realloc(prev_memory, size);
- } break;
+ case bh_allocator_action_resize: {
+ // TODO: Maybe replace with better custom function
+ retval = realloc(prev_memory, size);
+ } break;
- case bh_allocator_action_free: {
- free(prev_memory);
- } break;
- }
+ case bh_allocator_action_free: {
+ free(prev_memory);
+ } break;
+ }
- return retval;
+ return retval;
}
// ARENA ALLOCATOR IMPLEMENTATION
void bh_arena_init(bh_arena* alloc, bh_allocator backing, isize arena_size) {
- arena_size = bh_max(arena_size, sizeof(ptr));
- ptr data = bh_alloc(backing, arena_size);
+ arena_size = bh_max(arena_size, sizeof(ptr));
+ ptr data = bh_alloc(backing, arena_size);
- alloc->backing = backing;
- alloc->arena_size = arena_size;
- alloc->size = sizeof(ptr);
- alloc->first_arena = data;
- alloc->current_arena = data;
+ alloc->backing = backing;
+ alloc->arena_size = arena_size;
+ alloc->size = sizeof(ptr);
+ alloc->first_arena = data;
+ alloc->current_arena = data;
- ((bh__arena_internal *)(alloc->first_arena))->next_arena = NULL;
+ ((bh__arena_internal *)(alloc->first_arena))->next_arena = NULL;
}
void bh_arena_free(bh_arena* alloc) {
- bh__arena_internal *walker = (bh__arena_internal *) alloc->first_arena;
- bh__arena_internal *trailer = walker;
- while (walker != NULL) {
- walker = walker->next_arena;
- bh_free(alloc->backing, trailer);
- trailer = walker;
- }
+ bh__arena_internal *walker = (bh__arena_internal *) alloc->first_arena;
+ bh__arena_internal *trailer = walker;
+ while (walker != NULL) {
+ walker = walker->next_arena;
+ bh_free(alloc->backing, trailer);
+ trailer = walker;
+ }
- alloc->first_arena = NULL;
- alloc->current_arena = NULL;
- alloc->arena_size = 0;
- alloc->size = 0;
+ alloc->first_arena = NULL;
+ alloc->current_arena = NULL;
+ alloc->arena_size = 0;
+ alloc->size = 0;
}
bh_allocator bh_arena_allocator(bh_arena* alloc) {
- return (bh_allocator) {
- .proc = bh_arena_allocator_proc,
- .data = alloc,
- };
+ return (bh_allocator) {
+ .proc = bh_arena_allocator_proc,
+ .data = alloc,
+ };
}
BH_ALLOCATOR_PROC(bh_arena_allocator_proc) {
- bh_arena* alloc_arena = (bh_arena*) data;
+ bh_arena* alloc_arena = (bh_arena*) data;
- ptr retval = NULL;
+ ptr retval = NULL;
- switch (action) {
- case bh_allocator_action_alloc: {
+ switch (action) {
+ case bh_allocator_action_alloc: {
- // TODO: Do this better because right now bh__align is bad
- // size = bh__align(size, alignment);
- if (size > alloc_arena->arena_size - sizeof(ptr)) {
- // Size too large for the arena
- return NULL;
- }
+ // TODO: Do this better because right now bh__align is bad
+ // size = bh__align(size, alignment);
+ if (size > alloc_arena->arena_size - sizeof(ptr)) {
+ // Size too large for the arena
+ return NULL;
+ }
- if (alloc_arena->size + size >= alloc_arena->arena_size) {
- alloc_arena->size = sizeof(ptr);
- bh__arena_internal* new_arena = (bh__arena_internal *) bh_alloc(alloc_arena->backing, alloc_arena->arena_size);
+ if (alloc_arena->size + size >= alloc_arena->arena_size) {
+ alloc_arena->size = sizeof(ptr);
+ bh__arena_internal* new_arena = (bh__arena_internal *) bh_alloc(alloc_arena->backing, alloc_arena->arena_size);
- if (new_arena == NULL) {
- bh_printf_err("Arena Allocator: couldn't allocate new arena");
- return NULL;
- }
+ if (new_arena == NULL) {
+ bh_printf_err("Arena Allocator: couldn't allocate new arena");
+ return NULL;
+ }
- new_arena->next_arena = NULL;
- ((bh__arena_internal *)(alloc_arena->current_arena))->next_arena = new_arena;
- alloc_arena->current_arena = new_arena;
- }
+ new_arena->next_arena = NULL;
+ ((bh__arena_internal *)(alloc_arena->current_arena))->next_arena = new_arena;
+ alloc_arena->current_arena = new_arena;
+ }
- retval = bh_pointer_add(alloc_arena->current_arena, alloc_arena->size);
- alloc_arena->size += size;
- } break;
+ retval = bh_pointer_add(alloc_arena->current_arena, alloc_arena->size);
+ alloc_arena->size += size;
+ } break;
- case bh_allocator_action_resize: {
- // Do nothing since this is a fixed allocator
- } break;
+ case bh_allocator_action_resize: {
+ // Do nothing since this is a fixed allocator
+ } break;
- case bh_allocator_action_free: {
- // Do nothing since this allocator isn't made for freeing memory
- } break;
- }
+ case bh_allocator_action_free: {
+ // Do nothing since this allocator isn't made for freeing memory
+ } break;
+ }
- return retval;
+ return retval;
}
// SCRATCH ALLOCATOR IMPLEMENTATION
void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size) {
- ptr memory = bh_alloc(backing, scratch_size);
+ ptr memory = bh_alloc(backing, scratch_size);
- scratch->backing = backing;
- scratch->memory = memory;
- scratch->curr = memory;
- scratch->end = memory + scratch_size;
+ scratch->backing = backing;
+ scratch->memory = memory;
+ scratch->curr = memory;
+ scratch->end = memory + scratch_size;
}
void bh_scratch_free(bh_scratch* scratch) {
- bh_free(scratch->backing, scratch->memory);
+ bh_free(scratch->backing, scratch->memory);
- scratch->memory = NULL;
- scratch->curr = NULL;
- scratch->end = NULL;
+ scratch->memory = NULL;
+ scratch->curr = NULL;
+ scratch->end = NULL;
}
bh_allocator bh_scratch_allocator(bh_scratch* scratch) {
- return (bh_allocator) {
- .proc = bh_scratch_allocator_proc,
- .data = scratch,
- };
+ return (bh_allocator) {
+ .proc = bh_scratch_allocator_proc,
+ .data = scratch,
+ };
}
BH_ALLOCATOR_PROC(bh_scratch_allocator_proc) {
- bh_scratch* scratch = (bh_scratch*) data;
- ptr retval = NULL;
+ bh_scratch* scratch = (bh_scratch*) data;
+ ptr retval = NULL;
- switch (action) {
- case bh_allocator_action_alloc: {
- if (size > scratch->end - scratch->memory) {
- return NULL;
- }
+ switch (action) {
+ case bh_allocator_action_alloc: {
+ if (size > scratch->end - scratch->memory) {
+ return NULL;
+ }
- retval = scratch->curr;
- scratch->curr += size;
+ retval = scratch->curr;
+ scratch->curr += size;
- if (scratch->curr >= scratch->end) {
- scratch->curr = scratch->memory;
- retval = scratch->curr;
- }
- } break;
+ if (scratch->curr >= scratch->end) {
+ scratch->curr = scratch->memory;
+ retval = scratch->curr;
+ }
+ } break;
- case bh_allocator_action_free: break;
+ case bh_allocator_action_free: break;
- case bh_allocator_action_resize: {
- if (size > scratch->end - scratch->memory) {
- return NULL;
- }
+ case bh_allocator_action_resize: {
+ if (size > scratch->end - scratch->memory) {
+ return NULL;
+ }
- retval = scratch->curr;
- scratch->curr += size;
+ retval = scratch->curr;
+ scratch->curr += size;
- if (scratch->curr >= scratch->end) {
- scratch->curr = scratch->memory;
- retval = scratch->curr;
- }
+ if (scratch->curr >= scratch->end) {
+ scratch->curr = scratch->memory;
+ retval = scratch->curr;
+ }
// HACK!!!!!: Using size instead of some kind of "old size"
memcpy(retval, prev_memory, size);
- } break;
- }
+ } break;
+ }
- return retval;
+ return retval;
}
// CONVERSION FUNCTIONS IMPLEMENTATION
//-------------------------------------------------------------------------------------
u8* uint_to_uleb128(u64 n, i32* output_length) {
- static u8 buffer[16];
+ static u8 buffer[16];
- *output_length = 0;
- u8* output = buffer;
- u8 byte;
- do {
- byte = n & 0x7f;
- n >>= 7;
- if (n != 0) byte |= (1 << 7);
- *output++ = byte;
- (*output_length)++;
- } while (n != 0);
+ *output_length = 0;
+ u8* output = buffer;
+ u8 byte;
+ do {
+ byte = n & 0x7f;
+ n >>= 7;
+ if (n != 0) byte |= (1 << 7);
+ *output++ = byte;
+ (*output_length)++;
+ } while (n != 0);
- return buffer;
+ return buffer;
}
// Converts a signed integer to the signed LEB128 format
u8* int_to_leb128(i64 n, i32* output_length) {
- static u8 buffer[16];
+ static u8 buffer[16];
- *output_length = 0;
- u8* output = buffer;
- b32 more = 1;
+ *output_length = 0;
+ u8* output = buffer;
+ b32 more = 1;
- i32 size = 64;
+ i32 size = 64;
- u8 byte;
- do {
- byte = n & 0x7f;
- n >>= 7;
+ u8 byte;
+ do {
+ byte = n & 0x7f;
+ n >>= 7;
- more = !(((n == 0) && (byte & 0x40) == 0) || ((n == -1) && (byte & 0x40) != 0));
- if (more)
- byte |= 0x80;
- *output++ = byte;
- (*output_length)++;
- } while (more);
+ more = !(((n == 0) && (byte & 0x40) == 0) || ((n == -1) && (byte & 0x40) != 0));
+ if (more)
+ byte |= 0x80;
+ *output++ = byte;
+ (*output_length)++;
+ } while (more);
- return buffer;
+ return buffer;
}
// NOTE: This assumes the underlying implementation of float on the host
// system is already IEEE-754. This is safe to assume in most cases.
u8* float_to_ieee754(f32 f, b32 reverse) {
- static u8 buffer[4];
+ static u8 buffer[4];
- u8* fmem = (u8*) &f;
+ u8* fmem = (u8*) &f;
if (reverse) {
buffer[0] = fmem[3];
buffer[1] = fmem[2];
buffer[3] = fmem[3];
}
- return buffer;
+ return buffer;
}
u8* double_to_ieee754(f64 f, b32 reverse) {
- static u8 buffer[8];
+ static u8 buffer[8];
- u8* fmem = (u8*) &f;
+ u8* fmem = (u8*) &f;
if (reverse) {
buffer[0] = fmem[7];
buffer[1] = fmem[6];
buffer[7] = fmem[7];
}
- return buffer;
+ return buffer;
}
#ifndef BH_NO_FILE
bh_file_error bh_file_get_standard(bh_file* file, bh_file_standard stand) {
- i32 sd_fd = -1;
- const char* filename = NULL;
-
- switch (stand) {
- case BH_FILE_STANDARD_INPUT:
- sd_fd = STDIN_FILENO;
- filename = "stdin"; // These are constants in the data section so everything should be okay
- break;
- case BH_FILE_STANDARD_OUTPUT:
- sd_fd = STDOUT_FILENO;
- filename = "stdout";
- break;
- case BH_FILE_STANDARD_ERROR:
- sd_fd = STDERR_FILENO;
- filename = "stderr";
- break;
- default:
- return BH_FILE_ERROR_BAD_FD;
- }
-
- file->fd = sd_fd;
- file->filename = filename;
-
- return BH_FILE_ERROR_NONE;
+ i32 sd_fd = -1;
+ const char* filename = NULL;
+
+ switch (stand) {
+ case BH_FILE_STANDARD_INPUT:
+ sd_fd = STDIN_FILENO;
+ filename = "stdin"; // These are constants in the data section so everything should be okay
+ break;
+ case BH_FILE_STANDARD_OUTPUT:
+ sd_fd = STDOUT_FILENO;
+ filename = "stdout";
+ break;
+ case BH_FILE_STANDARD_ERROR:
+ sd_fd = STDERR_FILENO;
+ filename = "stderr";
+ break;
+ default:
+ return BH_FILE_ERROR_BAD_FD;
+ }
+
+ file->fd = sd_fd;
+ file->filename = filename;
+
+ return BH_FILE_ERROR_NONE;
}
bh_file_error bh_file_create(bh_file* file, const char* filename) {
- // Need to do this to avoid compiler complaining about types
- bh_file_mode write_rw = (bh_file_mode) (BH_FILE_MODE_WRITE | BH_FILE_MODE_RW);
- return bh_file_open_mode(file, write_rw, filename);
+ // Need to do this to avoid compiler complaining about types
+ bh_file_mode write_rw = (bh_file_mode) (BH_FILE_MODE_WRITE | BH_FILE_MODE_RW);
+ return bh_file_open_mode(file, write_rw, filename);
}
bh_file_error bh_file_open(bh_file* file, const char* filename) {
- return bh_file_open_mode(file, BH_FILE_MODE_READ, filename);
+ return bh_file_open_mode(file, BH_FILE_MODE_READ, filename);
}
bh_file_error bh_file_open_mode(bh_file* file, bh_file_mode mode, const char* filename) {
- i32 os_mode = 0;
+ i32 os_mode = 0;
- switch (mode & BH_FILE_MODE_MODES) {
- case BH_FILE_MODE_READ: os_mode = O_RDONLY; break;
- case BH_FILE_MODE_WRITE: os_mode = O_WRONLY | O_CREAT | O_TRUNC; break;
- case BH_FILE_MODE_APPEND: os_mode = O_RDONLY | O_APPEND | O_CREAT; break;
- case BH_FILE_MODE_READ | BH_FILE_MODE_RW: os_mode = O_RDWR; break;
- case BH_FILE_MODE_WRITE | BH_FILE_MODE_RW: os_mode = O_RDWR | O_CREAT | O_TRUNC; break;
- case BH_FILE_MODE_APPEND | BH_FILE_MODE_RW: os_mode = O_RDWR | O_APPEND | O_CREAT; break;
- //default: // TODO Handle errors
- }
+ switch (mode & BH_FILE_MODE_MODES) {
+ case BH_FILE_MODE_READ: os_mode = O_RDONLY; break;
+ case BH_FILE_MODE_WRITE: os_mode = O_WRONLY | O_CREAT | O_TRUNC; break;
+ case BH_FILE_MODE_APPEND: os_mode = O_RDONLY | O_APPEND | O_CREAT; break;
+ case BH_FILE_MODE_READ | BH_FILE_MODE_RW: os_mode = O_RDWR; break;
+ case BH_FILE_MODE_WRITE | BH_FILE_MODE_RW: os_mode = O_RDWR | O_CREAT | O_TRUNC; break;
+ case BH_FILE_MODE_APPEND | BH_FILE_MODE_RW: os_mode = O_RDWR | O_APPEND | O_CREAT; break;
+ //default: // TODO Handle errors
+ }
- file->fd = open(filename, os_mode,
- S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP //+rw-rw-rw-
- );
- if (file->fd < 0) {
- return BH_FILE_ERROR_INVALID;
- }
+ file->fd = open(filename, os_mode,
+ S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP //+rw-rw-rw-
+ );
+ if (file->fd < 0) {
+ return BH_FILE_ERROR_INVALID;
+ }
- // TODO: Set this using some allocator
- file->filename = filename;
+ // TODO: Set this using some allocator
+ file->filename = filename;
- return BH_FILE_ERROR_NONE;
+ return BH_FILE_ERROR_NONE;
}
bh_file_error bh_file_new(bh_file* file, bh_file_descriptor fd, const char* filename) {
- file->filename = filename; // This may be unsafe
- file->fd = fd;
- return BH_FILE_ERROR_NONE;
+ file->filename = filename; // This may be unsafe
+ file->fd = fd;
+ return BH_FILE_ERROR_NONE;
}
b32 bh_file_read_at(bh_file* file, i64 offset, void* buffer, isize buff_size, isize* bytes_read) {
- isize res = pread(file->fd, buffer, buff_size, offset);
- if (res < 0) return 0;
- if (bytes_read) *bytes_read = res;
- return 1;
+ isize res = pread(file->fd, buffer, buff_size, offset);
+ if (res < 0) return 0;
+ if (bytes_read) *bytes_read = res;
+ return 1;
}
b32 bh_file_write_at(bh_file* file, i64 offset, void const* buffer, isize buff_size, isize* bytes_wrote) {
- isize res;
- i64 current_offset = 0;
- bh__file_seek_wrapper(file->fd, offset, BH_FILE_WHENCE_CURRENT, ¤t_offset);
- if (current_offset == offset) {
- // Standard in and out do like pwrite()
- res = write(file->fd, buffer, buff_size);
- } else {
- res = pwrite(file->fd, buffer, buff_size, offset);
- }
- if (res < 0) return 0;
- if (bytes_wrote) *bytes_wrote = res;
+ isize res;
+ i64 current_offset = 0;
+ bh__file_seek_wrapper(file->fd, offset, BH_FILE_WHENCE_CURRENT, ¤t_offset);
+ if (current_offset == offset) {
+ // Standard in and out do like pwrite()
+ res = write(file->fd, buffer, buff_size);
+ } else {
+ res = pwrite(file->fd, buffer, buff_size, offset);
+ }
+ if (res < 0) return 0;
+ if (bytes_wrote) *bytes_wrote = res;
- return 1;
+ return 1;
}
static b32 bh__file_seek_wrapper(i32 fd, i64 offset, bh_file_whence whence, i64* new_offset) {
- i64 res = lseek(fd, offset, whence);
- if (res < 0) return 0;
- if (new_offset) *new_offset = res;
- return 1;
+ i64 res = lseek(fd, offset, whence);
+ if (res < 0) return 0;
+ if (new_offset) *new_offset = res;
+ return 1;
}
// Returns new offset
i64 bh_file_seek_to(bh_file* file, i64 offset) {
- i64 new_offset = -1;
- bh__file_seek_wrapper(file->fd, offset, BH_FILE_WHENCE_BEGIN, &new_offset);
- return new_offset;
+ i64 new_offset = -1;
+ bh__file_seek_wrapper(file->fd, offset, BH_FILE_WHENCE_BEGIN, &new_offset);
+ return new_offset;
}
i64 bh_file_seek_to_end(bh_file* file) {
- i64 new_offset = -1;
- bh__file_seek_wrapper(file->fd, 0, BH_FILE_WHENCE_END, &new_offset);
- return new_offset;
+ i64 new_offset = -1;
+ bh__file_seek_wrapper(file->fd, 0, BH_FILE_WHENCE_END, &new_offset);
+ return new_offset;
}
i64 bh_file_skip(bh_file* file, i64 bytes) {
- i64 new_offset = 0;
- bh__file_seek_wrapper(file->fd, bytes, BH_FILE_WHENCE_CURRENT, &new_offset);
- return new_offset;
+ i64 new_offset = 0;
+ bh__file_seek_wrapper(file->fd, bytes, BH_FILE_WHENCE_CURRENT, &new_offset);
+ return new_offset;
}
i64 bh_file_tell(bh_file* file) {
- i64 new_offset = 0;
- bh__file_seek_wrapper(file->fd, 0, BH_FILE_WHENCE_CURRENT, &new_offset);
- return new_offset;
+ i64 new_offset = 0;
+ bh__file_seek_wrapper(file->fd, 0, BH_FILE_WHENCE_CURRENT, &new_offset);
+ return new_offset;
}
bh_file_error bh_file_close(bh_file* file) {
- bh_file_error err = BH_FILE_ERROR_NONE;
- i32 res = close(file->fd);
- if (res < 0)
- err = BH_FILE_ERROR_INVALID;
+ bh_file_error err = BH_FILE_ERROR_NONE;
+ i32 res = close(file->fd);
+ if (res < 0)
+ err = BH_FILE_ERROR_INVALID;
- return err;
+ return err;
}
b32 bh_file_read(bh_file* file, void* buffer, isize buff_size) {
- return bh_file_read_at(file, bh_file_tell(file), buffer, buff_size, NULL);
+ return bh_file_read_at(file, bh_file_tell(file), buffer, buff_size, NULL);
}
b32 bh_file_write(bh_file* file, void* buffer, isize buff_size) {
- return bh_file_write_at(file, bh_file_tell(file), buffer, buff_size, NULL);
+ return bh_file_write_at(file, bh_file_tell(file), buffer, buff_size, NULL);
}
i64 bh_file_size(bh_file* file) {
- i64 size = 0;
- i64 prev = bh_file_tell(file);
- bh_file_seek_to_end(file);
- size = bh_file_tell(file);
- bh_file_seek_to(file, prev);
- return size;
+ i64 size = 0;
+ i64 prev = bh_file_tell(file);
+ bh_file_seek_to_end(file);
+ size = bh_file_tell(file);
+ bh_file_seek_to(file, prev);
+ return size;
}
bh_file_contents bh_file_read_contents_bh_file(bh_allocator alloc, bh_file* file) {
- bh_file_contents fc = {
- .allocator = alloc,
- .filename = file->filename,
- .length = 0, .data = NULL
- };
+ bh_file_contents fc = {
+ .allocator = alloc,
+ .filename = file->filename,
+ .length = 0, .data = NULL
+ };
- isize size = bh_file_size(file);
- if (size <= 0) return fc;
+ isize size = bh_file_size(file);
+ if (size <= 0) return fc;
- fc.data = bh_alloc(alloc, size + 1);
- fc.length = size;
- bh_file_read_at(file, 0, fc.data, fc.length, NULL);
- ((u8*) fc.data)[fc.length] = '\0';
+ fc.data = bh_alloc(alloc, size + 1);
+ fc.length = size;
+ bh_file_read_at(file, 0, fc.data, fc.length, NULL);
+ ((u8*) fc.data)[fc.length] = '\0';
- return fc;
+ return fc;
}
bh_file_contents bh_file_read_contents_direct(bh_allocator alloc, const char* filename) {
- bh_file file;
- bh_file_open(&file, filename);
- bh_file_contents fc = bh_file_read_contents(alloc, &file);
- bh_file_close(&file);
- return fc;
+ bh_file file;
+ bh_file_open(&file, filename);
+ bh_file_contents fc = bh_file_read_contents(alloc, &file);
+ bh_file_close(&file);
+ return fc;
}
b32 bh_file_contents_free(bh_file_contents* contents) {
- bh_free(contents->allocator, contents->data);
- contents->length = 0;
- return 1;
+ bh_free(contents->allocator, contents->data);
+ contents->length = 0;
+ return 1;
}
#endif // ifndef BH_NO_FILE
// ALTERNATE PRINTF IMPLEMENTATION
//-------------------------------------------------------------------------------------
isize bh_printf(char const *fmt, ...) {
- isize res;
- va_list va;
- va_start(va, fmt);
- res = bh_printf_va(fmt, va);
- va_end(va);
- return res;
+ isize res;
+ va_list va;
+ va_start(va, fmt);
+ res = bh_printf_va(fmt, va);
+ va_end(va);
+ return res;
}
isize bh_printf_va(char const *fmt, va_list va) {
- bh_file file;
- bh_file_get_standard(&file, BH_FILE_STANDARD_OUTPUT);
- return bh_fprintf_va(&file, fmt, va);
+ bh_file file;
+ bh_file_get_standard(&file, BH_FILE_STANDARD_OUTPUT);
+ return bh_fprintf_va(&file, fmt, va);
}
isize bh_printf_err(char const *fmt, ...) {
- isize res;
- va_list va;
- va_start(va, fmt);
- res = bh_printf_err_va(fmt, va);
- va_end(va);
- return res;
+ isize res;
+ va_list va;
+ va_start(va, fmt);
+ res = bh_printf_err_va(fmt, va);
+ va_end(va);
+ return res;
}
isize bh_printf_err_va(char const *fmt, va_list va) {
- bh_file file;
- bh_file_get_standard(&file, BH_FILE_STANDARD_ERROR);
- return bh_fprintf_va(&file, fmt, va);
+ bh_file file;
+ bh_file_get_standard(&file, BH_FILE_STANDARD_ERROR);
+ return bh_fprintf_va(&file, fmt, va);
}
isize bh_fprintf(bh_file* f, char const *fmt, ...) {
- isize res;
- va_list va;
- va_start(va, fmt);
- res = bh_fprintf_va(f, fmt, va);
- va_end(va);
- return res;
+ isize res;
+ va_list va;
+ va_start(va, fmt);
+ res = bh_fprintf_va(f, fmt, va);
+ va_end(va);
+ return res;
}
isize bh_fprintf_va(bh_file* f, char const *fmt, va_list va) {
- static char buffer[4096];
- isize len = bh_snprintf_va(buffer, sizeof(buffer), fmt, va);
- bh_file_write(f, buffer, len - 1);
- return len;
+ static char buffer[4096];
+ isize len = bh_snprintf_va(buffer, sizeof(buffer), fmt, va);
+ bh_file_write(f, buffer, len - 1);
+ return len;
}
char* bh_bprintf(char const *fmt, ...) {
- char* res;
- va_list va;
- va_start(va, fmt);
- res = bh_bprintf_va(fmt, va);
- va_end(va);
- return res;
+ char* res;
+ va_list va;
+ va_start(va, fmt);
+ res = bh_bprintf_va(fmt, va);
+ va_end(va);
+ return res;
}
char* bh_bprintf_va(char const *fmt, va_list va) {
- static char buffer[4096];
- bh_snprintf_va(buffer, sizeof(buffer), fmt, va);
- return buffer;
+ static char buffer[4096];
+ bh_snprintf_va(buffer, sizeof(buffer), fmt, va);
+ return buffer;
}
char* bh_aprintf(bh_allocator alloc, const char* fmt, ...) {
- char* res;
- va_list va;
- va_start(va, fmt);
- res = bh_aprintf_va(alloc, fmt, va);
- va_end(va);
- return res;
+ char* res;
+ va_list va;
+ va_start(va, fmt);
+ res = bh_aprintf_va(alloc, fmt, va);
+ va_end(va);
+ return res;
}
char* bh_aprintf_va(bh_allocator alloc, const char* fmt, va_list va) {
- static char buffer[4096];
- isize len = bh_snprintf_va(buffer, sizeof(buffer), fmt, va);
- char* res = bh_alloc(alloc, len);
- memcpy(res, buffer, len);
- res[len - 1] = 0;
- return res;
+ static char buffer[4096];
+ isize len = bh_snprintf_va(buffer, sizeof(buffer), fmt, va);
+ char* res = bh_alloc(alloc, len);
+ memcpy(res, buffer, len);
+ res[len - 1] = 0;
+ return res;
}
isize bh_snprintf(char *str, isize n, char const *fmt, ...) {
- isize res;
- va_list va;
- va_start(va, fmt);
- res = bh_snprintf_va(str, n, fmt, va);
- va_end(va);
- return res;
+ isize res;
+ va_list va;
+ va_start(va, fmt);
+ res = bh_snprintf_va(str, n, fmt, va);
+ va_end(va);
+ return res;
}
isize bh__print_string(char* dest, isize n, char* src) {
- isize len = 0;
- while (n-- && (*dest++ = *src++)) len++;
- return len;
+ isize len = 0;
+ while (n-- && (*dest++ = *src++)) len++;
+ return len;
}
isize bh__printu64(char* str, isize n, bh__print_format format, u64 value) {
- char buf[128];
- buf[127] = 0;
- char* walker = buf + 127;
- u32 base = format.base ? format.base : 10, tmp;
-
- while (value > 0) {
- tmp = value % base;
- if (tmp > 9) {
- switch (tmp) {
- case 10: tmp = 'a'; break;
- case 11: tmp = 'b'; break;
- case 12: tmp = 'c'; break;
- case 13: tmp = 'd'; break;
- case 14: tmp = 'e'; break;
- case 15: tmp = 'f'; break;
- }
- } else {
- tmp += '0';
- }
-
- *--walker = tmp;
- value /= base;
- }
-
- if (format.base == 16) {
- *--walker = 'x';
- *--walker = '0';
- }
-
- return bh__print_string(str, n, walker);
-}
+ char buf[128];
+ buf[127] = 0;
+ char* walker = buf + 127;
+ u32 base = format.base ? format.base : 10, tmp;
+
+ while (value > 0) {
+ tmp = value % base;
+ if (tmp > 9) {
+ switch (tmp) {
+ case 10: tmp = 'a'; break;
+ case 11: tmp = 'b'; break;
+ case 12: tmp = 'c'; break;
+ case 13: tmp = 'd'; break;
+ case 14: tmp = 'e'; break;
+ case 15: tmp = 'f'; break;
+ }
+ } else {
+ tmp += '0';
+ }
-isize bh__printi64(char* str, isize n, bh__print_format format, i64 value) {
- char buf[128];
- buf[127] = 0;
- char* walker = buf + 127;
- u32 base = format.base ? format.base : 10, tmp;
-
- b32 negative = value < 0;
- if (negative) value = -value;
-
- if (value == 0) {
- *--walker = '0';
- } else {
- while (value > 0) {
- tmp = value % base;
- if (tmp > 9) {
- switch (tmp) {
- case 10: tmp = 'a'; break;
- case 11: tmp = 'b'; break;
- case 12: tmp = 'c'; break;
- case 13: tmp = 'd'; break;
- case 14: tmp = 'e'; break;
- case 15: tmp = 'f'; break;
- }
- } else {
- tmp += '0';
- }
-
- *--walker = tmp;
- value /= base;
- }
- }
-
- if (negative) {
- *--walker = '-';
- }
-
- if (format.base == 16) {
- *--walker = 'x';
- *--walker = '0';
- }
-
- return bh__print_string(str, n, walker);
+ *--walker = tmp;
+ value /= base;
+ }
+
+ if (format.base == 16) {
+ *--walker = 'x';
+ *--walker = '0';
+ }
+
+ return bh__print_string(str, n, walker);
}
-// TODO: This is very hacked together but for now it will work.
-isize bh_snprintf_va(char *str, isize n, char const *fmt, va_list va) {
- char const *text_start = str;
- isize res;
+isize bh__printi64(char* str, isize n, bh__print_format format, i64 value) {
+ char buf[128];
+ buf[127] = 0;
+ char* walker = buf + 127;
+ u32 base = format.base ? format.base : 10, tmp;
- while (*fmt) {
- bh__print_format format = { 0 };
- isize len = 0;
+ b32 negative = value < 0;
+ if (negative) value = -value;
- while (*fmt && *fmt != '%') {
- *(str++) = *(fmt++);
- }
+ if (value == 0) {
+ *--walker = '0';
+ } else {
+ while (value > 0) {
+ tmp = value % base;
+ if (tmp > 9) {
+ switch (tmp) {
+ case 10: tmp = 'a'; break;
+ case 11: tmp = 'b'; break;
+ case 12: tmp = 'c'; break;
+ case 13: tmp = 'd'; break;
+ case 14: tmp = 'e'; break;
+ case 15: tmp = 'f'; break;
+ }
+ } else {
+ tmp += '0';
+ }
+
+ *--walker = tmp;
+ value /= base;
+ }
+ }
- if (!*fmt) goto end_of_format;
+ if (negative) {
+ *--walker = '-';
+ }
- fmt++;
+ if (format.base == 16) {
+ *--walker = 'x';
+ *--walker = '0';
+ }
- switch (*fmt++) {
- case 'o': format.base = 8; break;
- case 'x': format.base = 16; break;
- default: fmt--;
- }
+ return bh__print_string(str, n, walker);
+}
- switch (*fmt) {
- case 'c': {
- char c = (char) va_arg(va, int);
- *(str++) = c;
- } break;
+// TODO: This is very hacked together but for now it will work.
+isize bh_snprintf_va(char *str, isize n, char const *fmt, va_list va) {
+ char const *text_start = str;
+ isize res;
- case 'd': {
- i64 value = (i64) va_arg(va, int);
- len = bh__printi64(str, n, format, value);
- } break;
+ while (*fmt) {
+ bh__print_format format = { 0 };
+ isize len = 0;
- case 'l': {
- i64 value = (i64) va_arg(va, long);
- len = bh__printi64(str, n, format, value);
- } break;
+ while (*fmt && *fmt != '%') {
+ *(str++) = *(fmt++);
+ }
- case 'p': {
- u64 value = (u64) va_arg(va, ptr);
- format.base = 16;
- len = bh__printu64(str, n, format, value);
- } break;
+ if (!*fmt) goto end_of_format;
- case 's': {
- char* s = va_arg(va, char *);
- len = bh__print_string(str, n, s);
- } break;
+ fmt++;
- case 'b': { // String with a length (not null terminated)
- char* s = va_arg(va, char *);
- i32 l = va_arg(va, int);
- len = bh__print_string(str, bh_min(l, n), s);
- } break;
+ switch (*fmt++) {
+ case 'o': format.base = 8; break;
+ case 'x': format.base = 16; break;
+ default: fmt--;
+ }
- default: fmt--;
- }
+ switch (*fmt) {
+ case 'c': {
+ char c = (char) va_arg(va, int);
+ *(str++) = c;
+ } break;
+
+ case 'd': {
+ i64 value = (i64) va_arg(va, int);
+ len = bh__printi64(str, n, format, value);
+ } break;
+
+ case 'l': {
+ i64 value = (i64) va_arg(va, long);
+ len = bh__printi64(str, n, format, value);
+ } break;
+
+ case 'p': {
+ u64 value = (u64) va_arg(va, ptr);
+ format.base = 16;
+ len = bh__printu64(str, n, format, value);
+ } break;
+
+ case 's': {
+ char* s = va_arg(va, char *);
+ len = bh__print_string(str, n, s);
+ } break;
+
+ case 'b': { // String with a length (not null terminated)
+ char* s = va_arg(va, char *);
+ i32 l = va_arg(va, int);
+ len = bh__print_string(str, bh_min(l, n), s);
+ } break;
+
+ default: fmt--;
+ }
- fmt++;
+ fmt++;
end_of_format:
- str += len;
- n -= len;
- }
+ str += len;
+ n -= len;
+ }
- return str - text_start + 1;
+ return str - text_start + 1;
}
#ifndef BH_NO_BUFFER
void bh_buffer_init(bh_buffer* buffer, bh_allocator alloc, i32 init_size) {
- buffer->allocator = alloc;
- buffer->length = 0;
- buffer->capacity = init_size;
- buffer->data = bh_alloc(alloc, init_size);
+ buffer->allocator = alloc;
+ buffer->length = 0;
+ buffer->capacity = init_size;
+ buffer->data = bh_alloc(alloc, init_size);
}
void bh_buffer_free(bh_buffer* buffer) {
- bh_free(buffer->allocator, buffer->data);
- buffer->length = 0;
- buffer->capacity = 0;
+ bh_free(buffer->allocator, buffer->data);
+ buffer->length = 0;
+ buffer->capacity = 0;
}
void bh_buffer_grow(bh_buffer* buffer, i32 length) {
- if (buffer == NULL) return;
+ if (buffer == NULL) return;
- if (buffer->capacity >= length) {
- // NOTE: Already have enough room
- return;
- }
+ if (buffer->capacity >= length) {
+ // NOTE: Already have enough room
+ return;
+ }
- i32 newcap = buffer->capacity;
- while (newcap < length) newcap = BH_BUFFER_GROW_FORMULA(newcap);
+ i32 newcap = buffer->capacity;
+ while (newcap < length) newcap = BH_BUFFER_GROW_FORMULA(newcap);
- ptr new_data = bh_resize(buffer->allocator, buffer->data, newcap);
- if (new_data == NULL) return;
+ ptr new_data = bh_resize(buffer->allocator, buffer->data, newcap);
+ if (new_data == NULL) return;
- buffer->capacity = newcap;
- buffer->data = new_data;
+ buffer->capacity = newcap;
+ buffer->data = new_data;
}
void bh_buffer_append(bh_buffer* buffer, const void * data, i32 length) {
- if (buffer == NULL) return;
+ if (buffer == NULL) return;
- if (buffer->length + length > buffer->capacity) {
- bh_buffer_grow(buffer, buffer->length + length);
- }
+ if (buffer->length + length > buffer->capacity) {
+ bh_buffer_grow(buffer, buffer->length + length);
+ }
- memcpy(buffer->data + buffer->length, data, length);
- buffer->length += length;
+ memcpy(buffer->data + buffer->length, data, length);
+ buffer->length += length;
}
void bh_buffer_concat(bh_buffer* buffer, bh_buffer other) {
- bh_buffer_append(buffer, other.data, other.length);
+ bh_buffer_append(buffer, other.data, other.length);
}
void bh_buffer_write_byte(bh_buffer* buffer, u8 byte) {
- bh_buffer_grow(buffer, buffer->length + 1);
- buffer->data[buffer->length++] = byte;
+ bh_buffer_grow(buffer, buffer->length + 1);
+ buffer->data[buffer->length++] = byte;
}
#ifndef BH_NO_ARRAY
b32 bh__arr_grow(bh_allocator alloc, void** arr, i32 elemsize, i32 cap) {
- bh__arr* arrptr;
+ bh__arr* arrptr;
- if (*arr == NULL) {
- if (cap == 0 && elemsize == 0) return 1;
+ if (*arr == NULL) {
+ if (cap == 0 && elemsize == 0) return 1;
- arrptr = (bh__arr *) bh_alloc(alloc, sizeof(*arrptr) + elemsize * cap);
- if (arrptr == NULL) return 0;
+ arrptr = (bh__arr *) bh_alloc(alloc, sizeof(*arrptr) + elemsize * cap);
+ if (arrptr == NULL) return 0;
- arrptr->allocator = alloc;
- arrptr->capacity = cap;
- arrptr->length = 0;
+ arrptr->allocator = alloc;
+ arrptr->capacity = cap;
+ arrptr->length = 0;
- } else {
- arrptr = bh__arrhead(*arr);
+ } else {
+ arrptr = bh__arrhead(*arr);
- if (arrptr->capacity < cap) {
- void* p;
- i32 newcap = arrptr->capacity;
- while (newcap < cap) newcap = BH_ARR_GROW_FORMULA(newcap);
+ if (arrptr->capacity < cap) {
+ void* p;
+ i32 newcap = arrptr->capacity;
+ while (newcap < cap) newcap = BH_ARR_GROW_FORMULA(newcap);
- p = bh_resize(arrptr->allocator, arrptr, sizeof(*arrptr) + elemsize * newcap);
+ p = bh_resize(arrptr->allocator, arrptr, sizeof(*arrptr) + elemsize * newcap);
- if (p) {
- arrptr = (bh__arr *) p;
- arrptr->capacity = newcap;
- } else {
- return 0;
- }
- }
- }
+ if (p) {
+ arrptr = (bh__arr *) p;
+ arrptr->capacity = newcap;
+ } else {
+ return 0;
+ }
+ }
+ }
- *arr = arrptr + 1;
- return 1;
+ *arr = arrptr + 1;
+ return 1;
}
b32 bh__arr_shrink(void** arr, i32 elemsize, i32 cap) {
- if (*arr == NULL) return 0;
+ if (*arr == NULL) return 0;
- bh__arr* arrptr = bh__arrhead(*arr);
- cap = bh_max(cap, arrptr->length);
+ bh__arr* arrptr = bh__arrhead(*arr);
+ cap = bh_max(cap, arrptr->length);
- if (arrptr->capacity > cap) {
- void* p = bh_resize(arrptr->allocator, arrptr, sizeof(*arrptr) + elemsize * cap);
+ if (arrptr->capacity > cap) {
+ void* p = bh_resize(arrptr->allocator, arrptr, sizeof(*arrptr) + elemsize * cap);
- if (p) {
- arrptr = (bh__arr *) p;
- arrptr->capacity = cap;
- } else {
- return 0;
- }
- }
+ if (p) {
+ arrptr = (bh__arr *) p;
+ arrptr->capacity = cap;
+ } else {
+ return 0;
+ }
+ }
- *arr = arrptr + 1;
- return 1;
+ *arr = arrptr + 1;
+ return 1;
}
b32 bh__arr_free(void **arr) {
if (*arr == NULL) return 0;
- bh__arr* arrptr = bh__arrhead(*arr);
- bh_free(arrptr->allocator, arrptr);
- *arr = NULL;
+ bh__arr* arrptr = bh__arrhead(*arr);
+ bh_free(arrptr->allocator, arrptr);
+ *arr = NULL;
}
void* bh__arr_copy(bh_allocator alloc, void *arr, i32 elemsize) {
- bh__arr* arrptr = bh__arrhead(arr);
+ bh__arr* arrptr = bh__arrhead(arr);
- const i32 cap = arrptr->length;
+ const i32 cap = arrptr->length;
- void* newarr = NULL;
- bh__arr_grow(alloc, &newarr, elemsize, cap);
- bh__arrhead(newarr)->length = cap;
- bh__arrhead(newarr)->capacity = cap;
- memcpy(newarr, arr, elemsize * arrptr->length);
+ void* newarr = NULL;
+ bh__arr_grow(alloc, &newarr, elemsize, cap);
+ bh__arrhead(newarr)->length = cap;
+ bh__arrhead(newarr)->capacity = cap;
+ memcpy(newarr, arr, elemsize * arrptr->length);
- return newarr;
+ return newarr;
}
void bh__arr_deleten(void **arr, i32 elemsize, i32 index, i32 numelems) {
- bh__arr* arrptr = bh__arrhead(*arr);
+ bh__arr* arrptr = bh__arrhead(*arr);
- if (index >= arrptr->length) return; // Can't delete past the end of the array
- if (numelems <= 0) return; // Can't delete nothing
+ if (index >= arrptr->length) return; // Can't delete past the end of the array
+ if (numelems <= 0) return; // Can't delete nothing
- memmove(
- (char *)(*arr) + elemsize * index, // Target
- (char *)(*arr) + elemsize * (index + numelems), // Source
- elemsize * (arrptr->length - (index + numelems))); // Length
- arrptr->length -= numelems;
+ memmove(
+ (char *)(*arr) + elemsize * index, // Target
+ (char *)(*arr) + elemsize * (index + numelems), // Source
+ elemsize * (arrptr->length - (index + numelems))); // Length
+ arrptr->length -= numelems;
}
void bh__arr_insertn(void **arr, i32 elemsize, i32 index, i32 numelems) {
- if (numelems) {
- if (*arr == NULL) {
- bh__arr_grow(bh_arr_allocator(arr), arr, elemsize, numelems); // Making a new array
- return;
- }
-
- 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,
- elemsize * (arrptr->length - index));
- arrptr->length += numelems;
- }
+ if (numelems) {
+ if (*arr == NULL) {
+ bh__arr_grow(bh_arr_allocator(arr), arr, elemsize, numelems); // Making a new array
+ return;
+ }
+
+ 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,
+ elemsize * (arrptr->length - index));
+ arrptr->length += numelems;
+ }
}
#endif // ifndef BH_NO_ARRAY
#ifndef BH_NO_TABLE
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 = bh_alloc(allocator, sizeof(bh__table) + sizeof(ptr) * table_size);
+ if (*table == NULL) return 0;
- (*table)->allocator = allocator;
- (*table)->table_size = table_size;
+ (*table)->allocator = allocator;
+ (*table)->table_size = table_size;
- for (i32 i = 0; i < table_size; i++) {
- (*table)->arrs[i] = NULL;
- }
+ for (i32 i = 0; i < table_size; i++) {
+ (*table)->arrs[i] = NULL;
+ }
- return 1;
+ return 1;
}
b32 bh__table_free(bh__table **table) {
if (*table == NULL) return 0;
- for (i32 i = 0; i < (*table)->table_size; i++) {
- if ((*table)->arrs[i] != NULL) {
- bh_arr_free((*table)->arrs[i]);
- }
- }
+ for (i32 i = 0; i < (*table)->table_size; i++) {
+ if ((*table)->arrs[i] != NULL) {
+ bh_arr_free((*table)->arrs[i]);
+ }
+ }
- bh_free((*table)->allocator, *table);
- *table = NULL;
+ bh_free((*table)->allocator, *table);
+ *table = NULL;
}
// Assumes NULL terminated string for key
ptr bh__table_put(bh__table *table, i32 elemsize, char *key) {
- elemsize += (elemsize & 1);
-
- u64 index = bh__table_hash_function(key, 0, table->table_size);
- u8 arr_was_new = 0;
-
- ptr arrptr = table->arrs[index];
- if (arrptr == NULL) {
- arr_was_new = 1;
- goto add_new_element;
- }
- u64 len = *(u64 *) arrptr;
- arrptr = bh_pointer_add(arrptr, sizeof(u64));
-
- u16 key_length = 0;
- while (len--) {
- arrptr = bh_pointer_add(arrptr, elemsize);
- key_length = *(u16 *) arrptr;
- arrptr = bh_pointer_add(arrptr, sizeof(u16));
- if (strncmp(key, (char *) arrptr, key_length) == 0) goto found_matching;
- arrptr = bh_pointer_add(arrptr, key_length);
- }
+ elemsize += (elemsize & 1);
+
+ u64 index = bh__table_hash_function(key, 0, table->table_size);
+ u8 arr_was_new = 0;
+
+ ptr arrptr = table->arrs[index];
+ if (arrptr == NULL) {
+ arr_was_new = 1;
+ goto add_new_element;
+ }
+ u64 len = *(u64 *) arrptr;
+ arrptr = bh_pointer_add(arrptr, sizeof(u64));
+
+ u16 key_length = 0;
+ while (len--) {
+ arrptr = bh_pointer_add(arrptr, elemsize);
+ key_length = *(u16 *) arrptr;
+ arrptr = bh_pointer_add(arrptr, sizeof(u16));
+ if (strncmp(key, (char *) arrptr, key_length) == 0) goto found_matching;
+ arrptr = bh_pointer_add(arrptr, key_length);
+ }
add_new_element:
- arrptr = table->arrs[index];
- i32 byte_len = bh_arr_length(arrptr);
- if (byte_len == 0) byte_len = sizeof(u64);
- key_length = strlen(key) + 1;
-
- // NOTE: Align to 16 bytes
- if ((key_length + 2) % 16 != 0) {
- key_length = ((((key_length + 2) >> 4) + 1) << 4) - 2;
- }
-
- bh__arr_grow(table->allocator, &arrptr, 1, byte_len + elemsize + sizeof(u16) + key_length);
- bh__arrhead(arrptr)->length = byte_len + elemsize + sizeof(u16) + key_length;
- table->arrs[index] = arrptr;
-
- if (arr_was_new) {
- *(u64 *) arrptr = 1;
- } else {
- (*(u64 *) arrptr)++;
- }
-
- arrptr = bh_pointer_add(arrptr, byte_len + elemsize);
- *(u16 *) arrptr = key_length;
- arrptr = bh_pointer_add(arrptr, sizeof(u16));
- strncpy(arrptr, key, key_length);
+ arrptr = table->arrs[index];
+ i32 byte_len = bh_arr_length(arrptr);
+ if (byte_len == 0) byte_len = sizeof(u64);
+ key_length = strlen(key) + 1;
+
+ // NOTE: Align to 16 bytes
+ if ((key_length + 2) % 16 != 0) {
+ key_length = ((((key_length + 2) >> 4) + 1) << 4) - 2;
+ }
+
+ bh__arr_grow(table->allocator, &arrptr, 1, byte_len + elemsize + sizeof(u16) + key_length);
+ bh__arrhead(arrptr)->length = byte_len + elemsize + sizeof(u16) + key_length;
+ table->arrs[index] = arrptr;
+
+ if (arr_was_new) {
+ *(u64 *) arrptr = 1;
+ } else {
+ (*(u64 *) arrptr)++;
+ }
+
+ arrptr = bh_pointer_add(arrptr, byte_len + elemsize);
+ *(u16 *) arrptr = key_length;
+ arrptr = bh_pointer_add(arrptr, sizeof(u16));
+ strncpy(arrptr, key, key_length);
found_matching:
- return bh_pointer_add(arrptr, -(sizeof(u16) + elemsize));
+ return bh_pointer_add(arrptr, -(sizeof(u16) + elemsize));
}
b32 bh__table_has(bh__table *table, i32 elemsize, char *key) {
- elemsize += (elemsize & 1);
+ elemsize += (elemsize & 1);
- u64 index = bh__table_hash_function(key, 0, table->table_size);
+ u64 index = bh__table_hash_function(key, 0, table->table_size);
- ptr arrptr = table->arrs[index];
- if (arrptr == NULL) return 0;
+ ptr arrptr = table->arrs[index];
+ if (arrptr == NULL) return 0;
- u64 len = *(u64 *) arrptr;
- arrptr = bh_pointer_add(arrptr, sizeof(u64));
+ u64 len = *(u64 *) arrptr;
+ arrptr = bh_pointer_add(arrptr, sizeof(u64));
- u16 key_length = 0;
- while (len--) {
- arrptr = bh_pointer_add(arrptr, elemsize);
- key_length = *(u16 *) arrptr;
- arrptr = bh_pointer_add(arrptr, sizeof(u16));
- if (strncmp(key, (char *) arrptr, key_length) == 0) return 1;
- arrptr = bh_pointer_add(arrptr, key_length);
- }
+ u16 key_length = 0;
+ while (len--) {
+ arrptr = bh_pointer_add(arrptr, elemsize);
+ key_length = *(u16 *) arrptr;
+ arrptr = bh_pointer_add(arrptr, sizeof(u16));
+ if (strncmp(key, (char *) arrptr, key_length) == 0) return 1;
+ arrptr = bh_pointer_add(arrptr, key_length);
+ }
- return 0;
+ return 0;
}
ptr bh__table_get(bh__table *table, i32 elemsize, char *key) {
- elemsize += (elemsize & 1);
+ elemsize += (elemsize & 1);
- u64 index = bh__table_hash_function(key, 0, table->table_size);
+ u64 index = bh__table_hash_function(key, 0, table->table_size);
- ptr arrptr = table->arrs[index];
- if (arrptr == NULL) return 0;
+ ptr arrptr = table->arrs[index];
+ if (arrptr == NULL) return 0;
- u64 len = *(u64 *) arrptr;
- arrptr = bh_pointer_add(arrptr, sizeof(u64));
+ u64 len = *(u64 *) arrptr;
+ arrptr = bh_pointer_add(arrptr, sizeof(u64));
- u16 key_length = 0;
- while (len--) {
- arrptr = bh_pointer_add(arrptr, elemsize);
- key_length = *(u16 *) arrptr;
- arrptr = bh_pointer_add(arrptr, sizeof(u16));
- if (strncmp(key, (char *) arrptr, key_length) == 0) {
- return bh_pointer_add(arrptr, -(sizeof(u16) + elemsize));
- }
- arrptr = bh_pointer_add(arrptr, key_length);
- }
+ u16 key_length = 0;
+ while (len--) {
+ arrptr = bh_pointer_add(arrptr, elemsize);
+ key_length = *(u16 *) arrptr;
+ arrptr = bh_pointer_add(arrptr, sizeof(u16));
+ if (strncmp(key, (char *) arrptr, key_length) == 0) {
+ return bh_pointer_add(arrptr, -(sizeof(u16) + elemsize));
+ }
+ arrptr = bh_pointer_add(arrptr, key_length);
+ }
- return NULL;
+ return NULL;
}
void bh__table_delete(bh__table *table, i32 elemsize, char *key) {
- elemsize += (elemsize & 1);
+ elemsize += (elemsize & 1);
- u64 index = bh__table_hash_function(key, 0, table->table_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
- walker = arrptr;
+ ptr arrptr = table->arrs[index], walker;
+ if (arrptr == NULL) return; // Didn't exist
+ walker = arrptr;
- i32 byte_offset = 8;
- i32 delete_len = 0;
+ i32 byte_offset = 8;
+ i32 delete_len = 0;
- u64 len = *(u64 *) walker;
- walker = bh_pointer_add(walker, sizeof(u64));
+ u64 len = *(u64 *) walker;
+ walker = bh_pointer_add(walker, sizeof(u64));
- u16 key_length = 0;
- while (len--) {
- walker = bh_pointer_add(walker, elemsize);
- key_length = *(u16 *) walker;
- walker = bh_pointer_add(walker, sizeof(u16));
- if (strncmp(key, (char *) walker, key_length) == 0) {
- delete_len = elemsize + sizeof(u16) + key_length;
- goto found_matching;
- }
- walker = bh_pointer_add(walker, key_length);
- byte_offset += elemsize + sizeof(u16) + key_length;
- }
+ u16 key_length = 0;
+ while (len--) {
+ walker = bh_pointer_add(walker, elemsize);
+ key_length = *(u16 *) walker;
+ walker = bh_pointer_add(walker, sizeof(u16));
+ if (strncmp(key, (char *) walker, key_length) == 0) {
+ delete_len = elemsize + sizeof(u16) + key_length;
+ goto found_matching;
+ }
+ walker = bh_pointer_add(walker, key_length);
+ byte_offset += elemsize + sizeof(u16) + key_length;
+ }
- // NOTE: Already didn't exist
- return;
+ // NOTE: Already didn't exist
+ return;
found_matching:
- bh__arr_deleten((void **) &arrptr, 1, byte_offset, delete_len);
- table->arrs[index] = arrptr;
- (*(u64 *) arrptr)--;
+ bh__arr_deleten((void **) &arrptr, 1, byte_offset, delete_len);
+ table->arrs[index] = arrptr;
+ (*(u64 *) arrptr)--;
}
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_arr_set_length(table->arrs[i], 0);
- }
- }
+ 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_arr_set_length(table->arrs[i], 0);
+ }
+ }
}
bh_table_iterator bh__table_iter_setup(bh__table *table, i32 elemsize) {
- elemsize += (elemsize & 1);
+ elemsize += (elemsize & 1);
- bh_table_iterator it = {
- .tab = table->arrs,
- .endtab = table->arrs + table->table_size,
- .elemsize = elemsize,
- .entry = NULL
- };
- return it;
+ bh_table_iterator it = {
+ .tab = table->arrs,
+ .endtab = table->arrs + table->table_size,
+ .elemsize = elemsize,
+ .entry = NULL
+ };
+ return it;
}
b32 bh_table_iter_next(bh_table_iterator* it) {
- if (it->tab == NULL) return 0;
+ if (it->tab == NULL) return 0;
- if (it->entry != NULL) {
- it->arrlen--;
- if (it->arrlen <= 0) {
- it->tab++;
- goto step_to_next;
- }
+ if (it->entry != NULL) {
+ it->arrlen--;
+ if (it->arrlen <= 0) {
+ it->tab++;
+ goto step_to_next;
+ }
- it->entry = bh_pointer_add(it->entry, it->elemsize);
- it->entry = bh_pointer_add(it->entry, sizeof(u16) + (*(u16 *) it->entry));
- return 1;
- }
+ it->entry = bh_pointer_add(it->entry, it->elemsize);
+ it->entry = bh_pointer_add(it->entry, sizeof(u16) + (*(u16 *) it->entry));
+ return 1;
+ }
step_to_next:
- // Step forward to find next valid
- while (*it->tab == NULL && it->tab != it->endtab) {
- it->tab++;
- }
-
- if (it->tab == it->endtab) return 0;
-
- it->entry = *it->tab;
- it->arrlen = *(u64 *) it->entry;
- it->entry = bh_pointer_add(it->entry, sizeof(u64));
- if (it->arrlen <= 0) {
- it->tab++;
- goto step_to_next;
- }
- return 1;
+ // Step forward to find next valid
+ while (*it->tab == NULL && it->tab != it->endtab) {
+ it->tab++;
+ }
+
+ if (it->tab == it->endtab) return 0;
+
+ it->entry = *it->tab;
+ it->arrlen = *(u64 *) it->entry;
+ it->entry = bh_pointer_add(it->entry, sizeof(u64));
+ if (it->arrlen <= 0) {
+ it->tab++;
+ goto step_to_next;
+ }
+ return 1;
}
#endif // ifndef BH_NO_HASHTABLE
#include "bh.h"
typedef enum OnyxTokenType {
- TOKEN_TYPE_UNKNOWN,
- TOKEN_TYPE_END_STREAM,
-
- TOKEN_TYPE_COMMENT,
-
- TOKEN_TYPE_KEYWORD_STRUCT,
- TOKEN_TYPE_KEYWORD_USE,
- TOKEN_TYPE_KEYWORD_EXPORT,
- TOKEN_TYPE_KEYWORD_IF,
- TOKEN_TYPE_KEYWORD_ELSE,
- TOKEN_TYPE_KEYWORD_ELSEIF,
- TOKEN_TYPE_KEYWORD_RETURN,
- TOKEN_TYPE_KEYWORD_FOREIGN,
- TOKEN_TYPE_KEYWORD_PROC,
- TOKEN_TYPE_KEYWORD_CAST,
+ TOKEN_TYPE_UNKNOWN,
+ TOKEN_TYPE_END_STREAM,
+
+ TOKEN_TYPE_COMMENT,
+
+ TOKEN_TYPE_KEYWORD_STRUCT,
+ TOKEN_TYPE_KEYWORD_USE,
+ TOKEN_TYPE_KEYWORD_EXPORT,
+ TOKEN_TYPE_KEYWORD_IF,
+ TOKEN_TYPE_KEYWORD_ELSE,
+ TOKEN_TYPE_KEYWORD_ELSEIF,
+ TOKEN_TYPE_KEYWORD_RETURN,
+ TOKEN_TYPE_KEYWORD_FOREIGN,
+ TOKEN_TYPE_KEYWORD_PROC,
+ TOKEN_TYPE_KEYWORD_CAST,
TOKEN_TYPE_KEYWORD_WHILE,
TOKEN_TYPE_KEYWORD_BREAK,
TOKEN_TYPE_KEYWORD_CONTINUE,
- TOKEN_TYPE_RIGHT_ARROW,
- TOKEN_TYPE_LEFT_ARROW,
- TOKEN_TYPE_OPEN_PAREN,
- TOKEN_TYPE_CLOSE_PAREN,
- TOKEN_TYPE_OPEN_BRACE,
- TOKEN_TYPE_CLOSE_BRACE,
- TOKEN_TYPE_OPEN_BRACKET,
- TOKEN_TYPE_CLOSE_BRACKET,
-
- TOKEN_TYPE_SYM_PLUS,
- TOKEN_TYPE_SYM_MINUS,
- TOKEN_TYPE_SYM_STAR,
- TOKEN_TYPE_SYM_PERCENT,
- TOKEN_TYPE_SYM_DOT,
- TOKEN_TYPE_SYM_FSLASH,
- TOKEN_TYPE_SYM_BSLASH,
- TOKEN_TYPE_SYM_COLON,
- TOKEN_TYPE_SYM_SEMICOLON,
- TOKEN_TYPE_SYM_COMMA,
- TOKEN_TYPE_SYM_GREATER,
- TOKEN_TYPE_SYM_GREATER_EQUAL,
- TOKEN_TYPE_SYM_LESS,
- TOKEN_TYPE_SYM_LESS_EQUAL,
- TOKEN_TYPE_SYM_EQUAL_EQUAL,
- TOKEN_TYPE_SYM_NOT_EQUAL,
- TOKEN_TYPE_SYM_EQUALS,
- TOKEN_TYPE_SYM_TILDE,
- TOKEN_TYPE_SYM_BANG,
- TOKEN_TYPE_SYM_CARET,
- TOKEN_TYPE_SYM_AMPERSAND,
-
- TOKEN_TYPE_SYMBOL,
- TOKEN_TYPE_LITERAL_STRING,
- TOKEN_TYPE_LITERAL_NUMERIC,
+ TOKEN_TYPE_RIGHT_ARROW,
+ TOKEN_TYPE_LEFT_ARROW,
+ TOKEN_TYPE_OPEN_PAREN,
+ TOKEN_TYPE_CLOSE_PAREN,
+ TOKEN_TYPE_OPEN_BRACE,
+ TOKEN_TYPE_CLOSE_BRACE,
+ TOKEN_TYPE_OPEN_BRACKET,
+ TOKEN_TYPE_CLOSE_BRACKET,
+
+ TOKEN_TYPE_SYM_PLUS,
+ TOKEN_TYPE_SYM_MINUS,
+ TOKEN_TYPE_SYM_STAR,
+ TOKEN_TYPE_SYM_PERCENT,
+ TOKEN_TYPE_SYM_DOT,
+ TOKEN_TYPE_SYM_FSLASH,
+ TOKEN_TYPE_SYM_BSLASH,
+ TOKEN_TYPE_SYM_COLON,
+ TOKEN_TYPE_SYM_SEMICOLON,
+ TOKEN_TYPE_SYM_COMMA,
+ TOKEN_TYPE_SYM_GREATER,
+ TOKEN_TYPE_SYM_GREATER_EQUAL,
+ TOKEN_TYPE_SYM_LESS,
+ TOKEN_TYPE_SYM_LESS_EQUAL,
+ TOKEN_TYPE_SYM_EQUAL_EQUAL,
+ TOKEN_TYPE_SYM_NOT_EQUAL,
+ TOKEN_TYPE_SYM_EQUALS,
+ TOKEN_TYPE_SYM_TILDE,
+ TOKEN_TYPE_SYM_BANG,
+ TOKEN_TYPE_SYM_CARET,
+ TOKEN_TYPE_SYM_AMPERSAND,
+
+ TOKEN_TYPE_SYMBOL,
+ TOKEN_TYPE_LITERAL_STRING,
+ TOKEN_TYPE_LITERAL_NUMERIC,
TOKEN_TYPE_LITERAL_BOOL_TRUE,
TOKEN_TYPE_LITERAL_BOOL_FALSE,
- TOKEN_TYPE_COUNT
+ TOKEN_TYPE_COUNT
} OnyxTokenType;
typedef struct OnyxFilePos {
- const char* filename;
- u64 line, column;
+ const char* filename;
+ u64 line, column;
} OnyxFilePos;
typedef struct OnyxToken {
- OnyxTokenType type;
- i32 length;
- char* token;
- OnyxFilePos pos;
+ OnyxTokenType type;
+ i32 length;
+ char* token;
+ OnyxFilePos pos;
} OnyxToken;
typedef struct OnyxTokenizer {
- char *start, *curr, *end;
+ char *start, *curr, *end;
- const char* filename;
+ const char* filename;
- char* line_start;
- u64 line_number;
+ char* line_start;
+ u64 line_number;
- bh_arr(OnyxToken) tokens;
+ bh_arr(OnyxToken) tokens;
} OnyxTokenizer;
const char* onyx_get_token_type_name(OnyxTokenType tkn_type);
typedef enum OnyxMessageType {
ONYX_MESSAGE_TYPE_LITERAL,
- ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
- ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
- ONYX_MESSAGE_TYPE_UNKNOWN_TYPE,
- ONYX_MESSAGE_TYPE_NOT_LVAL,
- ONYX_MESSAGE_TYPE_ASSIGN_CONST,
- ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL,
- ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION,
- ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
- ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH,
- ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
+ ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
+ ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
+ ONYX_MESSAGE_TYPE_UNKNOWN_TYPE,
+ ONYX_MESSAGE_TYPE_NOT_LVAL,
+ ONYX_MESSAGE_TYPE_ASSIGN_CONST,
+ ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL,
+ ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION,
+ ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
+ ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH,
+ ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION,
ONYX_MESSAGE_TYPE_FUNCTION_RETURN_MISMATCH,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
- ONYX_MESSAGE_TYPE_COUNT,
+ ONYX_MESSAGE_TYPE_COUNT,
} OnyxMessageType;
typedef struct OnyxMessage {
- OnyxMessageType type;
- OnyxFilePos pos;
- struct OnyxMessage* next;
- char text[ONYX_MSG_BUFFER_SIZE];
+ OnyxMessageType type;
+ OnyxFilePos pos;
+ struct OnyxMessage* next;
+ char text[ONYX_MSG_BUFFER_SIZE];
} OnyxMessage;
typedef struct OnyxMessages {
- bh_allocator allocator;
+ bh_allocator allocator;
- OnyxMessage* first;
+ OnyxMessage* first;
} OnyxMessages;
void onyx_message_add(OnyxMessages* msgs, OnyxMessageType type, OnyxFilePos pos, ...);
#ifndef ONYXPARSER_H
+ negate_node->operation = ONYX_UNARY_OP_NEGATE;
#define ONYXPARSER_H
#include "bh.h"
typedef struct OnyxAstNodeFile OnyxAstNodeFile;
typedef struct OnyxParser {
- OnyxTokenizer *tokenizer; // NOTE: not used since all tokens are lexed before parsing starts
- OnyxToken *prev_token;
- OnyxToken *curr_token;
+ OnyxTokenizer *tokenizer; // NOTE: not used since all tokens are lexed before parsing starts
+ OnyxToken *prev_token;
+ OnyxToken *curr_token;
// NOTE: Identifiers currently is only used to resolve type names
// at parse time, since these are the only symbols we know.
bh_table(OnyxAstNode *) identifiers;
- OnyxMessages *msgs;
+ OnyxMessages *msgs;
- bh_allocator allocator;
+ bh_allocator allocator;
} OnyxParser;
typedef enum OnyxAstNodeKind {
- ONYX_AST_NODE_KIND_ERROR,
- ONYX_AST_NODE_KIND_PROGRAM,
+ ONYX_AST_NODE_KIND_ERROR,
+ ONYX_AST_NODE_KIND_PROGRAM,
- ONYX_AST_NODE_KIND_FUNCDEF,
+ ONYX_AST_NODE_KIND_FUNCDEF,
ONYX_AST_NODE_KIND_FOREIGN,
- ONYX_AST_NODE_KIND_BLOCK,
- ONYX_AST_NODE_KIND_SCOPE,
- ONYX_AST_NODE_KIND_LOCAL,
+ ONYX_AST_NODE_KIND_BLOCK,
+ ONYX_AST_NODE_KIND_SCOPE,
+ ONYX_AST_NODE_KIND_LOCAL,
ONYX_AST_NODE_KIND_SYMBOL,
ONYX_AST_NODE_KIND_UNARY_OP,
ONYX_AST_NODE_KIND_BIN_OP,
- ONYX_AST_NODE_KIND_TYPE,
- ONYX_AST_NODE_KIND_LITERAL,
- ONYX_AST_NODE_KIND_PARAM,
+ ONYX_AST_NODE_KIND_TYPE,
+ ONYX_AST_NODE_KIND_LITERAL,
+ ONYX_AST_NODE_KIND_PARAM,
ONYX_AST_NODE_KIND_ARGUMENT,
- ONYX_AST_NODE_KIND_CALL,
- ONYX_AST_NODE_KIND_ASSIGNMENT,
- ONYX_AST_NODE_KIND_RETURN,
+ ONYX_AST_NODE_KIND_CALL,
+ ONYX_AST_NODE_KIND_ASSIGNMENT,
+ ONYX_AST_NODE_KIND_RETURN,
- ONYX_AST_NODE_KIND_IF,
- ONYX_AST_NODE_KIND_WHILE,
+ ONYX_AST_NODE_KIND_IF,
+ ONYX_AST_NODE_KIND_WHILE,
ONYX_AST_NODE_KIND_BREAK,
ONYX_AST_NODE_KIND_CONTINUE,
- ONYX_AST_NODE_KIND_COUNT
+ ONYX_AST_NODE_KIND_COUNT
} OnyxAstNodeKind;
typedef enum OnyxTypeInfoKind {
- ONYX_TYPE_INFO_KIND_UNKNOWN,
- ONYX_TYPE_INFO_KIND_VOID,
- ONYX_TYPE_INFO_KIND_BOOL,
+ ONYX_TYPE_INFO_KIND_UNKNOWN,
+ ONYX_TYPE_INFO_KIND_VOID,
+ ONYX_TYPE_INFO_KIND_BOOL,
- ONYX_TYPE_INFO_KIND_UINT32,
- ONYX_TYPE_INFO_KIND_UINT64,
+ ONYX_TYPE_INFO_KIND_UINT32,
+ ONYX_TYPE_INFO_KIND_UINT64,
- ONYX_TYPE_INFO_KIND_INT32,
- ONYX_TYPE_INFO_KIND_INT64,
+ ONYX_TYPE_INFO_KIND_INT32,
+ ONYX_TYPE_INFO_KIND_INT64,
- ONYX_TYPE_INFO_KIND_FLOAT32,
- ONYX_TYPE_INFO_KIND_FLOAT64,
- ONYX_TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit
+ ONYX_TYPE_INFO_KIND_FLOAT32,
+ ONYX_TYPE_INFO_KIND_FLOAT64,
+ ONYX_TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit
} OnyxTypeInfoKind;
typedef struct OnyxTypeInfo {
- OnyxTypeInfoKind kind;
- u32 size; // in bytes
- const char* name;
- u32 is_int : 1;
- u32 is_unsigned : 1;
- u32 is_float : 1;
- u32 is_bool : 1;
- u32 is_known : 1;
+ OnyxTypeInfoKind kind;
+ u32 size; // in bytes
+ const char* name;
+ u32 is_int : 1;
+ u32 is_unsigned : 1;
+ u32 is_float : 1;
+ u32 is_bool : 1;
+ u32 is_known : 1;
} OnyxTypeInfo;
extern OnyxTypeInfo builtin_types[];
// NOTE: Some of these flags will overlap since there are
// only 32-bits of flags to play with
typedef enum OnyxAstFlags {
- // Top-level flags
- ONYX_AST_FLAG_EXPORTED = BH_BIT(0),
- ONYX_AST_FLAG_LVAL = BH_BIT(1),
- ONYX_AST_FLAG_CONST = BH_BIT(2),
- ONYX_AST_FLAG_COMPTIME = BH_BIT(3),
+ // Top-level flags
+ ONYX_AST_FLAG_EXPORTED = BH_BIT(0),
+ ONYX_AST_FLAG_LVAL = BH_BIT(1),
+ ONYX_AST_FLAG_CONST = BH_BIT(2),
+ ONYX_AST_FLAG_COMPTIME = BH_BIT(3),
} OnyxAstFlags;
typedef enum OnyxUnaryOp {
ONYX_BINARY_OP_DIVIDE,
ONYX_BINARY_OP_MODULUS,
- ONYX_BINARY_OP_EQUAL,
- ONYX_BINARY_OP_NOT_EQUAL,
- ONYX_BINARY_OP_LESS,
- ONYX_BINARY_OP_LESS_EQUAL,
- ONYX_BINARY_OP_GREATER,
- ONYX_BINARY_OP_GREATER_EQUAL,
+ ONYX_BINARY_OP_EQUAL,
+ ONYX_BINARY_OP_NOT_EQUAL,
+ ONYX_BINARY_OP_LESS,
+ ONYX_BINARY_OP_LESS_EQUAL,
+ ONYX_BINARY_OP_GREATER,
+ ONYX_BINARY_OP_GREATER_EQUAL,
} OnyxBinaryOp;
struct OnyxAstNodeBinOp {
};
struct OnyxAstNodeNumLit {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
- OnyxAstNode *next;
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo *type;
+ OnyxAstNode *next;
union { i32 i; i64 l; f32 f; f64 d; } value;
};
struct OnyxAstNodeLocal {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo *type;
u64 data; // NOTE: Unused
- OnyxAstNode *next;
- OnyxAstNodeLocal *prev_local;
+ OnyxAstNode *next;
+ OnyxAstNodeLocal *prev_local;
};
struct OnyxAstNodeParam {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // NOTE: Symbol name i.e. 'a', 'b'
- OnyxTypeInfo *type;
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token; // NOTE: Symbol name i.e. 'a', 'b'
+ OnyxTypeInfo *type;
u64 data; // NOTE: UNUSED
- OnyxAstNodeParam *next;
- OnyxAstNodeLocal *prev_local;
+ OnyxAstNodeParam *next;
+ OnyxAstNodeLocal *prev_local;
};
struct OnyxAstNodeScope {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // NOTE: UNUSED
- OnyxTypeInfo *type; // NOTE: UNUSED
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token; // NOTE: UNUSED
+ OnyxTypeInfo *type; // NOTE: UNUSED
u64 data; // NOTE: UNUSED
- OnyxAstNodeScope *prev_scope;
- OnyxAstNodeLocal *last_local;
+ OnyxAstNodeScope *prev_scope;
+ OnyxAstNodeLocal *last_local;
};
struct OnyxAstNodeBlock {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *return_type;
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo *return_type;
u64 data; // NOTE: UNUSED
- OnyxAstNode *next;
- OnyxAstNode *body;
- OnyxAstNodeScope *scope;
+ OnyxAstNode *next;
+ OnyxAstNode *body;
+ OnyxAstNodeScope *scope;
};
struct OnyxAstNodeIf {
};
struct OnyxAstNodeFuncDef {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // This will point to the symbol token to identify it
- OnyxTypeInfo *return_type;
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token; // This will point to the symbol token to identify it
+ OnyxTypeInfo *return_type;
u64 data;
- OnyxAstNode *next;
- OnyxAstNodeBlock *body;
- OnyxAstNodeParam *params;
+ OnyxAstNode *next;
+ OnyxAstNodeBlock *body;
+ OnyxAstNodeParam *params;
};
struct OnyxAstNodeForeign {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *mod_token;
- OnyxTypeInfo *type;
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *mod_token;
+ OnyxTypeInfo *type;
u64 data;
- OnyxAstNode *next;
+ OnyxAstNode *next;
OnyxToken *name_token;
- OnyxAstNode *import;
+ OnyxAstNode *import;
};
struct OnyxAstNodeCall {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type; // NOTE: The type that the function returns
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo *type; // NOTE: The type that the function returns
u64 data;
- OnyxAstNode *next;
- OnyxAstNode *callee; // NOTE: Function definition node
- OnyxAstNode *arguments; // NOTE: Expressions that form the actual param list
- // They will be chained down using the "next" property
- // unless this becomes used by something else
+ OnyxAstNode *next;
+ OnyxAstNode *callee; // NOTE: Function definition node
+ OnyxAstNode *arguments; // NOTE: Expressions that form the actual param list
+ // They will be chained down using the "next" property
+ // unless this becomes used by something else
};
struct OnyxAstNodeFile {
union OnyxAstNode {
- // Generic node structure for capturing all binary ops and statements
- struct {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
+ // Generic node structure for capturing all binary ops and statements
+ struct {
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo *type;
u64 data;
- OnyxAstNode *next;
- OnyxAstNode *left;
- OnyxAstNode *right;
- };
-
- OnyxAstNodeBlock as_block;
- OnyxAstNodeFuncDef as_funcdef;
- OnyxAstNodeParam as_param;
- OnyxAstNodeLocal as_local;
- OnyxAstNodeScope as_scope;
- OnyxAstNodeCall as_call;
+ OnyxAstNode *next;
+ OnyxAstNode *left;
+ OnyxAstNode *right;
+ };
+
+ OnyxAstNodeBlock as_block;
+ OnyxAstNodeFuncDef as_funcdef;
+ OnyxAstNodeParam as_param;
+ OnyxAstNodeLocal as_local;
+ OnyxAstNodeScope as_scope;
+ OnyxAstNodeCall as_call;
OnyxAstNodeNumLit as_numlit;
OnyxAstNodeBinOp as_binop;
OnyxAstNodeUnaryOp as_unaryop;
typedef struct OnyxSemPassState {
// NOTE: Adding node_allocator in case we need
// to make any more node in the tree
- bh_allocator allocator, node_allocator;
- OnyxMessages *msgs;
+ bh_allocator allocator, node_allocator;
+ OnyxMessages *msgs;
// NOTE: Used in symbol resolution phase
OnyxAstNodeScope* curr_scope;
extern const WasmType WASM_TYPE_FLOAT64;
typedef struct WasmFuncType {
- // NOTE: For now, WASM only allows for 1 return value.
- // This may be lifted in the future.
- i32 param_count;
- WasmType return_type;
- WasmType param_types[];
+ // NOTE: For now, WASM only allows for 1 return value.
+ // This may be lifted in the future.
+ i32 param_count;
+ WasmType return_type;
+ WasmType param_types[];
} WasmFuncType;
typedef enum WasmInstructionType {
- WI_UNREACHABLE = 0x00,
- WI_NOP = 0x01,
-
- // NOTE: Control flow
- WI_BLOCK_START = 0x02,
- WI_BLOCK_END = 0x0B, // NOTE: These ends are not unique
- WI_LOOP_START = 0x03,
- WI_LOOP_END = 0x0B,
- WI_IF_START = 0x04,
- WI_ELSE = 0x05,
- WI_IF_END = 0x0B,
- WI_JUMP = 0x0C,
- WI_COND_JUMP = 0x0D,
- WI_JUMP_TABLE = 0x0E,
- WI_RETURN = 0x0F,
- WI_CALL = 0x10,
- WI_CALL_INDIRECT = 0x11,
-
- // NOTE: Parametric instructions
- WI_DROP = 0x1A,
- WI_SELECT = 0x1B,
-
- // NOTE: Variable instructions
- WI_LOCAL_GET = 0x20,
- WI_LOCAL_SET = 0x21,
- WI_LOCAL_TEE = 0x22,
- WI_GLOBAL_GET = 0x23,
- WI_GLOBAL_SET = 0x24,
-
- // NOTE: Memory instructions
- WI_I32_LOAD = 0x28,
- WI_I64_LOAD = 0x29,
- WI_F32_LOAD = 0x2A,
- WI_F64_LOAD = 0x2B,
- WI_I32_LOAD_8_S = 0x2C,
- WI_I32_LOAD_8_U = 0x2D,
- WI_I32_LOAD_16_S = 0x2E,
- WI_I32_LOAD_16_U = 0x2F,
- WI_I64_LOAD_8_S = 0x30,
- WI_I64_LOAD_8_U = 0x31,
- WI_I64_LOAD_16_S = 0x32,
- WI_I64_LOAD_16_U = 0x33,
- WI_I64_LOAD_32_S = 0x34,
- WI_I64_LOAD_32_U = 0x35,
- WI_I32_STORE = 0x36,
- WI_I64_STORE = 0x37,
- WI_F32_STORE = 0x38,
- WI_F64_STORE = 0x39,
- WI_I32_STORE_8 = 0x3A,
- WI_I32_STORE_16 = 0x3B,
- WI_I64_STORE_8 = 0x3C,
- WI_I64_STORE_16 = 0x3D,
- WI_I64_STORE_32 = 0x3E,
- WI_MEMORY_SIZE = 0x3F,
- WI_MEMORY_GROW = 0x40,
-
- // NOTE: Numeric Instructions
- WI_I32_CONST = 0x41,
- WI_I64_CONST = 0x42,
- WI_F32_CONST = 0x43,
- WI_F64_CONST = 0x44,
-
- WI_I32_EQZ = 0x45, // NOTE: Autoincremented from here
- WI_I32_EQ,
- WI_I32_NE,
- WI_I32_LT_S,
- WI_I32_LT_U,
- WI_I32_GT_S,
- WI_I32_GT_U,
- WI_I32_LE_S,
- WI_I32_LE_U,
- WI_I32_GE_S,
- WI_I32_GE_U,
-
- WI_I64_EQZ,
- WI_I64_EQ,
- WI_I64_NE,
- WI_I64_LT_S,
- WI_I64_LT_U,
- WI_I64_GT_S,
- WI_I64_GT_U,
- WI_I64_LE_S,
- WI_I64_LE_U,
- WI_I64_GE_S,
- WI_I64_GE_U,
-
- WI_F32_EQ,
- WI_F32_NE,
- WI_F32_LT,
- WI_F32_GT,
- WI_F32_LE,
- WI_F32_GE,
-
- WI_F64_EQ,
- WI_F64_NE,
- WI_F64_LT,
- WI_F64_GT,
- WI_F64_LE,
- WI_F64_GE,
-
- WI_I32_CLZ,
- WI_I32_CTZ,
- WI_I32_POPCNT,
- WI_I32_ADD,
- WI_I32_SUB,
- WI_I32_MUL,
- WI_I32_DIV_S,
- WI_I32_DIV_U,
- WI_I32_REM_S,
- WI_I32_REM_U,
- WI_I32_AND,
- WI_I32_OR,
- WI_I32_XOR,
- WI_I32_SHL,
- WI_I32_SHR_S,
- WI_I32_SHR_U,
- WI_I32_ROTL,
- WI_I32_ROTR,
-
- WI_I64_CLZ,
- WI_I64_CTZ,
- WI_I64_POPCNT,
- WI_I64_ADD,
- WI_I64_SUB,
- WI_I64_MUL,
- WI_I64_DIV_S,
- WI_I64_DIV_U,
- WI_I64_REM_S,
- WI_I64_REM_U,
- WI_I64_AND,
- WI_I64_OR,
- WI_I64_XOR,
- WI_I64_SHL,
- WI_I64_SHR_S,
- WI_I64_SHR_U,
- WI_I64_ROTL,
- WI_I64_ROTR,
-
- WI_F32_ABS,
- WI_F32_NEG,
- WI_F32_CEIL,
- WI_F32_FLOOR,
- WI_F32_TRUNC,
- WI_F32_NEAREST,
- WI_F32_SQRT,
- WI_F32_ADD,
- WI_F32_SUB,
- WI_F32_MUL,
- WI_F32_DIV,
- WI_F32_MIN,
- WI_F32_MAX,
- WI_F32_COPYSIGN,
-
- WI_F64_ABS,
- WI_F64_NEG,
- WI_F64_CEIL,
- WI_F64_FLOOR,
- WI_F64_TRUNC,
- WI_F64_NEAREST,
- WI_F64_SQRT,
- WI_F64_ADD,
- WI_F64_SUB,
- WI_F64_MUL,
- WI_F64_DIV,
- WI_F64_MIN,
- WI_F64_MAX,
- WI_F64_COPYSIGN,
-
- WI_I32_FROM_I64 = 0xA7,
- WI_I32_FROM_F32_S = 0xA8,
- WI_I32_FROM_F32_U = 0xA9,
- WI_I32_FROM_F64_S = 0xAA,
- WI_I32_FROM_F64_U = 0xAB,
-
- WI_I64_FROM_I32_S = 0xAC,
- WI_I64_FROM_I32_U = 0xAD,
- WI_I64_FROM_F32_S = 0xAE,
- WI_I64_FROM_F32_U = 0xAF,
- WI_I64_FROM_F64_S = 0xB0,
- WI_I64_FROM_F64_U = 0xB1,
-
- WI_F32_FROM_I32_S = 0xB2,
- WI_F32_FROM_I32_U = 0xB3,
- WI_F32_FROM_I64_S = 0xB4,
- WI_F32_FROM_I64_U = 0xB5,
- WI_F32_FROM_F64 = 0xB6,
-
- WI_F64_FROM_I32_S = 0xB7,
- WI_F64_FROM_I32_U = 0xB8,
- WI_F64_FROM_I64_S = 0xB9,
- WI_F64_FROM_I64_U = 0xBA,
- WI_F64_FROM_F32 = 0xBB,
-
- WI_I32_REINTERPRET_F32 = 0xBC,
- WI_I64_REINTERPRET_F64 = 0xBD,
- WI_F32_REINTERPRET_I32 = 0xBE,
- WI_F64_REINTERPRET_I64 = 0xBF,
+ WI_UNREACHABLE = 0x00,
+ WI_NOP = 0x01,
+
+ // NOTE: Control flow
+ WI_BLOCK_START = 0x02,
+ WI_BLOCK_END = 0x0B, // NOTE: These ends are not unique
+ WI_LOOP_START = 0x03,
+ WI_LOOP_END = 0x0B,
+ WI_IF_START = 0x04,
+ WI_ELSE = 0x05,
+ WI_IF_END = 0x0B,
+ WI_JUMP = 0x0C,
+ WI_COND_JUMP = 0x0D,
+ WI_JUMP_TABLE = 0x0E,
+ WI_RETURN = 0x0F,
+ WI_CALL = 0x10,
+ WI_CALL_INDIRECT = 0x11,
+
+ // NOTE: Parametric instructions
+ WI_DROP = 0x1A,
+ WI_SELECT = 0x1B,
+
+ // NOTE: Variable instructions
+ WI_LOCAL_GET = 0x20,
+ WI_LOCAL_SET = 0x21,
+ WI_LOCAL_TEE = 0x22,
+ WI_GLOBAL_GET = 0x23,
+ WI_GLOBAL_SET = 0x24,
+
+ // NOTE: Memory instructions
+ WI_I32_LOAD = 0x28,
+ WI_I64_LOAD = 0x29,
+ WI_F32_LOAD = 0x2A,
+ WI_F64_LOAD = 0x2B,
+ WI_I32_LOAD_8_S = 0x2C,
+ WI_I32_LOAD_8_U = 0x2D,
+ WI_I32_LOAD_16_S = 0x2E,
+ WI_I32_LOAD_16_U = 0x2F,
+ WI_I64_LOAD_8_S = 0x30,
+ WI_I64_LOAD_8_U = 0x31,
+ WI_I64_LOAD_16_S = 0x32,
+ WI_I64_LOAD_16_U = 0x33,
+ WI_I64_LOAD_32_S = 0x34,
+ WI_I64_LOAD_32_U = 0x35,
+ WI_I32_STORE = 0x36,
+ WI_I64_STORE = 0x37,
+ WI_F32_STORE = 0x38,
+ WI_F64_STORE = 0x39,
+ WI_I32_STORE_8 = 0x3A,
+ WI_I32_STORE_16 = 0x3B,
+ WI_I64_STORE_8 = 0x3C,
+ WI_I64_STORE_16 = 0x3D,
+ WI_I64_STORE_32 = 0x3E,
+ WI_MEMORY_SIZE = 0x3F,
+ WI_MEMORY_GROW = 0x40,
+
+ // NOTE: Numeric Instructions
+ WI_I32_CONST = 0x41,
+ WI_I64_CONST = 0x42,
+ WI_F32_CONST = 0x43,
+ WI_F64_CONST = 0x44,
+
+ WI_I32_EQZ = 0x45, // NOTE: Autoincremented from here
+ WI_I32_EQ,
+ WI_I32_NE,
+ WI_I32_LT_S,
+ WI_I32_LT_U,
+ WI_I32_GT_S,
+ WI_I32_GT_U,
+ WI_I32_LE_S,
+ WI_I32_LE_U,
+ WI_I32_GE_S,
+ WI_I32_GE_U,
+
+ WI_I64_EQZ,
+ WI_I64_EQ,
+ WI_I64_NE,
+ WI_I64_LT_S,
+ WI_I64_LT_U,
+ WI_I64_GT_S,
+ WI_I64_GT_U,
+ WI_I64_LE_S,
+ WI_I64_LE_U,
+ WI_I64_GE_S,
+ WI_I64_GE_U,
+
+ WI_F32_EQ,
+ WI_F32_NE,
+ WI_F32_LT,
+ WI_F32_GT,
+ WI_F32_LE,
+ WI_F32_GE,
+
+ WI_F64_EQ,
+ WI_F64_NE,
+ WI_F64_LT,
+ WI_F64_GT,
+ WI_F64_LE,
+ WI_F64_GE,
+
+ WI_I32_CLZ,
+ WI_I32_CTZ,
+ WI_I32_POPCNT,
+ WI_I32_ADD,
+ WI_I32_SUB,
+ WI_I32_MUL,
+ WI_I32_DIV_S,
+ WI_I32_DIV_U,
+ WI_I32_REM_S,
+ WI_I32_REM_U,
+ WI_I32_AND,
+ WI_I32_OR,
+ WI_I32_XOR,
+ WI_I32_SHL,
+ WI_I32_SHR_S,
+ WI_I32_SHR_U,
+ WI_I32_ROTL,
+ WI_I32_ROTR,
+
+ WI_I64_CLZ,
+ WI_I64_CTZ,
+ WI_I64_POPCNT,
+ WI_I64_ADD,
+ WI_I64_SUB,
+ WI_I64_MUL,
+ WI_I64_DIV_S,
+ WI_I64_DIV_U,
+ WI_I64_REM_S,
+ WI_I64_REM_U,
+ WI_I64_AND,
+ WI_I64_OR,
+ WI_I64_XOR,
+ WI_I64_SHL,
+ WI_I64_SHR_S,
+ WI_I64_SHR_U,
+ WI_I64_ROTL,
+ WI_I64_ROTR,
+
+ WI_F32_ABS,
+ WI_F32_NEG,
+ WI_F32_CEIL,
+ WI_F32_FLOOR,
+ WI_F32_TRUNC,
+ WI_F32_NEAREST,
+ WI_F32_SQRT,
+ WI_F32_ADD,
+ WI_F32_SUB,
+ WI_F32_MUL,
+ WI_F32_DIV,
+ WI_F32_MIN,
+ WI_F32_MAX,
+ WI_F32_COPYSIGN,
+
+ WI_F64_ABS,
+ WI_F64_NEG,
+ WI_F64_CEIL,
+ WI_F64_FLOOR,
+ WI_F64_TRUNC,
+ WI_F64_NEAREST,
+ WI_F64_SQRT,
+ WI_F64_ADD,
+ WI_F64_SUB,
+ WI_F64_MUL,
+ WI_F64_DIV,
+ WI_F64_MIN,
+ WI_F64_MAX,
+ WI_F64_COPYSIGN,
+
+ WI_I32_FROM_I64 = 0xA7,
+ WI_I32_FROM_F32_S = 0xA8,
+ WI_I32_FROM_F32_U = 0xA9,
+ WI_I32_FROM_F64_S = 0xAA,
+ WI_I32_FROM_F64_U = 0xAB,
+
+ WI_I64_FROM_I32_S = 0xAC,
+ WI_I64_FROM_I32_U = 0xAD,
+ WI_I64_FROM_F32_S = 0xAE,
+ WI_I64_FROM_F32_U = 0xAF,
+ WI_I64_FROM_F64_S = 0xB0,
+ WI_I64_FROM_F64_U = 0xB1,
+
+ WI_F32_FROM_I32_S = 0xB2,
+ WI_F32_FROM_I32_U = 0xB3,
+ WI_F32_FROM_I64_S = 0xB4,
+ WI_F32_FROM_I64_U = 0xB5,
+ WI_F32_FROM_F64 = 0xB6,
+
+ WI_F64_FROM_I32_S = 0xB7,
+ WI_F64_FROM_I32_U = 0xB8,
+ WI_F64_FROM_I64_S = 0xB9,
+ WI_F64_FROM_I64_U = 0xBA,
+ WI_F64_FROM_F32 = 0xBB,
+
+ WI_I32_REINTERPRET_F32 = 0xBC,
+ WI_I64_REINTERPRET_F64 = 0xBD,
+ WI_F32_REINTERPRET_I32 = 0xBE,
+ WI_F64_REINTERPRET_I64 = 0xBF,
} WasmInstructionType;
typedef union {
- struct {
- u32 i1, i2;
- };
- i64 l;
- float f;
- double d;
- ptr p;
+ struct {
+ u32 i1, i2;
+ };
+ i64 l;
+ float f;
+ double d;
+ ptr p;
} WasmInstructionData;
typedef struct WasmInstruction {
- WasmInstructionType type;
- WasmInstructionData data;
+ WasmInstructionType type;
+ WasmInstructionData data;
} WasmInstruction;
typedef struct WasmFuncLocals {
- u8 i32_count;
- u8 i64_count;
- u8 f32_count;
- u8 f64_count;
+ u8 i32_count;
+ u8 i64_count;
+ u8 f32_count;
+ u8 f64_count;
} WasmFuncLocals;
typedef struct WasmFunc {
- i32 type_idx;
- WasmFuncLocals locals;
- bh_arr(WasmInstruction) code;
+ i32 type_idx;
+ WasmFuncLocals locals;
+ bh_arr(WasmInstruction) code;
} WasmFunc;
typedef enum WasmForeignKind {
- WASM_FOREIGN_FUNCTION = 0x00,
- WASM_FOREIGN_TABLE = 0x01,
- WASM_FOREIGN_MEMORY = 0x02,
- WASM_FOREIGN_GLOBAL = 0x03,
+ WASM_FOREIGN_FUNCTION = 0x00,
+ WASM_FOREIGN_TABLE = 0x01,
+ WASM_FOREIGN_MEMORY = 0x02,
+ WASM_FOREIGN_GLOBAL = 0x03,
} WasmForeignKind;
typedef struct WasmExport {
- WasmForeignKind kind;
- i32 idx;
+ WasmForeignKind kind;
+ i32 idx;
} WasmExport;
typedef struct WasmImport {
} WasmImport;
typedef struct OnyxWasmModule {
- bh_allocator allocator;
+ bh_allocator allocator;
- // NOTE: Mapping from local ast node ptrs to indicies
- bh_imap local_map;
+ // NOTE: Mapping from local ast node ptrs to indicies
+ bh_imap 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_table(i32) type_map;
- bh_arr(WasmFuncType*) functypes; // NOTE: This have to be pointers because the type is variadic in size
+ // 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_table(i32) type_map;
+ bh_arr(WasmFuncType*) functypes; // NOTE: This have to be pointers because the type is variadic in size
- bh_arr(WasmFunc) funcs;
+ bh_arr(WasmFunc) funcs;
bh_imap func_map; // NOTE: Maps from ast node pointers to the function index
- bh_table(WasmExport) exports;
+ bh_table(WasmExport) exports;
bh_arr(WasmImport) imports;
- i32 next_type_idx;
- i32 next_func_idx;
+ i32 next_type_idx;
+ i32 next_func_idx;
i32 next_import_func_idx;
- i32 export_count;
+ i32 export_count;
} OnyxWasmModule;
OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc);
" Last Change: 2020 June 20
if exists("b:current_syntax")
- finish
+ finish
endif
let s:cpo_save = &cpo
syn keyword onyxConstant true false
-syn keyword onyxCommentStart contained TODO NOTE BUG HACK
+syn keyword onyxCommentStart contained TODO NOTE BUG HACK
syn region onyxComment start="//" end="$" keepend contains=onyxCommentStart
-hi def link onyxKeyword Statement
-hi def link onyxType Type
-hi def link onyxComment Comment
-hi def link onyxCommentStart Todo
-hi def link onyxConstant Constant
+hi def link onyxKeyword Statement
+hi def link onyxType Type
+hi def link onyxComment Comment
+hi def link onyxCommentStart Todo
+hi def link onyxConstant Constant
let b:current_syntax = "onyx"
let &cpo = s:cpo_save
}
foo :: proc -> i32 {
- return 10;
+ return 10;
}
add :: proc (a i32, b i32) -> i32 {
- return a + b;
+ return a + b;
}
// NOTE: There is a weird bug here if the else is used instead
}
diff_square :: proc (a i32, b i32) -> i32 {
- // Typechecked
- c := a - b; // Mutable
- d :: a + b; // Constant
+ // Typechecked
+ c := a - b; // Mutable
+ d :: a + b; // Constant
{
c := a * 2;
d := (b + a) * 2;
}
- return c * d;
+ return c * d;
}
do_stuff :: proc -> i32 {
- res := diff_square(4 + 5, 2 + 3);
- res = res + foo();
+ res := diff_square(4 + 5, 2 + 3);
+ res = res + foo();
return res * -1;
}
foreign console {
- log :: proc (data ptr, length i32) -> void ---;
+ log :: proc (data ptr, length i32) -> void ---;
}
export add :: proc (a i32, b i32) -> i32 {
- return a + b;
+ return a + b;
}
export max :: proc (a i32, b i32) -> i32 {
- // Curly braces are always required
- if a > b {
- return a;
- } else {
- return b;
- }
+ // Curly braces are always required
+ if a > b {
+ return a;
+ } else {
+ return b;
+ }
}
export main :: proc () {
- console.log(add(2, 3));
- console.log(max(5, 10));
+ console.log(add(2, 3));
+ console.log(max(5, 10));
}
x : i32;
y := 0;
- while y < 10 {
+ while y < 5 {
x = 0;
- while x < 10 {
- print_i32(x + y * 10);
+ while x < 5 {
+ print_i32((x + y * 5) % 10);
x = x + 1;
}
OnyxAstNodeFile* parse_source_file(bh_file_contents* file_contents, CompilerState* compiler_state) {
// NOTE: Maybe don't want to recreate the tokenizer and parser for every file
- OnyxTokenizer tokenizer = onyx_tokenizer_create(compiler_state->token_alloc, file_contents);
+ OnyxTokenizer tokenizer = onyx_tokenizer_create(compiler_state->token_alloc, file_contents);
bh_printf("Lexing %s\n", file_contents->filename);
- onyx_lex_tokens(&tokenizer);
+ onyx_lex_tokens(&tokenizer);
bh_printf("Parsing %s\n", file_contents->filename);
- OnyxParser parser = onyx_parser_create(compiler_state->ast_alloc, &tokenizer, &compiler_state->msgs);
- return onyx_parse(&parser);
+ OnyxParser parser = onyx_parser_create(compiler_state->ast_alloc, &tokenizer, &compiler_state->msgs);
+ return onyx_parse(&parser);
}
i32 onyx_compile(OnyxCompileOptions* opts, CompilerState* compiler_state) {
- bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096);
- compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena);
+ bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096);
+ compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena);
onyx_message_create(compiler_state->msg_alloc, &compiler_state->msgs);
compiler_state->token_alloc = opts->allocator;
- // NOTE: Create the arena where AST nodes will exist
- // Prevents nodes from being scattered across memory due to fragmentation
- bh_arena_init(&compiler_state->ast_arena, opts->allocator, 16 * 1024 * 1024); // 16MB
- compiler_state->ast_alloc = bh_arena_allocator(&compiler_state->ast_arena);
+ // NOTE: Create the arena where AST nodes will exist
+ // Prevents nodes from being scattered across memory due to fragmentation
+ bh_arena_init(&compiler_state->ast_arena, opts->allocator, 16 * 1024 * 1024); // 16MB
+ compiler_state->ast_alloc = bh_arena_allocator(&compiler_state->ast_arena);
bh_arena_init(&compiler_state->sp_arena, opts->allocator, 16 * 1024);
compiler_state->sp_alloc = bh_arena_allocator(&compiler_state->sp_arena);
int main(int argc, char *argv[]) {
- bh_allocator alloc = bh_heap_allocator();
+ bh_allocator alloc = bh_heap_allocator();
bh_scratch_init(&global_scratch, alloc, 16 * 1024); // NOTE: 16 KB
global_scratch_allocator = bh_scratch_allocator(&global_scratch);
compiler_state_free(&compile_state);
- return compiler_progress != ONYX_COMPILER_PROGRESS_SUCCESS;
+ return compiler_progress != ONYX_COMPILER_PROGRESS_SUCCESS;
}
// NOTE: Old bits of code that may be useful again at some point.
#if 0
- bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr));
+ bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr));
- bh_arr_each(OnyxToken, it, token_arr) {
- onyx_token_null_toggle(*it);
- bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column);
- onyx_token_null_toggle(*it);
- }
+ bh_arr_each(OnyxToken, it, token_arr) {
+ onyx_token_null_toggle(*it);
+ bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column);
+ onyx_token_null_toggle(*it);
+ }
#endif
#if 0
- // NOTE: Ensure type table made correctly
-
- bh_printf("Type map:\n");
- bh_hash_each_start(i32, wasm_mod.type_map);
- bh_printf("%s -> %d\n", key, value);
- bh_hash_each_end;
-
- bh_printf("Type list:\n");
- WasmFuncType** func_type = wasm_mod.functypes;
- while (!bh_arr_end(wasm_mod.functypes, func_type)) {
- for (int p = 0; p < (*func_type)->param_count; p++) {
- bh_printf("%c ", (*func_type)->param_types[p]);
- }
- bh_printf("-> ");
- bh_printf("%c\n", (*func_type)->return_type);
-
- func_type++;
- }
+ // NOTE: Ensure type table made correctly
+
+ bh_printf("Type map:\n");
+ bh_hash_each_start(i32, wasm_mod.type_map);
+ bh_printf("%s -> %d\n", key, value);
+ bh_hash_each_end;
+
+ bh_printf("Type list:\n");
+ WasmFuncType** func_type = wasm_mod.functypes;
+ while (!bh_arr_end(wasm_mod.functypes, func_type)) {
+ for (int p = 0; p < (*func_type)->param_count; p++) {
+ bh_printf("%c ", (*func_type)->param_types[p]);
+ }
+ bh_printf("-> ");
+ bh_printf("%c\n", (*func_type)->return_type);
+
+ func_type++;
+ }
#endif
#if 0
- // NOTE: Ensure the export table was built correctly
+ // NOTE: Ensure the export table was built correctly
- bh_printf("Function types:\n");
- bh_arr_each(WasmFunc, func_it, wasm_mod.funcs) {
- bh_printf("%d\n", func_it->type_idx);
- }
+ bh_printf("Function types:\n");
+ bh_arr_each(WasmFunc, func_it, wasm_mod.funcs) {
+ bh_printf("%d\n", func_it->type_idx);
+ }
- bh_printf("Exports:\n");
- bh_hash_each_start(WasmExport, wasm_mod.exports);
- bh_printf("%s: %d %d\n", key, value.kind, value.idx);
- bh_hash_each_end;
+ bh_printf("Exports:\n");
+ bh_hash_each_start(WasmExport, wasm_mod.exports);
+ bh_printf("%s: %d %d\n", key, value.kind, value.idx);
+ bh_hash_each_end;
#endif
#include "onyxlex.h"
static const char* onyx_token_type_names[] = {
- "TOKEN_TYPE_UNKNOWN",
- "TOKEN_TYPE_END_STREAM",
-
- "TOKEN_TYPE_COMMENT",
-
- "struct", //"TOKEN_TYPE_KEYWORD_STRUCT",
- "use", //"TOKEN_TYPE_KEYWORD_USE",
- "export", //"TOKEN_TYPE_KEYWORD_EXPORT",
- "if", //"TOKEN_TYPE_KEYWORD_IF",
- "else", //"TOKEN_TYPE_KEYWORD_ELSE",
- "elseif", //"TOKEN_TYPE_KEYWORD_ELSEIF",
- "return", //"TOKEN_TYPE_KEYWORD_RETURN",
- "foreign", //"TOKEN_TYPE_KEYWORD_FOREIGN",
- "proc", //"TOKEN_TYPE_KEYWORD_PROC",
- "as", //"TOKEN_TYPE_KEYWORD_CAST",
+ "TOKEN_TYPE_UNKNOWN",
+ "TOKEN_TYPE_END_STREAM",
+
+ "TOKEN_TYPE_COMMENT",
+
+ "struct", //"TOKEN_TYPE_KEYWORD_STRUCT",
+ "use", //"TOKEN_TYPE_KEYWORD_USE",
+ "export", //"TOKEN_TYPE_KEYWORD_EXPORT",
+ "if", //"TOKEN_TYPE_KEYWORD_IF",
+ "else", //"TOKEN_TYPE_KEYWORD_ELSE",
+ "elseif", //"TOKEN_TYPE_KEYWORD_ELSEIF",
+ "return", //"TOKEN_TYPE_KEYWORD_RETURN",
+ "foreign", //"TOKEN_TYPE_KEYWORD_FOREIGN",
+ "proc", //"TOKEN_TYPE_KEYWORD_PROC",
+ "as", //"TOKEN_TYPE_KEYWORD_CAST",
"while", //"TOKEN_TYPE_KEYWORD_WHILE",
"break", //"TOKEN_TYPE_KEYWORD_BREAK",
"continue", //"TOKEN_TYPE_KEYWORD_CONTINUE,
- "->", //"TOKEN_TYPE_RIGHT_ARROW",
- "<-", //"TOKEN_TYPE_LEFT_ARROW",
- "(", //"TOKEN_TYPE_OPEN_PAREN",
- ")", //"TOKEN_TYPE_CLOSE_PAREN",
- "{", //"TOKEN_TYPE_OPEN_BRACE",
- "}", //"TOKEN_TYPE_CLOSE_BRACE",
- "[", //"TOKEN_TYPE_OPEN_BRACKET",
- "]", //"TOKEN_TYPE_CLOSE_BRACKET",
-
- "+", // "TOKEN_TYPE_SYM_PLUS",
- "-", // "TOKEN_TYPE_SYM_MINUS",
- "*", // "TOKEN_TYPE_SYM_STAR",
- "%", // "TOKEN_TYPE_SYM_PERCENT",
- ".", // "TOKEN_TYPE_SYM_DOT",
- "/", // "TOKEN_TYPE_SYM_FSLASH",
- "\\", // "TOKEN_TYPE_SYM_BSLASH",
- ":", // "TOKEN_TYPE_SYM_COLON",
- ";", // "TOKEN_TYPE_SYM_SEMICOLON",
- ",", // "TOKEN_TYPE_SYM_COMMA",
- ">", // "TOKEN_TYPE_SYM_GREATER",
- ">=", // "TOKEN_TYPE_SYM_GREATER_EQUAL",
- "<", // "TOKEN_TYPE_SYM_LESS",
- "<=", // "TOKEN_TYPE_SYM_LESS_EQUAL",
- "==", // "TOKEN_TYPE_SYM_EQUALS_EQUALS",
+ "->", //"TOKEN_TYPE_RIGHT_ARROW",
+ "<-", //"TOKEN_TYPE_LEFT_ARROW",
+ "(", //"TOKEN_TYPE_OPEN_PAREN",
+ ")", //"TOKEN_TYPE_CLOSE_PAREN",
+ "{", //"TOKEN_TYPE_OPEN_BRACE",
+ "}", //"TOKEN_TYPE_CLOSE_BRACE",
+ "[", //"TOKEN_TYPE_OPEN_BRACKET",
+ "]", //"TOKEN_TYPE_CLOSE_BRACKET",
+
+ "+", // "TOKEN_TYPE_SYM_PLUS",
+ "-", // "TOKEN_TYPE_SYM_MINUS",
+ "*", // "TOKEN_TYPE_SYM_STAR",
+ "%", // "TOKEN_TYPE_SYM_PERCENT",
+ ".", // "TOKEN_TYPE_SYM_DOT",
+ "/", // "TOKEN_TYPE_SYM_FSLASH",
+ "\\", // "TOKEN_TYPE_SYM_BSLASH",
+ ":", // "TOKEN_TYPE_SYM_COLON",
+ ";", // "TOKEN_TYPE_SYM_SEMICOLON",
+ ",", // "TOKEN_TYPE_SYM_COMMA",
+ ">", // "TOKEN_TYPE_SYM_GREATER",
+ ">=", // "TOKEN_TYPE_SYM_GREATER_EQUAL",
+ "<", // "TOKEN_TYPE_SYM_LESS",
+ "<=", // "TOKEN_TYPE_SYM_LESS_EQUAL",
+ "==", // "TOKEN_TYPE_SYM_EQUALS_EQUALS",
"!=", // "TOKEN_TYPE_SYM_NOT_EQUAL",
- "=", // "TOKEN_TYPE_SYM_EQUALS",
- "~", // "TOKEN_TYPE_SYM_TILDE",
- "!", // "TOKEN_TYPE_SYM_BANG",
- "^", // "TOKEN_TYPE_SYM_CARET",
- "&", // "TOKEN_TYPE_SYM_AMPERSAND",
-
- "TOKEN_TYPE_SYMBOL",
- "TOKEN_TYPE_LITERAL_STRING",
- "TOKEN_TYPE_LITERAL_NUMERIC",
+ "=", // "TOKEN_TYPE_SYM_EQUALS",
+ "~", // "TOKEN_TYPE_SYM_TILDE",
+ "!", // "TOKEN_TYPE_SYM_BANG",
+ "^", // "TOKEN_TYPE_SYM_CARET",
+ "&", // "TOKEN_TYPE_SYM_AMPERSAND",
+
+ "TOKEN_TYPE_SYMBOL",
+ "TOKEN_TYPE_LITERAL_STRING",
+ "TOKEN_TYPE_LITERAL_NUMERIC",
"true",
"false",
- "TOKEN_TYPE_COUNT"
+ "TOKEN_TYPE_COUNT"
};
#ifndef LITERAL_TOKEN
#define LITERAL_TOKEN(token, word, token_type) \
- if (token_lit(tokenizer, &tk, token, word, token_type)) goto token_parsed;
+ if (token_lit(tokenizer, &tk, token, word, token_type)) goto token_parsed;
#endif
#ifndef INCREMENT_CURR_TOKEN
#define INCREMENT_CURR_TOKEN(tkn) { \
- if (*(tkn)->curr == '\n') { \
- (tkn)->line_number++; \
- (tkn)->line_start = (tkn)->curr + 1; \
- } \
- (tkn)->curr++; \
+ if (*(tkn)->curr == '\n') { \
+ (tkn)->line_number++; \
+ (tkn)->line_start = (tkn)->curr + 1; \
+ } \
+ (tkn)->curr++; \
}
#endif
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) {
+ 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;
- tk->pos.line = tokenizer->line_number;
- tk->pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
+ tk->type = type;
+ tk->token = tokenizer->curr;
+ tk->length = len;
+ tk->pos.line = tokenizer->line_number;
+ tk->pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
- tokenizer->curr += len;
+ tokenizer->curr += len;
- return 1;
- }
- return 0;
+ return 1;
+ }
+ return 0;
}
const char* onyx_get_token_type_name(OnyxTokenType tkn_type) {
- return onyx_token_type_names[tkn_type];
+ return onyx_token_type_names[tkn_type];
}
void onyx_token_null_toggle(OnyxToken tkn) {
- static char backup = 0;
- char tmp = tkn.token[tkn.length];
- tkn.token[tkn.length] = backup;
- backup = tmp;
+ static char backup = 0;
+ char tmp = tkn.token[tkn.length];
+ tkn.token[tkn.length] = backup;
+ backup = tmp;
}
OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
- OnyxToken tk;
-
- // Skip whitespace
- while (char_is_whitespace(*tokenizer->curr) && tokenizer->curr != tokenizer->end)
- INCREMENT_CURR_TOKEN(tokenizer)
-
- tk.type = TOKEN_TYPE_UNKNOWN;
- tk.token = tokenizer->curr;
- tk.length = 1;
- tk.pos.filename = tokenizer->filename;
- tk.pos.line = tokenizer->line_number;
- tk.pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
-
- if (tokenizer->curr == tokenizer->end) {
- tk.type = TOKEN_TYPE_END_STREAM;
- goto token_parsed;
- }
-
- // Comments
- if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '/') {
- tokenizer->curr += 2;
- tk.type = TOKEN_TYPE_COMMENT;
- tk.token = tokenizer->curr;
-
- while (*tokenizer->curr != '\n') {
- INCREMENT_CURR_TOKEN(tokenizer);
- }
-
- tk.length = tokenizer->curr - tk.token - 2;
- goto token_parsed;
- }
-
- 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("elseif", 1, TOKEN_TYPE_KEYWORD_ELSEIF);
- LITERAL_TOKEN("else", 1, TOKEN_TYPE_KEYWORD_ELSE);
- LITERAL_TOKEN("foreign", 1, TOKEN_TYPE_KEYWORD_FOREIGN);
- LITERAL_TOKEN("return", 1, TOKEN_TYPE_KEYWORD_RETURN);
- LITERAL_TOKEN("proc", 1, TOKEN_TYPE_KEYWORD_PROC);
- LITERAL_TOKEN("as", 1, TOKEN_TYPE_KEYWORD_CAST);
+ OnyxToken tk;
+
+ // Skip whitespace
+ while (char_is_whitespace(*tokenizer->curr) && tokenizer->curr != tokenizer->end)
+ INCREMENT_CURR_TOKEN(tokenizer)
+
+ tk.type = TOKEN_TYPE_UNKNOWN;
+ tk.token = tokenizer->curr;
+ tk.length = 1;
+ tk.pos.filename = tokenizer->filename;
+ tk.pos.line = tokenizer->line_number;
+ tk.pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
+
+ if (tokenizer->curr == tokenizer->end) {
+ tk.type = TOKEN_TYPE_END_STREAM;
+ goto token_parsed;
+ }
+
+ // Comments
+ if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '/') {
+ tokenizer->curr += 2;
+ tk.type = TOKEN_TYPE_COMMENT;
+ tk.token = tokenizer->curr;
+
+ while (*tokenizer->curr != '\n') {
+ INCREMENT_CURR_TOKEN(tokenizer);
+ }
+
+ tk.length = tokenizer->curr - tk.token - 2;
+ goto token_parsed;
+ }
+
+ 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("elseif", 1, TOKEN_TYPE_KEYWORD_ELSEIF);
+ LITERAL_TOKEN("else", 1, TOKEN_TYPE_KEYWORD_ELSE);
+ LITERAL_TOKEN("foreign", 1, TOKEN_TYPE_KEYWORD_FOREIGN);
+ LITERAL_TOKEN("return", 1, TOKEN_TYPE_KEYWORD_RETURN);
+ LITERAL_TOKEN("proc", 1, TOKEN_TYPE_KEYWORD_PROC);
+ LITERAL_TOKEN("as", 1, TOKEN_TYPE_KEYWORD_CAST);
LITERAL_TOKEN("while", 1, TOKEN_TYPE_KEYWORD_WHILE);
LITERAL_TOKEN("break", 1, TOKEN_TYPE_KEYWORD_BREAK);
LITERAL_TOKEN("continue", 1, TOKEN_TYPE_KEYWORD_CONTINUE);
LITERAL_TOKEN("true", 1, TOKEN_TYPE_LITERAL_BOOL_TRUE);
LITERAL_TOKEN("false", 1, TOKEN_TYPE_LITERAL_BOOL_FALSE);
- 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_SYM_EQUAL_EQUAL);
- LITERAL_TOKEN("!=", 0, TOKEN_TYPE_SYM_NOT_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)) {
- u64 len = 0;
- while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) {
- len++;
- INCREMENT_CURR_TOKEN(tokenizer);
- }
-
- tk.length = len;
- tk.type = TOKEN_TYPE_SYMBOL;
- goto token_parsed;
- }
-
- // String literal
- if (*tk.token == '"') {
- u64 len = 0;
- u64 slash_count = 0;
-
- INCREMENT_CURR_TOKEN(tokenizer);
-
- while (!(*tokenizer->curr == '"' && slash_count == 0)) {
- len++;
-
- if (*tokenizer->curr == '\\') {
- slash_count += 1;
- slash_count %= 2;
- } else {
- slash_count = 0;
- }
-
- INCREMENT_CURR_TOKEN(tokenizer);
- }
-
- INCREMENT_CURR_TOKEN(tokenizer);
-
- tk.token++;
- tk.type = TOKEN_TYPE_LITERAL_STRING;
- tk.length = len;
- goto token_parsed;
- }
-
- // Number literal
- if (char_is_num(*tokenizer->curr)) {
- u32 len = 1;
- while (char_is_num(*(tokenizer->curr + 1)) || *(tokenizer->curr + 1) == '.') {
- len++;
- INCREMENT_CURR_TOKEN(tokenizer);
- }
+ 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_SYM_EQUAL_EQUAL);
+ LITERAL_TOKEN("!=", 0, TOKEN_TYPE_SYM_NOT_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)) {
+ u64 len = 0;
+ while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) {
+ len++;
+ INCREMENT_CURR_TOKEN(tokenizer);
+ }
+
+ tk.length = len;
+ tk.type = TOKEN_TYPE_SYMBOL;
+ goto token_parsed;
+ }
+
+ // String literal
+ if (*tk.token == '"') {
+ u64 len = 0;
+ u64 slash_count = 0;
+
+ INCREMENT_CURR_TOKEN(tokenizer);
+
+ while (!(*tokenizer->curr == '"' && slash_count == 0)) {
+ len++;
+
+ if (*tokenizer->curr == '\\') {
+ slash_count += 1;
+ slash_count %= 2;
+ } else {
+ slash_count = 0;
+ }
+
+ INCREMENT_CURR_TOKEN(tokenizer);
+ }
+
+ INCREMENT_CURR_TOKEN(tokenizer);
+
+ tk.token++;
+ tk.type = TOKEN_TYPE_LITERAL_STRING;
+ tk.length = len;
+ goto token_parsed;
+ }
+
+ // Number literal
+ if (char_is_num(*tokenizer->curr)) {
+ u32 len = 1;
+ while (char_is_num(*(tokenizer->curr + 1)) || *(tokenizer->curr + 1) == '.') {
+ len++;
+ INCREMENT_CURR_TOKEN(tokenizer);
+ }
if (*(tokenizer->curr + 1) == 'f') {
len++;
INCREMENT_CURR_TOKEN(tokenizer);
}
- tk.type = TOKEN_TYPE_LITERAL_NUMERIC;
- tk.length = len;
- }
+ tk.type = TOKEN_TYPE_LITERAL_NUMERIC;
+ tk.length = len;
+ }
- INCREMENT_CURR_TOKEN(tokenizer);
+ INCREMENT_CURR_TOKEN(tokenizer);
token_parsed:
- bh_arr_push(tokenizer->tokens, tk);
+ bh_arr_push(tokenizer->tokens, tk);
- return &tokenizer->tokens[bh_arr_length(tokenizer->tokens) - 1];
+ return &tokenizer->tokens[bh_arr_length(tokenizer->tokens) - 1];
}
OnyxTokenizer onyx_tokenizer_create(bh_allocator allocator, bh_file_contents *fc) {
- OnyxTokenizer tknizer = {
- .start = fc->data,
- .curr = fc->data,
- .end = fc->data + fc->length,
+ OnyxTokenizer tknizer = {
+ .start = fc->data,
+ .curr = fc->data,
+ .end = fc->data + fc->length,
- .filename = fc->filename,
+ .filename = fc->filename,
- .line_number = 1,
- .line_start = fc->data,
- .tokens = NULL,
- };
+ .line_number = 1,
+ .line_start = fc->data,
+ .tokens = NULL,
+ };
- bh_arr_new(allocator, tknizer.tokens, 512);
- return tknizer;
+ bh_arr_new(allocator, tknizer.tokens, 512);
+ return tknizer;
}
void onyx_tokenizer_free(OnyxTokenizer* tokenizer) {
- bh_arr_free(tokenizer->tokens);
+ bh_arr_free(tokenizer->tokens);
}
void onyx_lex_tokens(OnyxTokenizer* tokenizer) {
- OnyxToken* tk;
- do {
- tk = onyx_get_token(tokenizer);
- } while (tk->type != TOKEN_TYPE_END_STREAM);
+ OnyxToken* tk;
+ do {
+ tk = onyx_get_token(tokenizer);
+ } while (tk->type != TOKEN_TYPE_END_STREAM);
}
static const char* msg_formats[] = {
"%s",
- "expected token '%s', got '%s'",
- "unexpected token '%s'",
- "unknown type '%s'",
- "expected lval '%b'",
- "attempt to assign to constant '%b'",
- "unknown symbol '%s'",
- "redefinition of function '%s'",
- "mismatched types for binary operator, '%s', '%s'",
- "mismatched types on assignment, expected '%s', got '%s'",
- "expected expression, got '%s'",
+ "expected token '%s', got '%s'",
+ "unexpected token '%s'",
+ "unknown type '%s'",
+ "expected lval '%b'",
+ "attempt to assign to constant '%b'",
+ "unknown symbol '%s'",
+ "redefinition of function '%s'",
+ "mismatched types for binary operator, '%s', '%s'",
+ "mismatched types on assignment, expected '%s', got '%s'",
+ "expected expression, got '%s'",
"attempt to call non-function, '%b'",
"returning '%s' from function that returns '%s'",
};
void onyx_message_add(OnyxMessages* msgs, OnyxMessageType type, OnyxFilePos pos, ...) {
- OnyxMessage* msg = bh_alloc_item(msgs->allocator, OnyxMessage);
- msg->type = type;
- msg->pos = pos;
+ OnyxMessage* msg = bh_alloc_item(msgs->allocator, OnyxMessage);
+ msg->type = type;
+ msg->pos = pos;
- va_list arg_list;
- va_start(arg_list, pos);
- bh_snprintf_va(msg->text, ONYX_MSG_BUFFER_SIZE, msg_formats[type], arg_list);
- va_end(arg_list);
+ va_list arg_list;
+ va_start(arg_list, pos);
+ bh_snprintf_va(msg->text, ONYX_MSG_BUFFER_SIZE, msg_formats[type], arg_list);
+ va_end(arg_list);
- OnyxMessage** walker = &msgs->first;
- while (*walker && (*walker)->pos.line < pos.line) walker = &(*walker)->next;
- while (*walker && (*walker)->pos.line == pos.line && (*walker)->pos.column < pos.column) walker = &(*walker)->next;
+ OnyxMessage** walker = &msgs->first;
+ while (*walker && (*walker)->pos.line < pos.line) walker = &(*walker)->next;
+ while (*walker && (*walker)->pos.line == pos.line && (*walker)->pos.column < pos.column) walker = &(*walker)->next;
- msg->next = *walker;
- *walker = msg;
+ msg->next = *walker;
+ *walker = msg;
}
void onyx_message_print(OnyxMessages* msgs) {
- OnyxMessage* msg = msgs->first;
-
- while (msg) {
- if (msg->pos.filename) {
- bh_printf("(%s:%l:%l) %s\n", msg->pos.filename, msg->pos.line, msg->pos.column, msg->text);
- } else {
- bh_printf("(%l:%l) %s\n", msg->pos.line, msg->pos.column, msg->text);
- }
- msg = msg->next;
- }
+ OnyxMessage* msg = msgs->first;
+
+ while (msg) {
+ if (msg->pos.filename) {
+ bh_printf("(%s:%l:%l) %s\n", msg->pos.filename, msg->pos.line, msg->pos.column, msg->text);
+ } else {
+ bh_printf("(%l:%l) %s\n", msg->pos.line, msg->pos.column, msg->text);
+ }
+ msg = msg->next;
+ }
}
b32 onyx_message_has_errors(OnyxMessages* msgs) {
- return msgs->first != NULL;
+ return msgs->first != NULL;
}
void onyx_message_create(bh_allocator allocator, OnyxMessages* msgs) {
- msgs->allocator = allocator;
- msgs->first = NULL;
+ msgs->allocator = allocator;
+ msgs->first = NULL;
}
#include "onyxutils.h"
static const char* ast_node_names[] = {
- "ERROR",
- "PROGRAM",
+ "ERROR",
+ "PROGRAM",
- "FUNCDEF",
+ "FUNCDEF",
"FOREIGN",
- "BLOCK",
- "SCOPE",
- "LOCAL",
+ "BLOCK",
+ "SCOPE",
+ "LOCAL",
"SYMBOL",
"UN_OP",
"BIN_OP",
- "TYPE",
- "LITERAL",
- "CAST",
- "PARAM",
+ "TYPE",
+ "LITERAL",
+ "CAST",
+ "PARAM",
"ARGUMENT",
- "CALL",
- "ASSIGN",
- "RETURN",
+ "CALL",
+ "ASSIGN",
+ "RETURN",
- "IF",
- "WHILE",
+ "IF",
+ "WHILE",
- "ONYX_AST_NODE_KIND_COUNT",
+ "ONYX_AST_NODE_KIND_COUNT",
};
struct OnyxTypeInfo builtin_types[] = {
- { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
- { ONYX_TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
+ { ONYX_TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
+ { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
- { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
- { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
- { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
+ { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
+ { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
- { 0xffffffff } // Sentinel
+ { 0xffffffff } // Sentinel
};
static OnyxAstNode error_node = { { ONYX_AST_NODE_KIND_ERROR, 0, NULL, &builtin_types[0], 0, NULL, NULL, NULL } };
static OnyxAstNode* parse_top_level_statement(OnyxParser* parser);
static void parser_next_token(OnyxParser* parser) {
- parser->prev_token = parser->curr_token;
- parser->curr_token++;
- while (parser->curr_token->type == TOKEN_TYPE_COMMENT) parser->curr_token++;
+ parser->prev_token = parser->curr_token;
+ parser->curr_token++;
+ while (parser->curr_token->type == TOKEN_TYPE_COMMENT) parser->curr_token++;
}
static void parser_prev_token(OnyxParser* parser) {
- // TODO: This is probably wrong
- while (parser->prev_token->type == TOKEN_TYPE_COMMENT) parser->prev_token--;
- parser->curr_token = parser->prev_token;
- parser->prev_token--;
+ // TODO: This is probably wrong
+ while (parser->prev_token->type == TOKEN_TYPE_COMMENT) parser->prev_token--;
+ parser->curr_token = parser->prev_token;
+ parser->prev_token--;
}
static b32 is_terminating_token(OnyxTokenType token_type) {
- switch (token_type) {
+ switch (token_type) {
case TOKEN_TYPE_SYM_SEMICOLON:
case TOKEN_TYPE_CLOSE_BRACE:
case TOKEN_TYPE_OPEN_BRACE:
case TOKEN_TYPE_END_STREAM:
- return 1;
+ return 1;
default:
- return 0;
- }
+ return 0;
+ }
}
static void find_token(OnyxParser* parser, OnyxTokenType token_type) {
- while (parser->curr_token->type != token_type && !is_terminating_token(parser->curr_token->type)) {
- parser_next_token(parser);
- }
+ while (parser->curr_token->type != token_type && !is_terminating_token(parser->curr_token->type)) {
+ parser_next_token(parser);
+ }
}
// Advances to next token no matter what
static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type) {
- OnyxToken* token = parser->curr_token;
- parser_next_token(parser);
+ OnyxToken* token = parser->curr_token;
+ parser_next_token(parser);
- if (token->type != token_type) {
- onyx_message_add(parser->msgs,
+ if (token->type != token_type) {
+ onyx_message_add(parser->msgs,
ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
token->pos,
onyx_get_token_type_name(token_type), onyx_get_token_type_name(token->type));
- return NULL;
- }
+ return NULL;
+ }
- return token;
+ return token;
}
static OnyxAstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
static OnyxAstNode* parse_factor(OnyxParser* parser) {
OnyxAstNode* retval = NULL;
- switch (parser->curr_token->type) {
- case TOKEN_TYPE_OPEN_PAREN:
- {
- parser_next_token(parser);
- OnyxAstNode* expr = parse_expression(parser);
- expect(parser, TOKEN_TYPE_CLOSE_PAREN);
- retval = expr;
+ switch (parser->curr_token->type) {
+ case TOKEN_TYPE_OPEN_PAREN:
+ {
+ parser_next_token(parser);
+ OnyxAstNode* expr = parse_expression(parser);
+ expect(parser, TOKEN_TYPE_CLOSE_PAREN);
+ retval = expr;
break;
- }
+ }
case TOKEN_TYPE_SYM_MINUS:
{
break;
}
- case TOKEN_TYPE_SYMBOL:
- {
- OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL);
- OnyxAstNode* sym_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+ case TOKEN_TYPE_SYMBOL:
+ {
+ OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL);
+ OnyxAstNode* sym_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
sym_node->token = sym_token;
- if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN) {
- retval = sym_node;
+ if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN) {
+ retval = sym_node;
break;
- }
+ }
- // NOTE: Function call
- OnyxAstNodeCall* call_node = (OnyxAstNodeCall *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CALL);
+ // NOTE: Function call
+ OnyxAstNodeCall* call_node = (OnyxAstNodeCall *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CALL);
call_node->token = expect(parser, TOKEN_TYPE_OPEN_PAREN);
- 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) {
+ 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) {
curr = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ARGUMENT);
- curr->left = parse_expression(parser);
+ curr->left = parse_expression(parser);
curr->type = curr->left->type;
- if (curr != NULL && curr->kind != ONYX_AST_NODE_KIND_ERROR) {
- *prev = curr;
- prev = &curr->next;
- }
+ if (curr != NULL && curr->kind != ONYX_AST_NODE_KIND_ERROR) {
+ *prev = curr;
+ prev = &curr->next;
+ }
- if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN)
- break;
+ if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN)
+ break;
- if (parser->curr_token->type != TOKEN_TYPE_SYM_COMMA) {
- onyx_message_add(parser->msgs,
- ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
- parser->curr_token->pos,
- onyx_get_token_type_name(TOKEN_TYPE_SYM_COMMA),
- onyx_get_token_type_name(parser->curr_token->type));
- return &error_node;
- }
+ if (parser->curr_token->type != TOKEN_TYPE_SYM_COMMA) {
+ onyx_message_add(parser->msgs,
+ ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
+ parser->curr_token->pos,
+ onyx_get_token_type_name(TOKEN_TYPE_SYM_COMMA),
+ onyx_get_token_type_name(parser->curr_token->type));
+ return &error_node;
+ }
- parser_next_token(parser);
- }
- parser_next_token(parser);
+ parser_next_token(parser);
+ }
+ parser_next_token(parser);
- retval = (OnyxAstNode *) call_node;
+ retval = (OnyxAstNode *) call_node;
break;
- }
+ }
case TOKEN_TYPE_LITERAL_NUMERIC:
retval = (OnyxAstNode *) parse_numeric_literal(parser);
break;
}
- default:
- onyx_message_add(parser->msgs,
- ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
- parser->curr_token->pos,
- onyx_get_token_type_name(parser->curr_token->type));
+ default:
+ onyx_message_add(parser->msgs,
+ ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
+ parser->curr_token->pos,
+ onyx_get_token_type_name(parser->curr_token->type));
return NULL;
- }
+ }
if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CAST) {
OnyxAstNodeUnaryOp* cast_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
bh_arr_new(global_scratch_allocator, tree_stack, 4);
bh_arr_set_length(tree_stack, 0);
- OnyxAstNode* left = parse_factor(parser);
+ OnyxAstNode* left = parse_factor(parser);
OnyxAstNode* right;
OnyxAstNode* root = left;
}
expression_done:
- return root;
+ return root;
}
static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser) {
// Returns 1 if the symbol was consumed. Returns 0 otherwise
// ret is set to the statement to insert
static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) {
- if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) return 0;
- OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
-
- switch (parser->curr_token->type) {
- // NOTE: Declaration
- case TOKEN_TYPE_SYM_COLON:
- {
- parser_next_token(parser);
- OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
-
- // NOTE: var: type
- if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
- type = parse_type(parser);
- }
-
- OnyxAstNodeLocal* local = (OnyxAstNodeLocal*) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LOCAL);
- local->token = symbol;
- local->type = type;
- local->flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
+ if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) return 0;
+ OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
+
+ switch (parser->curr_token->type) {
+ // NOTE: Declaration
+ case TOKEN_TYPE_SYM_COLON:
+ {
+ parser_next_token(parser);
+ OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+
+ // NOTE: var: type
+ if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
+ type = parse_type(parser);
+ }
+
+ OnyxAstNodeLocal* local = (OnyxAstNodeLocal*) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LOCAL);
+ local->token = symbol;
+ local->type = type;
+ local->flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
*ret = (OnyxAstNode *) local;
- if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS || parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
- if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
- local->flags |= ONYX_AST_FLAG_CONST;
- }
+ if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS || parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
+ if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
+ local->flags |= ONYX_AST_FLAG_CONST;
+ }
- OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
+ OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
local->next = assignment;
- assignment->token = parser->curr_token;
- parser_next_token(parser);
-
- OnyxAstNode* expr = parse_expression(parser);
- if (expr == NULL) {
- onyx_token_null_toggle(*parser->curr_token);
- onyx_message_add(parser->msgs,
- ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
- assignment->token->pos,
- parser->curr_token->token);
- onyx_token_null_toggle(*parser->curr_token);
- return 1;
- }
- assignment->right = expr;
+ assignment->token = parser->curr_token;
+ parser_next_token(parser);
+
+ OnyxAstNode* expr = parse_expression(parser);
+ if (expr == NULL) {
+ onyx_token_null_toggle(*parser->curr_token);
+ onyx_message_add(parser->msgs,
+ ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
+ assignment->token->pos,
+ parser->curr_token->token);
+ onyx_token_null_toggle(*parser->curr_token);
+ return 1;
+ }
+ assignment->right = expr;
OnyxAstNode* left_symbol = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
left_symbol->token = symbol;
- assignment->left = left_symbol;
- }
- return 1;
- }
-
- // NOTE: Assignment
- case TOKEN_TYPE_SYM_EQUALS:
- {
+ assignment->left = left_symbol;
+ }
+ return 1;
+ }
+
+ // NOTE: Assignment
+ case TOKEN_TYPE_SYM_EQUALS:
+ {
OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
assignment->token = parser->curr_token;
- parser_next_token(parser);
+ parser_next_token(parser);
- OnyxAstNode* lval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+ OnyxAstNode* lval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
lval->token = symbol;
OnyxAstNode* rval = parse_expression(parser);
assignment->left = lval;
*ret = assignment;
return 1;
- }
+ }
- default:
- parser_prev_token(parser);
- }
+ default:
+ parser_prev_token(parser);
+ }
- return 0;
+ return 0;
}
static OnyxAstNode* parse_return_statement(OnyxParser* parser) {
- OnyxAstNode* return_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_RETURN);
- return_node->token = expect(parser, TOKEN_TYPE_KEYWORD_RETURN);
+ OnyxAstNode* return_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_RETURN);
+ return_node->token = expect(parser, TOKEN_TYPE_KEYWORD_RETURN);
- OnyxAstNode* expr = NULL;
+ OnyxAstNode* expr = NULL;
- if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) {
- expr = parse_expression(parser);
+ if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) {
+ expr = parse_expression(parser);
- if (expr == NULL || expr == &error_node) {
- return &error_node;
- } else {
- return_node->left = expr;
- }
- }
+ if (expr == NULL || expr == &error_node) {
+ return &error_node;
+ } else {
+ return_node->left = expr;
+ }
+ }
- return return_node;
+ return return_node;
}
static OnyxAstNode* parse_statement(OnyxParser* parser) {
b32 needs_semicolon = 1;
OnyxAstNode* retval = NULL;
- switch (parser->curr_token->type) {
- case TOKEN_TYPE_KEYWORD_RETURN:
- retval = parse_return_statement(parser);
+ switch (parser->curr_token->type) {
+ case TOKEN_TYPE_KEYWORD_RETURN:
+ retval = parse_return_statement(parser);
break;
- case TOKEN_TYPE_OPEN_BRACE:
+ case TOKEN_TYPE_OPEN_BRACE:
needs_semicolon = 0;
- retval = (OnyxAstNode *) parse_block(parser);
+ retval = (OnyxAstNode *) parse_block(parser);
break;
- case TOKEN_TYPE_SYMBOL:
+ case TOKEN_TYPE_SYMBOL:
if (parse_symbol_statement(parser, &retval)) break;
// fallthrough
- case TOKEN_TYPE_OPEN_PAREN:
- case TOKEN_TYPE_SYM_PLUS:
- case TOKEN_TYPE_SYM_MINUS:
- case TOKEN_TYPE_SYM_BANG:
- case TOKEN_TYPE_LITERAL_NUMERIC:
- case TOKEN_TYPE_LITERAL_STRING:
- retval = parse_expression(parser);
+ case TOKEN_TYPE_OPEN_PAREN:
+ case TOKEN_TYPE_SYM_PLUS:
+ case TOKEN_TYPE_SYM_MINUS:
+ case TOKEN_TYPE_SYM_BANG:
+ case TOKEN_TYPE_LITERAL_NUMERIC:
+ case TOKEN_TYPE_LITERAL_STRING:
+ retval = parse_expression(parser);
break;
- case TOKEN_TYPE_KEYWORD_IF:
+ case TOKEN_TYPE_KEYWORD_IF:
needs_semicolon = 0;
- retval = (OnyxAstNode *) parse_if_stmt(parser);
+ retval = (OnyxAstNode *) parse_if_stmt(parser);
break;
case TOKEN_TYPE_KEYWORD_WHILE:
retval->token = expect(parser, TOKEN_TYPE_KEYWORD_CONTINUE);
break;
- default:
+ default:
break;
- }
+ }
if (needs_semicolon) {
- if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) {
- onyx_message_add(parser->msgs,
- ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
- parser->curr_token->pos,
- onyx_get_token_type_name(TOKEN_TYPE_SYM_SEMICOLON),
- onyx_get_token_type_name(parser->curr_token->type));
-
- find_token(parser, TOKEN_TYPE_SYM_SEMICOLON);
- }
- parser_next_token(parser);
+ if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) {
+ onyx_message_add(parser->msgs,
+ ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
+ parser->curr_token->pos,
+ onyx_get_token_type_name(TOKEN_TYPE_SYM_SEMICOLON),
+ onyx_get_token_type_name(parser->curr_token->type));
+
+ find_token(parser, TOKEN_TYPE_SYM_SEMICOLON);
+ }
+ parser_next_token(parser);
}
return retval;
}
static OnyxAstNodeBlock* parse_block(OnyxParser* parser) {
- OnyxAstNodeBlock* block = (OnyxAstNodeBlock *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BLOCK);
+ OnyxAstNodeBlock* block = (OnyxAstNodeBlock *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BLOCK);
OnyxAstNodeScope* scope = (OnyxAstNodeScope *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SCOPE);
block->scope = scope;
- // --- is for an empty block
- if (parser->curr_token->type == TOKEN_TYPE_SYM_MINUS) {
- expect(parser, TOKEN_TYPE_SYM_MINUS);
- expect(parser, TOKEN_TYPE_SYM_MINUS);
- expect(parser, TOKEN_TYPE_SYM_MINUS);
- return block;
- }
+ // --- is for an empty block
+ if (parser->curr_token->type == TOKEN_TYPE_SYM_MINUS) {
+ expect(parser, TOKEN_TYPE_SYM_MINUS);
+ expect(parser, TOKEN_TYPE_SYM_MINUS);
+ expect(parser, TOKEN_TYPE_SYM_MINUS);
+ return block;
+ }
- expect(parser, TOKEN_TYPE_OPEN_BRACE);
+ expect(parser, TOKEN_TYPE_OPEN_BRACE);
- OnyxAstNode** next = &block->body;
- OnyxAstNode* stmt = NULL;
- while (parser->curr_token->type != TOKEN_TYPE_CLOSE_BRACE) {
- stmt = parse_statement(parser);
+ OnyxAstNode** next = &block->body;
+ OnyxAstNode* stmt = NULL;
+ while (parser->curr_token->type != TOKEN_TYPE_CLOSE_BRACE) {
+ stmt = parse_statement(parser);
- if (stmt != NULL && stmt->kind != ONYX_AST_NODE_KIND_ERROR) {
- *next = stmt;
+ if (stmt != NULL && stmt->kind != ONYX_AST_NODE_KIND_ERROR) {
+ *next = stmt;
while (stmt->next != NULL) stmt = stmt->next;
- next = &stmt->next;
- }
- }
+ next = &stmt->next;
+ }
+ }
- expect(parser, TOKEN_TYPE_CLOSE_BRACE);
+ expect(parser, TOKEN_TYPE_CLOSE_BRACE);
- return block;
+ return block;
}
static OnyxTypeInfo* parse_type(OnyxParser* parser) {
- OnyxTypeInfo* type_info = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+ OnyxTypeInfo* type_info = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
- OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
- if (symbol == NULL) return type_info;
+ OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
+ if (symbol == NULL) return type_info;
- onyx_token_null_toggle(*symbol);
+ onyx_token_null_toggle(*symbol);
- 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_table_get(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_table_get(OnyxAstNode*, parser->identifiers, symbol->token);
- if (type_info_node->kind == ONYX_AST_NODE_KIND_TYPE) {
- type_info = type_info_node->type;
- }
- }
+ if (type_info_node->kind == ONYX_AST_NODE_KIND_TYPE) {
+ type_info = type_info_node->type;
+ }
+ }
- onyx_token_null_toggle(*symbol);
- return type_info;
+ onyx_token_null_toggle(*symbol);
+ return type_info;
}
static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) {
if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN)
return NULL;
- expect(parser, TOKEN_TYPE_OPEN_PAREN);
+ expect(parser, TOKEN_TYPE_OPEN_PAREN);
- if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN) {
- parser_next_token(parser);
- return NULL;
- }
+ if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN) {
+ parser_next_token(parser);
+ return NULL;
+ }
- OnyxAstNodeParam* first_param = NULL;
- OnyxAstNodeParam* curr_param = NULL;
- OnyxAstNodeParam* trailer = NULL;
+ OnyxAstNodeParam* first_param = NULL;
+ OnyxAstNodeParam* curr_param = NULL;
+ OnyxAstNodeParam* trailer = NULL;
- OnyxToken* symbol;
- while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) {
- if (parser->curr_token->type == TOKEN_TYPE_SYM_COMMA) parser_next_token(parser);
+ OnyxToken* symbol;
+ while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) {
+ if (parser->curr_token->type == TOKEN_TYPE_SYM_COMMA) parser_next_token(parser);
- symbol = expect(parser, TOKEN_TYPE_SYMBOL);
+ symbol = expect(parser, TOKEN_TYPE_SYMBOL);
- curr_param = (OnyxAstNodeParam *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PARAM);
- curr_param->token = symbol;
- curr_param->type = parse_type(parser);
+ curr_param = (OnyxAstNodeParam *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PARAM);
+ curr_param->token = symbol;
+ curr_param->type = parse_type(parser);
curr_param->flags |= ONYX_AST_FLAG_CONST;
- if (first_param == NULL) first_param = curr_param;
+ if (first_param == NULL) first_param = curr_param;
- curr_param->next = NULL;
- if (trailer) trailer->next = curr_param;
+ curr_param->next = NULL;
+ if (trailer) trailer->next = curr_param;
- trailer = curr_param;
- }
+ trailer = curr_param;
+ }
- parser_next_token(parser); // Skip the )
- return first_param;
+ parser_next_token(parser); // Skip the )
+ return first_param;
}
static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) {
- expect(parser, TOKEN_TYPE_KEYWORD_PROC);
+ expect(parser, TOKEN_TYPE_KEYWORD_PROC);
- OnyxAstNodeFuncDef* func_def = (OnyxAstNodeFuncDef *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCDEF);
+ OnyxAstNodeFuncDef* func_def = (OnyxAstNodeFuncDef *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCDEF);
- OnyxAstNodeParam* params = parse_function_params(parser);
- func_def->params = params;
+ OnyxAstNodeParam* params = parse_function_params(parser);
+ func_def->params = params;
- if (parser->curr_token->type == TOKEN_TYPE_RIGHT_ARROW) {
- expect(parser, TOKEN_TYPE_RIGHT_ARROW);
+ if (parser->curr_token->type == TOKEN_TYPE_RIGHT_ARROW) {
+ expect(parser, TOKEN_TYPE_RIGHT_ARROW);
- OnyxTypeInfo* return_type = parse_type(parser);
- func_def->return_type = return_type;
- } else {
- func_def->return_type = &builtin_types[ONYX_TYPE_INFO_KIND_VOID];
- }
+ OnyxTypeInfo* return_type = parse_type(parser);
+ func_def->return_type = return_type;
+ } else {
+ func_def->return_type = &builtin_types[ONYX_TYPE_INFO_KIND_VOID];
+ }
- func_def->body = parse_block(parser);
+ func_def->body = parse_block(parser);
- return func_def;
+ return func_def;
}
static OnyxAstNode* parse_top_level_symbol(OnyxParser* parser) {
}
static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
- switch (parser->curr_token->type) {
- case TOKEN_TYPE_KEYWORD_USE:
- assert(0);
- break;
-
- case TOKEN_TYPE_KEYWORD_EXPORT:
- {
- expect(parser, TOKEN_TYPE_KEYWORD_EXPORT);
- if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) {
- onyx_message_add(parser->msgs,
- ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
- parser->curr_token->pos,
- onyx_get_token_type_name(TOKEN_TYPE_SYMBOL),
- onyx_get_token_type_name(parser->curr_token->type));
- break;
- }
-
- OnyxAstNode* top_level_decl = parse_top_level_statement(parser);
- top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED;
- return top_level_decl;
- }
-
- case TOKEN_TYPE_SYMBOL:
- {
- OnyxToken* symbol = parser->curr_token;
- parser_next_token(parser);
-
- expect(parser, TOKEN_TYPE_SYM_COLON);
- expect(parser, TOKEN_TYPE_SYM_COLON);
+ switch (parser->curr_token->type) {
+ case TOKEN_TYPE_KEYWORD_USE:
+ assert(0);
+ break;
+
+ case TOKEN_TYPE_KEYWORD_EXPORT:
+ {
+ expect(parser, TOKEN_TYPE_KEYWORD_EXPORT);
+ if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) {
+ onyx_message_add(parser->msgs,
+ ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
+ parser->curr_token->pos,
+ onyx_get_token_type_name(TOKEN_TYPE_SYMBOL),
+ onyx_get_token_type_name(parser->curr_token->type));
+ break;
+ }
+
+ OnyxAstNode* top_level_decl = parse_top_level_statement(parser);
+ top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED;
+ return top_level_decl;
+ }
+
+ case TOKEN_TYPE_SYMBOL:
+ {
+ OnyxToken* symbol = parser->curr_token;
+ parser_next_token(parser);
+
+ expect(parser, TOKEN_TYPE_SYM_COLON);
+ expect(parser, TOKEN_TYPE_SYM_COLON);
OnyxAstNode* node = parse_top_level_symbol(parser);
if (node->kind == ONYX_AST_NODE_KIND_FUNCDEF) {
}
return node;
- }
+ }
- default: break;
- }
+ default: break;
+ }
- parser_next_token(parser);
- return NULL;
+ parser_next_token(parser);
+ return NULL;
}
const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind) {
- return ast_node_names[kind];
+ return ast_node_names[kind];
}
// NOTE: This returns a void* so I don't need to cast it everytime I use it
void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind) {\
- OnyxAstNode* node = bh_alloc_item(alloc, OnyxAstNode);
- node->kind = kind;
- node->flags = 0;
- node->token = NULL;
- node->type = NULL;
+ OnyxAstNode* node = bh_alloc_item(alloc, OnyxAstNode);
+ node->kind = kind;
+ node->flags = 0;
+ node->token = NULL;
+ node->type = NULL;
node->data = 0;
- node->next = NULL;
- node->left = NULL;
- node->right = NULL;
+ node->next = NULL;
+ node->left = NULL;
+ node->right = NULL;
- return node;
+ return node;
}
OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs) {
- OnyxParser parser;
+ OnyxParser parser;
- bh_table_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_table_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp);
- it++;
- }
+ 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_table_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp);
+ it++;
+ }
- parser.allocator = alloc;
- parser.tokenizer = tokenizer;
- parser.curr_token = tokenizer->tokens;
- parser.prev_token = NULL;
- parser.msgs = msgs;
+ parser.allocator = alloc;
+ parser.tokenizer = tokenizer;
+ parser.curr_token = tokenizer->tokens;
+ parser.prev_token = NULL;
+ parser.msgs = msgs;
- return parser;
+ return parser;
}
void onyx_parser_free(OnyxParser* parser) {
- bh_table_free(parser->identifiers);
+ bh_table_free(parser->identifiers);
}
OnyxAstNodeFile* onyx_parse(OnyxParser *parser) {
- OnyxAstNodeFile* program = (OnyxAstNodeFile *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM);
+ OnyxAstNodeFile* program = (OnyxAstNodeFile *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM);
- OnyxAstNode** prev_stmt = &program->contents;
- OnyxAstNode* curr_stmt = NULL;
- while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) {
- curr_stmt = parse_top_level_statement(parser);
+ OnyxAstNode** prev_stmt = &program->contents;
+ OnyxAstNode* curr_stmt = NULL;
+ while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) {
+ curr_stmt = parse_top_level_statement(parser);
- // Building a linked list of statements down the "next" chain
- if (curr_stmt != NULL && curr_stmt != &error_node) {
- *prev_stmt = curr_stmt;
+ // Building a linked list of statements down the "next" chain
+ if (curr_stmt != NULL && curr_stmt != &error_node) {
+ *prev_stmt = curr_stmt;
while (curr_stmt->next != NULL) curr_stmt = curr_stmt->next;
- prev_stmt = &curr_stmt->next;
- }
- }
+ prev_stmt = &curr_stmt->next;
+ }
+ }
- return program;
+ return program;
}
static void typecheck_statement(OnyxSemPassState* state, OnyxAstNode* stmt) {
switch (stmt->kind) {
case ONYX_AST_NODE_KIND_ASSIGNMENT: typecheck_assignment(state, stmt); break;
- case ONYX_AST_NODE_KIND_RETURN: typecheck_return(state, stmt); break;
+ case ONYX_AST_NODE_KIND_RETURN: typecheck_return(state, stmt); break;
case ONYX_AST_NODE_KIND_IF: typecheck_if(state, &stmt->as_if); break;
case ONYX_AST_NODE_KIND_WHILE: typecheck_while(state, &stmt->as_while); break;
case ONYX_AST_NODE_KIND_CALL: typecheck_call(state, &stmt->as_call); break;
#define print_indent { if (indent > 0) bh_printf("\n"); for (int i = 0; i < indent; i++) bh_printf(" "); }
void onyx_ast_print(OnyxAstNode* node, i32 indent) {
- if (node == NULL) return;
+ if (node == NULL) return;
- print_indent;
- bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
+ print_indent;
+ bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
- switch (node->kind) {
- case ONYX_AST_NODE_KIND_PROGRAM: {
- if (node->next)
- onyx_ast_print(node->next, indent + 1);
+ switch (node->kind) {
+ case ONYX_AST_NODE_KIND_PROGRAM: {
+ if (node->next)
+ onyx_ast_print(node->next, indent + 1);
- break;
- }
+ break;
+ }
- case ONYX_AST_NODE_KIND_FUNCDEF: {
+ case ONYX_AST_NODE_KIND_FUNCDEF: {
if (node->token)
bh_printf("(%b) ", node->token->token, node->token->length);
- OnyxAstNodeFuncDef* fd = &node->as_funcdef;
-
- print_indent;
- bh_printf("Params ");
- if (fd->params)
- onyx_ast_print((OnyxAstNode *) fd->params, 0);
-
- print_indent;
- bh_printf("Returns %s", fd->return_type->name);
-
- print_indent;
- bh_printf("Body");
- if (fd->body)
- onyx_ast_print((OnyxAstNode *) fd->body, indent + 1);
-
- if (fd->next)
- onyx_ast_print((OnyxAstNode *) fd->next, indent);
-
- break;
- }
-
- case ONYX_AST_NODE_KIND_PARAM: {
- OnyxAstNodeParam* param = &node->as_param;
- bh_printf("%b %s", param->token->token, param->token->length, param->type->name);
- if (param->next && indent == 0) {
- bh_printf(", ");
- onyx_ast_print((OnyxAstNode *) param->next, 0);
- }
-
- break;
- }
-
- case ONYX_AST_NODE_KIND_BLOCK: {
- OnyxAstNodeBlock* block = &node->as_block;
- if (block->scope) {
- onyx_ast_print((OnyxAstNode *) block->scope, indent + 1);
- }
-
- if (block->body) {
- onyx_ast_print((OnyxAstNode *) block->body, indent + 1);
- }
-
- if (block->next) {
- onyx_ast_print(block->next, indent);
- }
-
- break;
- }
-
- case ONYX_AST_NODE_KIND_SCOPE: {
- OnyxAstNodeScope* scope = &node->as_scope;
- if (scope->last_local) {
- onyx_ast_print((OnyxAstNode *) scope->last_local, 0);
- }
-
- break;
- }
-
- case ONYX_AST_NODE_KIND_LOCAL: {
- OnyxAstNodeLocal* local = &node->as_local;
- bh_printf("%b %s", local->token->token, local->token->length, local->type->name);
- if (local->prev_local && indent == 0) {
- bh_printf(", ");
- onyx_ast_print((OnyxAstNode *) local->prev_local, 0);
- } else if (local->next && indent != 0) {
+ OnyxAstNodeFuncDef* fd = &node->as_funcdef;
+
+ print_indent;
+ bh_printf("Params ");
+ if (fd->params)
+ onyx_ast_print((OnyxAstNode *) fd->params, 0);
+
+ print_indent;
+ bh_printf("Returns %s", fd->return_type->name);
+
+ print_indent;
+ bh_printf("Body");
+ if (fd->body)
+ onyx_ast_print((OnyxAstNode *) fd->body, indent + 1);
+
+ if (fd->next)
+ onyx_ast_print((OnyxAstNode *) fd->next, indent);
+
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_PARAM: {
+ OnyxAstNodeParam* param = &node->as_param;
+ bh_printf("%b %s", param->token->token, param->token->length, param->type->name);
+ if (param->next && indent == 0) {
+ bh_printf(", ");
+ onyx_ast_print((OnyxAstNode *) param->next, 0);
+ }
+
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_BLOCK: {
+ OnyxAstNodeBlock* block = &node->as_block;
+ if (block->scope) {
+ onyx_ast_print((OnyxAstNode *) block->scope, indent + 1);
+ }
+
+ if (block->body) {
+ onyx_ast_print((OnyxAstNode *) block->body, indent + 1);
+ }
+
+ if (block->next) {
+ onyx_ast_print(block->next, indent);
+ }
+
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_SCOPE: {
+ OnyxAstNodeScope* scope = &node->as_scope;
+ if (scope->last_local) {
+ onyx_ast_print((OnyxAstNode *) scope->last_local, 0);
+ }
+
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_LOCAL: {
+ OnyxAstNodeLocal* local = &node->as_local;
+ bh_printf("%b %s", local->token->token, local->token->length, local->type->name);
+ if (local->prev_local && indent == 0) {
+ bh_printf(", ");
+ onyx_ast_print((OnyxAstNode *) local->prev_local, 0);
+ } else if (local->next && indent != 0) {
onyx_ast_print(local->next, indent);
}
- break;
- }
+ break;
+ }
case ONYX_AST_NODE_KIND_SYMBOL: {
bh_printf("%b", node->token->token, node->token->length);
break;
}
- case ONYX_AST_NODE_KIND_RETURN: {
- if (node->left) {
- onyx_ast_print(node->left, indent + 1);
- }
-
- break;
- }
-
- case ONYX_AST_NODE_KIND_LITERAL: {
- bh_printf("(%s) %b", node->type->name, node->token->token, node->token->length);
- if (node->next) {
- onyx_ast_print(node->next, indent);
- }
- break;
- }
-
- case ONYX_AST_NODE_KIND_CAST: {
- bh_printf("to %s ", node->type->name);
- onyx_ast_print(node->left, indent + 1);
- if (node->next) {
- onyx_ast_print(node->next, indent);
- }
- break;
- }
-
- case ONYX_AST_NODE_KIND_CALL: {
- OnyxAstNodeCall* call = &node->as_call;
+ case ONYX_AST_NODE_KIND_RETURN: {
+ if (node->left) {
+ onyx_ast_print(node->left, indent + 1);
+ }
+
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_LITERAL: {
+ bh_printf("(%s) %b", node->type->name, node->token->token, node->token->length);
+ if (node->next) {
+ onyx_ast_print(node->next, indent);
+ }
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_CAST: {
+ bh_printf("to %s ", node->type->name);
+ onyx_ast_print(node->left, indent + 1);
+ if (node->next) {
+ onyx_ast_print(node->next, indent);
+ }
+ break;
+ }
+
+ case ONYX_AST_NODE_KIND_CALL: {
+ OnyxAstNodeCall* call = &node->as_call;
if (call->callee) {
if (call->callee->kind == ONYX_AST_NODE_KIND_FUNCDEF) {
bh_printf("function: %b", call->callee->token->token, call->callee->token->length);
onyx_ast_print(call->callee, indent + 1);
}
}
- onyx_ast_print(call->arguments, indent + 1);
- if (call->next) {
- onyx_ast_print(call->next, indent);
- }
- break;
- }
+ onyx_ast_print(call->arguments, indent + 1);
+ if (call->next) {
+ onyx_ast_print(call->next, indent);
+ }
+ break;
+ }
case ONYX_AST_NODE_KIND_FOREIGN: {
OnyxAstNodeForeign* foreign = &node->as_foreign;
onyx_ast_print(foreign->import, indent + 1);
}
- if (foreign->next) {
- onyx_ast_print(foreign->next, indent);
- }
+ if (foreign->next) {
+ onyx_ast_print(foreign->next, indent);
+ }
break;
}
break;
}
- default: {
- onyx_ast_print(node->left, indent + 1);
- onyx_ast_print(node->right, indent + 1);
- if (node->next) {
- onyx_ast_print(node->next, indent);
- }
- break;
- }
- }
+ default: {
+ onyx_ast_print(node->left, indent + 1);
+ onyx_ast_print(node->right, indent + 1);
+ if (node->next) {
+ onyx_ast_print(node->next, indent);
+ }
+ break;
+ }
+ }
}
#endif
static const char* wi_string(WasmInstructionType wit) {
- switch (wit) {
- case WI_UNREACHABLE: return "WI_UNREACHABLE";
- case WI_NOP: return "WI_NOP";
- case WI_BLOCK_START: return "WI_BLOCK_START";
- case WI_BLOCK_END: return "WI_BLOCK_END";
- case WI_LOOP_START: return "WI_LOOP_START";
- case WI_IF_START: return "WI_IF_START";
- case WI_ELSE: return "WI_ELSE";
- case WI_JUMP: return "WI_JUMP";
- case WI_COND_JUMP: return "WI_COND_JUMP";
- case WI_JUMP_TABLE: return "WI_JUMP_TABLE";
- case WI_RETURN: return "WI_RETURN";
- case WI_CALL: return "WI_CALL";
- case WI_CALL_INDIRECT: return "WI_CALL_INDIRECT";
- case WI_DROP: return "WI_DROP";
- case WI_SELECT: return "WI_SELECT";
- case WI_LOCAL_GET: return "WI_LOCAL_GET";
- case WI_LOCAL_SET: return "WI_LOCAL_SET";
- case WI_LOCAL_TEE: return "WI_LOCAL_TEE";
- case WI_GLOBAL_GET: return "WI_GLOBAL_GET";
- case WI_GLOBAL_SET: return "WI_GLOBAL_SET";
- case WI_I32_LOAD: return "WI_I32_LOAD";
- case WI_I64_LOAD: return "WI_I64_LOAD";
- case WI_F32_LOAD: return "WI_F32_LOAD";
- case WI_F64_LOAD: return "WI_F64_LOAD";
- case WI_I32_LOAD_8_S: return "WI_I32_LOAD_8_S";
- case WI_I32_LOAD_8_U: return "WI_I32_LOAD_8_U";
- case WI_I32_LOAD_16_S: return "WI_I32_LOAD_16_S";
- case WI_I32_LOAD_16_U: return "WI_I32_LOAD_16_U";
- case WI_I64_LOAD_8_S: return "WI_I64_LOAD_8_S";
- case WI_I64_LOAD_8_U: return "WI_I64_LOAD_8_U";
- case WI_I64_LOAD_16_S: return "WI_I64_LOAD_16_S";
- case WI_I64_LOAD_16_U: return "WI_I64_LOAD_16_U";
- case WI_I64_LOAD_32_S: return "WI_I64_LOAD_32_S";
- case WI_I64_LOAD_32_U: return "WI_I64_LOAD_32_U";
- case WI_I32_STORE: return "WI_I32_STORE";
- case WI_I64_STORE: return "WI_I64_STORE";
- case WI_F32_STORE: return "WI_F32_STORE";
- case WI_F64_STORE: return "WI_F64_STORE";
- case WI_I32_STORE_8: return "WI_I32_STORE_8";
- case WI_I32_STORE_16: return "WI_I32_STORE_16";
- case WI_I64_STORE_8: return "WI_I64_STORE_8";
- case WI_I64_STORE_16: return "WI_I64_STORE_16";
- case WI_I64_STORE_32: return "WI_I64_STORE_32";
- case WI_MEMORY_SIZE: return "WI_MEMORY_SIZE";
- case WI_MEMORY_GROW: return "WI_MEMORY_GROW";
- case WI_I32_CONST: return "WI_I32_CONST";
- case WI_I64_CONST: return "WI_I64_CONST";
- case WI_F32_CONST: return "WI_F32_CONST";
- case WI_F64_CONST: return "WI_F64_CONST";
- case WI_I32_EQZ: return "WI_I32_EQZ";
- case WI_I32_EQ: return "WI_I32_EQ";
- case WI_I32_NE: return "WI_I32_NE";
- case WI_I32_LT_S: return "WI_I32_LT_S";
- case WI_I32_LT_U: return "WI_I32_LT_U";
- case WI_I32_GT_S: return "WI_I32_GT_S";
- case WI_I32_GT_U: return "WI_I32_GT_U";
- case WI_I32_LE_S: return "WI_I32_LE_S";
- case WI_I32_LE_U: return "WI_I32_LE_U";
- case WI_I32_GE_S: return "WI_I32_GE_S";
- case WI_I32_GE_U: return "WI_I32_GE_U";
- case WI_I64_EQZ: return "WI_I64_EQZ";
- case WI_I64_EQ: return "WI_I64_EQ";
- case WI_I64_NE: return "WI_I64_NE";
- case WI_I64_LT_S: return "WI_I64_LT_S";
- case WI_I64_LT_U: return "WI_I64_LT_U";
- case WI_I64_GT_S: return "WI_I64_GT_S";
- case WI_I64_GT_U: return "WI_I64_GT_U";
- case WI_I64_LE_S: return "WI_I64_LE_S";
- case WI_I64_LE_U: return "WI_I64_LE_U";
- case WI_I64_GE_S: return "WI_I64_GE_S";
- case WI_I64_GE_U: return "WI_I64_GE_U";
- case WI_F32_EQ: return "WI_F32_EQ";
- case WI_F32_NE: return "WI_F32_NE";
- case WI_F32_LT: return "WI_F32_LT";
- case WI_F32_GT: return "WI_F32_GT";
- case WI_F32_LE: return "WI_F32_LE";
- case WI_F32_GE: return "WI_F32_GE";
- case WI_F64_EQ: return "WI_F64_EQ";
- case WI_F64_NE: return "WI_F64_NE";
- case WI_F64_LT: return "WI_F64_LT";
- case WI_F64_GT: return "WI_F64_GT";
- case WI_F64_LE: return "WI_F64_LE";
- case WI_F64_GE: return "WI_F64_GE";
- case WI_I32_CLZ: return "WI_I32_CLZ";
- case WI_I32_CTZ: return "WI_I32_CTZ";
- case WI_I32_POPCNT: return "WI_I32_POPCNT";
- case WI_I32_ADD: return "WI_I32_ADD";
- case WI_I32_SUB: return "WI_I32_SUB";
- case WI_I32_MUL: return "WI_I32_MUL";
- case WI_I32_DIV_S: return "WI_I32_DIV_S";
- case WI_I32_DIV_U: return "WI_I32_DIV_U";
- case WI_I32_REM_S: return "WI_I32_REM_S";
- case WI_I32_REM_U: return "WI_I32_REM_U";
- case WI_I32_AND: return "WI_I32_AND";
- case WI_I32_OR: return "WI_I32_OR";
- case WI_I32_XOR: return "WI_I32_XOR";
- case WI_I32_SHL: return "WI_I32_SHL";
- case WI_I32_SHR_S: return "WI_I32_SHR_S";
- case WI_I32_SHR_U: return "WI_I32_SHR_U";
- case WI_I32_ROTL: return "WI_I32_ROTL";
- case WI_I32_ROTR: return "WI_I32_ROTR";
- case WI_I64_CLZ: return "WI_I64_CLZ";
- case WI_I64_CTZ: return "WI_I64_CTZ";
- case WI_I64_POPCNT: return "WI_I64_POPCNT";
- case WI_I64_ADD: return "WI_I64_ADD";
- case WI_I64_SUB: return "WI_I64_SUB";
- case WI_I64_MUL: return "WI_I64_MUL";
- case WI_I64_DIV_S: return "WI_I64_DIV_S";
- case WI_I64_DIV_U: return "WI_I64_DIV_U";
- case WI_I64_REM_S: return "WI_I64_REM_S";
- case WI_I64_REM_U: return "WI_I64_REM_U";
- case WI_I64_AND: return "WI_I64_AND";
- case WI_I64_OR: return "WI_I64_OR";
- case WI_I64_XOR: return "WI_I64_XOR";
- case WI_I64_SHL: return "WI_I64_SHL";
- case WI_I64_SHR_S: return "WI_I64_SHR_S";
- case WI_I64_SHR_U: return "WI_I64_SHR_U";
- case WI_I64_ROTL: return "WI_I64_ROTL";
- case WI_I64_ROTR: return "WI_I64_ROTR";
- case WI_F32_ABS: return "WI_F32_ABS";
- case WI_F32_NEG: return "WI_F32_NEG";
- case WI_F32_CEIL: return "WI_F32_CEIL";
- case WI_F32_FLOOR: return "WI_F32_FLOOR";
- case WI_F32_TRUNC: return "WI_F32_TRUNC";
- case WI_F32_NEAREST: return "WI_F32_NEAREST";
- case WI_F32_SQRT: return "WI_F32_SQRT";
- case WI_F32_ADD: return "WI_F32_ADD";
- case WI_F32_SUB: return "WI_F32_SUB";
- case WI_F32_MUL: return "WI_F32_MUL";
- case WI_F32_DIV: return "WI_F32_DIV";
- case WI_F32_MIN: return "WI_F32_MIN";
- case WI_F32_MAX: return "WI_F32_MAX";
- case WI_F32_COPYSIGN: return "WI_F32_COPYSIGN";
- case WI_F64_ABS: return "WI_F64_ABS";
- case WI_F64_NEG: return "WI_F64_NEG";
- case WI_F64_CEIL: return "WI_F64_CEIL";
- case WI_F64_FLOOR: return "WI_F64_FLOOR";
- case WI_F64_TRUNC: return "WI_F64_TRUNC";
- case WI_F64_NEAREST: return "WI_F64_NEAREST";
- case WI_F64_SQRT: return "WI_F64_SQRT";
- case WI_F64_ADD: return "WI_F64_ADD";
- case WI_F64_SUB: return "WI_F64_SUB";
- case WI_F64_MUL: return "WI_F64_MUL";
- case WI_F64_DIV: return "WI_F64_DIV";
- case WI_F64_MIN: return "WI_F64_MIN";
- case WI_F64_MAX: return "WI_F64_MAX";
- case WI_F64_COPYSIGN: return "WI_F64_COPYSIGN";
- case WI_I32_FROM_I64: return "WI_I32_FROM_I64";
- case WI_I32_FROM_F32_S: return "WI_I32_FROM_F32_S";
- case WI_I32_FROM_F32_U: return "WI_I32_FROM_F32_U";
- case WI_I32_FROM_F64_S: return "WI_I32_FROM_F64_S";
- case WI_I32_FROM_F64_U: return "WI_I32_FROM_F64_U";
- case WI_I64_FROM_I32_S: return "WI_I64_FROM_I32_S";
- case WI_I64_FROM_I32_U: return "WI_I64_FROM_I32_U";
- case WI_I64_FROM_F32_S: return "WI_I64_FROM_F32_S";
- case WI_I64_FROM_F32_U: return "WI_I64_FROM_F32_U";
- case WI_I64_FROM_F64_S: return "WI_I64_FROM_F64_S";
- case WI_I64_FROM_F64_U: return "WI_I64_FROM_F64_U";
- case WI_F32_FROM_I32_S: return "WI_F32_FROM_I32_S";
- case WI_F32_FROM_I32_U: return "WI_F32_FROM_I32_U";
- case WI_F32_FROM_I64_S: return "WI_F32_FROM_I64_S";
- case WI_F32_FROM_I64_U: return "WI_F32_FROM_I64_U";
- case WI_F32_FROM_F64: return "WI_F32_FROM_F64";
- case WI_F64_FROM_I32_S: return "WI_F64_FROM_I32_S";
- case WI_F64_FROM_I32_U: return "WI_F64_FROM_I32_U";
- case WI_F64_FROM_I64_S: return "WI_F64_FROM_I64_S";
- case WI_F64_FROM_I64_U: return "WI_F64_FROM_I64_U";
- case WI_F64_FROM_F32: return "WI_F64_FROM_F32";
- case WI_I32_REINTERPRET_F32: return "WI_I32_REINTERPRET_F32";
- case WI_I64_REINTERPRET_F64: return "WI_I64_REINTERPRET_F64";
- case WI_F32_REINTERPRET_I32: return "WI_F32_REINTERPRET_I32";
- case WI_F64_REINTERPRET_I64: return "WI_F64_REINTERPRET_I64";
- }
+ switch (wit) {
+ case WI_UNREACHABLE: return "WI_UNREACHABLE";
+ case WI_NOP: return "WI_NOP";
+ case WI_BLOCK_START: return "WI_BLOCK_START";
+ case WI_BLOCK_END: return "WI_BLOCK_END";
+ case WI_LOOP_START: return "WI_LOOP_START";
+ case WI_IF_START: return "WI_IF_START";
+ case WI_ELSE: return "WI_ELSE";
+ case WI_JUMP: return "WI_JUMP";
+ case WI_COND_JUMP: return "WI_COND_JUMP";
+ case WI_JUMP_TABLE: return "WI_JUMP_TABLE";
+ case WI_RETURN: return "WI_RETURN";
+ case WI_CALL: return "WI_CALL";
+ case WI_CALL_INDIRECT: return "WI_CALL_INDIRECT";
+ case WI_DROP: return "WI_DROP";
+ case WI_SELECT: return "WI_SELECT";
+ case WI_LOCAL_GET: return "WI_LOCAL_GET";
+ case WI_LOCAL_SET: return "WI_LOCAL_SET";
+ case WI_LOCAL_TEE: return "WI_LOCAL_TEE";
+ case WI_GLOBAL_GET: return "WI_GLOBAL_GET";
+ case WI_GLOBAL_SET: return "WI_GLOBAL_SET";
+ case WI_I32_LOAD: return "WI_I32_LOAD";
+ case WI_I64_LOAD: return "WI_I64_LOAD";
+ case WI_F32_LOAD: return "WI_F32_LOAD";
+ case WI_F64_LOAD: return "WI_F64_LOAD";
+ case WI_I32_LOAD_8_S: return "WI_I32_LOAD_8_S";
+ case WI_I32_LOAD_8_U: return "WI_I32_LOAD_8_U";
+ case WI_I32_LOAD_16_S: return "WI_I32_LOAD_16_S";
+ case WI_I32_LOAD_16_U: return "WI_I32_LOAD_16_U";
+ case WI_I64_LOAD_8_S: return "WI_I64_LOAD_8_S";
+ case WI_I64_LOAD_8_U: return "WI_I64_LOAD_8_U";
+ case WI_I64_LOAD_16_S: return "WI_I64_LOAD_16_S";
+ case WI_I64_LOAD_16_U: return "WI_I64_LOAD_16_U";
+ case WI_I64_LOAD_32_S: return "WI_I64_LOAD_32_S";
+ case WI_I64_LOAD_32_U: return "WI_I64_LOAD_32_U";
+ case WI_I32_STORE: return "WI_I32_STORE";
+ case WI_I64_STORE: return "WI_I64_STORE";
+ case WI_F32_STORE: return "WI_F32_STORE";
+ case WI_F64_STORE: return "WI_F64_STORE";
+ case WI_I32_STORE_8: return "WI_I32_STORE_8";
+ case WI_I32_STORE_16: return "WI_I32_STORE_16";
+ case WI_I64_STORE_8: return "WI_I64_STORE_8";
+ case WI_I64_STORE_16: return "WI_I64_STORE_16";
+ case WI_I64_STORE_32: return "WI_I64_STORE_32";
+ case WI_MEMORY_SIZE: return "WI_MEMORY_SIZE";
+ case WI_MEMORY_GROW: return "WI_MEMORY_GROW";
+ case WI_I32_CONST: return "WI_I32_CONST";
+ case WI_I64_CONST: return "WI_I64_CONST";
+ case WI_F32_CONST: return "WI_F32_CONST";
+ case WI_F64_CONST: return "WI_F64_CONST";
+ case WI_I32_EQZ: return "WI_I32_EQZ";
+ case WI_I32_EQ: return "WI_I32_EQ";
+ case WI_I32_NE: return "WI_I32_NE";
+ case WI_I32_LT_S: return "WI_I32_LT_S";
+ case WI_I32_LT_U: return "WI_I32_LT_U";
+ case WI_I32_GT_S: return "WI_I32_GT_S";
+ case WI_I32_GT_U: return "WI_I32_GT_U";
+ case WI_I32_LE_S: return "WI_I32_LE_S";
+ case WI_I32_LE_U: return "WI_I32_LE_U";
+ case WI_I32_GE_S: return "WI_I32_GE_S";
+ case WI_I32_GE_U: return "WI_I32_GE_U";
+ case WI_I64_EQZ: return "WI_I64_EQZ";
+ case WI_I64_EQ: return "WI_I64_EQ";
+ case WI_I64_NE: return "WI_I64_NE";
+ case WI_I64_LT_S: return "WI_I64_LT_S";
+ case WI_I64_LT_U: return "WI_I64_LT_U";
+ case WI_I64_GT_S: return "WI_I64_GT_S";
+ case WI_I64_GT_U: return "WI_I64_GT_U";
+ case WI_I64_LE_S: return "WI_I64_LE_S";
+ case WI_I64_LE_U: return "WI_I64_LE_U";
+ case WI_I64_GE_S: return "WI_I64_GE_S";
+ case WI_I64_GE_U: return "WI_I64_GE_U";
+ case WI_F32_EQ: return "WI_F32_EQ";
+ case WI_F32_NE: return "WI_F32_NE";
+ case WI_F32_LT: return "WI_F32_LT";
+ case WI_F32_GT: return "WI_F32_GT";
+ case WI_F32_LE: return "WI_F32_LE";
+ case WI_F32_GE: return "WI_F32_GE";
+ case WI_F64_EQ: return "WI_F64_EQ";
+ case WI_F64_NE: return "WI_F64_NE";
+ case WI_F64_LT: return "WI_F64_LT";
+ case WI_F64_GT: return "WI_F64_GT";
+ case WI_F64_LE: return "WI_F64_LE";
+ case WI_F64_GE: return "WI_F64_GE";
+ case WI_I32_CLZ: return "WI_I32_CLZ";
+ case WI_I32_CTZ: return "WI_I32_CTZ";
+ case WI_I32_POPCNT: return "WI_I32_POPCNT";
+ case WI_I32_ADD: return "WI_I32_ADD";
+ case WI_I32_SUB: return "WI_I32_SUB";
+ case WI_I32_MUL: return "WI_I32_MUL";
+ case WI_I32_DIV_S: return "WI_I32_DIV_S";
+ case WI_I32_DIV_U: return "WI_I32_DIV_U";
+ case WI_I32_REM_S: return "WI_I32_REM_S";
+ case WI_I32_REM_U: return "WI_I32_REM_U";
+ case WI_I32_AND: return "WI_I32_AND";
+ case WI_I32_OR: return "WI_I32_OR";
+ case WI_I32_XOR: return "WI_I32_XOR";
+ case WI_I32_SHL: return "WI_I32_SHL";
+ case WI_I32_SHR_S: return "WI_I32_SHR_S";
+ case WI_I32_SHR_U: return "WI_I32_SHR_U";
+ case WI_I32_ROTL: return "WI_I32_ROTL";
+ case WI_I32_ROTR: return "WI_I32_ROTR";
+ case WI_I64_CLZ: return "WI_I64_CLZ";
+ case WI_I64_CTZ: return "WI_I64_CTZ";
+ case WI_I64_POPCNT: return "WI_I64_POPCNT";
+ case WI_I64_ADD: return "WI_I64_ADD";
+ case WI_I64_SUB: return "WI_I64_SUB";
+ case WI_I64_MUL: return "WI_I64_MUL";
+ case WI_I64_DIV_S: return "WI_I64_DIV_S";
+ case WI_I64_DIV_U: return "WI_I64_DIV_U";
+ case WI_I64_REM_S: return "WI_I64_REM_S";
+ case WI_I64_REM_U: return "WI_I64_REM_U";
+ case WI_I64_AND: return "WI_I64_AND";
+ case WI_I64_OR: return "WI_I64_OR";
+ case WI_I64_XOR: return "WI_I64_XOR";
+ case WI_I64_SHL: return "WI_I64_SHL";
+ case WI_I64_SHR_S: return "WI_I64_SHR_S";
+ case WI_I64_SHR_U: return "WI_I64_SHR_U";
+ case WI_I64_ROTL: return "WI_I64_ROTL";
+ case WI_I64_ROTR: return "WI_I64_ROTR";
+ case WI_F32_ABS: return "WI_F32_ABS";
+ case WI_F32_NEG: return "WI_F32_NEG";
+ case WI_F32_CEIL: return "WI_F32_CEIL";
+ case WI_F32_FLOOR: return "WI_F32_FLOOR";
+ case WI_F32_TRUNC: return "WI_F32_TRUNC";
+ case WI_F32_NEAREST: return "WI_F32_NEAREST";
+ case WI_F32_SQRT: return "WI_F32_SQRT";
+ case WI_F32_ADD: return "WI_F32_ADD";
+ case WI_F32_SUB: return "WI_F32_SUB";
+ case WI_F32_MUL: return "WI_F32_MUL";
+ case WI_F32_DIV: return "WI_F32_DIV";
+ case WI_F32_MIN: return "WI_F32_MIN";
+ case WI_F32_MAX: return "WI_F32_MAX";
+ case WI_F32_COPYSIGN: return "WI_F32_COPYSIGN";
+ case WI_F64_ABS: return "WI_F64_ABS";
+ case WI_F64_NEG: return "WI_F64_NEG";
+ case WI_F64_CEIL: return "WI_F64_CEIL";
+ case WI_F64_FLOOR: return "WI_F64_FLOOR";
+ case WI_F64_TRUNC: return "WI_F64_TRUNC";
+ case WI_F64_NEAREST: return "WI_F64_NEAREST";
+ case WI_F64_SQRT: return "WI_F64_SQRT";
+ case WI_F64_ADD: return "WI_F64_ADD";
+ case WI_F64_SUB: return "WI_F64_SUB";
+ case WI_F64_MUL: return "WI_F64_MUL";
+ case WI_F64_DIV: return "WI_F64_DIV";
+ case WI_F64_MIN: return "WI_F64_MIN";
+ case WI_F64_MAX: return "WI_F64_MAX";
+ case WI_F64_COPYSIGN: return "WI_F64_COPYSIGN";
+ case WI_I32_FROM_I64: return "WI_I32_FROM_I64";
+ case WI_I32_FROM_F32_S: return "WI_I32_FROM_F32_S";
+ case WI_I32_FROM_F32_U: return "WI_I32_FROM_F32_U";
+ case WI_I32_FROM_F64_S: return "WI_I32_FROM_F64_S";
+ case WI_I32_FROM_F64_U: return "WI_I32_FROM_F64_U";
+ case WI_I64_FROM_I32_S: return "WI_I64_FROM_I32_S";
+ case WI_I64_FROM_I32_U: return "WI_I64_FROM_I32_U";
+ case WI_I64_FROM_F32_S: return "WI_I64_FROM_F32_S";
+ case WI_I64_FROM_F32_U: return "WI_I64_FROM_F32_U";
+ case WI_I64_FROM_F64_S: return "WI_I64_FROM_F64_S";
+ case WI_I64_FROM_F64_U: return "WI_I64_FROM_F64_U";
+ case WI_F32_FROM_I32_S: return "WI_F32_FROM_I32_S";
+ case WI_F32_FROM_I32_U: return "WI_F32_FROM_I32_U";
+ case WI_F32_FROM_I64_S: return "WI_F32_FROM_I64_S";
+ case WI_F32_FROM_I64_U: return "WI_F32_FROM_I64_U";
+ case WI_F32_FROM_F64: return "WI_F32_FROM_F64";
+ case WI_F64_FROM_I32_S: return "WI_F64_FROM_I32_S";
+ case WI_F64_FROM_I32_U: return "WI_F64_FROM_I32_U";
+ case WI_F64_FROM_I64_S: return "WI_F64_FROM_I64_S";
+ case WI_F64_FROM_I64_U: return "WI_F64_FROM_I64_U";
+ case WI_F64_FROM_F32: return "WI_F64_FROM_F32";
+ case WI_I32_REINTERPRET_F32: return "WI_I32_REINTERPRET_F32";
+ case WI_I64_REINTERPRET_F64: return "WI_I64_REINTERPRET_F64";
+ case WI_F32_REINTERPRET_I32: return "WI_F32_REINTERPRET_I32";
+ case WI_F64_REINTERPRET_I64: return "WI_F64_REINTERPRET_I64";
+ }
}
static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) {
- if (type->is_bool) return WASM_TYPE_INT32;
- else if (type->is_int) {
- if (type->size == 4) return WASM_TYPE_INT32;
- if (type->size == 8) return WASM_TYPE_INT64;
- }
- else if (type->is_float) {
- if (type->size == 4) return WASM_TYPE_FLOAT32;
- if (type->size == 8) return WASM_TYPE_FLOAT64;
- }
-
- return WASM_TYPE_VOID;
+ if (type->is_bool) return WASM_TYPE_INT32;
+ else if (type->is_int) {
+ if (type->size == 4) return WASM_TYPE_INT32;
+ if (type->size == 8) return WASM_TYPE_INT64;
+ }
+ else if (type->is_float) {
+ if (type->size == 4) return WASM_TYPE_FLOAT32;
+ if (type->size == 8) return WASM_TYPE_FLOAT64;
+ }
+
+ return WASM_TYPE_VOID;
}
static void compile_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd);
static void compile_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret);
static void compile_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd) {
- if (fd->body == NULL) return;
+ if (fd->body == NULL) return;
- forll (OnyxAstNode, stmt, fd->body->body, next) {
- compile_statement(mod, func, stmt);
- }
+ forll (OnyxAstNode, stmt, fd->body->body, next) {
+ compile_statement(mod, func, stmt);
+ }
- bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
+ bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
}
static void compile_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block) {
- bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_START, 0x40 }));
+ bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_START, 0x40 }));
- forll (OnyxAstNode, stmt, block->body, next) {
- compile_statement(mod, func, stmt);
- }
+ forll (OnyxAstNode, stmt, block->body, next) {
+ compile_statement(mod, func, stmt);
+ }
- bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
+ bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
}
static void compile_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt) {
- switch (stmt->kind) {
- case ONYX_AST_NODE_KIND_SCOPE: break;
- case ONYX_AST_NODE_KIND_RETURN: compile_return(mod, func, stmt); break;
- case ONYX_AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, func, stmt); break;
+ switch (stmt->kind) {
+ case ONYX_AST_NODE_KIND_SCOPE: break;
+ case ONYX_AST_NODE_KIND_RETURN: compile_return(mod, func, stmt); break;
+ case ONYX_AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, func, stmt); break;
case ONYX_AST_NODE_KIND_IF: compile_if(mod, func, (OnyxAstNodeIf *) stmt); break;
case ONYX_AST_NODE_KIND_WHILE: compile_while(mod, func, (OnyxAstNodeWhile *) stmt); break;
case ONYX_AST_NODE_KIND_CALL: compile_expression(mod, func, stmt); break;
case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, func, (OnyxAstNodeBlock *) stmt); break;
- default: break;
- }
+ default: break;
+ }
}
static void compile_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval) {
- if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) {
- i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval);
+ if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) {
+ i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval);
- bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_SET, localidx }));
- } else {
- assert(("Invalid lval", 0));
- }
+ bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_SET, localidx }));
+ } else {
+ assert(("Invalid lval", 0));
+ }
}
static void compile_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node) {
bh_arr_push(func->code, ((WasmInstruction){ WI_I32_EQZ, 0x00 }));
bh_arr_push(func->code, ((WasmInstruction){ WI_COND_JUMP, 0x01 }));
- forll (OnyxAstNode, stmt, while_node->body->body, next) {
- compile_statement(mod, func, stmt);
- }
+ forll (OnyxAstNode, stmt, while_node->body->body, next) {
+ compile_statement(mod, func, stmt);
+ }
bh_arr_push(func->code, ((WasmInstruction){ WI_JUMP, 0x00 }));
}
static void compile_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign) {
- compile_expression(mod, func, assign->right);
- compile_assign_lval(mod, func, assign->left);
+ compile_expression(mod, func, assign->right);
+ compile_assign_lval(mod, func, assign->left);
}
// NOTE: These need to be in the same order as
}
static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr) {
- switch (expr->kind) {
+ switch (expr->kind) {
case ONYX_AST_NODE_KIND_BIN_OP:
compile_binop(mod, func, &expr->as_binop);
break;
compile_unaryop(mod, func, &expr->as_unaryop);
break;
- case ONYX_AST_NODE_KIND_LOCAL:
- case ONYX_AST_NODE_KIND_PARAM:
- {
- i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) expr);
+ case ONYX_AST_NODE_KIND_LOCAL:
+ case ONYX_AST_NODE_KIND_PARAM:
+ {
+ i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) expr);
- bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_GET, localidx }));
- break;
- }
+ bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_GET, localidx }));
+ break;
+ }
- case ONYX_AST_NODE_KIND_LITERAL:
- {
+ case ONYX_AST_NODE_KIND_LITERAL:
+ {
OnyxAstNodeNumLit* lit = &expr->as_numlit;
WasmType lit_type = onyx_type_to_wasm_type(lit->type);
WasmInstruction instr = { WI_NOP, 0 };
instr.data.d = lit->value.d;
}
- bh_arr_push(func->code, instr);
- break;
- }
+ bh_arr_push(func->code, instr);
+ break;
+ }
- case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, func, (OnyxAstNodeBlock *) expr); break;
+ case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, func, (OnyxAstNodeBlock *) expr); break;
- case ONYX_AST_NODE_KIND_CALL:
- {
- OnyxAstNodeCall* call = &expr->as_call;
- forll (OnyxAstNode, arg, call->arguments, next) {
- compile_expression(mod, func, arg->left);
- }
+ case ONYX_AST_NODE_KIND_CALL:
+ {
+ OnyxAstNodeCall* call = &expr->as_call;
+ forll (OnyxAstNode, arg, call->arguments, next) {
+ compile_expression(mod, func, arg->left);
+ }
i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) call->callee);
bh_arr_push(func->code, ((WasmInstruction){ WI_CALL, func_idx }));
- break;
- }
+ break;
+ }
- default:
- DEBUG_HERE;
- bh_printf("Unhandled case: %d\n", expr->kind);
- assert(0);
- }
+ default:
+ DEBUG_HERE;
+ bh_printf("Unhandled case: %d\n", expr->kind);
+ assert(0);
+ }
}
static const WasmInstructionType cast_map[][6] = {
- // I32 U32 I64 U64 F32 F64
- /* I32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S },
- /* U32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U },
- /* I64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_S, WI_F64_FROM_I64_S },
- /* U64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_U, WI_F64_FROM_I64_U },
- /* F32 */ { WI_I32_FROM_F32_S, WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP, WI_F64_FROM_F32 },
- /* F64 */ { WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64, WI_NOP, },
+ // I32 U32 I64 U64 F32 F64
+ /* I32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S },
+ /* U32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U },
+ /* I64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_S, WI_F64_FROM_I64_S },
+ /* U64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_U, WI_F64_FROM_I64_U },
+ /* F32 */ { WI_I32_FROM_F32_S, WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP, WI_F64_FROM_F32 },
+ /* F64 */ { WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64, WI_NOP, },
};
static void compile_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeUnaryOp* cast) {
- compile_expression(mod, func, cast->left);
-
- OnyxTypeInfo* from = cast->left->type;
- OnyxTypeInfo* to = cast->type;
-
- i32 fromidx = 0, toidx = 0;
- if (from->is_int) {
- if (from->size == 4 && !from->is_unsigned) fromidx = 0;
- else if (from->size == 4 && from->is_unsigned) fromidx = 1;
- else if (from->size == 8 && !from->is_unsigned) fromidx = 2;
- else if (from->size == 8 && from->is_unsigned) fromidx = 3;
- } else if (from->is_float) {
- if (from->size == 4) fromidx = 4;
- else if (from->size == 8) fromidx = 5;
- }
-
- if (to->is_int) {
- if (to->size == 4 && !to->is_unsigned) toidx = 0;
- else if (to->size == 4 && to->is_unsigned) toidx = 1;
- else if (to->size == 8 && !to->is_unsigned) toidx = 2;
- else if (to->size == 8 && to->is_unsigned) toidx = 3;
- } else if (to->is_float) {
- if (to->size == 4) toidx = 4;
- else if (to->size == 8) toidx = 5;
- }
-
- WasmInstructionType cast_op = cast_map[fromidx][toidx];
- if (cast_op != WI_NOP) {
- bh_arr_push(func->code, ((WasmInstruction){ cast_op, 0x00 }));
- }
+ compile_expression(mod, func, cast->left);
+
+ OnyxTypeInfo* from = cast->left->type;
+ OnyxTypeInfo* to = cast->type;
+
+ i32 fromidx = 0, toidx = 0;
+ if (from->is_int) {
+ if (from->size == 4 && !from->is_unsigned) fromidx = 0;
+ else if (from->size == 4 && from->is_unsigned) fromidx = 1;
+ else if (from->size == 8 && !from->is_unsigned) fromidx = 2;
+ else if (from->size == 8 && from->is_unsigned) fromidx = 3;
+ } else if (from->is_float) {
+ if (from->size == 4) fromidx = 4;
+ else if (from->size == 8) fromidx = 5;
+ }
+
+ if (to->is_int) {
+ if (to->size == 4 && !to->is_unsigned) toidx = 0;
+ else if (to->size == 4 && to->is_unsigned) toidx = 1;
+ else if (to->size == 8 && !to->is_unsigned) toidx = 2;
+ else if (to->size == 8 && to->is_unsigned) toidx = 3;
+ } else if (to->is_float) {
+ if (to->size == 4) toidx = 4;
+ else if (to->size == 8) toidx = 5;
+ }
+
+ WasmInstructionType cast_op = cast_map[fromidx][toidx];
+ if (cast_op != WI_NOP) {
+ bh_arr_push(func->code, ((WasmInstruction){ cast_op, 0x00 }));
+ }
}
static void compile_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret) {
- if (ret->left) {
- compile_expression(mod, func, ret->left);
- }
+ if (ret->left) {
+ compile_expression(mod, func, ret->left);
+ }
- bh_arr_push(func->code, ((WasmInstruction){ WI_RETURN, 0x00 }));
+ bh_arr_push(func->code, ((WasmInstruction){ WI_RETURN, 0x00 }));
}
static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) {
- static char type_repr_buf[128];
-
- char* t = type_repr_buf;
- OnyxAstNodeParam* param = fd->params;
- i32 param_count = 0;
- while (param) {
- // HACK: Using these directly as part of a string feels weird but they are
- // valid characters so I don't think it is going to be much of an issue
- *(t++) = (char) onyx_type_to_wasm_type(param->type);
- param_count++;
- param = param->next;
- }
- *(t++) = ':';
-
- WasmType return_type = onyx_type_to_wasm_type(fd->return_type);
- *(t++) = (char) return_type;
- *t = '\0';
-
- i32 type_idx = 0;
- 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
- WasmFuncType* type = (WasmFuncType*) bh_alloc(mod->allocator, sizeof(WasmFuncType) + sizeof(WasmType) * param_count);
- type->return_type = return_type;
- type->param_count = param_count;
-
- // HACK ish thing
- memcpy(type->param_types, type_repr_buf, type->param_count);
-
- bh_arr_push(mod->functypes, type);
-
- bh_table_put(i32, mod->type_map, type_repr_buf, mod->next_type_idx);
- type_idx = mod->next_type_idx;
- mod->next_type_idx++;
- }
+ static char type_repr_buf[128];
+
+ char* t = type_repr_buf;
+ OnyxAstNodeParam* param = fd->params;
+ i32 param_count = 0;
+ while (param) {
+ // HACK: Using these directly as part of a string feels weird but they are
+ // valid characters so I don't think it is going to be much of an issue
+ *(t++) = (char) onyx_type_to_wasm_type(param->type);
+ param_count++;
+ param = param->next;
+ }
+ *(t++) = ':';
+
+ WasmType return_type = onyx_type_to_wasm_type(fd->return_type);
+ *(t++) = (char) return_type;
+ *t = '\0';
+
+ i32 type_idx = 0;
+ 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
+ WasmFuncType* type = (WasmFuncType*) bh_alloc(mod->allocator, sizeof(WasmFuncType) + sizeof(WasmType) * param_count);
+ type->return_type = return_type;
+ type->param_count = param_count;
+
+ // HACK ish thing
+ memcpy(type->param_types, type_repr_buf, type->param_count);
+
+ bh_arr_push(mod->functypes, type);
+
+ bh_table_put(i32, mod->type_map, type_repr_buf, mod->next_type_idx);
+ type_idx = mod->next_type_idx;
+ mod->next_type_idx++;
+ }
return type_idx;
}
static void compile_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) {
i32 type_idx = generate_type_idx(mod, fd);
- WasmFunc wasm_func = {
- .type_idx = type_idx,
- .locals = {
- .i32_count = 0,
- .i64_count = 0,
- .f32_count = 0,
- .f64_count = 0,
- },
- .code = NULL,
- };
+ WasmFunc wasm_func = {
+ .type_idx = type_idx,
+ .locals = {
+ .i32_count = 0,
+ .i64_count = 0,
+ .f32_count = 0,
+ .f64_count = 0,
+ },
+ .code = NULL,
+ };
- if (fd->flags & ONYX_AST_FLAG_EXPORTED) {
- onyx_token_null_toggle(*fd->token);
+ if (fd->flags & ONYX_AST_FLAG_EXPORTED) {
+ onyx_token_null_toggle(*fd->token);
i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) fd);
- WasmExport wasm_export = {
- .kind = WASM_FOREIGN_FUNCTION,
- .idx = func_idx,
- };
- bh_table_put(WasmExport, mod->exports, fd->token->token, wasm_export);
- mod->export_count++;
+ WasmExport wasm_export = {
+ .kind = WASM_FOREIGN_FUNCTION,
+ .idx = func_idx,
+ };
+ bh_table_put(WasmExport, mod->exports, fd->token->token, wasm_export);
+ mod->export_count++;
- onyx_token_null_toggle(*fd->token);
- }
+ onyx_token_null_toggle(*fd->token);
+ }
- // If there is no body then don't process the code
- if (fd->body != NULL) {
+ // If there is no body then don't process the code
+ if (fd->body != NULL) {
// NOTE: Generate the local map
i32 localidx = 0;
forll (OnyxAstNodeParam, param, fd->params, next) {
bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
}
- bh_arr_push(mod->funcs, wasm_func);
+ bh_arr_push(mod->funcs, wasm_func);
- // NOTE: Clear the local map on exit of generating this function
- bh_imap_clear(&mod->local_map);
+ // NOTE: Clear the local map on exit of generating this function
+ bh_imap_clear(&mod->local_map);
}
static void compile_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) {
}
OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
- OnyxWasmModule module = {
- .allocator = alloc,
+ OnyxWasmModule module = {
+ .allocator = alloc,
- .type_map = NULL,
- .next_type_idx = 0,
- .functypes = NULL,
+ .type_map = NULL,
+ .next_type_idx = 0,
+ .functypes = NULL,
- .funcs = NULL,
- .next_func_idx = 0,
+ .funcs = NULL,
+ .next_func_idx = 0,
- .exports = NULL,
- .export_count = 0,
+ .exports = NULL,
+ .export_count = 0,
.imports = NULL,
.next_import_func_idx = 0,
- };
+ };
- bh_arr_new(alloc, module.functypes, 4);
- bh_arr_new(alloc, module.funcs, 4);
+ bh_arr_new(alloc, module.functypes, 4);
+ bh_arr_new(alloc, module.funcs, 4);
bh_arr_new(alloc, module.imports, 4);
- bh_table_init(bh_heap_allocator(), module.type_map, 61);
- bh_table_init(bh_heap_allocator(), module.exports, 61);
+ bh_table_init(bh_heap_allocator(), module.type_map, 61);
+ bh_table_init(bh_heap_allocator(), module.exports, 61);
- bh_imap_init(&module.local_map, bh_heap_allocator());
+ bh_imap_init(&module.local_map, bh_heap_allocator());
bh_imap_init(&module.func_map, bh_heap_allocator());
return module;
}
void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxAstNodeFile* program) {
- OnyxAstNode* walker;
+ OnyxAstNode* walker;
OnyxAstNodeFile* top_walker = program;
while (top_walker) {
top_walker = top_walker->next;
}
- top_walker = program;
+ top_walker = program;
while (top_walker) {
walker = top_walker->contents;
}
void onyx_wasm_module_free(OnyxWasmModule* module) {
- bh_arr_free(module->functypes);
- bh_arr_free(module->funcs);
- bh_imap_free(&module->local_map);
+ bh_arr_free(module->functypes);
+ bh_arr_free(module->funcs);
+ bh_imap_free(&module->local_map);
bh_imap_free(&module->func_map);
- bh_table_free(module->type_map);
- bh_table_free(module->exports);
+ bh_table_free(module->type_map);
+ bh_table_free(module->exports);
}
static const u8 WASM_VERSION[] = { 0x01, 0x00, 0x00, 0x00 };
static i32 output_vector(void** arr, i32 stride, i32 arrlen, vector_func elem, bh_buffer* vec_buff) {
- i32 len;
- u8* leb = uint_to_uleb128((u64) arrlen, &len);
- bh_buffer_append(vec_buff, leb, len);
-
- i32 i = 0;
- while (i < arrlen) {
- elem(*arr, vec_buff);
- arr = bh_pointer_add(arr, stride);
- i++;
- }
-
- return vec_buff->length;
+ i32 len;
+ u8* leb = uint_to_uleb128((u64) arrlen, &len);
+ bh_buffer_append(vec_buff, leb, len);
+
+ i32 i = 0;
+ while (i < arrlen) {
+ elem(*arr, vec_buff);
+ arr = bh_pointer_add(arr, stride);
+ i++;
+ }
+
+ return vec_buff->length;
}
static i32 output_name(const char* start, i32 length, bh_buffer* buff) {
}
static i32 output_functype(WasmFuncType* type, bh_buffer* buff) {
- i32 prev_len = buff->length;
+ i32 prev_len = buff->length;
- bh_buffer_write_byte(buff, 0x60);
+ bh_buffer_write_byte(buff, 0x60);
- i32 len;
- u8* leb_buff = uint_to_uleb128(type->param_count, &len);
- bh_buffer_append(buff, leb_buff, len);
- bh_buffer_append(buff, type->param_types, type->param_count);
+ i32 len;
+ u8* leb_buff = uint_to_uleb128(type->param_count, &len);
+ bh_buffer_append(buff, leb_buff, len);
+ bh_buffer_append(buff, type->param_types, type->param_count);
- if (type->return_type != WASM_TYPE_VOID) {
- bh_buffer_write_byte(buff, 0x01);
- bh_buffer_write_byte(buff, type->return_type);
- } else {
- bh_buffer_write_byte(buff, 0x00);
- }
+ if (type->return_type != WASM_TYPE_VOID) {
+ bh_buffer_write_byte(buff, 0x01);
+ bh_buffer_write_byte(buff, type->return_type);
+ } else {
+ bh_buffer_write_byte(buff, 0x00);
+ }
- return buff->length - prev_len;
+ return buff->length - prev_len;
}
static i32 output_typesection(OnyxWasmModule* module, bh_buffer* buff) {
- i32 prev_len = buff->length;
- bh_buffer_write_byte(buff, 0x01);
+ i32 prev_len = buff->length;
+ bh_buffer_write_byte(buff, 0x01);
- bh_buffer vec_buff;
- bh_buffer_init(&vec_buff, buff->allocator, 128);
+ bh_buffer vec_buff;
+ bh_buffer_init(&vec_buff, buff->allocator, 128);
- i32 vec_len = output_vector(
- (void**) module->functypes,
- sizeof(WasmFuncType*),
- bh_arr_length(module->functypes),
- (vector_func *) output_functype,
- &vec_buff);
+ i32 vec_len = output_vector(
+ (void**) module->functypes,
+ sizeof(WasmFuncType*),
+ bh_arr_length(module->functypes),
+ (vector_func *) output_functype,
+ &vec_buff);
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) vec_len, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) vec_len, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
- bh_buffer_concat(buff, vec_buff);
- bh_buffer_free(&vec_buff);
+ bh_buffer_concat(buff, vec_buff);
+ bh_buffer_free(&vec_buff);
- return buff->length - prev_len;
+ return buff->length - prev_len;
}
static i32 output_funcsection(OnyxWasmModule* module, bh_buffer* buff) {
- i32 prev_len = buff->length;
- bh_buffer_write_byte(buff, WASM_SECTION_ID_FUNCTION);
+ i32 prev_len = buff->length;
+ bh_buffer_write_byte(buff, WASM_SECTION_ID_FUNCTION);
- bh_buffer vec_buff;
- bh_buffer_init(&vec_buff, buff->allocator, 128);
+ bh_buffer vec_buff;
+ bh_buffer_init(&vec_buff, buff->allocator, 128);
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) (bh_arr_length(module->funcs)), &leb_len);
- bh_buffer_append(&vec_buff, leb, leb_len);
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) (bh_arr_length(module->funcs)), &leb_len);
+ bh_buffer_append(&vec_buff, leb, leb_len);
- bh_arr_each(WasmFunc, func, module->funcs) {
- leb = uint_to_uleb128((u64) (func->type_idx), &leb_len);
- bh_buffer_append(&vec_buff, leb, leb_len);
- }
+ bh_arr_each(WasmFunc, func, module->funcs) {
+ leb = uint_to_uleb128((u64) (func->type_idx), &leb_len);
+ bh_buffer_append(&vec_buff, leb, leb_len);
+ }
- leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
- bh_buffer_append(buff, leb, leb_len);
+ leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
- bh_buffer_concat(buff, vec_buff);
- bh_buffer_free(&vec_buff);
+ bh_buffer_concat(buff, vec_buff);
+ bh_buffer_free(&vec_buff);
- return buff->length - prev_len;
+ return buff->length - prev_len;
}
static i32 output_importsection(OnyxWasmModule* module, bh_buffer* buff) {
- i32 prev_len = buff->length;
- bh_buffer_write_byte(buff, WASM_SECTION_ID_IMPORT);
+ i32 prev_len = buff->length;
+ bh_buffer_write_byte(buff, WASM_SECTION_ID_IMPORT);
- bh_buffer vec_buff;
- bh_buffer_init(&vec_buff, buff->allocator, 128);
+ bh_buffer vec_buff;
+ bh_buffer_init(&vec_buff, buff->allocator, 128);
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) (bh_arr_length(module->imports)), &leb_len);
- bh_buffer_append(&vec_buff, leb, leb_len);
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) (bh_arr_length(module->imports)), &leb_len);
+ bh_buffer_append(&vec_buff, leb, leb_len);
bh_arr_each(WasmImport, import, module->imports) {
output_name(import->mod->token, import->mod->length, &vec_buff);
bh_buffer_append(&vec_buff, leb, leb_len);
}
- leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
- bh_buffer_append(buff, leb, leb_len);
+ leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
- bh_buffer_concat(buff, vec_buff);
- bh_buffer_free(&vec_buff);
+ bh_buffer_concat(buff, vec_buff);
+ bh_buffer_free(&vec_buff);
- return buff->length - prev_len;
+ return buff->length - prev_len;
}
static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) {
- i32 prev_len = buff->length;
- bh_buffer_write_byte(buff, WASM_SECTION_ID_EXPORT);
+ i32 prev_len = buff->length;
+ bh_buffer_write_byte(buff, WASM_SECTION_ID_EXPORT);
- bh_buffer vec_buff;
- bh_buffer_init(&vec_buff, buff->allocator, 128);
+ bh_buffer vec_buff;
+ bh_buffer_init(&vec_buff, buff->allocator, 128);
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) (module->export_count), &leb_len);
- bh_buffer_append(&vec_buff, leb, leb_len);
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) (module->export_count), &leb_len);
+ bh_buffer_append(&vec_buff, leb, leb_len);
- i32 key_len = 0;
- bh_table_each_start(WasmExport, module->exports);
- key_len = strlen(key);
+ i32 key_len = 0;
+ bh_table_each_start(WasmExport, module->exports);
+ key_len = strlen(key);
output_name(key, key_len, &vec_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_table_each_end;
+ 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_table_each_end;
- leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
- bh_buffer_append(buff, leb, leb_len);
+ leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
- bh_buffer_concat(buff, vec_buff);
- bh_buffer_free(&vec_buff);
+ bh_buffer_concat(buff, vec_buff);
+ bh_buffer_free(&vec_buff);
- return buff->length - prev_len;
+ return buff->length - prev_len;
}
static i32 output_startsection(OnyxWasmModule* module, bh_buffer* buff) {
- i32 prev_len = buff->length;
-
- i32 start_idx = -1;
- bh_table_each_start(WasmExport, module->exports) {
- if (value.kind == WASM_FOREIGN_FUNCTION) {
- if (strncmp("main", key, 5) == 0) {
- start_idx = value.idx;
- break;
- }
- }
- } bh_table_each_end;
-
- if (start_idx != -1) {
- bh_buffer_write_byte(buff, WASM_SECTION_ID_START);
-
- i32 start_leb_len, section_leb_len;
- uint_to_uleb128((u64) start_idx, &start_leb_len);
- u8* section_leb = uint_to_uleb128((u64) start_leb_len, §ion_leb_len);
- bh_buffer_append(buff, section_leb, section_leb_len);
-
- u8* start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len);
- bh_buffer_append(buff, start_leb, start_leb_len);
- }
-
- return buff->length - prev_len;
+ i32 prev_len = buff->length;
+
+ i32 start_idx = -1;
+ bh_table_each_start(WasmExport, module->exports) {
+ if (value.kind == WASM_FOREIGN_FUNCTION) {
+ if (strncmp("main", key, 5) == 0) {
+ start_idx = value.idx;
+ break;
+ }
+ }
+ } bh_table_each_end;
+
+ if (start_idx != -1) {
+ bh_buffer_write_byte(buff, WASM_SECTION_ID_START);
+
+ i32 start_leb_len, section_leb_len;
+ uint_to_uleb128((u64) start_idx, &start_leb_len);
+ u8* section_leb = uint_to_uleb128((u64) start_leb_len, §ion_leb_len);
+ bh_buffer_append(buff, section_leb, section_leb_len);
+
+ u8* start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len);
+ bh_buffer_append(buff, start_leb, start_leb_len);
+ }
+
+ return buff->length - prev_len;
}
static i32 output_locals(WasmFunc* func, bh_buffer* buff) {
- i32 prev_len = buff->length;
-
- // NOTE: Output vector length
- i32 total_locals =
- (i32) (func->locals.i32_count != 0) +
- (i32) (func->locals.i64_count != 0) +
- (i32) (func->locals.f32_count != 0) +
- (i32) (func->locals.f64_count != 0);
-
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) total_locals, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
-
- if (func->locals.i32_count != 0) {
- leb = uint_to_uleb128((u64) func->locals.i32_count, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
- bh_buffer_write_byte(buff, WASM_TYPE_INT32);
- }
- if (func->locals.i64_count != 0) {
- leb = uint_to_uleb128((u64) func->locals.i64_count, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
- bh_buffer_write_byte(buff, WASM_TYPE_INT64);
- }
- if (func->locals.f32_count != 0) {
- leb = uint_to_uleb128((u64) func->locals.f32_count, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
- bh_buffer_write_byte(buff, WASM_TYPE_FLOAT32);
- }
- if (func->locals.f64_count != 0) {
- leb = uint_to_uleb128((u64) func->locals.f64_count, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
- bh_buffer_write_byte(buff, WASM_TYPE_FLOAT64);
- }
-
- return buff->length - prev_len;
+ i32 prev_len = buff->length;
+
+ // NOTE: Output vector length
+ i32 total_locals =
+ (i32) (func->locals.i32_count != 0) +
+ (i32) (func->locals.i64_count != 0) +
+ (i32) (func->locals.f32_count != 0) +
+ (i32) (func->locals.f64_count != 0);
+
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) total_locals, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+
+ if (func->locals.i32_count != 0) {
+ leb = uint_to_uleb128((u64) func->locals.i32_count, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ bh_buffer_write_byte(buff, WASM_TYPE_INT32);
+ }
+ if (func->locals.i64_count != 0) {
+ leb = uint_to_uleb128((u64) func->locals.i64_count, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ bh_buffer_write_byte(buff, WASM_TYPE_INT64);
+ }
+ if (func->locals.f32_count != 0) {
+ leb = uint_to_uleb128((u64) func->locals.f32_count, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ bh_buffer_write_byte(buff, WASM_TYPE_FLOAT32);
+ }
+ if (func->locals.f64_count != 0) {
+ leb = uint_to_uleb128((u64) func->locals.f64_count, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ bh_buffer_write_byte(buff, WASM_TYPE_FLOAT64);
+ }
+
+ return buff->length - prev_len;
}
static void output_instruction(WasmInstruction* instr, bh_buffer* buff) {
- i32 leb_len;
- u8* leb;
+ i32 leb_len;
+ u8* leb;
bh_buffer_write_byte(buff, (u8) instr->type);
- switch (instr->type) {
- case WI_LOCAL_GET:
- case WI_LOCAL_SET:
+ switch (instr->type) {
+ case WI_LOCAL_GET:
+ case WI_LOCAL_SET:
case WI_CALL:
- case WI_BLOCK_START:
+ case WI_BLOCK_START:
case WI_LOOP_START:
case WI_JUMP:
case WI_COND_JUMP:
- case WI_IF_START:
- leb = uint_to_uleb128((u64) instr->data.i1, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
- break;
+ case WI_IF_START:
+ leb = uint_to_uleb128((u64) instr->data.i1, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
+ break;
- case WI_I32_CONST:
+ case WI_I32_CONST:
leb = int_to_leb128((i64) instr->data.i1, &leb_len);
bh_buffer_append(buff, leb, leb_len);
break;
- case WI_I64_CONST:
+ case WI_I64_CONST:
leb = int_to_leb128((i64) instr->data.l, &leb_len);
bh_buffer_append(buff, leb, leb_len);
break;
- case WI_F32_CONST:
+ case WI_F32_CONST:
leb = float_to_ieee754(instr->data.f, 0);
bh_buffer_append(buff, leb, 4);
break;
- case WI_F64_CONST:
+ case WI_F64_CONST:
leb = double_to_ieee754(instr->data.d, 0);
bh_buffer_append(buff, leb, 8);
break;
- default: break;
- }
+ default: break;
+ }
}
static i32 output_code(WasmFunc* func, bh_buffer* buff) {
- bh_buffer code_buff;
- bh_buffer_init(&code_buff, buff->allocator, 128);
+ bh_buffer code_buff;
+ bh_buffer_init(&code_buff, buff->allocator, 128);
- // Output locals
- output_locals(func, &code_buff);
+ // Output locals
+ output_locals(func, &code_buff);
- // Output code
- bh_arr_each(WasmInstruction, instr, func->code) output_instruction(instr, &code_buff);
+ // Output code
+ bh_arr_each(WasmInstruction, instr, func->code) output_instruction(instr, &code_buff);
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) code_buff.length, &leb_len);
- bh_buffer_append(buff, leb, leb_len);
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) code_buff.length, &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
- bh_buffer_concat(buff, code_buff);
- bh_buffer_free(&code_buff);
+ bh_buffer_concat(buff, code_buff);
+ bh_buffer_free(&code_buff);
- return 0;
+ return 0;
}
static i32 output_codesection(OnyxWasmModule* module, bh_buffer* buff) {
- i32 prev_len = buff->length;
+ i32 prev_len = buff->length;
- bh_buffer_write_byte(buff, WASM_SECTION_ID_CODE);
+ bh_buffer_write_byte(buff, WASM_SECTION_ID_CODE);
- bh_buffer vec_buff;
- bh_buffer_init(&vec_buff, buff->allocator, 128);
+ bh_buffer vec_buff;
+ bh_buffer_init(&vec_buff, buff->allocator, 128);
- i32 leb_len;
- u8* leb = uint_to_uleb128((u64) bh_arr_length(module->funcs), &leb_len);
- bh_buffer_append(&vec_buff, leb, leb_len);
+ i32 leb_len;
+ u8* leb = uint_to_uleb128((u64) bh_arr_length(module->funcs), &leb_len);
+ bh_buffer_append(&vec_buff, leb, leb_len);
- // DEBUG_HERE;
+ // DEBUG_HERE;
- bh_arr_each(WasmFunc, func, module->funcs) output_code(func, &vec_buff);
+ bh_arr_each(WasmFunc, func, module->funcs) output_code(func, &vec_buff);
- leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
- bh_buffer_append(buff, leb, leb_len);
+ leb = uint_to_uleb128((u64) (vec_buff.length), &leb_len);
+ bh_buffer_append(buff, leb, leb_len);
- bh_buffer_concat(buff, vec_buff);
- bh_buffer_free(&vec_buff);
+ bh_buffer_concat(buff, vec_buff);
+ bh_buffer_free(&vec_buff);
- return buff->length - prev_len;
+ return buff->length - prev_len;
}
void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file) {
- bh_buffer master_buffer;
- bh_buffer_init(&master_buffer, bh_heap_allocator(), 128);
- bh_buffer_append(&master_buffer, WASM_MAGIC_STRING, 4);
- bh_buffer_append(&master_buffer, WASM_VERSION, 4);
+ bh_buffer master_buffer;
+ bh_buffer_init(&master_buffer, bh_heap_allocator(), 128);
+ bh_buffer_append(&master_buffer, WASM_MAGIC_STRING, 4);
+ bh_buffer_append(&master_buffer, WASM_VERSION, 4);
- output_typesection(module, &master_buffer);
+ output_typesection(module, &master_buffer);
output_importsection(module, &master_buffer);
- output_funcsection(module, &master_buffer);
- output_exportsection(module, &master_buffer);
- output_startsection(module, &master_buffer);
- output_codesection(module, &master_buffer);
+ output_funcsection(module, &master_buffer);
+ output_exportsection(module, &master_buffer);
+ output_startsection(module, &master_buffer);
+ output_codesection(module, &master_buffer);
- bh_file_write(&file, master_buffer.data, master_buffer.length);
+ bh_file_write(&file, master_buffer.data, master_buffer.length);
}