OBJ_FILES=\
onyxlex.o \
+ onyxparser.o \
onyx.o
CC=gcc
#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_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm))
+#define BH_BIT(x) (1 << (x))
+// SCRATCH ALLOCATOR
+typedef struct bh_scratch {
+ bh_allocator backing;
+ ptr memory, end, curr;
+} bh_scratch;
-
-
-
+void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size);
+void bh_scratch_free(bh_scratch* scratch);
+bh_allocator bh_scratch_allocator(bh_scratch* scratch);
+BH_ALLOCATOR_PROC(bh_scratch_allocator_proc);
+// SCRATCH ALLOCATOR IMPLEMENTATION
+void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size) {
+ ptr memory = bh_alloc(backing, 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);
+
+ 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,
+ };
+}
+
+BH_ALLOCATOR_PROC(bh_scratch_allocator_proc) {
+ bh_scratch* scratch = (bh_scratch*) data;
+ ptr retval = NULL;
+
+ switch (action) {
+ case bh_allocator_action_alloc: {
+ if (size > scratch->end - scratch->memory) {
+ return NULL;
+ }
+
+ retval = scratch->curr;
+ scratch->curr += size;
+
+ if (scratch->curr >= scratch->end) {
+ scratch->curr = scratch->memory;
+ retval = scratch->curr;
+ }
+ } break;
+
+ case bh_allocator_action_free:
+ case bh_allocator_action_resize:
+ // Do nothing
+ break;
+ }
+
+ return retval;
+}
//-------------------------------------------------------------------------------------
FUNCTION_DECLARATION = proc FUNCTION_TYPE BLOCK
-FUNCTION_TYPE = :: ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL
+FUNCTION_TYPE = ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL
-- This may be too weird...
BLOCK = { STATEMENTS | ---
#include <stdio.h> // TODO: Replace with custom lib
#include "onyxlex.h"
+#include "onyxparser.h"
int main(int argc, char *argv[]) {
bh_file source_file;
"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_TYPE_SIGNATURE",
LITERAL_TOKEN("+", TOKEN_TYPE_SYM_PLUS);
LITERAL_TOKEN("-", TOKEN_TYPE_SYM_MINUS);
LITERAL_TOKEN("*", TOKEN_TYPE_SYM_STAR);
- LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH);
+ LITERAL_TOKEN(".", TOKEN_TYPE_SYM_DOT);
LITERAL_TOKEN("%", TOKEN_TYPE_SYM_PERCENT);
+ LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH);
LITERAL_TOKEN("\\", TOKEN_TYPE_SYM_BSLASH);
LITERAL_TOKEN("::", TOKEN_TYPE_SYM_TYPE_SIGNATURE);
LITERAL_TOKEN(":", TOKEN_TYPE_SYM_COLON);
// Number literal
if (char_is_num(*tokenizer->curr)) {
u64 len = 0;
- while (char_is_num(*tokenizer->curr) || *tokenizer->curr == '.') {
+ while (char_is_num(*(tokenizer->curr + 1)) || *(tokenizer->curr + 1) == '.') {
len++;
INCREMENT_CURR_TOKEN(tokenizer);
}
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_TYPE_SIGNATURE,
#include "onyxparser.h"
+
+struct OnyxTypeInfo builtin_types[] = {
+ { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
+ { ONYX_TYPE_INFO_KIND_VOID, 0, "void" },
+
+ { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 0, 0, 1 },
+
+ { ONYX_TYPE_INFO_KIND_UINT8, 1, "u8", 1, 1, 0, 0 },
+ { ONYX_TYPE_INFO_KIND_UINT16, 2, "u16", 1, 1, 0, 0 },
+ { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0 },
+ { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0 },
+
+ { ONYX_TYPE_INFO_KIND_INT8, 1, "i8", 1, 0, 0, 0 },
+ { ONYX_TYPE_INFO_KIND_INT16, 2, "i16", 1, 0, 0, 0 },
+ { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0 },
+ { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0 },
+
+ { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0 },
+ { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0 },
+ { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0 },
+};
\ No newline at end of file
+#define BH_NO_STRING
#include "bh.h"
#include "onyxlex.h"
OnyxToken *prev;
OnyxToken *curr;
- bh_hash(OnyxIdentifier) idens;
-
- bh_arr(OnyxToken) tokens; /* Maybe don't store the whole array? Ask for one as you need it? */
+ bh_allocator allocator;
} OnyxParser;
-typedef struct OnyxParseNode {
+typedef enum OnyxAstNodeKind {
+ ONYX_PARSE_NODE_KIND_ERROR,
+ ONYX_PARSE_NODE_KIND_PROGRAM,
+
+ ONYX_PARSE_NODE_KIND_FUNCDEF,
+ ONYX_PARSE_NODE_KIND_BLOCK,
+ ONYX_PARSE_NODE_KIND_SCOPE,
+
+ ONYX_PARSE_NODE_KIND_ADD,
+ ONYX_PARSE_NODE_KIND_SUB,
+ ONYX_PARSE_NODE_KIND_MUL,
+ ONYX_PARSE_NODE_KIND_DIVIDE,
+ ONYX_PARSE_NODE_KIND_MODULUS,
+ ONYX_PARSE_NODE_KIND_NEGATE,
+
+ ONYX_PARSE_NODE_KIND_TYPE,
+ ONYX_PARSE_NODE_KIND_LITERAL,
+ ONYX_PARSE_NODE_KIND_CAST,
+ ONYX_PARSE_NODE_KIND_PARAM,
+ ONYX_PARSE_NODE_KIND_CALL,
+ ONYX_PARSE_NODE_KIND_RETURN,
+
+ ONYX_PARSE_NODE_KIND_EQUAL,
+ ONYX_PARSE_NODE_KIND_NOT_EQUAL,
+ ONYX_PARSE_NODE_KIND_GREATER,
+ ONYX_PARSE_NODE_KIND_GREATER_EQUAL,
+ ONYX_PARSE_NODE_KIND_LESS,
+ ONYX_PARSE_NODE_KIND_LESS_EQUAL,
+ ONYX_PARSE_NODE_KIND_NOT,
+
+ ONYX_PARSE_NODE_KIND_IF,
+ ONYX_PARSE_NODE_KIND_LOOP,
+
+ ONYX_PARSE_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_UINT8,
+ ONYX_TYPE_INFO_KIND_UINT16,
+ ONYX_TYPE_INFO_KIND_UINT32,
+ ONYX_TYPE_INFO_KIND_UINT64,
+
+ ONYX_TYPE_INFO_KIND_INT8,
+ ONYX_TYPE_INFO_KIND_INT16,
+ 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
+} 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;
+} OnyxTypeInfo;
+
+extern OnyxTypeInfo builtin_types[];
+
+typedef union OnyxAstNode OnyxAstNode;
+typedef struct OnyxAstNodeBlock OnyxAstNodeBlock;
+typedef struct OnyxAstNodeParam OnyxAstNodeParam;
+typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef;
+
+typedef enum OnyxAstFlags {
+ ONYX_AST_BLOCK_FLAG_HAS_RETURN = BH_BIT(1),
+ ONYX_AST_BLOCK_FLAG_TOP_LEVEL = BH_BIT(2),
+ ONYX_AST_BLOCK_FLAG_EXPORTED = BH_BIT(3),
+} OnyxAstFlags;
+
+struct OnyxAstNodeBlock {
+ OnyxAstNodeKind kind;
+ u32 flags;
OnyxToken *token;
+ OnyxTypeInfo *return_type;
+ OnyxAstNode *next;
+ OnyxAstNode *unused1;
+ OnyxAstNode *unused2;
+};
+
+struct OnyxAstNodeParam {
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo *type;
+ OnyxAstNode *next;
+ OnyxAstNode *left;
+ OnyxAstNode *right;
+};
+
+struct OnyxAstNodeFuncDef {
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token; // This will point to the symbol token to identify it
+ OnyxTypeInfo *return_type;
+ OnyxAstNodeBlock *body;
+ OnyxAstNodeParam *params;
+ u64 param_count; // Same size as ptr
+ u64 unused1;
+};
+
+union OnyxAstNode {
+
+ // Generic node structure for capturing all binary ops and statements
+ struct {
+ OnyxAstNodeKind kind;
+ u32 flags;
+ OnyxToken *token;
+ OnyxTypeInfo* type;
+ OnyxAstNode *next;
+ OnyxAstNode *left;
+ OnyxAstNode *right;
+ } as_node;
+
+ OnyxAstNodeBlock as_block;
+};
-};
\ No newline at end of file
+ptr onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind);
+OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer tokenizer);
+OnyxAstNode* onyx_parse(OnyxParser parser);
\ No newline at end of file
--- /dev/null
+add :: proc(a i32, b i32) -> i32 {
+ return a + b
+};
\ No newline at end of file
/* nested comments /* are /* okay */ */ */
*/
-foreign "console" "log" :: proc (data ptr, length i32) -> void ---;
-
-global thing ::
+foreign console {
+ log :: proc (data ptr, length i32) -> void ---;
+}
export add :: proc (a i32, b i32) -> i32 {
return a + b;
} else {
return b;
}
+};
+
+export main :: proc () -> void {
+ console.log(add(2, 3));
+ console.log(max(5, 10));
};
\ No newline at end of file