Small refactor; Added more detailed error printing
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 9 Jul 2020 17:49:39 +0000 (12:49 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 9 Jul 2020 17:49:39 +0000 (12:49 -0500)
12 files changed:
docs/plan
include/onyxlex.h
include/onyxmsgs.h
onyx
progs/test.onyx
src/onyx.c
src/onyxchecker.c
src/onyxlex.c
src/onyxmsgs.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index 26de694bbd6fd99902401d8a2f75d2558c2aed6a..1c0078d9239ef5150ff5bb513dda618ef6a3b225 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -84,10 +84,15 @@ HOW:
             - Changing output location
             - Viewing help screen
 
-        [ ] 'use' statements work
+        [X] 'use' statements work
             - Adds '.onyx' to the end of the file name list
             - Only searches in current directory for now
 
+        [ ] Completely overhaul the type system
+            - Keep the builtins
+            - Add pointers
+            - Add structs
+
         [ ] Output 'drop' instruction for functions whose return value isn't used
 
         [ ] Devise and implement a simple set of implicit type casting rules.
index 6b35fe6187fd090eb4875f42ab6e871f54df7aa0..f145b410a9ec1088004d777ab7258e10f9b2edb0 100644 (file)
@@ -48,13 +48,14 @@ typedef enum TokenType {
 
 typedef struct OnyxFilePos {
     const char* filename;
-    u64 line, column;
+    char* line_start;
+    u32 line, column;
 } OnyxFilePos;
 
 typedef struct OnyxToken {
     TokenType type;
     i32 length;
-    char* token;
+    char* text;
     OnyxFilePos pos;
 } OnyxToken;
 
index f30c5b46ebe87b2672182fab305734a16b66ca2b..8490bd066bbcff4ef549329a144da5e5a928eb42 100644 (file)
@@ -42,12 +42,16 @@ typedef struct OnyxMessage {
 typedef struct OnyxMessages {
     bh_allocator allocator;
 
+    // NOTE: Pointer to a table mapping file paths to
+    // their file contents. Used for better error messages
+    bh_table(bh_file_contents)* file_contents;
+
     OnyxMessage* first;
 } OnyxMessages;
 
 void onyx_message_add(OnyxMessages* msgs, OnyxMessageType type, OnyxFilePos pos, ...);
 void onyx_message_print(OnyxMessages* msgs);
 b32 onyx_message_has_errors(OnyxMessages* msgs);
-void onyx_message_create(bh_allocator allocator, OnyxMessages* msgs);
+void onyx_message_create(bh_allocator allocator, OnyxMessages* msgs, bh_table(bh_file_contents)* files);
 
 #endif
diff --git a/onyx b/onyx
index 11e0a223d083689be923236ac124cff10a443b56..c96373e52331992eb241a71850623ece26fa74f4 100755 (executable)
Binary files a/onyx and b/onyx differ
index 3858a7adc5a3d75ce0e869c60a57269bc5e81df4..5da6fd85cae63e28cbe9d74b88b3a3c76e786f59 100644 (file)
@@ -62,7 +62,6 @@ export main2 :: proc {
 // }
 
 export main :: proc {
-    print_i32(shl_i32(16, 2));
     print_f32(sqrt_f32(2.0f));
 
     print_i32(5 * 6 + 2 * 3);
index f91500c8bdca0a32cb398e972a5cbe859856a6c5..680cff77eb0985a806818d811222236970602ae8 100644 (file)
@@ -174,7 +174,7 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
         char* formatted_name = bh_aprintf(
                 global_heap_allocator,
                 "%b.onyx",
-                (*use_node)->filename->token, (*use_node)->filename->length);
+                (*use_node)->filename->text, (*use_node)->filename->length);
 
         bh_arr_push(compiler_state->queued_files, formatted_name);
     }
@@ -198,7 +198,9 @@ static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOption
     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);
+    bh_table_init(opts->allocator, compiler_state->loaded_files, 15);
+
+    onyx_message_create(compiler_state->msg_alloc, &compiler_state->msgs, &compiler_state->loaded_files);
 
     compiler_state->token_alloc = opts->allocator;
 
@@ -210,8 +212,6 @@ static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOption
     bh_arena_init(&compiler_state->sp_arena, opts->allocator, 16 * 1024);
     compiler_state->sp_alloc = bh_arena_allocator(&compiler_state->sp_arena);
 
-    bh_table_init(opts->allocator, compiler_state->loaded_files, 15);
-
     bh_arr_new(opts->allocator, compiler_state->queued_files, 4);
 
     // NOTE: Add all files passed by command line to the queue
index dfc905cc94731821f15bcd9104a8d769f942a39c..b63ae843421314c8787a9a41aeb467245e7c6a36 100644 (file)
@@ -18,7 +18,7 @@ static void check_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
                 assign->lval->token->pos,
-                assign->lval->token->token, assign->lval->token->length);
+                assign->lval->token->text, assign->lval->token->length);
         return;
     }
 
