From: Brendan Hansen Date: Thu, 9 Jul 2020 17:49:39 +0000 (-0500) Subject: Small refactor; Added more detailed error printing X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=a3607441cbd3aa52265fe159da4340601fa563b3;p=onyx.git Small refactor; Added more detailed error printing --- diff --git a/docs/plan b/docs/plan index 26de694b..1c0078d9 100644 --- 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. diff --git a/include/onyxlex.h b/include/onyxlex.h index 6b35fe61..f145b410 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -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; diff --git a/include/onyxmsgs.h b/include/onyxmsgs.h index f30c5b46..8490bd06 100644 --- a/include/onyxmsgs.h +++ b/include/onyxmsgs.h @@ -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 11e0a223..c96373e5 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/test.onyx b/progs/test.onyx index 3858a7ad..5da6fd85 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -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); diff --git a/src/onyx.c b/src/onyx.c index f91500c8..680cff77 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -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 diff --git a/src/onyxchecker.c b/src/onyxchecker.c index dfc905cc..b63ae843 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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; } } diff --git a/src/onyxlex.c b/src/onyxlex.c index 600d796d..ae206870 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -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; diff --git a/src/onyxmsgs.c b/src/onyxmsgs.c index b05432a2..959c7969 100644 --- a/src/onyxmsgs.c +++ b/src/onyxmsgs.c @@ -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; } diff --git a/src/onyxparser.c b/src/onyxparser.c index 7fa72f6f..b286f4c2 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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); } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 463fff61..accec6e5 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 20faa77a..3b4de695 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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);