- 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.
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;
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
// }
export main :: proc {
- print_i32(shl_i32(16, 2));
print_f32(sqrt_f32(2.0f));
print_i32(5 * 6 + 2 * 3);
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);
}
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;
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
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;
}
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;
}
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;
}
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;
}
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;
}
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;
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;
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:
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;
}
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;
}
}
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;
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;
}
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;
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;
}
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++;
}
// String literal
- if (*tk.token == '"') {
+ if (*tk.text == '"') {
u64 len = 0;
u64 slash_count = 0;
INCREMENT_CURR_TOKEN(tokenizer);
- tk.token++;
+ tk.text++;
tk.type = TOKEN_TYPE_LITERAL_STRING;
tk.length = len;
goto token_parsed;
#include "onyxmsgs.h"
+#include "onyxutils.h"
static const char* msg_formats[] = {
"%s",
*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);
}
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;
}
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
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;
}
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;
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) {
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);
}
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;
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);
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;
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);
.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);
.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);
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);