@@ -26,7 +26,7 @@ static void check_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_ASSIGN_CONST,
                 assign->base.token->pos,
-                assign->lval->token->token, assign->lval->token->length);
+                assign->lval->token->text, assign->lval->token->length);
         return;
     }
 
@@ -34,7 +34,7 @@ static void check_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_NOT_LVAL,
                 assign->base.token->pos,
-                assign->lval->token->token, assign->lval->token->length);
+                assign->lval->token->text, assign->lval->token->length);
         return;
     }
 
@@ -107,7 +107,7 @@ static void check_call(OnyxSemPassState* state, AstNodeCall* call) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
                 callee->base.token->pos,
-                callee->base.token->token, callee->base.token->length);
+                callee->base.token->text, callee->base.token->length);
         return;
     }
 
@@ -115,7 +115,7 @@ static void check_call(OnyxSemPassState* state, AstNodeCall* call) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION,
                 call->base.token->pos,
-                callee->base.token->token, callee->base.token->length);
+                callee->base.token->text, callee->base.token->length);
         return;
     }
 
@@ -127,7 +127,7 @@ static void check_call(OnyxSemPassState* state, AstNodeCall* call) {
 
         onyx_token_null_toggle(callee->base.token);
 
-        char* intr_name = callee->base.token->token;
+        char* intr_name = callee->base.token->text;
         OnyxIntrinsic intrinsic = ONYX_INTRINSIC_UNDEFINED;
 
         if (!strcmp("memory_size", intr_name))       intrinsic = ONYX_INTRINSIC_MEMORY_SIZE;
@@ -195,7 +195,7 @@ static void check_call(OnyxSemPassState* state, AstNodeCall* call) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_FUNCTION_PARAM_TYPE_MISMATCH,
                     call->base.token->pos,
-                    callee->base.token->token, callee->base.token->length,
+                    callee->base.token->text, callee->base.token->length,
                     formal_param->base.type->name, arg_pos,
                     actual_param->base.type->name);
             return;
@@ -284,7 +284,7 @@ static void check_expression(OnyxSemPassState* state, AstNodeTyped* expr) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
                     expr->token->pos,
-                    expr->token->token, expr->token->length);
+                    expr->token->text, expr->token->length);
             break;
 
         case AST_NODE_KIND_LOCAL:
@@ -332,7 +332,7 @@ static void check_global(OnyxSemPassState* state, AstNodeGlobal* global) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_GLOBAL_TYPE_MISMATCH,
                         global->base.token->pos,
-                        global->base.token->token, global->base.token->length,
+                        global->base.token->text, global->base.token->length,
                         global->base.type->name, global->initial_value->type->name);
                 return;
             }
@@ -379,7 +379,7 @@ static void check_block(OnyxSemPassState* state, AstNodeBlock* block) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
                     local->base.token->pos,
-                    local->base.token->token, local->base.token->length);
+                    local->base.token->text, local->base.token->length);
             return;
         }
     }
