From: Brendan Hansen Date: Fri, 19 Jun 2020 03:09:00 +0000 (-0500) Subject: Started work on importing external functions X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8041f0b511ffb63ba782b11dc9b9db6d8e7fe4c0;p=onyx.git Started work on importing external functions --- diff --git a/docs/plan b/docs/plan index 66c9d3f8..21597ed3 100644 --- a/docs/plan +++ b/docs/plan @@ -55,6 +55,7 @@ HOW: [X] Curly braces are required for all bodies of blocks [X] Numeric literals are parsed [X] Numeric literals have the minimum type detected + [ ] Foreign imports (functions only) [ ] Comparison operators [ ] Proper boolean type [ ] Conditional branching works as expected diff --git a/include/onyxparser.h b/include/onyxparser.h index 80690f2f..b80e2cb9 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -13,6 +13,7 @@ typedef struct OnyxAstNodeScope OnyxAstNodeScope; typedef struct OnyxAstNodeBlock OnyxAstNodeBlock; typedef struct OnyxAstNodeParam OnyxAstNodeParam; typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef; +typedef struct OnyxAstNodeForeign OnyxAstNodeForeign; typedef struct OnyxAstNodeCall OnyxAstNodeCall; typedef struct OnyxParser { @@ -40,6 +41,7 @@ typedef enum OnyxAstNodeKind { ONYX_AST_NODE_KIND_PROGRAM, ONYX_AST_NODE_KIND_FUNCDEF, + ONYX_AST_NODE_KIND_FOREIGN, ONYX_AST_NODE_KIND_BLOCK, ONYX_AST_NODE_KIND_SCOPE, ONYX_AST_NODE_KIND_LOCAL, @@ -173,6 +175,16 @@ struct OnyxAstNodeFuncDef { OnyxAstNodeParam *params; }; +struct OnyxAstNodeForeign { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *mod_token; + OnyxTypeInfo *type; + OnyxAstNode *next; + OnyxToken *name_token; + OnyxAstNode *import; +}; + struct OnyxAstNodeCall { OnyxAstNodeKind kind; u32 flags; @@ -205,6 +217,7 @@ union OnyxAstNode { OnyxAstNodeScope as_scope; OnyxAstNodeCall as_call; OnyxAstNodeNumLit as_numlit; + OnyxAstNodeForeign as_foreign; }; const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind); diff --git a/onyx b/onyx index 944178d4..e09523b8 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/game.onyx b/progs/game.onyx new file mode 100644 index 00000000..85ac24da --- /dev/null +++ b/progs/game.onyx @@ -0,0 +1,16 @@ + +gfx_draw_rect :: foreign "gfx" "draw_rect" proc (x i32, y i32, w i32, h i32) --- + +update :: proc --- + +draw :: proc { + draw_rect(0, 0, 100, 100); +} + +export main :: proc { + + while true { + update(); + draw(); + } +} diff --git a/progs/minimal.onyx b/progs/minimal.onyx index 8b153fc7..83b863d6 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -1,4 +1,7 @@ -foo :: proc () -> i32 { + +print :: foreign "host" "print" proc (value i32) --- + +foo :: proc -> i32 { return 10 as i32; } @@ -17,6 +20,7 @@ diff_square :: proc (a i32, b i32) -> i32 { export do_stuff :: proc -> i32 { res := diff_square((4 + 5) as i32, (2 + 3) as i32); res = res + foo(); + // res should be 66 return res; } diff --git a/src/onyxparser.c b/src/onyxparser.c index 0c5d5dae..b0ad3861 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -7,6 +7,7 @@ static const char* ast_node_names[] = { "PROGRAM", "FUNCDEF", + "FOREIGN", "BLOCK", "SCOPE", "LOCAL", @@ -682,6 +683,32 @@ static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) { return func_def; } +static OnyxAstNode* parse_top_level_symbol(OnyxParser* parser) { + if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) { + OnyxAstNodeFuncDef* func_def = parse_function_definition(parser); + return (OnyxAstNode *) func_def; + + } 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) { + parser_next_token(parser); + + OnyxAstNodeForeign* foreign = (OnyxAstNodeForeign *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FOREIGN); + foreign->mod_token = expect(parser, TOKEN_TYPE_LITERAL_STRING); + foreign->name_token = expect(parser, TOKEN_TYPE_LITERAL_STRING); + foreign->import = parse_top_level_symbol(parser); + + return (OnyxAstNode *) foreign; + } else { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, + parser->curr_token->pos, + onyx_get_token_type_name(parser->curr_token->type)); + return &error_node; + } +} + static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { switch (parser->curr_token->type) { case TOKEN_TYPE_KEYWORD_USE: @@ -713,38 +740,28 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) { expect(parser, TOKEN_TYPE_SYM_COLON); expect(parser, TOKEN_TYPE_SYM_COLON); - if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) { - OnyxAstNodeFuncDef* func_def = parse_function_definition(parser); - func_def->token = symbol; + OnyxAstNode* node = parse_top_level_symbol(parser); + if (node->kind == ONYX_AST_NODE_KIND_FUNCDEF) { + node->token = symbol; - onyx_token_null_toggle(*symbol); + onyx_token_null_toggle(*symbol); - if (!bh_table_has(OnyxAstNode *, parser->identifiers, symbol->token)) { - bh_table_put(OnyxAstNode *, parser->identifiers, symbol->token, (OnyxAstNode *) func_def); - } else { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, - symbol->pos, - symbol->token); + if (!bh_table_has(OnyxAstNode *, parser->identifiers, symbol->token)) { + bh_table_put(OnyxAstNode *, parser->identifiers, symbol->token, node); + } else { + onyx_message_add(parser->msgs, + ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION, + symbol->pos, + symbol->token); - // NOTE: I really wish C had defer... - onyx_token_null_toggle(*symbol); - return NULL; - } - - onyx_token_null_toggle(*symbol); - return (OnyxAstNode *) func_def; + // NOTE: I really wish C had defer... + onyx_token_null_toggle(*symbol); + return NULL; + } - } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) { - // Handle struct case - assert(0); - } else { - onyx_message_add(parser->msgs, - ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN, - parser->curr_token->pos, - onyx_get_token_type_name(parser->curr_token->type)); - break; - } + onyx_token_null_toggle(*symbol); + } + return node; } default: break; diff --git a/src/onyxutils.c b/src/onyxutils.c index 055932fd..5f0e97c9 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -19,7 +19,8 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { } case ONYX_AST_NODE_KIND_FUNCDEF: { - bh_printf("(%b) ", node->token->token, node->token->length); + if (node->token) + bh_printf("(%b) ", node->token->token, node->token->length); OnyxAstNodeFuncDef* fd = &node->as_funcdef; print_indent; @@ -123,6 +124,22 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { break; } + case ONYX_AST_NODE_KIND_FOREIGN: { + OnyxAstNodeForeign* foreign = &node->as_foreign; + bh_printf("%b:%b", + foreign->mod_token->token, foreign->mod_token->length, + foreign->name_token->token, foreign->name_token->length); + + if (foreign->import) { + onyx_ast_print(foreign->import, indent + 1); + } + + if (foreign->next) { + onyx_ast_print(foreign->next, indent); + } + break; + } + default: { onyx_ast_print(node->left, indent + 1); onyx_ast_print(node->right, indent + 1); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 4d768fba..f4515a4a 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -506,33 +506,36 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* } // If there is no body then don't process the code - if (fd->body == NULL) return; - - // NOTE: Generate the local map - i32 localidx = 0; - forll (OnyxAstNodeParam, param, fd->params, next) { - bh_imap_put(&mod->local_map, (u64) param, localidx++); - } - - static const WasmType local_types[4] = { WASM_TYPE_INT32, WASM_TYPE_INT64, WASM_TYPE_FLOAT32, WASM_TYPE_FLOAT64 }; - - // HACK: This assumes that the order of the count members - // is the same as the order of the local_types above - u8* count = &wasm_func.locals.i32_count; - fori (ti, 0, 3) { - forll (OnyxAstNodeLocal, local, fd->body->scope->last_local, prev_local) { - if (onyx_type_to_wasm_type(local->type) == local_types[ti]) { - bh_imap_put(&mod->local_map, (u64) local, localidx++); - - (*count)++; - } - } + if (fd->body != NULL) { + // NOTE: Generate the local map + i32 localidx = 0; + forll (OnyxAstNodeParam, param, fd->params, next) { + bh_imap_put(&mod->local_map, (u64) param, localidx++); + } + + static const WasmType local_types[4] = { WASM_TYPE_INT32, WASM_TYPE_INT64, WASM_TYPE_FLOAT32, WASM_TYPE_FLOAT64 }; + + // HACK: This assumes that the order of the count members + // is the same as the order of the local_types above + u8* count = &wasm_func.locals.i32_count; + fori (ti, 0, 3) { + forll (OnyxAstNodeLocal, local, fd->body->scope->last_local, prev_local) { + if (onyx_type_to_wasm_type(local->type) == local_types[ti]) { + bh_imap_put(&mod->local_map, (u64) local, localidx++); + + (*count)++; + } + } - count++; - } + count++; + } - // Generate code - process_function_body(mod, &wasm_func, fd); + // Generate code + process_function_body(mod, &wasm_func, fd); + } else { + // NOTE: Empty bodies still need a block end instruction + bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 })); + } bh_arr_push(mod->funcs, wasm_func); @@ -540,6 +543,10 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* bh_imap_clear(&mod->local_map); } +void process_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) { + +} + OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program) { OnyxWasmModule module = { .allocator = alloc, @@ -570,6 +577,9 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra case ONYX_AST_NODE_KIND_FUNCDEF: process_function_definition(&module, &walker->as_funcdef); break; + case ONYX_AST_NODE_KIND_FOREIGN: + process_foreign(&module, &walker->as_foreign); + break; default: break; } @@ -804,10 +814,6 @@ static void output_instruction(WasmInstruction* instr, bh_buffer* buff) { case WI_LOCAL_GET: case WI_LOCAL_SET: case WI_CALL: - leb = uint_to_uleb128((u64) instr->data.i1, &leb_len); - bh_buffer_append(buff, leb, leb_len); - break; - case WI_BLOCK_START: leb = uint_to_uleb128((u64) instr->data.i1, &leb_len); bh_buffer_append(buff, leb, leb_len);