From: Brendan Hansen Date: Thu, 16 Jul 2020 20:38:43 +0000 (-0500) Subject: Added a proper function type X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=86ec9117b26459e5a7f526ca0196fd341faa4f9c;p=onyx.git Added a proper function type --- diff --git a/.vimspector.json b/.vimspector.json index 88493853..e309f7f9 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -6,7 +6,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/onyx", - "args": ["progs/basic.onyx"], + "args": ["progs/test.onyx"], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], diff --git a/docs/thoughts b/docs/thoughts index 188e314d..8bedc24a 100644 --- a/docs/thoughts +++ b/docs/thoughts @@ -14,7 +14,7 @@ Memory design: Example use: {{{ ptr: ^i32 = 0; // Address starting at 0 - ptr_ptr := ^ptr; + ptr_ptr := *ptr; }}} diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 081d20f1..9a80bb6c 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -175,7 +175,7 @@ struct AstIf { struct AstType { AstKind kind; u32 flags; char* name; }; struct AstBasicType { AstType base; Type* type; }; struct AstPointerType { AstType base; AstType* elem; }; -struct AstFunctionType { AstType base; bh_arr(AstType *) params; AstType* results; }; +struct AstFunctionType { AstType base; AstType* return_type; u64 param_count; AstType* params[]; }; // Top level nodes struct AstBinding { AstTyped base; AstNode* node; }; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index e6fccbb7..1aa719de 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -47,8 +47,9 @@ typedef struct TypeBasic { typedef struct Type Type; #define TYPE_KINDS \ - TYPE_KIND(Basic, TypeBasic) \ - TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) // TypePointer utilizes the elements of TypeBasic + TYPE_KIND(Basic, TypeBasic) \ + TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; }) \ + TYPE_KIND(Function, struct { Type *return_type; u64 param_count; Type* params[]; }) typedef enum TypeKind { Type_Kind_Invalid, @@ -71,13 +72,13 @@ enum TypeFlag { struct Type { TypeKind kind; + u32 flags; + union { #define TYPE_KIND(k, ...) Type##k k; TYPE_KINDS #undef TYPE_KIND }; - - u32 flags; }; extern Type basic_types[]; diff --git a/onyx b/onyx index b0040d8f..ceca3e23 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/other.onyx b/progs/other.onyx index 70b9a52e..cb576406 100644 --- a/progs/other.onyx +++ b/progs/other.onyx @@ -1,5 +1,3 @@ -use "progs/test" - other_value :: proc (n: i32) -> i32 { return 8675309 + something_else(n) + global_value; } diff --git a/progs/test.onyx b/progs/test.onyx index 1522bf3b..1e6a9277 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -40,7 +40,6 @@ main3 :: proc #export { local_brute(); } - // This is the entry point main2 :: proc #export { i := 0; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 64e6836d..120e5514 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -134,7 +134,11 @@ static b32 check_call(OnyxSemPassState* state, AstCall* call) { return 1; } - if (callee->base.kind != Ast_Kind_Function) { + if (callee->base.type == NULL) { + callee->base.type = type_build_from_ast(state->node_allocator, callee->base.type_node); + } + + if (callee->base.type->kind != Type_Kind_Function) { onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION, call->base.token->pos, @@ -205,10 +209,7 @@ static b32 check_call(OnyxSemPassState* state, AstCall* call) { onyx_token_null_toggle(callee->base.token); } - if (callee->base.type == NULL) { - callee->base.type = type_build_from_ast(state->node_allocator, callee->base.type_node); - } - call->base.type = callee->base.type; + call->base.type = callee->base.type->Function.return_type; AstLocal* formal_param = callee->params; AstArgument* actual_param = call->arguments; @@ -372,6 +373,8 @@ static b32 check_expression(OnyxSemPassState* state, AstTyped* expr) { assert(expr->type != NULL); break; + case Ast_Kind_Function: break; + default: retval = 1; DEBUG_HERE; @@ -477,7 +480,6 @@ static b32 check_function(OnyxSemPassState* state, AstFunction* func) { } } - // NOTE: Acutally the return type if (func->base.type == NULL) { func->base.type = type_build_from_ast(state->node_allocator, func->base.type_node); } @@ -508,7 +510,7 @@ static b32 check_function(OnyxSemPassState* state, AstFunction* func) { } } - state->expected_return_type = func->base.type; + state->expected_return_type = func->base.type->Function.return_type; if (func->body) { return check_block(state, func->body); } diff --git a/src/onyxparser.c b/src/onyxparser.c index c99608b5..e0260c1a 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -781,15 +781,34 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { AstLocal* params = parse_function_params(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); - AstType* return_type = parse_type(parser); - func_def->base.type_node = return_type; - } else { - func_def->base.type_node = (AstType *) &basic_type_void; + return_type = parse_type(parser); + } + + u64 param_count = 0; + for (AstLocal* param = params; + param != NULL; + param = (AstLocal *) param->base.next) + param_count++; + + AstFunctionType* type_node = bh_alloc(parser->allocator, sizeof(AstFunctionType) + param_count * sizeof(AstType *)); + type_node->base.kind = Ast_Kind_Function_Type; + type_node->param_count = param_count; + type_node->return_type = return_type; + + u32 i = 0; + for (AstLocal* param = params; + param != NULL; + param = (AstLocal *) param->base.next) { + type_node->params[i] = param->base.type_node; + i++; } + func_def->base.type_node = (AstType *) type_node; + func_def->body = parse_block(parser); return func_def; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 02774125..7a9a5857 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -138,6 +138,19 @@ static AstType* symres_type(OnyxSemPassState* state, AstType* type) { return type; } + if (type->kind == Ast_Kind_Function_Type) { + AstFunctionType* ftype = (AstFunctionType *) type; + + ftype->return_type = symres_type(state, ftype->return_type); + + if (ftype->param_count > 0) + fori (i, 0, ftype->param_count - 1) { + ftype->params[i] = symres_type(state, ftype->params[i]); + } + + return type; + } + assert(("Bad type node", 0)); return NULL; } @@ -149,8 +162,17 @@ static void symres_local(OnyxSemPassState* state, AstLocal** local) { static void symres_call(OnyxSemPassState* state, AstCall* call) { AstNode* callee = symbol_resolve(state, call->callee->token); - if (callee) call->callee = callee; - else DEBUG_HERE; + if (callee) + call->callee = callee; + else { + onyx_token_null_toggle(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); + return; + } symres_statement_chain(state, (AstNode *) call->arguments, (AstNode **) &call->arguments); } @@ -185,6 +207,7 @@ static void symres_expression(OnyxSemPassState* state, AstTyped** expr) { // NOTE: This is a good case, since it means the symbol is already resolved case Ast_Kind_Local: break; + case Ast_Kind_Function: case Ast_Kind_Literal: (*expr)->type_node = symres_type(state, (*expr)->type_node); break; @@ -282,9 +305,7 @@ static void symres_function(OnyxSemPassState* state, AstFunction* func) { } if (func->base.type_node != NULL) { - if (func->base.type_node->kind == Ast_Kind_Symbol) { - func->base.type_node = symres_type(state, func->base.type_node); - } + func->base.type_node = symres_type(state, func->base.type_node); } symres_block(state, func->body); @@ -331,27 +352,6 @@ void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program) { symbol_basic_type_introduce(state, &basic_type_f64); symbol_basic_type_introduce(state, &basic_type_rawptr); - // NOTE: Introduce all global symbols - // bh_arr_each(AstGlobal *, global, program->globals) - // if (!symbol_unique_introduce(state, (AstNode *) *global)) return; - - // bh_arr_each(AstFunction *, function, program->functions) - // if (!symbol_unique_introduce(state, (AstNode *) *function)) return; - - // bh_arr_each(AstForeign *, foreign, program->foreigns) { - // AstKind import_kind = (*foreign)->import->kind; - - // if (import_kind == Ast_Kind_Function || import_kind == Ast_Kind_Global) - // if (!symbol_unique_introduce(state, (*foreign)->import)) return; - // } - - // // NOTE: Then, resolve all symbols in all functions - // bh_arr_each(AstForeign *, foreign, program->foreigns) { - // if ((*foreign)->import->kind == Ast_Kind_Function) { - // symres_function(state, (AstFunction *) (*foreign)->import); - // } - // } - bh_arr_each(AstBinding *, binding, program->top_level_bindings) if (!symbol_unique_introduce(state, (*binding)->base.token, (*binding)->node)) return; diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 908ae1cc..10746fdf 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -4,23 +4,23 @@ // NOTE: These have to be in the same order as Basic Type basic_types[] = { - { Type_Kind_Basic, { Basic_Kind_Void, 0, 0, "void" } }, + { Type_Kind_Basic, 0, { Basic_Kind_Void, 0, 0, "void" } }, - { Type_Kind_Basic, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, "bool" } }, + { Type_Kind_Basic, 0, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, "bool" } }, - { Type_Kind_Basic, { Basic_Kind_I8, Basic_Flag_Integer, 1, "i8" } }, - { Type_Kind_Basic, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, "u8" } }, - { Type_Kind_Basic, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } }, - { Type_Kind_Basic, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, "u16" } }, - { Type_Kind_Basic, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } }, - { Type_Kind_Basic, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, "u32" } }, - { Type_Kind_Basic, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } }, - { Type_Kind_Basic, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, "u64" } }, + { Type_Kind_Basic, 0, { Basic_Kind_I8, Basic_Flag_Integer, 1, "i8" } }, + { Type_Kind_Basic, 0, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, "u8" } }, + { Type_Kind_Basic, 0, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } }, + { Type_Kind_Basic, 0, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, "u16" } }, + { Type_Kind_Basic, 0, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } }, + { Type_Kind_Basic, 0, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, "u32" } }, + { Type_Kind_Basic, 0, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } }, + { Type_Kind_Basic, 0, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, "u64" } }, - { Type_Kind_Basic, { Basic_Kind_F32, Basic_Flag_Float, 4, "f32" } }, - { Type_Kind_Basic, { Basic_Kind_F64, Basic_Flag_Float, 8, "f64" } }, + { Type_Kind_Basic, 0, { Basic_Kind_F32, Basic_Flag_Float, 4, "f32" } }, + { Type_Kind_Basic, 0, { Basic_Kind_F64, Basic_Flag_Float, 8, "f64" } }, - { Type_Kind_Basic, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, "rawptr" } }, + { Type_Kind_Basic, 0, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, "rawptr" } }, }; b32 types_are_compatible(Type* t1, Type* t2) { @@ -66,6 +66,24 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return (Type *) ptr_type; } + case Ast_Kind_Function_Type: { + AstFunctionType* ftype_node = (AstFunctionType *) type_node; + u64 param_count = ftype_node->param_count; + + Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count); + + func_type->kind = Type_Kind_Function; + func_type->Function.param_count = param_count; + func_type->Function.return_type = type_build_from_ast(alloc, ftype_node->return_type); + + if (param_count > 0) + fori (i, 0, param_count - 1) { + func_type->Function.params[i] = type_build_from_ast(alloc, ftype_node->params[i]); + } + + return func_type; + } + case Ast_Kind_Basic_Type: return ((AstBasicType *) type_node)->type; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index cf80a271..8733c75b 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -756,18 +756,18 @@ static i32 generate_type_idx(OnyxWasmModule* mod, AstFunction* fd) { static char type_repr_buf[128]; char* t = type_repr_buf; - AstLocal* param = fd->params; - i32 param_count = 0; - while (param) { + Type** param_type = fd->base.type->Function.params; + i32 param_count = fd->base.type->Function.param_count; + i32 params_left = param_count; + while (params_left-- > 0) { // HACK: Using these directly as part of a string feels weird but they are // valid characters so I don't think it is going to be much of an issue - *(t++) = (char) onyx_type_to_wasm_type(param->base.type); - param_count++; - param = (AstLocal *) param->base.next; + *(t++) = (char) onyx_type_to_wasm_type(*param_type); + param_type++; } *(t++) = ':'; - WasmType return_type = onyx_type_to_wasm_type(fd->base.type); + WasmType return_type = onyx_type_to_wasm_type(fd->base.type->Function.return_type); *(t++) = (char) return_type; *t = '\0';