index 600d796d3db0c6f13c4f06d8fb657d37d3ad00be..ae206870752a24a1ab0ecd2061969687d578fb06 100644 (file)
@@ -66,7 +66,7 @@ static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_
             return 0;
 
         tk->type = type;
-        tk->token = tokenizer->curr;
+        tk->text = tokenizer->curr;
         tk->length = len;
         tk->pos.line = tokenizer->line_number;
         tk->pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
@@ -88,8 +88,8 @@ const char* onyx_get_token_type_name(TokenType tkn_type) {
 
 void onyx_token_null_toggle(OnyxToken* tkn) {
     static char backup = 0;
-    char tmp = tkn->token[tkn->length];
-    tkn->token[tkn->length] = backup;
+    char tmp = tkn->text[tkn->length];
+    tkn->text[tkn->length] = backup;
     backup = tmp;
 }
 
@@ -101,8 +101,9 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
         INCREMENT_CURR_TOKEN(tokenizer)
 
     tk.type = TOKEN_TYPE_UNKNOWN;
-    tk.token = tokenizer->curr;
+    tk.text = tokenizer->curr;
     tk.length = 1;
+    tk.pos.line_start = tokenizer->line_start;
     tk.pos.filename = tokenizer->filename;
     tk.pos.line = tokenizer->line_number;
     tk.pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
@@ -116,13 +117,13 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
     if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '/') {
         tokenizer->curr += 2;
         tk.type = TOKEN_TYPE_COMMENT;
-        tk.token = tokenizer->curr;
+        tk.text = tokenizer->curr;
 
         while (*tokenizer->curr != '\n') {
             INCREMENT_CURR_TOKEN(tokenizer);
         }
 
-        tk.length = tokenizer->curr - tk.token - 2;
+        tk.length = tokenizer->curr - tk.text - 2;
         goto token_parsed;
     }
 
@@ -154,7 +155,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
     LITERAL_TOKEN("%=",         0, TOKEN_TYPE_PERCENT_EQUAL);
 
     // Symbols
