Revamping type system;
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 10 Jul 2020 04:36:39 +0000 (23:36 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 10 Jul 2020 04:36:39 +0000 (23:36 -0500)
CODE IS VERY BROKEN

13 files changed:
.vimspector.json
include/onyxastnodes.h
include/onyxparser.h
include/onyxsempass.h
include/onyxtypes.h
onyx
progs/basic.onyx [new file with mode: 0644]
src/onyxchecker.c
src/onyxmsgs.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxwasm.c

index e309f7f9bf9838e0c2649137abd51c35f11dd304..88493853a3314d6b6d7717d1fe5c86193f4b554c 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/test.onyx"],
+                "args": ["progs/basic.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index a19b4954e301bcae7f9f0371fc3954108fe60a78..ae30f3ae944ad43251a3fd1a7ddb97e85e2c0b3c 100644 (file)
@@ -24,6 +24,10 @@ typedef struct AstIntrinsicCall AstIntrinsicCall;
 typedef struct AstArgument AstArgument;
 typedef struct AstUse AstUse;
 
+typedef struct AstType AstType;
+typedef struct AstBasicType AstBasicType;
+typedef struct AstPointerType AstPointerType;
+
 typedef enum AstKind {
     Ast_Kind_Error,
     Ast_Kind_Program,
@@ -41,6 +45,9 @@ typedef enum AstKind {
     Ast_Kind_Binary_Op,
 
     Ast_Kind_Type,
+    Ast_Kind_Basic_Type,
+    Ast_Kind_Pointer_Type,
+
     Ast_Kind_Literal,
     Ast_Kind_Param,
     Ast_Kind_Argument,
@@ -92,6 +99,9 @@ typedef enum BinaryOp {
     Binary_Op_Greater_Equal = 10,
 } BinaryOp;
 
+
+// Base Nodes
+
 // NOTE: AstNode and AstTyped need to be EXACTLY the same for all
 // arguments existing in AstNode. I do this to avoid a nested
 // "inheiritance" where you would have to say node.base.base.next
@@ -108,67 +118,38 @@ struct AstTyped {
     u32 flags;
     OnyxToken *token;
     AstNode *next;
-    Type *type;
-};
-
-struct AstBinOp {
-    AstTyped base;
 
-    BinaryOp operation;
-
-    AstTyped *left, *right;
-};
-
-struct AstUnaryOp {
-    AstTyped base;
-
-    UnaryOp operation;
-
-    AstTyped *expr;
-};
-
-struct AstAssign {
-    AstNode base;
-
-    AstTyped* lval;
-    AstTyped* expr;
-};
-
-struct AstNumLit {
-    AstTyped base;
-
-    union { i32 i; i64 l; f32 f; f64 d; } value;
-};
-
-struct AstLocal {
-    AstTyped base;
-
-    AstLocal *prev_local;
-};
-
-struct AstReturn {
-    AstNode base;
-
-    AstTyped* expr;
-};
-
-struct AstLocalGroup {
-    AstNode base;
-
-    AstLocalGroup *prev_group;
-    AstLocal *last_local;
-};
-
-struct AstBlock {
-    AstNode base;
-
-    AstNode *body;
-    AstLocalGroup *locals;
+    // NOTE: 'type_node' is filled out by the parser.
+    // For a type such as '^^i32', the tree would look something like
+    //
+    //      Typed Thing -> AstPointerType -> AstPointerType -> AstNode (symbol node)
+    //
+    // The symbol node will be filled out during symbol resolution.
+    // It will end up pointing to an AstBasicType that corresponds to
+    // the underlying type.
+    //
+    // 'type' is filled out afterwards. If it is NULL, the Type* is built
+    // using the type_node. This can then be used to typecheck this node.
+    AstType *type_node;
+    Type *type;
 };
 
+// Expression Nodes
+struct AstBinOp         { AstTyped base; BinaryOp operation; AstTyped *left, *right; };
+struct AstUnaryOp       { AstTyped base; UnaryOp operation; AstTyped *expr; };
+struct AstAssign        { AstNode base;  AstTyped* lval; AstTyped* expr; };
+struct AstNumLit        { AstTyped base; union { i32 i; i64 l; f32 f; f64 d; } value; };
+struct AstLocal         { AstTyped base; AstLocal *prev_local; };
+struct AstReturn        { AstNode base;  AstTyped* expr; };
+struct AstCall          { AstTyped base; AstArgument *arguments; AstNode *callee; };
+struct AstArgument      { AstTyped base; AstTyped *value; };
+
+// Structure Nodes
+struct AstLocalGroup    { AstNode base; AstLocalGroup *prev_group; AstLocal *last_local; };
+struct AstBlock         { AstNode base; AstNode *body; AstLocalGroup *locals; };
+struct AstWhile         { AstNode base; AstTyped *cond; AstBlock *body; };
 struct AstIf {
     AstNode base;
-
     AstTyped *cond;
 
     union {
@@ -177,47 +158,20 @@ struct AstIf {
     } true_block, false_block;
 };
 
-struct AstWhile {
-    AstNode base;
-
-    AstTyped *cond;
-    AstBlock *body;
-};
-
-struct AstFunction {
-    AstTyped base;
-
-    AstBlock *body;
-    AstLocal *params;
-};
-
-struct AstForeign {
-    AstNode base;
-
-    OnyxToken *mod_token, *name_token;
-    AstNode *import;
-};
-
-struct AstGlobal {
-    AstTyped base;
-
-    AstTyped *initial_value;
-};
-
-struct AstCall {
-    AstTyped base;
-
-    AstArgument *arguments;     // NOTE: Expressions that form the actual param list
-                                    // They will be chained down using the "next" property
-                                    // unless this becomes used by something else
-    AstNode *callee;                // NOTE: Function definition node
-};
-
-struct AstArgument {
-    AstTyped base;
-
-    AstTyped *value;
-};
+// Type Nodes
+// NOTE: This node is very similar to an AstNode, just
+// without the 'next' member. This is because types
+// can't be in expressions so a 'next' thing
+// doesn't make sense.
+struct AstType          { AstKind kind; u32 flags; char* name; };
+struct AstBasicType     { AstType base; Type* type; };
+struct AstPointerType   { AstType base; AstType* elem; };
+
+// Top level nodes
+struct AstFunction      { AstTyped base; AstBlock *body; AstLocal *params; };
+struct AstForeign       { AstNode base;  OnyxToken *mod_token, *name_token; AstNode *import; };
+struct AstGlobal        { AstTyped base; AstTyped *initial_value; };
+struct AstUse           { AstNode base;  OnyxToken *filename; };
 
 typedef enum OnyxIntrinsic {
     ONYX_INTRINSIC_UNDEFINED,
@@ -279,16 +233,29 @@ struct AstIntrinsicCall {
     OnyxIntrinsic intrinsic;
 };
 
-struct AstUse {
-    AstNode base;
-
-    OnyxToken *filename;
-};
-
 typedef struct OnyxProgram {
     bh_arr(AstGlobal *) globals;
     bh_arr(AstFunction *) functions;
     bh_arr(AstForeign *) foreigns;
 } OnyxProgram;
 
+
+
+
+
+// NOTE: Basic internal types constructed in the parser
+extern AstBasicType basic_type_void;
+extern AstBasicType basic_type_bool;
+extern AstBasicType basic_type_i8;
+extern AstBasicType basic_type_u8;
+extern AstBasicType basic_type_i16;
+extern AstBasicType basic_type_u16;
+extern AstBasicType basic_type_i32;
+extern AstBasicType basic_type_u32;
+extern AstBasicType basic_type_i64;
+extern AstBasicType basic_type_u64;
+extern AstBasicType basic_type_f32;
+extern AstBasicType basic_type_f64;
+extern AstBasicType basic_type_rawptr;
+
 #endif // #ifndef ONYXASTNODES_H
index 98c67d437f86dfc71ae2f9676c37cd047bb2c9bf..fbf30cbbf51d1cb51db9cf48f264b9ea87cbffcf 100644 (file)
@@ -12,9 +12,6 @@ typedef struct OnyxParser {
     OnyxToken *prev_token;
     OnyxToken *curr_token;
 
-    // NOTE: Identifiers currently is only used to resolve type names
-    // at parse time, since these are the only symbols we know.
-    bh_table(AstNode *) identifiers;
     OnyxMessages *msgs;
 
     bh_allocator allocator;
index 287c4b33b640dec84c3c54b005efa7461856d929..138ef8e09580e8f7277776cc5efd593a8375b4a6 100644 (file)
@@ -22,7 +22,7 @@ typedef struct OnyxSemPassState {
     AstLocalGroup* curr_local_group;
 
     // NOTE: Used in type checking phase
-    TypeInfo* expected_return_type;
+    Type* expected_return_type;
 
     // NOTE: All symbols a given point that we can resolve
     bh_table(SemPassSymbol *) symbols;
index 5a50ba4bc5fa425134e69ad24ffbe003557421bb..5954d375c4db3de328316fcd05d5124e39ba8bde 100644 (file)
@@ -48,7 +48,7 @@ typedef struct Type Type;
 
 #define TYPE_KINDS \
     TYPE_KIND(Basic, TypeBasic)                       \
-    TYPE_KIND(Pointer, struct { Type *elem; })
+    TYPE_KIND(Pointer, struct { TypeBasic base; Type *elem; })
 
 typedef enum TypeKind {
     Type_Kind_Invalid,
@@ -82,5 +82,8 @@ struct Type {
 
 extern Type basic_types[];
 
+struct AstType;
+b32 types_are_compatible(Type* t1, Type* t2);
+Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node);
 
 #endif // #ifndef ONYX_TYPES
diff --git a/onyx b/onyx
index 6d1375199e08677a71833fbb674e66d6bfc52d42..25b0e01d5c1b2fbdd99e8007198a5774e4adb6c1 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/progs/basic.onyx b/progs/basic.onyx
new file mode 100644 (file)
index 0000000..3d3f158
--- /dev/null
@@ -0,0 +1,9 @@
+use "progs/intrinsics"
+
+test :: proc (a: bool) -> i32 {
+    return 0;
+}
+
+export main :: proc {
+    a : i32 = 0;
+}
index c7d0fcd7483583ea9bd438846d38b512c0774724..38b9bac4c4fd26e01c0fcf8ae7653634377ee2f9 100644 (file)
@@ -10,6 +10,7 @@ static void check_return(OnyxSemPassState* state, AstReturn* retnode);
 static void check_if(OnyxSemPassState* state, AstIf* ifnode);
 static void check_while(OnyxSemPassState* state, AstWhile* whilenode);
 static void check_call(OnyxSemPassState* state, AstCall* call);
+static void check_binaryop(OnyxSemPassState* state, AstBinaryOp* binop);
 static void check_expression(OnyxSemPassState* state, AstTyped* expr);
 static void check_global(OnyxSemPassState* state, AstGlobal* global);
 
@@ -22,7 +23,11 @@ static void check_assignment(OnyxSemPassState* state, AstAssign* assign) {
         return;
     }
 
-    if ((assign->lval->flags & Ast_Flag_Const) != 0 && assign->lval->type->is_known) {
+    if (assign->lval->type == NULL) {
+        assign->lval->type = type_build_from_ast(state->node_allocator, assign->lval->type_node);
+    }
+
+    if ((assign->lval->flags & Ast_Flag_Const) != 0 && assign->lval->type != NULL) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_ASSIGN_CONST,
                 assign->base.token->pos,
@@ -40,14 +45,14 @@ static void check_assignment(OnyxSemPassState* state, AstAssign* assign) {
 
     check_expression(state, assign->expr);
 
-    if (!assign->lval->type->is_known) {
+    if (assign->lval->type == NULL) {
         assign->lval->type = assign->expr->type;
     } else {
-        if (assign->lval->type != assign->expr->type) {
+        if (!types_are_compatible(assign->lval->type, assign->expr->type)) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH,
                     assign->base.token->pos,
-                    assign->lval->type->name, assign->expr->type->name);
+                    "TEMP", "TEMP");
             return;
         }
     }
@@ -57,14 +62,14 @@ static void check_return(OnyxSemPassState* state, AstReturn* retnode) {
     if (retnode->expr) {
         check_expression(state, retnode->expr);
 
-        if (retnode->expr->type != state->expected_return_type) {
+        if (!types_are_compatible(retnode->expr->type, state->expected_return_type)) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_FUNCTION_RETURN_MISMATCH,
                     retnode->expr->token->pos,
-                    retnode->expr->type->name, state->expected_return_type->name);
+                    "TEMP", "TEMP");
         }
     } else {
-        if (state->expected_return_type->size > 0) {
+        if (state->expected_return_type->Basic.size > 0) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
                     retnode->base.token->pos,
@@ -75,7 +80,10 @@ static void check_return(OnyxSemPassState* state, AstReturn* retnode) {
 
 static void check_if(OnyxSemPassState* state, AstIf* ifnode) {
     check_expression(state, ifnode->cond);
-    if (ifnode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
+
+    if (ifnode->cond->type->kind != Type_Kind_Basic
+            || ifnode->cond->type->Basic.kind != Basic_Kind_Bool) {
+
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
                 ifnode->cond->token->pos,
@@ -83,13 +91,16 @@ static void check_if(OnyxSemPassState* state, AstIf* ifnode) {
         return;
     }
 
-    if (ifnode->true_block.as_if) check_statement(state,  (AstNode *) ifnode->true_block.as_block);
+    if (ifnode->true_block.as_if)  check_statement(state, (AstNode *) ifnode->true_block.as_block);
     if (ifnode->false_block.as_if) check_statement(state, (AstNode *) ifnode->false_block.as_block);
 }
 
 static void check_while(OnyxSemPassState* state, AstWhile* whilenode) {
     check_expression(state, whilenode->cond);
-    if (whilenode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
+
+    if (whilenode->cond->type->kind != Type_Kind_Basic
+            || whilenode->cond->type->Basic.kind != Basic_Kind_Bool) {
+
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
                 whilenode->cond->token->pos,
@@ -182,6 +193,9 @@ static void 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;
 
     AstLocal* formal_param = callee->params;
@@ -191,13 +205,17 @@ static void check_call(OnyxSemPassState* state, AstCall* call) {
     while (formal_param != NULL && actual_param != NULL) {
         check_expression(state, (AstTyped *) actual_param);
 
-        if (formal_param->base.type != actual_param->base.type) {
+        if (formal_param->base.type == NULL) {
+            formal_param->base.type = type_build_from_ast(state->node_allocator, formal_param->base.type_node);
+        }
+
+        if (!types_are_compatible(formal_param->base.type, actual_param->base.type)) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_FUNCTION_PARAM_TYPE_MISMATCH,
                     actual_param->value->token->pos,
                     callee->base.token->text, callee->base.token->length,
-                    formal_param->base.type->name, arg_pos,
-                    actual_param->base.type->name);
+                    "TEMP", arg_pos,
+                    "TEMP");
             return;
         }
 
@@ -223,46 +241,59 @@ static void check_call(OnyxSemPassState* state, AstCall* call) {
     }
 }
 
-static void check_expression(OnyxSemPassState* state, AstTyped* expr) {
-    switch (expr->kind) {
-        case Ast_Kind_Binary_Op:
-            expr->type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
+static void check_binaryop(OnyxSemPassState* state, AstBinaryOp* binop) {
+    check_expression(state, binop->left);
+    check_expression(state, binop->right);
 
-            check_expression(state, ((AstBinaryOp *) expr)->left);
-            check_expression(state, ((AstBinaryOp *) expr)->right);
+    if (binop->left->type == NULL) {
+        onyx_message_add(state->msgs,
+                ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
+                binop->base.token->pos,
+                NULL, 0);
+        return;
+    }
 
-            if (((AstBinaryOp *) expr)->left->type == NULL) {
-                onyx_message_add(state->msgs,
-                        ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
-                        expr->token->pos,
-                        NULL, 0);
-                return;
-            }
+    if (binop->right->type == NULL) {
+        onyx_message_add(state->msgs,
+                ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
+                binop->base.token->pos,
+                NULL, 0);
+        return;
+    }
 
-            if (((AstBinaryOp *) expr)->right->type == NULL) {
-                onyx_message_add(state->msgs,
-                        ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
-                        expr->token->pos,
-                        NULL, 0);
-                return;
-            }
+    if (binop->left->type->kind == Type_Kind_Pointer
+            || binop->right->type->kind == Type_Kind_Pointer) {
+        onyx_message_add(state->msgs,
+                ONYX_MESSAGE_TYPE_LITERAL,
+                binop->base.token->pos,
+                "binary operations are not supported for pointers (yet).");
+        return;
+    }
 
-            if (((AstBinaryOp *) expr)->left->type != ((AstBinaryOp *) expr)->right->type) {
-                onyx_message_add(state->msgs,
-                        ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
-                        expr->token->pos,
-                        ((AstBinaryOp *) expr)->left->type->name,
-                        ((AstBinaryOp *) expr)->right->type->name);
-                return;
-            }
+    if (!types_are_compatible(binop->left->type, binop->right->type)) {
+        onyx_message_add(state->msgs,
+                ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
+                binop->base.token->pos,
+                "TEMP", "TEMP");
+        return;
+    }
 
-            if (((AstBinaryOp *) expr)->operation >= Binary_Op_Equal
-                    && ((AstBinaryOp *) expr)->operation <= Binary_Op_Greater_Equal) {
-                expr->type = &builtin_types[TYPE_INFO_KIND_BOOL];
-            } else {
-                expr->type = ((AstBinaryOp *) expr)->left->type;
-            }
+    if (binop->operation >= Binary_Op_Equal
+            && binop->operation <= Binary_Op_Greater_Equal) {
+        binop->base.type = &basic_types[Basic_Kind_Bool];
+    } else {
+        binop->base.type = binop->left->type;
+    }
+}
 
+static void check_expression(OnyxSemPassState* state, AstTyped* expr) {
+    if (expr->type == NULL) {
+        expr->type = type_build_from_ast(state->node_allocator, expr->type_node);
+    }
+
+    switch (expr->kind) {
+        case Ast_Kind_Binary_Op:
+            check_binaryop(state, (AstBinaryOp *) expr);
             break;
 
         case Ast_Kind_Unary_Op:
@@ -289,7 +320,7 @@ static void check_expression(OnyxSemPassState* state, AstTyped* expr) {
 
         case Ast_Kind_Local:
         case Ast_Kind_Param:
-            if (!expr->type->is_known) {
+            if (expr->type == NULL) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_LITERAL,
                         expr->token->pos,
@@ -298,7 +329,7 @@ static void check_expression(OnyxSemPassState* state, AstTyped* expr) {
             break;
 
         case Ast_Kind_Global:
-            if (!expr->type->is_known) {
+            if (expr->type == NULL) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_LITERAL,
                         expr->token->pos,
@@ -314,7 +345,7 @@ static void check_expression(OnyxSemPassState* state, AstTyped* expr) {
         case Ast_Kind_Literal:
             // NOTE: Literal types should have been decided
             // in the parser (for now).
-            assert(expr->type->is_known);
+            assert(expr->type != NULL);
             break;
 
         default:
@@ -327,13 +358,17 @@ static void check_global(OnyxSemPassState* state, AstGlobal* global) {
     if (global->initial_value) {
         check_expression(state, global->initial_value);
 
-        if (global->base.type->is_known) {
-            if (global->base.type != global->initial_value->type) {
+        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,
-                        global->base.type->name, global->initial_value->type->name);
+                        "TEMP", "TEMP");
                 return;
             }
         } else {
@@ -342,7 +377,7 @@ static void check_global(OnyxSemPassState* state, AstGlobal* global) {
         }
 
     } else {
-        if (!global->base.type || !global->base.type->is_known) {
+        if (global->base.type == NULL) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
                     global->base.token->pos,
@@ -375,7 +410,7 @@ static void check_block(OnyxSemPassState* state, AstBlock* block) {
     check_statement_chain(state, block->body);
 
     forll(AstLocal, local, block->locals->last_local, prev_local) {
-        if (!local->base.type->is_known) {
+        if (local->base.type == NULL) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
                     local->base.token->pos,
@@ -387,7 +422,11 @@ static void check_block(OnyxSemPassState* state, AstBlock* block) {
 
 static void check_function(OnyxSemPassState* state, AstFunction* func) {
     for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->base.next) {
-        if (!param->base.type->is_known) {
+        if (param->base.type == NULL) {
+            param->base.type = type_build_from_ast(state->node_allocator, param->base.type_node);
+        }
+
+        if (param->base.type == NULL) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
                     param->base.token->pos,
@@ -395,7 +434,7 @@ static void check_function(OnyxSemPassState* state, AstFunction* func) {
             return;
         }
 
-        if (param->base.type->size == 0) {
+        if (param->base.type->Basic.size == 0) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
                     param->base.token->pos,
@@ -404,6 +443,10 @@ static void check_function(OnyxSemPassState* state, AstFunction* func) {
         }
     }
 
+    if (func->base.type == NULL) {
+        func->base.type = type_build_from_ast(state->node_allocator, func->base.type_node);
+    }
+
     state->expected_return_type = func->base.type;
     if (func->body) {
         check_block(state, func->body);
index 4ef2848c7597dd814ca6978186d6d09af18cc543..949adcf15754301c8946aca3b6b3880d889a5759 100644 (file)
@@ -63,7 +63,7 @@ static void print_detailed_message(OnyxMessage* msg, bh_file_contents* fc) {
 
 void onyx_message_print(OnyxMessages* msgs) {
     OnyxMessage* msg = msgs->first;
-    i32 msg_count = 3;
+    i32 msg_count = 1000;
 
     while (msg && msg_count-- > 0) {
         if (msg->pos.filename) {
index 0f5fb536dab083ae2aa6fef874ed7d132c4fe6e0..3356c981eed69f19a8360f55216eae018ac86aae 100644 (file)
@@ -6,27 +6,22 @@
 // NOTE: The one weird define you need to know before read the code below
 #define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind)
 
-struct TypeInfo builtin_types[] = {
-    { TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
-    { TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
-
-    { TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
-
-    { TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
-    { TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
-
-    { TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
-    { TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
-
-    { TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
-    { TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
-    { TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
-
-    { 0xffffffff } // Sentinel
-};
-
 static AstNode error_node = { Ast_Kind_Error, 0, NULL, NULL };
 
+AstBasicType basic_type_void   = { { Ast_Kind_Basic_Type, 0, "void"   }, &basic_types[Basic_Kind_Void]  };
+AstBasicType basic_type_bool   = { { Ast_Kind_Basic_Type, 0, "bool"   }, &basic_types[Basic_Kind_Bool]  };
+AstBasicType basic_type_i8     = { { Ast_Kind_Basic_Type, 0, "i8"     }, &basic_types[Basic_Kind_I8]    };
+AstBasicType basic_type_u8     = { { Ast_Kind_Basic_Type, 0, "u8"     }, &basic_types[Basic_Kind_U8]    };
+AstBasicType basic_type_i16    = { { Ast_Kind_Basic_Type, 0, "i16"    }, &basic_types[Basic_Kind_I16]   };
+AstBasicType basic_type_u16    = { { Ast_Kind_Basic_Type, 0, "u16"    }, &basic_types[Basic_Kind_U16]   };
+AstBasicType basic_type_i32    = { { Ast_Kind_Basic_Type, 0, "i32"    }, &basic_types[Basic_Kind_I32]   };
+AstBasicType basic_type_u32    = { { Ast_Kind_Basic_Type, 0, "u32"    }, &basic_types[Basic_Kind_U32]   };
+AstBasicType basic_type_i64    = { { Ast_Kind_Basic_Type, 0, "i64"    }, &basic_types[Basic_Kind_I64]   };
+AstBasicType basic_type_u64    = { { Ast_Kind_Basic_Type, 0, "u64"    }, &basic_types[Basic_Kind_U64]   };
+AstBasicType basic_type_f32    = { { Ast_Kind_Basic_Type, 0, "f32"    }, &basic_types[Basic_Kind_F32]   };
+AstBasicType basic_type_f64    = { { Ast_Kind_Basic_Type, 0, "f64"    }, &basic_types[Basic_Kind_F64]   };
+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);
@@ -41,7 +36,7 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret);
 static AstReturn* parse_return_statement(OnyxParser* parser);
 static AstBlock* parse_block(OnyxParser* parser);
 static AstNode* parse_statement(OnyxParser* parser);
-static AstNode* parse_type(OnyxParser* parser);
+static AstType* parse_type(OnyxParser* parser);
 static AstLocal* parse_function_params(OnyxParser* parser);
 static AstFunction* parse_function_definition(OnyxParser* parser);
 static AstNode* parse_top_level_statement(OnyxParser* parser);
@@ -94,33 +89,32 @@ static AstNumLit* parse_numeric_literal(OnyxParser* parser) {
     lit_node->base.flags |= Ast_Flag_Comptime;
     lit_node->value.l = 0ll;
 
+    AstType* type;
     onyx_token_null_toggle(lit_node->base.token);
-
-    TypeInfo* type;
     char* tok = lit_node->base.token->text;
 
     // NOTE: charset_contains() behaves more like string_contains()
     // so I'm using it in this case
     if (charset_contains(tok, '.')) {
         if (tok[lit_node->base.token->length - 1] == 'f') {
-            type = &builtin_types[TYPE_INFO_KIND_FLOAT32];
+            type = (AstType *) &basic_type_f32;
             lit_node->value.f = strtof(tok, NULL);
         } else {
-            type = &builtin_types[TYPE_INFO_KIND_FLOAT64];
+            type = (AstType *) &basic_type_f64;
             lit_node->value.d = strtod(tok, NULL);
         }
     } else {
         i64 value = strtoll(tok, NULL, 0);
         if (bh_abs(value) < ((u64) 1 << 32)) {
-            type = &builtin_types[TYPE_INFO_KIND_INT32];
+            type = (AstType *) &basic_type_i32;
         } else {
-            type = &builtin_types[TYPE_INFO_KIND_INT64];
+            type = (AstType *) &basic_type_i64;
         }
 
         lit_node->value.l = value;
     }
 
-    lit_node->base.type = type;
+    lit_node->base.type_node = type;
     onyx_token_null_toggle(lit_node->base.token);
     return lit_node;
 }
@@ -209,7 +203,7 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         case Token_Type_Literal_True:
             {
                 AstNumLit* bool_node = make_node(AstNumLit, Ast_Kind_Literal);
-                bool_node->base.type = &builtin_types[TYPE_INFO_KIND_BOOL];
+                bool_node->base.type_node = (AstType *) &basic_type_i8;
                 bool_node->base.token = expect(parser, Token_Type_Literal_True);
                 bool_node->value.i = 1;
                 retval = (AstTyped *) bool_node;
@@ -219,7 +213,7 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         case Token_Type_Literal_False:
             {
                 AstNumLit* bool_node = make_node(AstNumLit, Ast_Kind_Literal);
-                bool_node->base.type = &builtin_types[TYPE_INFO_KIND_BOOL];
+                bool_node->base.type_node = (AstType *) &basic_type_i8;
                 bool_node->base.token = expect(parser, Token_Type_Literal_False);
                 bool_node->value.i = 0;
                 retval = (AstTyped *) bool_node;
@@ -238,7 +232,7 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         parser_next_token(parser);
 
         AstUnaryOp* cast_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op);
-        cast_node->base.type = parse_type(parser);
+        cast_node->base.type_node = parse_type(parser);
         cast_node->operation = Unary_Op_Cast;
         cast_node->expr = retval;
         retval = (AstTyped *) cast_node;
@@ -398,16 +392,16 @@ static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) {
         case ':':
             {
                 parser_next_token(parser);
-                TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
+                AstType* type_node = NULL;
 
                 // NOTE: var: type
                 if (parser->curr_token->type == Token_Type_Symbol) {
-                    type = parse_type(parser);
+                    type_node = parse_type(parser);
                 }
 
                 AstLocal* local = make_node(AstLocal, Ast_Kind_Local);
                 local->base.token = symbol;
-                local->base.type = type;
+                local->base.type_node = type_node;
                 local->base.flags |= Ast_Flag_Lval; // NOTE: DELETE
                 *ret = (AstNode *) local;
 
@@ -621,26 +615,40 @@ static AstBlock* parse_block(OnyxParser* parser) {
     return block;
 }
 
-static TypeInfo* parse_type(OnyxParser* parser) {
-    TypeInfo* type_info = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
+static AstType* parse_type(OnyxParser* parser) {
+    AstType* root = NULL;
+    AstType** next_insertion = &root;
 
-    OnyxToken* symbol = expect(parser, Token_Type_Symbol);
-    if (symbol == NULL) return type_info;
+    while (1) {
+        if (parser->curr_token->type == '^') {
+            AstPointerType* new = make_node(AstPointerType, Ast_Kind_Pointer_Type);
+            *next_insertion = (AstType *) new;
+            next_insertion = &new->elem;
+        }
 
-    onyx_token_null_toggle(symbol);
+        else if (parser->curr_token->type == Token_Type_Symbol) {
+            AstNode* symbol_node = make_node(AstNode, Ast_Kind_Symbol);
+            symbol_node->token = expect(parser, Token_Type_Symbol);
+            *next_insertion = (AstType *) symbol_node;
+            next_insertion = NULL;
+        }
 
-    if (!bh_table_has(AstNode*, parser->identifiers, symbol->text)) {
-        onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->text);
-    } else {
-        AstTyped* type_info_node = bh_table_get(AstTyped*, parser->identifiers, symbol->text);
+        else {
+            onyx_token_null_toggle(parser->curr_token);
+            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);
 
-        if (type_info_node->kind == Ast_Kind_Type) {
-            type_info = type_info_node->type;
+            parser_next_token(parser);
+            break;
         }
+
+        if (next_insertion == NULL) break;
     }
 
-    onyx_token_null_toggle(symbol);
-    return type_info;
+    return root;
 }
 
 static AstLocal* parse_function_params(OnyxParser* parser) {
@@ -668,7 +676,7 @@ static AstLocal* parse_function_params(OnyxParser* parser) {
         curr_param = make_node(AstLocal, Ast_Kind_Param);
         curr_param->base.token = symbol;
         curr_param->base.flags |= Ast_Flag_Const;
-        curr_param->base.type = parse_type(parser);
+        curr_param->base.type_node = parse_type(parser);
 
         if (first_param == NULL) first_param = curr_param;
 
@@ -727,10 +735,10 @@ static AstFunction* parse_function_definition(OnyxParser* parser) {
     if (parser->curr_token->type == Token_Type_Right_Arrow) {
         expect(parser, Token_Type_Right_Arrow);
 
-        TypeInfo* return_type = parse_type(parser);
-        func_def->base.type = return_type;
+        AstType* return_type = parse_type(parser);
+        func_def->base.type_node = return_type;
     } else {
-        func_def->base.type = &builtin_types[TYPE_INFO_KIND_VOID];
+        func_def->base.type_node = (AstType *) &basic_type_void;
     }
 
     func_def->body = parse_block(parser);
@@ -749,10 +757,10 @@ static AstNode* parse_foreign(OnyxParser* parser) {
         foreign->import = (AstNode *) parse_function_definition(parser);
 
     } else {
-        TypeInfo* type = parse_type(parser);
+        AstType* type = parse_type(parser);
 
         AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global);
-        global->base.type = type;
+        global->base.type_node = type;
         global->base.flags |= Ast_Flag_Lval;
 
         foreign->import = (AstNode *) global;
@@ -776,7 +784,6 @@ static AstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
         // Global constant with initial value
         AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global);
         global->initial_value = parse_expression(parser);
-        global->base.type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
         global->base.flags |= Ast_Flag_Const;
         global->base.flags |= Ast_Flag_Lval;
         global->base.flags |= Ast_Flag_Comptime;
@@ -820,7 +827,7 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
 
                 expect(parser, ':');
 
-                TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
+                AstType* type = NULL;
 
                 if (parser->curr_token->type == Token_Type_Symbol) {
                     type = parse_type(parser);
@@ -832,7 +839,7 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
                     AstNode* node = parse_top_level_constant_symbol(parser);
 
                     if (node->kind == Ast_Kind_Global) {
-                        ((AstGlobal *) node)->base.type = type;
+                        ((AstGlobal *) node)->base.type_node = type;
                     }
 
                     if (node->kind == Ast_Kind_Foreign) {
@@ -851,7 +858,7 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
                     global->base.token = symbol;
                     global->base.flags |= Ast_Flag_Lval;
                     global->initial_value = parse_expression(parser);
-                    global->base.type = type;
+                    global->base.type_node = type;
 
                     return (AstNode *) global;
 
@@ -891,16 +898,6 @@ void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstKind kind) {
 OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs) {
     OnyxParser parser;
 
-    bh_table_init(bh_heap_allocator(), parser.identifiers, 61);
-
-    TypeInfo* it = &builtin_types[0];
-    while (it->kind != 0xffffffff) {
-        AstTyped* tmp = onyx_ast_node_new(alloc, sizeof(AstTyped), Ast_Kind_Type);
-        tmp->type = it;
-        bh_table_put(AstNode*, parser.identifiers, (char *)it->name, tmp);
-        it++;
-    }
-
     parser.allocator = alloc;
     parser.tokenizer = tokenizer;
     parser.curr_token = tokenizer->tokens;
@@ -909,7 +906,6 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, Onyx
 }
 
 void onyx_parser_free(OnyxParser* parser) {
-    bh_table_free(parser->identifiers);
 }
 
 bh_arr(AstNode *) onyx_parse(OnyxParser *parser) {
index e3a19b5dccda7ead862eab4961d859cf926ed110..06e430443a65e2178a04758a60a74e55456b77ad 100644 (file)
@@ -2,6 +2,7 @@
 #include "onyxsempass.h"
 
 static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol);
+static void symbol_basic_type_introduce(OnyxSemPassState* state, AstBasicType* basic_type);
 static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol);
 static void symbol_remove(OnyxSemPassState* state, AstNode* symbol);
 static AstNode* symbol_resolve(OnyxSemPassState* state, AstNode* symbol);
@@ -9,7 +10,7 @@ static void local_group_enter(OnyxSemPassState* state, AstLocalGroup* local_grou
 static void local_group_leave(OnyxSemPassState* state);
 static void symres_local(OnyxSemPassState* state, AstLocal** local);
 static void symres_call(OnyxSemPassState* state, AstCall* call);
-static void symres_expression(OnyxSemPassState* state, AstNode** expr);
+static void symres_expression(OnyxSemPassState* state, AstTyped** expr);
 static void symres_assignment(OnyxSemPassState* state, AstAssign* assign);
 static void symres_return(OnyxSemPassState* state, AstReturn* ret);
 static void symres_if(OnyxSemPassState* state, AstIf* ifnode);
@@ -18,6 +19,7 @@ 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 symbol_introduce(OnyxSemPassState* state, AstNode* symbol) {
     onyx_token_null_toggle(symbol->token);
@@ -89,6 +91,13 @@ static void local_group_leave(OnyxSemPassState* state) {
     state->curr_local_group = state->curr_local_group->prev_group;
 }
 
+static void symbol_basic_type_introduce(OnyxSemPassState* state, AstBasicType* basic_type) {
+    SemPassSymbol* sp_sym = bh_alloc_item(state->allocator, SemPassSymbol);
+    sp_sym->node = (AstNode *) basic_type;
+    sp_sym->shadowed = NULL;
+    bh_table_put(SemPassSymbol *, state->symbols, basic_type->base.name, sp_sym);
+}
+
 static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol) {
     onyx_token_null_toggle(symbol->token);
 
@@ -113,7 +122,27 @@ static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol) {
     return 1;
 }
 
+static AstType* symres_type(OnyxSemPassState* state, AstType* type) {
+    if (type == NULL) return NULL;
+
+    if (type->kind == Ast_Kind_Symbol) {
+        return (AstType *) symbol_resolve(state, (AstNode *) type);
+    }
+
+    // NOTE: Already resolved
+    if (type->kind == Ast_Kind_Basic_Type) return type;
+
+    if (type->kind == Ast_Kind_Pointer_Type) {
+        ((AstPointerType *) type)->elem = symres_type(state, ((AstPointerType *) type)->elem);
+        return type;
+    }
+
+    assert(("Bad type node", 0));
+    return NULL;
+}
+
 static void symres_local(OnyxSemPassState* state, AstLocal** local) {
+    (*local)->base.type_node = symres_type(state, (*local)->base.type_node);
     symbol_introduce(state, (AstNode *) *local);
 }
 
@@ -125,15 +154,23 @@ static void symres_call(OnyxSemPassState* state, AstCall* call) {
     symres_statement_chain(state, (AstNode *) call->arguments, (AstNode **) &call->arguments);
 }
 
-static void symres_expression(OnyxSemPassState* state, AstNode** expr) {
+static void symres_unaryop(OnyxSemPassState* state, AstUnaryOp** unaryop) {
+    if ((*unaryop)->operation == Unary_Op_Cast) {
+        (*unaryop)->base.type_node = symres_type(state, (*unaryop)->base.type_node);
+    }
+
+    symres_expression(state, &(*unaryop)->expr);
+}
+
+static void symres_expression(OnyxSemPassState* state, AstTyped** expr) {
     switch ((*expr)->kind) {
         case Ast_Kind_Binary_Op:
-            symres_expression(state, (AstNode **) &((AstBinaryOp *)(*expr))->left);
-            symres_expression(state, (AstNode **) &((AstBinaryOp *)(*expr))->right);
+            symres_expression(state, &((AstBinaryOp *)(*expr))->left);
+            symres_expression(state, &((AstBinaryOp *)(*expr))->right);
             break;
 
         case Ast_Kind_Unary_Op:
-            symres_expression(state, (AstNode **) &((AstUnaryOp *)(*expr))->expr);
+            symres_unaryop(state, (AstUnaryOp **) expr);
             break;
 
         case Ast_Kind_Call: symres_call(state, (AstCall *) *expr); break;
@@ -141,13 +178,15 @@ static void symres_expression(OnyxSemPassState* state, AstNode** expr) {
         case Ast_Kind_Block: symres_block(state, (AstBlock *) *expr); break;
 
         case Ast_Kind_Symbol:
-            *expr = symbol_resolve(state, *expr);
+            *expr = (AstTyped *) symbol_resolve(state, (AstNode *) *expr);
             break;
 
         // NOTE: This is a good case, since it means the symbol is already resolved
         case Ast_Kind_Local: break;
 
-        case Ast_Kind_Literal: break;
+        case Ast_Kind_Literal:
+            (*expr)->type_node = symres_type(state, (*expr)->type_node);
+            break;
 
         default:
             DEBUG_HERE;
@@ -160,16 +199,16 @@ static void symres_assignment(OnyxSemPassState* state, AstAssign* assign) {
     if (lval == NULL) return;
     assign->lval = lval;
 
-    symres_expression(state, (AstNode **) &assign->expr);
+    symres_expression(state, &assign->expr);
 }
 
 static void symres_return(OnyxSemPassState* state, AstReturn* ret) {
     if (ret->expr)
-        symres_expression(state, (AstNode **) &ret->expr);
+        symres_expression(state, &ret->expr);
 }
 
 static void symres_if(OnyxSemPassState* state, AstIf* ifnode) {
-    symres_expression(state, (AstNode **) &ifnode->cond);
+    symres_expression(state, &ifnode->cond);
     if (ifnode->true_block.as_if != NULL) {
         if (ifnode->true_block.as_if->base.kind == Ast_Kind_Block)
             symres_block(state, ifnode->true_block.as_block);
@@ -192,7 +231,7 @@ static void symres_if(OnyxSemPassState* state, AstIf* ifnode) {
 }
 
 static void symres_while(OnyxSemPassState* state, AstWhile* whilenode) {
-    symres_expression(state, (AstNode **) &whilenode->cond);
+    symres_expression(state, &whilenode->cond);
     symres_block(state, whilenode->body);
 }
 
@@ -205,7 +244,7 @@ static b32 symres_statement(OnyxSemPassState* state, AstNode* stmt) {
         case Ast_Kind_If:         symres_if(state, (AstIf *) stmt);                        return 0;
         case Ast_Kind_While:      symres_while(state, (AstWhile *) stmt);                 return 0;
         case Ast_Kind_Call:       symres_call(state, (AstCall *) stmt);                    return 0;
-        case Ast_Kind_Argument:   symres_expression(state, (AstNode **) &((AstArgument *)stmt)->value); return 0;
+        case Ast_Kind_Argument:   symres_expression(state, (AstTyped **) &((AstArgument *)stmt)->value); return 0;
         case Ast_Kind_Block:      symres_block(state, (AstBlock *) stmt);                  return 0;
 
         default: return 0;
@@ -236,9 +275,17 @@ static void symres_block(OnyxSemPassState* state, AstBlock* block) {
 
 static void symres_function(OnyxSemPassState* state, AstFunction* func) {
     for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->base.next) {
+        param->base.type_node = symres_type(state, param->base.type_node);
+
         symbol_introduce(state, (AstNode *) param);
     }
 
+    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);
+        }
+    }
+
     symres_block(state, func->body);
 
     for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->base.next) {
@@ -248,7 +295,22 @@ static void symres_function(OnyxSemPassState* state, AstFunction* func) {
 
 void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) {
 
-    // NOTE: First, introduce all global symbols
+    // NOTE: Add types to global scope
+    symbol_basic_type_introduce(state, &basic_type_void);
+    symbol_basic_type_introduce(state, &basic_type_bool);
+    symbol_basic_type_introduce(state, &basic_type_i8);
+    symbol_basic_type_introduce(state, &basic_type_u8);
+    symbol_basic_type_introduce(state, &basic_type_i16);
+    symbol_basic_type_introduce(state, &basic_type_u16);
+    symbol_basic_type_introduce(state, &basic_type_i32);
+    symbol_basic_type_introduce(state, &basic_type_u32);
+    symbol_basic_type_introduce(state, &basic_type_i64);
+    symbol_basic_type_introduce(state, &basic_type_u64);
+    symbol_basic_type_introduce(state, &basic_type_f32);
+    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;
 
index eee00a7dca193be7c775803ad71d51751cde3880..f70a271087cf2daf40c3be2930646ad73f3a051d 100644 (file)
@@ -1,5 +1,7 @@
 #include "onyxtypes.h"
+#include "onyxastnodes.h"
 
+// NOTE: These have to be in the same order as Basiuc
 Type basic_types[] = {
     { Type_Kind_Basic, { Basic_Kind_Void,                    0,                       0, "void"   } },
 
@@ -47,3 +49,26 @@ b32 types_are_compatible(Type* t1, Type* t2) {
 
     return 0;
 }
+
+Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
+    if (type_node == NULL) return NULL;
+
+    switch (type_node->kind) {
+        case Ast_Kind_Pointer_Type: {
+            TypePointer* ptr_type = bh_alloc_item(alloc, TypePointer);
+
+            ptr_type->base.flags |= Basic_Flag_Pointer;
+            ptr_type->base.size = 4;
+            ptr_type->elem = type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem);
+
+            return (Type *) ptr_type;
+        }
+
+        case Ast_Kind_Basic_Type:
+            return ((AstBasicType *) type_node)->type;
+
+        default:
+            assert(("Node is not a type node", 0));
+            return NULL;
+    }
+}
index aaee1bbb058b612183c1ece1782f09f9a63eb2f3..9eb365a0fa787f3f3635092d2fd072bae3eb5b19 100644 (file)
@@ -195,15 +195,23 @@ static const char* wi_string(WasmInstructionType wit) {
     }
 }
 
-static WasmType onyx_type_to_wasm_type(TypeInfo* type) {
-    if (type->is_bool) return WASM_TYPE_INT32;
-    else if (type->is_int) {
-        if (type->size == 4) return WASM_TYPE_INT32;
-        if (type->size == 8) return WASM_TYPE_INT64;
+static WasmType onyx_type_to_wasm_type(Type* type) {
+    if (type->kind == Type_Kind_Pointer) {
+        return WASM_TYPE_INT32;
     }
-    else if (type->is_float) {
-        if (type->size == 4) return WASM_TYPE_FLOAT32;
-        if (type->size == 8) return WASM_TYPE_FLOAT64;
+
+    if (type->kind == Type_Kind_Basic) {
+        TypeBasic* basic = &type->Basic;
+        if (basic->flags & Basic_Flag_Boolean) return WASM_TYPE_INT32;
+        if (basic->flags & Basic_Flag_Integer) {
+            if (basic->size <= 4) return WASM_TYPE_INT32;
+            if (basic->size == 8) return WASM_TYPE_INT64;
+        }
+        if (basic->flags & Basic_Flag_Float) {
+            if (basic->size <= 4) return WASM_TYPE_FLOAT32;
+            if (basic->size == 8) return WASM_TYPE_FLOAT64;;
+        }
+        if (basic->size == 0) return WASM_TYPE_VOID;
     }
 
     return WASM_TYPE_VOID;
@@ -457,7 +465,7 @@ static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, A
     // Unsigned instructions are always right after
     // the signed equivalent
     if (is_sign_significant) {
-        if (binop->left->type->is_unsigned) {
+        if (binop->left->type->Basic.flags & Basic_Flag_Unsigned) {
             binop_instr = (WasmInstructionType) ((i32) binop_instr + 1);
         }
     }
@@ -476,25 +484,29 @@ static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode,
     switch (unop->operation) {
         case Unary_Op_Negate:
             {
-                TypeInfoKind type_kind = unop->base.type->kind;
+                TypeBasic* type = &unop->base.type->Basic;
 
-                if (type_kind == TYPE_INFO_KIND_INT32) {
+                if (type->kind == Basic_Kind_I32
+                        || type->kind == Basic_Kind_I16
+                        || type->kind == Basic_Kind_I8) {
                     WID(WI_I32_CONST, 0x00);
                     compile_expression(mod, &code, unop->expr);
                     WI(WI_I32_SUB);
 
-                } else if (type_kind == TYPE_INFO_KIND_INT64) {
+                }
+                else if (type->kind == Basic_Kind_I64) {
                     WID(WI_I64_CONST, 0x00);
                     compile_expression(mod, &code, unop->expr);
                     WI(WI_I64_SUB);
 
-                } else {
+                }
+                else {
                     compile_expression(mod, &code, unop->expr);
 
-                    if (type_kind == TYPE_INFO_KIND_FLOAT32)
+                    if (type->kind == Basic_Kind_F32)
                         WI(WI_F32_NEG);
 
-                    if (type_kind == TYPE_INFO_KIND_FLOAT64)
+                    if (type->kind == Basic_Kind_F64)
                         WI(WI_F64_NEG);
                 }
 
@@ -687,28 +699,34 @@ static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, As
 
     compile_expression(mod, &code, cast->expr);
 
-    TypeInfo* from = cast->expr->type;
-    TypeInfo* to = cast->base.type;
+    Type* from = cast->expr->type;
+    Type* to = cast->base.type;
 
     i32 fromidx = 0, toidx = 0;
-    if (from->is_int) {
-        if (from->size == 4 && !from->is_unsigned) fromidx = 0;
-        else if (from->size == 4 && from->is_unsigned) fromidx = 1;
-        else if (from->size == 8 && !from->is_unsigned) fromidx = 2;
-        else if (from->size == 8 && from->is_unsigned) fromidx = 3;
-    } else if (from->is_float) {
-        if (from->size == 4) fromidx = 4;
-        else if (from->size == 8) fromidx = 5;
+    if (from->Basic.flags & Basic_Flag_Numeric) {
+        b32 unsign = (from->Basic.flags & Basic_Flag_Unsigned) != 0;
+
+        if (from->Basic.size == 4 && !unsign) fromidx = 0;
+        else if (from->Basic.size == 4 && unsign) fromidx = 1;
+        else if (from->Basic.size == 8 && !unsign) fromidx = 2;
+        else if (from->Basic.size == 8 && unsign) fromidx = 3;
+    }
+    else if (from->Basic.flags & Basic_Flag_Float) {
+        if (from->Basic.size == 4) fromidx = 4;
+        else if (from->Basic.size == 8) fromidx = 5;
     }
 
-    if (to->is_int) {
-        if (to->size == 4 && !to->is_unsigned) toidx = 0;
-        else if (to->size == 4 && to->is_unsigned) toidx = 1;
-        else if (to->size == 8 && !to->is_unsigned) toidx = 2;
-        else if (to->size == 8 && to->is_unsigned) toidx = 3;
-    } else if (to->is_float) {
-        if (to->size == 4) toidx = 4;
-        else if (to->size == 8) toidx = 5;
+    if (to->Basic.flags & Basic_Flag_Numeric) {
+        b32 unsign = (to->Basic.flags & Basic_Flag_Unsigned) != 0;
+
+        if (to->Basic.size == 4 && !unsign) toidx = 0;
+        else if (to->Basic.size == 4 && unsign) toidx = 1;
+        else if (to->Basic.size == 8 && !unsign) toidx = 2;
+        else if (to->Basic.size == 8 && unsign) toidx = 3;
+    }
+    else if (to->Basic.flags & Basic_Flag_Float) {
+        if (to->Basic.size == 4) toidx = 4;
+        else if (to->Basic.size == 8) toidx = 5;
     }
 
     WasmInstructionType cast_op = cast_map[fromidx][toidx];