From: Brendan Hansen Date: Fri, 17 Jul 2020 04:24:13 +0000 (-0500) Subject: Added back WASM globals; small name changes X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=c8981a401661ffa2e451b4552aabf8ae6fc9c14b;p=onyx.git Added back WASM globals; small name changes --- diff --git a/.vimspector.json b/.vimspector.json index e309f7f9..88493853 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -6,7 +6,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/onyx", - "args": ["progs/test.onyx"], + "args": ["progs/basic.onyx"], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 189a3f0f..7f6278f0 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -180,8 +180,21 @@ struct AstFunctionType { AstType base; AstType* return_type; u64 param_count; A // Top level nodes struct AstBinding { AstTyped base; AstNode* node; }; struct AstForeign { AstNode base; OnyxToken *mod_token, *name_token; AstNode *import; }; -struct AstGlobal { AstTyped base; AstTyped *initial_value; }; struct AstUse { AstNode base; OnyxToken *filename; }; +struct AstGlobal { + AstTyped base; + + union { + // NOTE: Used when a global is exported with a specific name + OnyxToken* exported_name; + + // NOTE: Used when the global is declared as foreign + struct { + OnyxToken* foreign_module; + OnyxToken* foreign_name; + }; + }; +}; struct AstFunction { AstTyped base; @@ -192,11 +205,13 @@ struct AstFunction { // NOTE: Used when a function is exported with a specific name OnyxToken* exported_name; OnyxToken* intrinsic_name; - }; - // NOTE: Used when the function is declared as foreign - OnyxToken* foreign_module; - OnyxToken* foreign_name; + // NOTE: Used when the function is declared as foreign + struct { + OnyxToken* foreign_module; + OnyxToken* foreign_name; + }; + }; }; typedef enum OnyxIntrinsic { @@ -237,6 +252,7 @@ typedef struct ParserOutput { bh_arr(AstNode *) nodes_to_process; bh_arr(AstFunction *) functions; + bh_arr(AstGlobal *) globals; } ParserOutput; diff --git a/include/onyxlex.h b/include/onyxlex.h index 9a6d407a..87e957e7 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -17,7 +17,7 @@ typedef enum TokenType { Token_Type_Keyword_Else = 263, Token_Type_Keyword_Elseif = 264, Token_Type_Keyword_Return = 265, - Token_Type_Keyword_Foreign = 266, + Token_Type_Keyword_Global = 266, Token_Type_Keyword_Proc = 267, Token_Type_Keyword_Cast = 268, Token_Type_Keyword_While = 269, @@ -71,8 +71,8 @@ typedef struct OnyxTokenizer { bh_arr(OnyxToken) tokens; } OnyxTokenizer; -const char* onyx_get_token_type_name(TokenType tkn_type); -void onyx_token_null_toggle(OnyxToken* tkn); +const char* token_name(TokenType tkn_type); +void token_toggle_end(OnyxToken* tkn); OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer); OnyxTokenizer onyx_tokenizer_create(bh_allocator allocator, bh_file_contents *fc); void onyx_tokenizer_free(OnyxTokenizer* tokenizer); diff --git a/include/onyxparser.h b/include/onyxparser.h index fba6bfaf..74ad6030 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -23,8 +23,8 @@ typedef struct OnyxParser { // NOTE: not used since all tokens are lexed before parsing starts OnyxTokenizer *tokenizer; - OnyxToken *prev_token; - OnyxToken *curr_token; + OnyxToken *prev; + OnyxToken *curr; OnyxMessages *msgs; diff --git a/misc/onyx.vim b/misc/onyx.vim index 23ebf5b7..bf1fdd66 100644 --- a/misc/onyx.vim +++ b/misc/onyx.vim @@ -10,7 +10,7 @@ endif let s:cpo_save = &cpo set cpo&vim -syn keyword onyxKeyword struct proc use +syn keyword onyxKeyword struct proc use global syn keyword onyxKeyword if elseif else syn keyword onyxKeyword for while do syn keyword onyxKeyword break continue return diff --git a/onyx b/onyx index 9d590f0d..fd4bedcb 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/basic.onyx b/progs/basic.onyx index fdba0aec..1d10f18e 100644 --- a/progs/basic.onyx +++ b/progs/basic.onyx @@ -1,5 +1,3 @@ -use "progs/intrinsics" - pointer_test :: proc { p := 0 as ^i32; } @@ -23,16 +21,19 @@ foo :: proc (n: i32) -> i32 { // OR // This could be immediately substituted in the expression tree. i.e. // 4 + global => 4 + (5 * 2 + 6) -global :: 5 * 2 + 6 +global_value :: 5 * 2 + 6 // WASM globals would be declared as such: -// wasm_global :: global i32 +wasm_global :: global i32 main :: proc #export { a := 16; print(clz_i32(a)); - print(4 + global); + wasm_global = 5 + global_value; + print(wasm_global); + + print(4 + global_value); b := 1 + foo(2); print(b); @@ -45,3 +46,6 @@ main :: proc #export { cond :: true; print(test(cond) as i32); } + +use "progs/intrinsics" + diff --git a/progs/test.onyx b/progs/test.onyx index 1e6a9277..3d546c15 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -17,8 +17,9 @@ echo :: proc (n: i32) -> i32 { global_value :: echo(fib(4) * 2); -local_brute :: proc { +test_proc :: local_brute; +local_brute :: proc { a := 123; b := 123.0f; c := 123.0; @@ -36,10 +37,6 @@ local_brute :: proc { print_f64(c); } -main3 :: proc #export { - local_brute(); -} - // This is the entry point main2 :: proc #export { i := 0; @@ -90,6 +87,7 @@ main2 :: proc #export { // } main :: proc #export { + test_proc(); local_brute(); print_i32(clz_i32(16)); diff --git a/src/onyx.c b/src/onyx.c index 93824ca0..d0a6da5f 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -172,6 +172,7 @@ static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOption bh_arr_new(global_heap_allocator, compiler_state->parse_output.top_level_bindings, 4); bh_arr_new(global_heap_allocator, compiler_state->parse_output.nodes_to_process, 4); bh_arr_new(global_heap_allocator, compiler_state->parse_output.functions, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.globals, 4); bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096); compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena); @@ -271,6 +272,7 @@ int main(int argc, char *argv[]) { .nodes_to_process = NULL, .functions = NULL, + .globals = NULL, }, .wasm_mod = { 0 } }; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 51e3d552..05f34e44 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -146,7 +146,7 @@ static b32 check_call(OnyxSemPassState* state, AstCall* call) { call->base.kind = Ast_Kind_Intrinsic_Call; call->callee = NULL; - onyx_token_null_toggle(callee->intrinsic_name); + token_toggle_end(callee->intrinsic_name); char* intr_name = callee->intrinsic_name->text; OnyxIntrinsic intrinsic = ONYX_INTRINSIC_UNDEFINED; @@ -200,7 +200,7 @@ static b32 check_call(OnyxSemPassState* state, AstCall* call) { ((AstIntrinsicCall *)call)->intrinsic = intrinsic; - onyx_token_null_toggle(callee->intrinsic_name); + token_toggle_end(callee->intrinsic_name); } call->base.type = callee->base.type->Function.return_type; @@ -379,34 +379,16 @@ static b32 check_expression(OnyxSemPassState* state, AstTyped* expr) { } static b32 check_global(OnyxSemPassState* state, AstGlobal* global) { - if (global->initial_value) { - if (check_expression(state, global->initial_value)) return 1; - - if (global->base.type == NULL) { - global->base.type = type_build_from_ast(state->node_allocator, global->base.type_node); - } - - if (global->base.type != NULL) { - if (!types_are_compatible(global->base.type, global->initial_value->type)) { - onyx_message_add(state->msgs, - ONYX_MESSAGE_TYPE_GLOBAL_TYPE_MISMATCH, - global->base.token->pos, - global->base.token->text, global->base.token->length, - type_get_name(global->base.type), - type_get_name(global->initial_value->type)); - return 1; - } - } else { - if (global->initial_value->type) - global->base.type = global->initial_value->type; - } - } + if (global->base.type == NULL) + global->base.type = type_build_from_ast(state->allocator, global->base.type_node); if (global->base.type == NULL) { onyx_message_add(state->msgs, - ONYX_MESSAGE_TYPE_LITERAL, + ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE, global->base.token->pos, - "global variable with unknown type"); + global->exported_name->text, + global->exported_name->length); + return 1; } @@ -541,5 +523,9 @@ void onyx_type_check(OnyxSemPassState* state, ParserOutput* program) { if ((*node)->kind == Ast_Kind_Function) { bh_arr_push(program->functions, (AstFunction *) *node); } + + if ((*node)->kind == Ast_Kind_Global) { + bh_arr_push(program->globals, (AstGlobal *) *node); + } } } diff --git a/src/onyxir.c b/src/onyxir.c index 1002249b..e326eed7 100644 --- a/src/onyxir.c +++ b/src/onyxir.c @@ -90,25 +90,25 @@ IR_FUNC(ir_function, AstFunction* ast_func) { func->is_intrinsic = (ast_func->base.flags & Ast_Flag_Intrinsic) != 0; if (func->is_intrinsic) { - onyx_token_null_toggle(ast_func->base.token); + token_toggle_end(ast_func->base.token); func->intrinsic = intrinsic_lookup(ast_func->base.token->text); - onyx_token_null_toggle(ast_func->base.token); + token_toggle_end(ast_func->base.token); } else if (func->is_exported) { - onyx_token_null_toggle(ast_func->base.token); + token_toggle_end(ast_func->base.token); func->exported_name = bh_aprintf(c->allocator, "%s", ast_func->base.token->text); - onyx_token_null_toggle(ast_func->base.token); + token_toggle_end(ast_func->base.token); } else if (func->is_foreign) { - onyx_token_null_toggle(ast_func->foreign_module); + token_toggle_end(ast_func->foreign_module); func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_module); - onyx_token_null_toggle(ast_func->foreign_module); + token_toggle_end(ast_func->foreign_module); - onyx_token_null_toggle(ast_func->foreign_name); + token_toggle_end(ast_func->foreign_name); func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_name); - onyx_token_null_toggle(ast_func->foreign_name); + token_toggle_end(ast_func->foreign_name); } if (func->body != NULL) { diff --git a/src/onyxlex.c b/src/onyxlex.c index 6987e51b..1c6edea8 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -15,7 +15,7 @@ static const char* token_type_names[] = { "else", "elseif", "return", - "foreign", + "global", "proc", "as", "while", @@ -79,7 +79,7 @@ static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_ return 0; } -const char* onyx_get_token_type_name(TokenType tkn_type) { +const char* token_name(TokenType tkn_type) { if (tkn_type < Token_Type_Ascii_End) { return bh_aprintf(global_scratch_allocator, "%c", (char) tkn_type); } else { @@ -87,7 +87,7 @@ const char* onyx_get_token_type_name(TokenType tkn_type) { } } -void onyx_token_null_toggle(OnyxToken* tkn) { +void token_toggle_end(OnyxToken* tkn) { static char backup = 0; char tmp = tkn->text[tkn->length]; tkn->text[tkn->length] = backup; @@ -129,12 +129,11 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { } 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("global", 1, Token_Type_Keyword_Global); LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return); LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc); LITERAL_TOKEN("as", 1, Token_Type_Keyword_Cast); diff --git a/src/onyxparser.c b/src/onyxparser.c index 48799935..a8ef82ec 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -23,10 +23,10 @@ AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, "f64" }, &basic_ AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, "rawptr" }, &basic_types[Basic_Kind_Rawptr] }; // NOTE: Forward declarations -static void parser_next_token(OnyxParser* parser); -static void parser_prev_token(OnyxParser* parser); +static void consume_token(OnyxParser* parser); +static void unconsume_token(OnyxParser* parser); static b32 is_terminating_token(TokenType token_type); -static OnyxToken* expect(OnyxParser* parser, TokenType token_type); +static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type); static AstNumLit* parse_numeric_literal(OnyxParser* parser); static AstTyped* parse_factor(OnyxParser* parser); @@ -40,19 +40,21 @@ static AstNode* parse_statement(OnyxParser* parser); static AstType* parse_type(OnyxParser* parser); static AstLocal* parse_function_params(OnyxParser* parser); static AstFunction* parse_function_definition(OnyxParser* parser); +static AstTyped* parse_global_declaration(OnyxParser* parser); +static AstTyped* parse_top_level_expression(OnyxParser* parser); static AstNode* 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++; +static void consume_token(OnyxParser* parser) { + parser->prev = parser->curr; + parser->curr++; + while (parser->curr->type == Token_Type_Comment) parser->curr++; } -static void parser_prev_token(OnyxParser* parser) { +static void unconsume_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--; + while (parser->prev->type == Token_Type_Comment) parser->prev--; + parser->curr = parser->prev; + parser->prev--; } static b32 is_terminating_token(TokenType token_type) { @@ -63,21 +65,21 @@ static b32 is_terminating_token(TokenType token_type) { } static void find_token(OnyxParser* parser, TokenType token_type) { - while (parser->curr_token->type != token_type && !is_terminating_token(parser->curr_token->type)) { - parser_next_token(parser); + while (parser->curr->type != token_type && !is_terminating_token(parser->curr->type)) { + consume_token(parser); } } // Advances to next token no matter what -static OnyxToken* expect(OnyxParser* parser, TokenType token_type) { - OnyxToken* token = parser->curr_token; - parser_next_token(parser); +static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type) { + OnyxToken* token = parser->curr; + consume_token(parser); 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)); + token_name(token_type), token_name(token->type)); return NULL; } @@ -86,12 +88,12 @@ static OnyxToken* expect(OnyxParser* parser, TokenType token_type) { static AstNumLit* parse_numeric_literal(OnyxParser* parser) { AstNumLit* lit_node = make_node(AstNumLit, Ast_Kind_Literal); - lit_node->base.token = expect(parser, Token_Type_Literal_Numeric); + lit_node->base.token = expect_token(parser, Token_Type_Literal_Numeric); lit_node->base.flags |= Ast_Flag_Comptime; lit_node->value.l = 0ll; AstType* type; - onyx_token_null_toggle(lit_node->base.token); + token_toggle_end(lit_node->base.token); char* tok = lit_node->base.token->text; // NOTE: charset_contains() behaves more like string_contains() @@ -116,26 +118,35 @@ static AstNumLit* parse_numeric_literal(OnyxParser* parser) { } lit_node->base.type_node = type; - onyx_token_null_toggle(lit_node->base.token); + token_toggle_end(lit_node->base.token); return lit_node; } +// ( ) +// - +// ! +// proc ... +// ( '(' ')' )? +// +// 'true' +// 'false' +// All of these could be followed by a cast static AstTyped* parse_factor(OnyxParser* parser) { AstTyped* retval = NULL; - switch ((u16) parser->curr_token->type) { + switch ((u16) parser->curr->type) { case '(': { - parser_next_token(parser); + consume_token(parser); AstTyped* expr = parse_expression(parser); - expect(parser, ')'); + expect_token(parser, ')'); retval = expr; break; } case '-': { - parser_next_token(parser); + consume_token(parser); AstTyped* factor = parse_factor(parser); AstUnaryOp* negate_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op); @@ -154,7 +165,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { { AstUnaryOp* not_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op); not_node->operation = Unary_Op_Not; - not_node->base.token = expect(parser, '!'); + not_node->base.token = expect_token(parser, '!'); not_node->expr = parse_factor(parser); if ((not_node->expr->flags & Ast_Flag_Comptime) != 0) { @@ -167,25 +178,25 @@ static AstTyped* parse_factor(OnyxParser* parser) { case Token_Type_Symbol: { - OnyxToken* sym_token = expect(parser, Token_Type_Symbol); + OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol); AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol); sym_node->token = sym_token; - if (parser->curr_token->type != '(') { + if (parser->curr->type != '(') { retval = sym_node; break; } // NOTE: Function call AstCall* call_node = make_node(AstCall, Ast_Kind_Call); - call_node->base.token = expect(parser, '('); + call_node->base.token = expect_token(parser, '('); call_node->callee = (AstNode *) sym_node; AstArgument** prev = &call_node->arguments; AstArgument* curr = NULL; - while (parser->curr_token->type != ')') { + while (parser->curr->type != ')') { curr = make_node(AstArgument, Ast_Kind_Argument); - curr->base.token = parser->curr_token; + curr->base.token = parser->curr; curr->value = parse_expression(parser); if (curr != NULL && curr->base.kind != Ast_Kind_Error) { @@ -193,21 +204,21 @@ static AstTyped* parse_factor(OnyxParser* parser) { prev = (AstArgument **) &curr->base.next; } - if (parser->curr_token->type == ')') + if (parser->curr->type == ')') break; - if (parser->curr_token->type != ',') { + if (parser->curr->type != ',') { onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_EXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(','), - onyx_get_token_type_name(parser->curr_token->type)); + parser->curr->pos, + token_name(','), + token_name(parser->curr->type)); return (AstTyped *) &error_node; } - parser_next_token(parser); + consume_token(parser); } - parser_next_token(parser); + consume_token(parser); retval = (AstTyped *) call_node; break; @@ -221,7 +232,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { { AstNumLit* bool_node = make_node(AstNumLit, Ast_Kind_Literal); bool_node->base.type_node = (AstType *) &basic_type_bool; - bool_node->base.token = expect(parser, Token_Type_Literal_True); + bool_node->base.token = expect_token(parser, Token_Type_Literal_True); bool_node->value.i = 1; retval = (AstTyped *) bool_node; break; @@ -231,32 +242,22 @@ static AstTyped* parse_factor(OnyxParser* parser) { { AstNumLit* bool_node = make_node(AstNumLit, Ast_Kind_Literal); bool_node->base.type_node = (AstType *) &basic_type_bool; - bool_node->base.token = expect(parser, Token_Type_Literal_False); + bool_node->base.token = expect_token(parser, Token_Type_Literal_False); bool_node->value.i = 0; retval = (AstTyped *) bool_node; break; } - case Token_Type_Keyword_Proc: - { - AstFunction* func_node = parse_function_definition(parser); - - bh_arr_push(parser->results.nodes_to_process, (AstNode *) func_node); - - retval = (AstTyped *) func_node; - 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)); + parser->curr->pos, + token_name(parser->curr->type)); return NULL; } - while (parser->curr_token->type == Token_Type_Keyword_Cast) { - parser_next_token(parser); + while (parser->curr->type == Token_Type_Keyword_Cast) { + consume_token(parser); AstUnaryOp* cast_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op); cast_node->base.type_node = parse_type(parser); @@ -289,6 +290,18 @@ static inline i32 get_precedence(BinaryOp kind) { } } +// + +// - +// * +// / +// % +// == +// != +// <= +// >= +// < +// > +// With expected precedence rules static AstTyped* parse_expression(OnyxParser* parser) { bh_arr(AstBinaryOp*) tree_stack = NULL; bh_arr_new(global_scratch_allocator, tree_stack, 4); @@ -303,7 +316,7 @@ static AstTyped* parse_expression(OnyxParser* parser) { while (1) { bin_op_kind = -1; - switch ((u16) parser->curr_token->type) { + switch ((u16) parser->curr->type) { case Token_Type_Equal_Equal: bin_op_kind = Binary_Op_Equal; break; case Token_Type_Not_Equal: bin_op_kind = Binary_Op_Not_Equal; break; case Token_Type_Less_Equal: bin_op_kind = Binary_Op_Less_Equal; break; @@ -320,8 +333,8 @@ static AstTyped* parse_expression(OnyxParser* parser) { } if (bin_op_kind != -1) { - bin_op_tok = parser->curr_token; - parser_next_token(parser); + bin_op_tok = parser->curr; + consume_token(parser); AstBinaryOp* bin_op = make_node(AstBinaryOp, Ast_Kind_Binary_Op); bin_op->operation = bin_op_kind; @@ -355,8 +368,9 @@ expression_done: return root; } +// 'if' ('elseif' )* ('else' )? static AstIf* parse_if_stmt(OnyxParser* parser) { - expect(parser, Token_Type_Keyword_If); + expect_token(parser, Token_Type_Keyword_If); AstTyped* cond = parse_expression(parser); AstBlock* true_block = parse_block(parser); @@ -368,8 +382,8 @@ static AstIf* parse_if_stmt(OnyxParser* parser) { if (true_block != NULL) if_node->true_block.as_block = true_block; - while (parser->curr_token->type == Token_Type_Keyword_Elseif) { - parser_next_token(parser); + while (parser->curr->type == Token_Type_Keyword_Elseif) { + consume_token(parser); AstIf* elseif_node = make_node(AstIf, Ast_Kind_If); cond = parse_expression(parser); @@ -383,8 +397,8 @@ static AstIf* parse_if_stmt(OnyxParser* parser) { if_node = elseif_node; } - if (parser->curr_token->type == Token_Type_Keyword_Else) { - parser_next_token(parser); + if (parser->curr->type == Token_Type_Keyword_Else) { + consume_token(parser); AstBlock* false_block = parse_block(parser); if (false_block != NULL) @@ -394,8 +408,9 @@ static AstIf* parse_if_stmt(OnyxParser* parser) { return root_if; } +// 'while' static AstWhile* parse_while_stmt(OnyxParser* parser) { - OnyxToken* while_token = expect(parser, Token_Type_Keyword_While); + OnyxToken* while_token = expect_token(parser, Token_Type_Keyword_While); AstTyped* cond = parse_expression(parser); AstBlock* body = parse_block(parser); @@ -410,20 +425,30 @@ static AstWhile* parse_while_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, AstNode** ret) { - if (parser->curr_token->type != Token_Type_Symbol) return 0; - OnyxToken* symbol = expect(parser, Token_Type_Symbol); + if (parser->curr->type != Token_Type_Symbol) return 0; + OnyxToken* symbol = expect_token(parser, Token_Type_Symbol); - switch ((u16) parser->curr_token->type) { + switch ((u16) parser->curr->type) { // NOTE: Declaration case ':': { - parser_next_token(parser); + consume_token(parser); AstType* type_node = NULL; // NOTE: var: type - if (parser->curr_token->type != ':' - && parser->curr_token->type != '=') { + if (parser->curr->type != ':' + && parser->curr->type != '=') { type_node = parse_type(parser); } @@ -433,24 +458,24 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) { local->base.flags |= Ast_Flag_Lval; // NOTE: DELETE *ret = (AstNode *) local; - if (parser->curr_token->type == '=' || parser->curr_token->type == ':') { - if (parser->curr_token->type == ':') { + if (parser->curr->type == '=' || parser->curr->type == ':') { + if (parser->curr->type == ':') { local->base.flags |= Ast_Flag_Const; } AstAssign* assignment = make_node(AstAssign, Ast_Kind_Assignment); local->base.next = (AstNode *) assignment; - assignment->base.token = parser->curr_token; - parser_next_token(parser); + assignment->base.token = parser->curr; + consume_token(parser); AstTyped* expr = parse_expression(parser); if (expr == NULL) { - onyx_token_null_toggle(parser->curr_token); + token_toggle_end(parser->curr); onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION, assignment->base.token->pos, - parser->curr_token->text); - onyx_token_null_toggle(parser->curr_token); + parser->curr->text); + token_toggle_end(parser->curr); return 1; } assignment->expr = expr; @@ -466,8 +491,8 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) { case '=': { AstAssign* assignment = make_node(AstAssign, Ast_Kind_Assignment); - assignment->base.token = parser->curr_token; - parser_next_token(parser); + assignment->base.token = parser->curr; + consume_token(parser); AstNode* lval = make_node(AstNode, Ast_Kind_Symbol); lval->token = symbol; @@ -486,17 +511,17 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) { case Token_Type_Percent_Equal: { BinaryOp bin_op; - if (parser->curr_token->type == Token_Type_Plus_Equal) bin_op = Binary_Op_Add; - else if (parser->curr_token->type == Token_Type_Minus_Equal) bin_op = Binary_Op_Minus; - else if (parser->curr_token->type == Token_Type_Star_Equal) bin_op = Binary_Op_Multiply; - else if (parser->curr_token->type == Token_Type_Fslash_Equal) bin_op = Binary_Op_Divide; - else if (parser->curr_token->type == Token_Type_Percent_Equal) bin_op = Binary_Op_Modulus; + if (parser->curr->type == Token_Type_Plus_Equal) bin_op = Binary_Op_Add; + else if (parser->curr->type == Token_Type_Minus_Equal) bin_op = Binary_Op_Minus; + else if (parser->curr->type == Token_Type_Star_Equal) bin_op = Binary_Op_Multiply; + else if (parser->curr->type == Token_Type_Fslash_Equal) bin_op = Binary_Op_Divide; + else if (parser->curr->type == Token_Type_Percent_Equal) bin_op = Binary_Op_Modulus; AstBinaryOp* bin_op_node = make_node(AstBinaryOp, Ast_Kind_Binary_Op); bin_op_node->operation = bin_op; - bin_op_node->base.token = parser->curr_token; + bin_op_node->base.token = parser->curr; - parser_next_token(parser); + consume_token(parser); AstTyped* expr = parse_expression(parser); AstNode* bin_op_left = make_node(AstNode, Ast_Kind_Symbol); @@ -519,19 +544,20 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) { } default: - parser_prev_token(parser); + unconsume_token(parser); } return 0; } +// 'return' ? static AstReturn* parse_return_statement(OnyxParser* parser) { AstReturn* return_node = make_node(AstReturn, Ast_Kind_Return); - return_node->base.token = expect(parser, Token_Type_Keyword_Return); + return_node->base.token = expect_token(parser, Token_Type_Keyword_Return); AstTyped* expr = NULL; - if (parser->curr_token->type != ';') { + if (parser->curr->type != ';') { expr = parse_expression(parser); if (expr == NULL || expr == (AstTyped *) &error_node) { @@ -544,11 +570,19 @@ static AstReturn* parse_return_statement(OnyxParser* parser) { return return_node; } +// ; +// +// ; +// ; +// +// +// 'break' ; +// 'continue' ; static AstNode* parse_statement(OnyxParser* parser) { b32 needs_semicolon = 1; AstNode* retval = NULL; - switch ((u16) parser->curr_token->type) { + switch ((u16) parser->curr->type) { case Token_Type_Keyword_Return: retval = (AstNode *) parse_return_statement(parser); break; @@ -583,12 +617,12 @@ static AstNode* parse_statement(OnyxParser* parser) { case Token_Type_Keyword_Break: retval = make_node(AstNode, Ast_Kind_Break); - retval->token = expect(parser, Token_Type_Keyword_Break); + retval->token = expect_token(parser, Token_Type_Keyword_Break); break; case Token_Type_Keyword_Continue: retval = make_node(AstNode, Ast_Kind_Break); - retval->token = expect(parser, Token_Type_Keyword_Continue); + retval->token = expect_token(parser, Token_Type_Keyword_Continue); break; default: @@ -596,37 +630,39 @@ static AstNode* parse_statement(OnyxParser* parser) { } if (needs_semicolon) { - if (parser->curr_token->type != ';') { + if (parser->curr->type != ';') { onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_EXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(';'), - onyx_get_token_type_name(parser->curr_token->type)); + parser->curr->pos, + token_name(';'), + token_name(parser->curr->type)); find_token(parser, ';'); } - parser_next_token(parser); + consume_token(parser); } return retval; } +// '---' +// '{' '}' static AstBlock* parse_block(OnyxParser* parser) { AstBlock* block = make_node(AstBlock, Ast_Kind_Block); AstLocalGroup* lg = make_node(AstLocalGroup, Ast_Kind_Local_Group); block->locals = lg; // NOTE: --- is for an empty block - if (parser->curr_token->type == Token_Type_Empty_Block) { - expect(parser, Token_Type_Empty_Block); + if (parser->curr->type == Token_Type_Empty_Block) { + expect_token(parser, Token_Type_Empty_Block); return block; } - expect(parser, '{'); + expect_token(parser, '{'); AstNode** next = &block->body; AstNode* stmt = NULL; - while (parser->curr_token->type != '}') { + while (parser->curr->type != '}') { stmt = parse_statement(parser); if (stmt != NULL && stmt->kind != Ast_Kind_Error) { @@ -637,40 +673,42 @@ static AstBlock* parse_block(OnyxParser* parser) { } } - expect(parser, '}'); + expect_token(parser, '}'); return block; } +// +// '^' static AstType* parse_type(OnyxParser* parser) { AstType* root = NULL; AstType** next_insertion = &root; while (1) { - if (parser->curr_token->type == '^') { - parser_next_token(parser); + if (parser->curr->type == '^') { + consume_token(parser); AstPointerType* new = make_node(AstPointerType, Ast_Kind_Pointer_Type); new->base.flags |= Basic_Flag_Pointer; *next_insertion = (AstType *) new; next_insertion = &new->elem; } - else if (parser->curr_token->type == Token_Type_Symbol) { + else if (parser->curr->type == Token_Type_Symbol) { AstNode* symbol_node = make_node(AstNode, Ast_Kind_Symbol); - symbol_node->token = expect(parser, Token_Type_Symbol); + symbol_node->token = expect_token(parser, Token_Type_Symbol); *next_insertion = (AstType *) symbol_node; next_insertion = NULL; } else { - onyx_token_null_toggle(parser->curr_token); + token_toggle_end(parser->curr); onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, - parser->curr_token->pos, - parser->curr_token->text); - onyx_token_null_toggle(parser->curr_token); + parser->curr->pos, + parser->curr->text); + token_toggle_end(parser->curr); - parser_next_token(parser); + consume_token(parser); break; } @@ -680,14 +718,16 @@ static AstType* parse_type(OnyxParser* parser) { return root; } +// e +// '(' (: ,?)* ')' static AstLocal* parse_function_params(OnyxParser* parser) { - if (parser->curr_token->type != '(') + if (parser->curr->type != '(') return NULL; - expect(parser, '('); + expect_token(parser, '('); - if (parser->curr_token->type == ')') { - parser_next_token(parser); + if (parser->curr->type == ')') { + consume_token(parser); return NULL; } @@ -696,11 +736,11 @@ static AstLocal* parse_function_params(OnyxParser* parser) { AstLocal* trailer = NULL; OnyxToken* symbol; - while (parser->curr_token->type != ')') { - if (parser->curr_token->type == ',') parser_next_token(parser); + while (parser->curr->type != ')') { + if (parser->curr->type == ',') consume_token(parser); - symbol = expect(parser, Token_Type_Symbol); - expect(parser, ':'); + symbol = expect_token(parser, Token_Type_Symbol); + expect_token(parser, ':'); curr_param = make_node(AstLocal, Ast_Kind_Param); curr_param->base.token = symbol; @@ -715,35 +755,38 @@ static AstLocal* parse_function_params(OnyxParser* parser) { trailer = curr_param; } - parser_next_token(parser); // Skip the ) + consume_token(parser); // Skip the ) return first_param; } +// e +// '#' static b32 parse_possible_directive(OnyxParser* parser, const char* dir) { - if (parser->curr_token->type != '#') return 0; + if (parser->curr->type != '#') return 0; - expect(parser, '#'); - OnyxToken* sym = expect(parser, Token_Type_Symbol); + expect_token(parser, '#'); + OnyxToken* sym = expect_token(parser, Token_Type_Symbol); b32 match = (strlen(dir) == sym->length) && (strncmp(dir, sym->text, sym->length) == 0); if (!match) { - parser_prev_token(parser); - parser_prev_token(parser); + unconsume_token(parser); + unconsume_token(parser); } return match; } +// 'proc' * ('->' )? static AstFunction* parse_function_definition(OnyxParser* parser) { AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function); - func_def->base.token = expect(parser, Token_Type_Keyword_Proc); + func_def->base.token = expect_token(parser, Token_Type_Keyword_Proc); - while (parser->curr_token->type == '#') { + while (parser->curr->type == '#') { if (parse_possible_directive(parser, "intrinsic")) { func_def->base.flags |= Ast_Flag_Intrinsic; - if (parser->curr_token->type == Token_Type_Literal_String) { - OnyxToken* str_token = expect(parser, Token_Type_Literal_String); + if (parser->curr->type == Token_Type_Literal_String) { + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); func_def->intrinsic_name = str_token; } } @@ -753,8 +796,8 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { } else if (parse_possible_directive(parser, "foreign")) { - func_def->foreign_module = expect(parser, Token_Type_Literal_String); - func_def->foreign_name = expect(parser, Token_Type_Literal_String); + func_def->foreign_module = expect_token(parser, Token_Type_Literal_String); + func_def->foreign_name = expect_token(parser, Token_Type_Literal_String); func_def->base.flags |= Ast_Flag_Foreign; } @@ -762,15 +805,15 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { else if (parse_possible_directive(parser, "export")) { func_def->base.flags |= Ast_Flag_Exported; - if (parser->curr_token->type == Token_Type_Literal_String) { - OnyxToken* str_token = expect(parser, Token_Type_Literal_String); + if (parser->curr->type == Token_Type_Literal_String) { + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); func_def->exported_name = str_token; } } else { - OnyxToken* directive_token = expect(parser, '#'); - OnyxToken* symbol_token = expect(parser, Token_Type_Symbol); + OnyxToken* directive_token = expect_token(parser, '#'); + OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_DIRECTIVE, @@ -783,8 +826,8 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { func_def->params = params; AstType* return_type = (AstType *) &basic_type_void; - if (parser->curr_token->type == Token_Type_Right_Arrow) { - expect(parser, Token_Type_Right_Arrow); + if (parser->curr->type == Token_Type_Right_Arrow) { + expect_token(parser, Token_Type_Right_Arrow); return_type = parse_type(parser); } @@ -815,80 +858,99 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { return func_def; } -// static AstNode* parse_foreign(OnyxParser* parser) { -// expect(parser, Token_Type_Keyword_Foreign); -// -// AstForeign* foreign = make_node(AstForeign, Ast_Kind_Foreign); -// foreign->mod_token = expect(parser, Token_Type_Literal_String); -// foreign->name_token = expect(parser, Token_Type_Literal_String); -// -// if (parser->curr_token->type == Token_Type_Keyword_Proc) { -// foreign->import = (AstNode *) parse_function_definition(parser); -// -// } else { -// AstType* type = parse_type(parser); -// -// AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global); -// global->base.type_node = type; -// global->base.flags |= Ast_Flag_Lval; -// -// foreign->import = (AstNode *) global; -// } -// -// return (AstNode *) foreign; -// } - -static AstTyped* parse_top_level_constant_symbol(OnyxParser* parser) { -// if (parser->curr_token->type == Token_Type_Keyword_Proc) { -// return (AstNode *) parse_function_definition(parser); -// -// } else if (parser->curr_token->type == Token_Type_Keyword_Struct) { -// // Handle struct case -// assert(0); -// -// } else if (parser->curr_token->type == Token_Type_Keyword_Foreign) { -// return (AstNode *) parse_foreign(parser); -// -// } else { -// // Global constant with initial value -// AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global); -// global->initial_value = parse_expression(parser); -// global->base.flags |= Ast_Flag_Const; -// global->base.flags |= Ast_Flag_Lval; -// global->base.flags |= Ast_Flag_Comptime; -// -// return (AstNode *) global; -// } - - return parse_expression(parser); +// 'global' +static AstTyped* parse_global_declaration(OnyxParser* parser) { + AstGlobal* global_node = make_node(AstGlobal, Ast_Kind_Global); + global_node->base.token = expect_token(parser, Token_Type_Keyword_Global); + + while (parser->curr->type == '#') { + if (parse_possible_directive(parser, "foreign")) { + global_node->foreign_module = expect_token(parser, Token_Type_Literal_String); + global_node->foreign_name = expect_token(parser, Token_Type_Literal_String); + + global_node->base.flags |= Ast_Flag_Foreign; + } + + else if (parse_possible_directive(parser, "export")) { + global_node->base.flags |= Ast_Flag_Exported; + + if (parser->curr->type == Token_Type_Literal_String) { + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); + global_node->exported_name = str_token; + } + } + + else { + OnyxToken* directive_token = expect_token(parser, '#'); + OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); + + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNKNOWN_DIRECTIVE, + directive_token->pos, + symbol_token->text, symbol_token->length); + } + } + + global_node->base.type_node = parse_type(parser); + global_node->base.flags |= Ast_Flag_Lval; + + + bh_arr_push(parser->results.nodes_to_process, (AstNode *) global_node); + + return (AstTyped *) global_node; +} + +static AstTyped* parse_top_level_expression(OnyxParser* parser) { + if (parser->curr->type == Token_Type_Keyword_Proc) { + AstFunction* func_node = parse_function_definition(parser); + + bh_arr_push(parser->results.nodes_to_process, (AstNode *) func_node); + + return (AstTyped *) func_node; + } + else if (parser->curr->type == Token_Type_Keyword_Global) { + return parse_global_declaration(parser); + } + else { + return parse_expression(parser); + } } +// 'use' +// :: static AstNode* parse_top_level_statement(OnyxParser* parser) { - switch (parser->curr_token->type) { + switch (parser->curr->type) { case Token_Type_Keyword_Use: { AstUse* use_node = make_node(AstUse, Ast_Kind_Use); - use_node->base.token = expect(parser, Token_Type_Keyword_Use); - use_node->filename = expect(parser, Token_Type_Literal_String); + use_node->base.token = expect_token(parser, Token_Type_Keyword_Use); + use_node->filename = expect_token(parser, Token_Type_Literal_String); return (AstNode *) use_node; } case Token_Type_Symbol: { - OnyxToken* symbol = parser->curr_token; - parser_next_token(parser); + OnyxToken* symbol = parser->curr; + consume_token(parser); - expect(parser, ':'); - expect(parser, ':'); + expect_token(parser, ':'); + expect_token(parser, ':'); - AstTyped* node = parse_top_level_constant_symbol(parser); + AstTyped* node = parse_top_level_expression(parser); if (node->kind == Ast_Kind_Function) { AstFunction* func = (AstFunction *) node; if (func->exported_name == NULL) func->exported_name = symbol; + + } else if (node->kind == Ast_Kind_Global) { + AstGlobal* global = (AstGlobal *) node; + + if (global->exported_name == NULL) + global->exported_name = symbol; + } else { // HACK bh_arr_push(parser->results.nodes_to_process, (AstNode *) node); @@ -904,7 +966,7 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { default: break; } - parser_next_token(parser); + consume_token(parser); return NULL; } @@ -927,8 +989,8 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, Onyx parser.allocator = alloc; parser.tokenizer = tokenizer; - parser.curr_token = tokenizer->tokens; - parser.prev_token = NULL; + parser.curr = tokenizer->tokens; + parser.prev = NULL; parser.msgs = msgs; parser.results = (ParseResults) { @@ -950,7 +1012,7 @@ void onyx_parser_free(OnyxParser* parser) { } ParseResults onyx_parse(OnyxParser *parser) { - while (parser->curr_token->type != Token_Type_End_Stream) { + while (parser->curr->type != Token_Type_End_Stream) { AstNode* curr_stmt = parse_top_level_statement(parser); if (curr_stmt != NULL && curr_stmt != &error_node) { diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 7a9a5857..2aa84b35 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -9,6 +9,7 @@ static AstNode* symbol_resolve(OnyxSemPassState* state, OnyxToken* tkn); static void local_group_enter(OnyxSemPassState* state, AstLocalGroup* local_group); static void local_group_leave(OnyxSemPassState* state); +static AstType* symres_type(OnyxSemPassState* state, AstType* type); static void symres_local(OnyxSemPassState* state, AstLocal** local); static void symres_call(OnyxSemPassState* state, AstCall* call); static void symres_expression(OnyxSemPassState* state, AstTyped** expr); @@ -20,10 +21,10 @@ static void symres_statement_chain(OnyxSemPassState* state, AstNode* walker, Ast static b32 symres_statement(OnyxSemPassState* state, AstNode* stmt); static void symres_block(OnyxSemPassState* state, AstBlock* block); static void symres_function(OnyxSemPassState* state, AstFunction* func); -static AstType* symres_type(OnyxSemPassState* state, AstType* type); +static void symres_global(OnyxSemPassState* state, AstGlobal* global); static void symbol_introduce(OnyxSemPassState* state, OnyxToken* tkn, AstNode* symbol) { - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); SemPassSymbol* sp_sym = (SemPassSymbol *) bh_alloc_item(state->allocator, SemPassSymbol); sp_sym->node = symbol; @@ -41,11 +42,11 @@ static void symbol_introduce(OnyxSemPassState* state, OnyxToken* tkn, AstNode* s state->curr_local_group->last_local = local; } - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); } static void symbol_remove(OnyxSemPassState* state, OnyxToken* tkn) { - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, tkn->text); @@ -55,26 +56,32 @@ static void symbol_remove(OnyxSemPassState* state, OnyxToken* tkn) { bh_table_delete(SemPassSymbol *, state->symbols, tkn->text); } - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); } static AstNode* symbol_resolve(OnyxSemPassState* state, OnyxToken* tkn) { - onyx_token_null_toggle(tkn); + AstNode* res = NULL; - if (!bh_table_has(SemPassSymbol *, state->symbols, tkn->text)) { - onyx_message_add(state->msgs, - ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, - tkn->pos, - tkn->text); + while (res == NULL || res->kind == Ast_Kind_Symbol) { + token_toggle_end(tkn); - onyx_token_null_toggle(tkn); - return NULL; - } + if (!bh_table_has(SemPassSymbol *, state->symbols, tkn->text)) { + onyx_message_add(state->msgs, + ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, + tkn->pos, + tkn->text); - SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, tkn->text); + token_toggle_end(tkn); + return NULL; + } + + res = bh_table_get(SemPassSymbol *, state->symbols, tkn->text)->node; + token_toggle_end(tkn); + + tkn = res->token; + } - onyx_token_null_toggle(tkn); - return sp_sym->node; + return res; } static void local_group_enter(OnyxSemPassState* state, AstLocalGroup* local_group) { @@ -100,7 +107,7 @@ static void symbol_basic_type_introduce(OnyxSemPassState* state, AstBasicType* b } static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxToken* tkn, AstNode* symbol) { - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); // NOTE: If the function hasn't already been defined if (!bh_table_has(SemPassSymbol *, state->symbols, tkn->text)) { @@ -115,11 +122,11 @@ static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxToken* tkn, AstN tkn->text); // NOTE: I really wish C had defer... - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); return 0; } - onyx_token_null_toggle(tkn); + token_toggle_end(tkn); return 1; } @@ -165,12 +172,12 @@ static void symres_call(OnyxSemPassState* state, AstCall* call) { if (callee) call->callee = callee; else { - onyx_token_null_toggle(call->callee->token); + token_toggle_end(call->callee->token); onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_SYMBOL, call->callee->token->pos, call->callee->token->text); - onyx_token_null_toggle(call->callee->token); + token_toggle_end(call->callee->token); return; } @@ -315,6 +322,10 @@ static void symres_function(OnyxSemPassState* state, AstFunction* func) { } } +static void symres_global(OnyxSemPassState* state, AstGlobal* global) { + global->base.type_node = symres_type(state, global->base.type_node); +} + static void symres_top_node(OnyxSemPassState* state, AstNode** node) { switch ((*node)->kind) { case Ast_Kind_Call: @@ -325,6 +336,10 @@ static void symres_top_node(OnyxSemPassState* state, AstNode** node) { symres_expression(state, (AstTyped **) node); break; + case Ast_Kind_Global: + symres_global(state, (AstGlobal *) *node); + break; + case Ast_Kind_Function: symres_function(state, (AstFunction *) *node); break; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 66123bff..56a9a025 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -5,17 +5,17 @@ // NOTE: Allows easier testing of types since most of the characters // corresponding to these values are not printable #if 1 -const WasmType WASM_TYPE_INT32 = 0x7F; -const WasmType WASM_TYPE_INT64 = 0x7E; -const WasmType WASM_TYPE_FLOAT32 = 0x7D; -const WasmType WASM_TYPE_FLOAT64 = 0x7C; -const WasmType WASM_TYPE_VOID = 0x00; +#define WASM_TYPE_INT32 0x7F +#define WASM_TYPE_INT64 0x7E +#define WASM_TYPE_FLOAT32 0x7D +#define WASM_TYPE_FLOAT64 0x7C +#define WASM_TYPE_VOID 0x00 #else -const WasmType WASM_TYPE_INT32 = 'A'; -const WasmType WASM_TYPE_INT64 = 'B'; -const WasmType WASM_TYPE_FLOAT32 = 'C'; -const WasmType WASM_TYPE_FLOAT64 = 'D'; -const WasmType WASM_TYPE_VOID = '\0'; +#define WASM_TYPE_INT32 'A' +#define WASM_TYPE_INT64 'B' +#define WASM_TYPE_FLOAT32 'C' +#define WASM_TYPE_FLOAT64 'D' +#define WASM_TYPE_VOID 'E' #endif static const char* wi_string(WasmInstructionType wit) { @@ -826,7 +826,7 @@ static void compile_function(OnyxWasmModule* mod, AstFunction* fd) { bh_arr_new(mod->allocator, wasm_func.code, 4); if (fd->base.flags & Ast_Flag_Exported) { - onyx_token_null_toggle(fd->exported_name); + token_toggle_end(fd->exported_name); i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) fd); @@ -837,7 +837,7 @@ static void compile_function(OnyxWasmModule* mod, AstFunction* fd) { bh_table_put(WasmExport, mod->exports, fd->exported_name->text, wasm_export); mod->export_count++; - onyx_token_null_toggle(fd->exported_name); + token_toggle_end(fd->exported_name); } // If there is no body then don't process the code @@ -880,22 +880,28 @@ static void compile_function(OnyxWasmModule* mod, AstFunction* fd) { } static void compile_global_declaration(OnyxWasmModule* module, AstGlobal* global) { + WasmType global_type = onyx_type_to_wasm_type(global->base.type); + + if (global->base.flags & Ast_Flag_Foreign) { + WasmImport import = { + .kind = WASM_FOREIGN_GLOBAL, + .idx = global_type, + .mod = global->foreign_module, + .name = global->foreign_name, + }; + + bh_arr_push(module->imports, import); + return; + } + WasmGlobal glob = { - .type = onyx_type_to_wasm_type(global->base.type), + .type = global_type, .mutable = (global->base.flags & Ast_Flag_Const) == 0, .initial_value = NULL, }; - if (!global->initial_value) { - onyx_message_add(module->msgs, - ONYX_MESSAGE_TYPE_LITERAL, - global->base.token->pos, - "global without initial value"); - return; - } - if ((global->base.flags & Ast_Flag_Exported) != 0) { - onyx_token_null_toggle(global->base.token); + token_toggle_end(global->exported_name); i32 global_idx = (i32) bh_imap_get(&module->func_map, (u64) global); @@ -903,46 +909,24 @@ static void compile_global_declaration(OnyxWasmModule* module, AstGlobal* global .kind = WASM_FOREIGN_GLOBAL, .idx = global_idx, }; - bh_table_put(WasmExport, module->exports, global->base.token->text, wasm_export); + bh_table_put(WasmExport, module->exports, global->exported_name->text, wasm_export); module->export_count++; - onyx_token_null_toggle(global->base.token); + token_toggle_end(global->exported_name); } - compile_expression(module, &glob.initial_value, global->initial_value); - bh_arr_push(module->globals, glob); -} + bh_arr_new(global_heap_allocator, glob.initial_value, 1); -static void compile_foreign(OnyxWasmModule* module, AstForeign* foreign) { - if (foreign->import->kind == Ast_Kind_Function) { - i32 type_idx = generate_type_idx(module, (AstFunction *) foreign->import); + switch (global_type) { + case WASM_TYPE_INT32: bh_arr_push(glob.initial_value, ((WasmInstruction) { WI_I32_CONST, 0 })); break; + case WASM_TYPE_INT64: bh_arr_push(glob.initial_value, ((WasmInstruction) { WI_I64_CONST, 0 })); break; + case WASM_TYPE_FLOAT32: bh_arr_push(glob.initial_value, ((WasmInstruction) { WI_F32_CONST, 0 })); break; + case WASM_TYPE_FLOAT64: bh_arr_push(glob.initial_value, ((WasmInstruction) { WI_F64_CONST, 0 })); break; - WasmImport import = { - .kind = WASM_FOREIGN_FUNCTION, - .idx = type_idx, - .mod = foreign->mod_token, - .name = foreign->name_token, - }; - - bh_arr_push(module->imports, import); - - } else if (foreign->import->kind == Ast_Kind_Global) { - WasmType global_type = onyx_type_to_wasm_type(((AstGlobal *) foreign->import)->base.type); - - WasmImport import = { - .kind = WASM_FOREIGN_GLOBAL, - .idx = global_type, - .mod = foreign->mod_token, - .name = foreign->name_token, - }; - - bh_arr_push(module->imports, import); - - } else { - DEBUG_HERE; - // NOTE: Invalid foreign - assert(0); + default: assert(("Invalid global type", 0)); break; } + + bh_arr_push(module->globals, glob); } OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) { @@ -994,6 +978,12 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program) { } } + bh_arr_each(AstGlobal *, global, program->globals) { + if ((*global)->base.flags & Ast_Flag_Foreign) { + bh_imap_put(&module->global_map, (u64) *global, module->next_global_idx++); + } + } + bh_arr_each(AstFunction *, function, program->functions) { if ((*function)->base.flags & Ast_Flag_Foreign) continue; @@ -1001,7 +991,16 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program) { bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++); } + bh_arr_each(AstGlobal *, global, program->globals) { + if ((*global)->base.flags & Ast_Flag_Foreign) continue; + + bh_imap_put(&module->global_map, (u64) *global, module->next_global_idx++); + } + // NOTE: Then, compile everything + bh_arr_each(AstGlobal *, global, program->globals) + compile_global_declaration(module, *global); + bh_arr_each(AstFunction *, function, program->functions) compile_function(module, *function);