Added a proper function type
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jul 2020 20:38:43 +0000 (15:38 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jul 2020 20:38:43 +0000 (15:38 -0500)
12 files changed:
.vimspector.json
docs/thoughts
include/onyxastnodes.h
include/onyxtypes.h
onyx
progs/other.onyx
progs/test.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxwasm.c

index 88493853a3314d6b6d7717d1fe5c86193f4b554c..e309f7f9bf9838e0c2649137abd51c35f11dd304 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/basic.onyx"],
+                "args": ["progs/test.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index 188e314d586030aea5fbda2cb9bc02088506e159..8bedc24af27686b99bbf0b52c3566963667732b4 100644 (file)
@@ -14,7 +14,7 @@ Memory design:
             Example use:
             {{{
                 ptr: ^i32 = 0; // Address starting at 0
-                ptr_ptr := ^ptr;
+                ptr_ptr := *ptr;
             }}}
 
 
index 081d20f1865d0845ebab7adc7fdc05bbc0aec264..9a80bb6c2db20e08780e6a1c92a7a67aa371eaf3 100644 (file)
@@ -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; };
index e6fccbb7c8acb0764bcd1f044c13dff8ec40588c..1aa719def55682ba832a130237fad2bc7baeffa8 100644 (file)
@@ -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 b0040d8f5d0f8640a3a9fa98239db9bc3e0e5321..ceca3e2326da7225053462373ae7903b2a73f873 100755 (executable)
Binary files a/onyx and b/onyx differ
index 70b9a52e273ef12228f83f8cc807fec053851c31..cb576406458a4bf7ea25b0c93e17d4a04f3684f2 100644 (file)
@@ -1,5 +1,3 @@
-use "progs/test"
-
 other_value :: proc (n: i32) -> i32 {
     return 8675309 + something_else(n) + global_value;
 }
index 1522bf3b21432a74a8720f8a66dcac50a7f88933..1e6a92774e4e5ca9324dab24480c5d8583979b93 100644 (file)
@@ -40,7 +40,6 @@ main3 :: proc #export {
     local_brute();
 }
 
-
 // This is the entry point
 main2 :: proc #export {
     i := 0;
index 64e6836dd48fdb6fd3a66ebe820144645869e3c6..120e551490d0065588e74f6d99f31f7e5795c8ba 100644 (file)
@@ -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);
     }
index c99608b532a41a51cc33cf846ae9eac5a7bbb232..e0260c1ab183ae3f3875bbf8a9a444a3a8b79197 100644 (file)
@@ -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;
index 027741257358831e58c0f84c9a835d325d258a60..7a9a5857e999a34fe702036edbad891a87ed9aac 100644 (file)
@@ -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;
 
index 908ae1cc7a3308c9c419068bd4bf6b02678b9cf0..10746fdf5777222fd5161795daf82f692a7fcc16 100644 (file)
@@ -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;
 
index cf80a27180c40dcaa568a517b4464e55134cd30f..8733c75b12be7f5b658a2ce3eb8674683a65681c 100644 (file)
@@ -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';