-    if (char_is_alpha(*tk.token)) {
+    if (char_is_alpha(*tk.text)) {
         u64 len = 0;
         while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) {
             len++;
@@ -167,7 +168,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
     }
 
     // String literal
-    if (*tk.token == '"') {
+    if (*tk.text == '"') {
         u64 len = 0;
         u64 slash_count = 0;
 
@@ -188,7 +189,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
 
         INCREMENT_CURR_TOKEN(tokenizer);
 
-        tk.token++;
+        tk.text++;
         tk.type = TOKEN_TYPE_LITERAL_STRING;
         tk.length = len;
         goto token_parsed;
index b05432a26fd815c0d509f07595256ee50eebe877..959c7969edabd6cb62c414e75422116689859d7a 100644 (file)
@@ -1,5 +1,6 @@
 
 #include "onyxmsgs.h"
+#include "onyxutils.h"
 
 static const char* msg_formats[] = {
     "%s",
@@ -41,12 +42,32 @@ void onyx_message_add(OnyxMessages* msgs, OnyxMessageType type, OnyxFilePos pos,
     *walker = msg;
 }
 
+static void print_detailed_message(OnyxMessage* msg, bh_file_contents* fc) {
+    bh_printf("(%s:%l:%l) %s\n", msg->pos.filename, msg->pos.line, msg->pos.column, msg->text);
+
+    i32 linelength = 0;
+    char* walker = msg->pos.line_start;
+    while (*walker != '\n') linelength++, walker++;
+
+    bh_printf("| %b\n", msg->pos.line_start, linelength);
+
+    char* pointer_str = bh_alloc_array(global_scratch_allocator, char, linelength);
+    memset(pointer_str, 0, linelength);
+    memset(pointer_str, '~', msg->pos.column - 1);
+    pointer_str[msg->pos.column - 1] = '^';
+
+    bh_printf("|~%s\n", pointer_str);
+}
+
 void onyx_message_print(OnyxMessages* msgs) {
     OnyxMessage* msg = msgs->first;
+    i32 msg_count = 3;
 
-    while (msg) {
+    while (msg && msg_count--) {
         if (msg->pos.filename) {
-            bh_printf("(%s:%l:%l) %s\n", msg->pos.filename, msg->pos.line, msg->pos.column, msg->text);
+            bh_file_contents* fc = &bh_table_get(bh_file_contents, *msgs->file_contents, (char *) msg->pos.filename);
+
+            print_detailed_message(msg, fc);
         } else {
             bh_printf("(%l:%l) %s\n", msg->pos.line, msg->pos.column, msg->text);
         }
@@ -58,7 +79,8 @@ b32 onyx_message_has_errors(OnyxMessages* msgs) {
     return msgs->first != NULL;
 }
 
-void onyx_message_create(bh_allocator allocator, OnyxMessages* msgs) {
+void onyx_message_create(bh_allocator allocator, OnyxMessages* msgs, bh_table(bh_file_contents)* files) {
     msgs->allocator = allocator;
     msgs->first = NULL;
+    msgs->file_contents = files;
 }
index 7fa72f6fe47574fcf59f7348f4aaaaabd43df7d9..b286f4c2fd7341fd43704a68dd4942147ababeb8 100644 (file)
@@ -97,7 +97,7 @@ static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
     onyx_token_null_toggle(lit_node->base.token);
 
     TypeInfo* type;
-    char* tok = lit_node->base.token->token;
+    char* tok = lit_node->base.token->text;
 
     // NOTE: charset_contains() behaves more like string_contains()
     // so I'm using it in this case
@@ -427,7 +427,7 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) {
                         onyx_message_add(parser->msgs,
                                 ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
                                 assignment->base.token->pos,
-                                parser->curr_token->token);
+                                parser->curr_token->text);
                         onyx_token_null_toggle(parser->curr_token);
                         return 1;
                     }
@@ -629,10 +629,10 @@ static TypeInfo* parse_type(OnyxParser* parser) {
 
     onyx_token_null_toggle(symbol);
 
-    if (!bh_table_has(AstNode*, parser->identifiers, symbol->token)) {
-        onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->token);
+    if (!bh_table_has(AstNode*, parser->identifiers, symbol->text)) {
+        onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->text);
     } else {
-        AstNodeTyped* type_info_node = bh_table_get(AstNodeTyped*, parser->identifiers, symbol->token);
+        AstNodeTyped* type_info_node = bh_table_get(AstNodeTyped*, parser->identifiers, symbol->text);
 
         if (type_info_node->kind == AST_NODE_KIND_TYPE) {
             type_info = type_info_node->type;
@@ -688,7 +688,7 @@ static b32 parse_possible_directive(OnyxParser* parser, const char* dir) {
     expect(parser, '#');
     OnyxToken* sym = expect(parser, TOKEN_TYPE_SYMBOL);
 
-    return strncmp(dir, sym->token, sym->length) == 0;
+    return strncmp(dir, sym->text, sym->length) == 0;
 }
 
 static AstNodeFunction* parse_function_definition(OnyxParser* parser) {
@@ -845,7 +845,7 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
                     onyx_message_add(parser->msgs,
                             ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
                             parser->curr_token->pos,
-                            parser->curr_token->token);
+                            parser->curr_token->text);
                     onyx_token_null_toggle(parser->curr_token);
                 }
 
index 463fff61f98029f62abbc5b293518994eae8482e..accec6e5960629fd482fc3a23b09660a3b692f6a 100644 (file)
@@ -26,11 +26,11 @@ static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol) {
     sp_sym->node = symbol;
     sp_sym->shadowed = NULL;
 
-    if (bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
-        sp_sym->shadowed = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
+    if (bh_table_has(SemPassSymbol *, state->symbols, symbol->token->text)) {
+        sp_sym->shadowed = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->text);
     }
 
-    bh_table_put(SemPassSymbol *, state->symbols, symbol->token->token, sp_sym);
+    bh_table_put(SemPassSymbol *, state->symbols, symbol->token->text, sp_sym);
 
     if (symbol->kind == AST_NODE_KIND_LOCAL) {
         AstNodeLocal* local = (AstNodeLocal *) symbol;
@@ -44,12 +44,12 @@ static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol) {
 static void symbol_remove(OnyxSemPassState* state, AstNode* symbol) {
     onyx_token_null_toggle(symbol->token);
 
-    SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
+    SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->text);
 
     if (sp_sym->shadowed) {
-        bh_table_put(SemPassSymbol *, state->symbols, symbol->token->token, sp_sym->shadowed);
+        bh_table_put(SemPassSymbol *, state->symbols, symbol->token->text, sp_sym->shadowed);
     } else {
-        bh_table_delete(SemPassSymbol *, state->symbols, symbol->token->token);
+        bh_table_delete(SemPassSymbol *, state->symbols, symbol->token->text);
     }
 
     onyx_token_null_toggle(symbol->token);
@@ -58,17 +58,17 @@ static void symbol_remove(OnyxSemPassState* state, AstNode* symbol) {
 static AstNode* symbol_resolve(OnyxSemPassState* state, AstNode* symbol) {
     onyx_token_null_toggle(symbol->token);
 
-    if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
+    if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->text)) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL,
                 symbol->token->pos,
-                symbol->token->token);
+                symbol->token->text);
 
         onyx_token_null_toggle(symbol->token);
         return symbol;
     }
 
-    SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
+    SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->text);
 
     onyx_token_null_toggle(symbol->token);
     return sp_sym->node;
@@ -93,16 +93,16 @@ static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol) {
     onyx_token_null_toggle(symbol->token);
 
     // NOTE: If the function hasn't already been defined
-    if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
+    if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->text)) {
         SemPassSymbol* sp_sym = bh_alloc_item(state->allocator, SemPassSymbol);
         sp_sym->node = symbol;
         sp_sym->shadowed = NULL;
-        bh_table_put(SemPassSymbol *, state->symbols, symbol->token->token, sp_sym);
+        bh_table_put(SemPassSymbol *, state->symbols, symbol->token->text, sp_sym);
     } else {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_CONFLICTING_GLOBALS,
                 symbol->token->pos,
-                symbol->token->token);
+                symbol->token->text);
 
         // NOTE: I really wish C had defer...
         onyx_token_null_toggle(symbol->token);
index 20faa77a24263087de8750cf2a37112e82aa526c..3b4de695e6cbba0240ac8a4094851dc1b24fbdcc 100644 (file)
@@ -801,7 +801,7 @@ static void compile_function(OnyxWasmModule* mod, AstNodeFunction* fd) {
             .kind = WASM_FOREIGN_FUNCTION,
             .idx = func_idx,
         };
-        bh_table_put(WasmExport, mod->exports, fd->base.token->token, wasm_export);
+        bh_table_put(WasmExport, mod->exports, fd->base.token->text, wasm_export);
         mod->export_count++;
 
         onyx_token_null_toggle(fd->base.token);
@@ -870,7 +870,7 @@ static void compile_global_declaration(OnyxWasmModule* module, AstNodeGlobal* gl
             .kind = WASM_FOREIGN_GLOBAL,
             .idx = global_idx,
         };
-        bh_table_put(WasmExport, module->exports, global->base.token->token, wasm_export);
+        bh_table_put(WasmExport, module->exports, global->base.token->text, wasm_export);
         module->export_count++;
 
         onyx_token_null_toggle(global->base.token);
@@ -1161,8 +1161,8 @@ static i32 output_importsection(OnyxWasmModule* module, bh_buffer* buff) {
     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);
-        output_name(import->name->token, import->name->length, &vec_buff);
+        output_name(import->mod->text, import->mod->length, &vec_buff);
+        output_name(import->name->text, import->name->length, &vec_buff);
         bh_buffer_write_byte(&vec_buff, (u8) import->kind);
 
         leb = uint_to_uleb128((u64) import->idx, &leb_len);