first class-ish types
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 23 Jun 2021 00:59:34 +0000 (19:59 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 23 Jun 2021 00:59:34 +0000 (19:59 -0500)
bin/onyx
core/type_info.onyx
include/onyxastnodes.h
include/onyxtypes.h
src/onyxbuiltins.c
src/onyxchecker.c
src/onyxtypes.c
src/onyxwasm.c
src/onyxwasm_type_table.c

index 410ed5f91f8b1cbed6a556348701ea53ba31599d..14477b46c57ff62eda8ed1cc8b8bb7a76b57326a 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index bad1026e5fe2280cd5d71ef7cc5621ee2175fa96..ea094e7e413a7e4d84e39d5411c31971d6e2da78 100644 (file)
@@ -57,6 +57,8 @@ Type_Info_Basic :: struct {
         F32X4 :: 0x13;
         F64X2 :: 0x14;
         V128  :: 0x15;
+
+        Type_Index :: 0x16;
     }
 
     basic_kind: Kind;
index 5213bcae0e8b1a3236b6b4f807aa15bc419deb48..a762abba490f6dcb27f327d02c4b0070eee1fbe2 100644 (file)
@@ -693,10 +693,12 @@ struct AstSwitch {
     u32 flags;             \
     OnyxToken* token;      \
     struct Entity* entity; \
-    char* name
+    char* name;            \
+    void* __unused;        \
+    Type* type
 struct AstType { AstType_base; };
 
-struct AstBasicType     { AstType_base; Type* type; };
+struct AstBasicType     { AstType_base; Type* basic_type; };
 struct AstPointerType   { AstType_base; AstType* elem; };
 struct AstFunctionType  { AstType_base; AstType* return_type; u64 param_count; AstType* params[]; };
 struct AstArrayType     { AstType_base; AstType* elem; AstTyped *count_expr; };
index 9bacca848ae86e6f74269717c0b48dd3a03a5dab..6113fead6291b43032ef50e5522b1e2aac328007 100644 (file)
@@ -32,6 +32,8 @@ enum BasicKind {
     Basic_Kind_F64X2,
     Basic_Kind_V128,
 
+    Basic_Kind_Type_Index,
+
     Basic_Kind_Count,
 };
 
@@ -44,8 +46,11 @@ enum BasicFlag {
 
     Basic_Flag_SIMD             = BH_BIT(5),
 
+    Basic_Flag_Type_Index       = BH_BIT(6),
+
     Basic_Flag_Numeric          = Basic_Flag_Integer | Basic_Flag_Float,
     Basic_Flag_Ordered          = Basic_Flag_Integer | Basic_Flag_Float | Basic_Flag_Pointer,
+    Basic_Flag_Equality         = Basic_Flag_Ordered | Basic_Flag_Type_Index,
     Basic_Flag_Constant_Type    = Basic_Flag_Boolean | Basic_Flag_Numeric | Basic_Flag_Pointer,
     Basic_Flag_Numeric_Ordered  = Basic_Flag_Numeric | Basic_Flag_Ordered,
 };
index 404e419911a2d2b9123ce677551294eed040adc5..745209a508e0a95c7a2622e5215aed35a0940027 100644 (file)
@@ -3,32 +3,32 @@
 #include "onyxerrors.h"
 #include "onyxutils.h"
 
-AstBasicType basic_type_void   = { Ast_Kind_Basic_Type, 0, NULL, NULL, "void"  , &basic_types[Basic_Kind_Void]  };
-AstBasicType basic_type_bool   = { Ast_Kind_Basic_Type, 0, NULL, NULL, "bool"  , &basic_types[Basic_Kind_Bool]  };
-AstBasicType basic_type_i8     = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i8"    , &basic_types[Basic_Kind_I8]    };
-AstBasicType basic_type_u8     = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u8"    , &basic_types[Basic_Kind_U8]    };
-AstBasicType basic_type_i16    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i16"   , &basic_types[Basic_Kind_I16]   };
-AstBasicType basic_type_u16    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u16"   , &basic_types[Basic_Kind_U16]   };
-AstBasicType basic_type_i32    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i32"   , &basic_types[Basic_Kind_I32]   };
-AstBasicType basic_type_u32    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u32"   , &basic_types[Basic_Kind_U32]   };
-AstBasicType basic_type_i64    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i64"   , &basic_types[Basic_Kind_I64]   };
-AstBasicType basic_type_u64    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u64"   , &basic_types[Basic_Kind_U64]   };
-AstBasicType basic_type_f32    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "f32"   , &basic_types[Basic_Kind_F32]   };
-AstBasicType basic_type_f64    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "f64"   , &basic_types[Basic_Kind_F64]   };
-AstBasicType basic_type_rawptr = { Ast_Kind_Basic_Type, 0, NULL, NULL, "rawptr", &basic_types[Basic_Kind_Rawptr] };
+AstBasicType basic_type_void   = { Ast_Kind_Basic_Type, 0, NULL, NULL, "void"  , NULL, NULL, &basic_types[Basic_Kind_Void]  };
+AstBasicType basic_type_bool   = { Ast_Kind_Basic_Type, 0, NULL, NULL, "bool"  , NULL, NULL, &basic_types[Basic_Kind_Bool]  };
+AstBasicType basic_type_i8     = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i8"    , NULL, NULL, &basic_types[Basic_Kind_I8]    };
+AstBasicType basic_type_u8     = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u8"    , NULL, NULL, &basic_types[Basic_Kind_U8]    };
+AstBasicType basic_type_i16    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i16"   , NULL, NULL, &basic_types[Basic_Kind_I16]   };
+AstBasicType basic_type_u16    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u16"   , NULL, NULL, &basic_types[Basic_Kind_U16]   };
+AstBasicType basic_type_i32    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i32"   , NULL, NULL, &basic_types[Basic_Kind_I32]   };
+AstBasicType basic_type_u32    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u32"   , NULL, NULL, &basic_types[Basic_Kind_U32]   };
+AstBasicType basic_type_i64    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "i64"   , NULL, NULL, &basic_types[Basic_Kind_I64]   };
+AstBasicType basic_type_u64    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "u64"   , NULL, NULL, &basic_types[Basic_Kind_U64]   };
+AstBasicType basic_type_f32    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "f32"   , NULL, NULL, &basic_types[Basic_Kind_F32]   };
+AstBasicType basic_type_f64    = { Ast_Kind_Basic_Type, 0, NULL, NULL, "f64"   , NULL, NULL, &basic_types[Basic_Kind_F64]   };
+AstBasicType basic_type_rawptr = { Ast_Kind_Basic_Type, 0, NULL, NULL, "rawptr", NULL, NULL, &basic_types[Basic_Kind_Rawptr] };
 
 // NOTE: Types used for numeric literals
-AstBasicType basic_type_int_unsized   = { Ast_Kind_Basic_Type, 0, NULL, NULL, "unsized_int",   &basic_types[Basic_Kind_Int_Unsized] };
-AstBasicType basic_type_float_unsized = { Ast_Kind_Basic_Type, 0, NULL, NULL, "unsized_float", &basic_types[Basic_Kind_Float_Unsized] };
+AstBasicType basic_type_int_unsized   = { Ast_Kind_Basic_Type, 0, NULL, NULL, "unsized_int",   NULL, NULL, &basic_types[Basic_Kind_Int_Unsized] };
+AstBasicType basic_type_float_unsized = { Ast_Kind_Basic_Type, 0, NULL, NULL, "unsized_float", NULL, NULL, &basic_types[Basic_Kind_Float_Unsized] };
 
 static OnyxToken simd_token = { Token_Type_Symbol, 0, "", { 0 } };
-AstBasicType basic_type_i8x16 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i8x16", &basic_types[Basic_Kind_I8X16] };
-AstBasicType basic_type_i16x8 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i16x8", &basic_types[Basic_Kind_I16X8] };
-AstBasicType basic_type_i32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i32x4", &basic_types[Basic_Kind_I32X4] };
-AstBasicType basic_type_i64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i64x2", &basic_types[Basic_Kind_I64X2] };
-AstBasicType basic_type_f32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "f32x4", &basic_types[Basic_Kind_F32X4] };
-AstBasicType basic_type_f64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "f64x2", &basic_types[Basic_Kind_F64X2] };
-AstBasicType basic_type_v128  = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "v128",  &basic_types[Basic_Kind_V128]  };
+AstBasicType basic_type_i8x16 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i8x16", NULL, NULL, &basic_types[Basic_Kind_I8X16] };
+AstBasicType basic_type_i16x8 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i16x8", NULL, NULL, &basic_types[Basic_Kind_I16X8] };
+AstBasicType basic_type_i32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i32x4", NULL, NULL, &basic_types[Basic_Kind_I32X4] };
+AstBasicType basic_type_i64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "i64x2", NULL, NULL, &basic_types[Basic_Kind_I64X2] };
+AstBasicType basic_type_f32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "f32x4", NULL, NULL, &basic_types[Basic_Kind_F32X4] };
+AstBasicType basic_type_f64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "f64x2", NULL, NULL, &basic_types[Basic_Kind_F64X2] };
+AstBasicType basic_type_v128  = { Ast_Kind_Basic_Type, 0, &simd_token, NULL, "v128",  NULL, NULL, &basic_types[Basic_Kind_V128]  };
 
 OnyxToken builtin_package_token = { Token_Type_Symbol, 7, "builtin ", { 0 } };
 
index 6f316f06b8ca57c9b5e700faa8fdfe9991f54bbd..9ff489ec08d68646ce7adf4c3e79d3900da13589 100644 (file)
@@ -747,6 +747,60 @@ CheckStatus check_binaryop_assignment(AstBinaryOp* binop, b32 assignment_is_ok)
     return Check_Success;
 }
 
+static b32 binary_op_is_allowed(BinaryOp operation, Type* type) {
+    static const u8 binop_allowed[Binary_Op_Count] = {
+        /* Add */             Basic_Flag_Numeric | Basic_Flag_Pointer,
+        /* Minus */           Basic_Flag_Numeric | Basic_Flag_Pointer,
+        /* Multiply */        Basic_Flag_Numeric,
+        /* Divide */          Basic_Flag_Numeric,
+        /* Modulus */         Basic_Flag_Integer,
+
+        /* Equal */           Basic_Flag_Equality,
+        /* Not_Equal */       Basic_Flag_Equality,
+        /* Less */            Basic_Flag_Ordered,
+        /* Less_Equal */      Basic_Flag_Ordered,
+        /* Greater */         Basic_Flag_Ordered,
+        /* Greater_Equal */   Basic_Flag_Ordered,
+
+        /* And */             Basic_Flag_Integer,
+        /* Or */              Basic_Flag_Integer,
+        /* Xor */             Basic_Flag_Integer,
+        /* Shl */             Basic_Flag_Integer,
+        /* Shr */             Basic_Flag_Integer,
+        /* Sar */             Basic_Flag_Integer,
+
+        /* Bool_And */        Basic_Flag_Boolean,
+        /* Bool_Or */         Basic_Flag_Boolean,
+
+        /* Assign_Start */    0,
+        /* Assign */          0,
+        /* Assign_Add */      0,
+        /* Assign_Minus */    0,
+        /* Assign_Multiply */ 0,
+        /* Assign_Divide */   0,
+        /* Assign_Modulus */  0,
+        /* Assign_And */      0,
+        /* Assign_Or */       0,
+        /* Assign_Xor */      0,
+        /* Assign_Shl */      0,
+        /* Assign_Shr */      0,
+        /* Assign_Sar */      0,
+        /* Assign_End */      0,
+
+        /* Pipe */            0,
+        /* Range */           0,
+    };
+
+    enum BasicFlag effective_flags = 0;
+    switch (type->kind) {
+        case Type_Kind_Basic:   effective_flags = binop->type->Basic.flags; break;
+        case Type_Kind_Pointer: effective_flags = Basic_Flag_Pointer;       break;
+        case Type_Kind_Enum:    effective_flags = Basic_Flag_Integer;       break;
+    }
+
+    return (binop_allowed[binop->operation] & effective_flags) == 0;
+}
+
 CheckStatus check_binaryop_compare(AstBinaryOp** pbinop) {
     AstBinaryOp* binop = *pbinop;
 
@@ -934,59 +988,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop, b32 assignment_is_ok) {
         }
     }
 
-    static const u8 binop_allowed[Binary_Op_Count] = {
-        /* Add */             Basic_Flag_Numeric | Basic_Flag_Pointer,
-        /* Minus */           Basic_Flag_Numeric | Basic_Flag_Pointer,
-        /* Multiply */        Basic_Flag_Numeric,
-        /* Divide */          Basic_Flag_Numeric,
-        /* Modulus */         Basic_Flag_Integer,
-
-        /* Equal */           Basic_Flag_Ordered,
-        /* Not_Equal */       Basic_Flag_Ordered,
-        /* Less */            Basic_Flag_Ordered,
-        /* Less_Equal */      Basic_Flag_Ordered,
-        /* Greater */         Basic_Flag_Ordered,
-        /* Greater_Equal */   Basic_Flag_Ordered,
-
-        /* And */             Basic_Flag_Integer,
-        /* Or */              Basic_Flag_Integer,
-        /* Xor */             Basic_Flag_Integer,
-        /* Shl */             Basic_Flag_Integer,
-        /* Shr */             Basic_Flag_Integer,
-        /* Sar */             Basic_Flag_Integer,
-
-        /* Bool_And */        Basic_Flag_Boolean,
-        /* Bool_Or */         Basic_Flag_Boolean,
-
-        /* Assign_Start */    0,
-        /* Assign */          0,
-        /* Assign_Add */      0,
-        /* Assign_Minus */    0,
-        /* Assign_Multiply */ 0,
-        /* Assign_Divide */   0,
-        /* Assign_Modulus */  0,
-        /* Assign_And */      0,
-        /* Assign_Or */       0,
-        /* Assign_Xor */      0,
-        /* Assign_Shl */      0,
-        /* Assign_Shr */      0,
-        /* Assign_Sar */      0,
-        /* Assign_End */      0,
-
-        /* Pipe */            0,
-        /* Range */           0,
-    };
-
     binop->type = binop->left->type;
-
-    enum BasicFlag effective_flags = 0;
-    switch (binop->type->kind) {
-        case Type_Kind_Basic:   effective_flags = binop->type->Basic.flags; break;
-        case Type_Kind_Pointer: effective_flags = Basic_Flag_Pointer;       break;
-        case Type_Kind_Enum:    effective_flags = Basic_Flag_Integer;       break;
-    }
-
-    if ((binop_allowed[binop->operation] & effective_flags) == 0) goto bad_binaryop;
+    if (!binary_op_is_allowed(binop->operation, binop->type)) goto bad_binaryop;
 
     // NOTE: Enum flags with '&' result in a boolean value
     if (binop->type->kind == Type_Kind_Enum && binop->type->Enum.is_flags && binop->operation == Binary_Op_And) {
@@ -1274,7 +1277,7 @@ CheckStatus check_dereference(AstDereference* deref) {
         return Check_Error;
     }
 
-    if (deref->expr->type == basic_type_rawptr.type) {
+    if (deref->expr->type == basic_type_rawptr.basic_type) {
         onyx_report_error(deref->token->pos, "Cannot dereference 'rawptr'. Cast to another pointer type first.");
         return Check_Error;
     }
@@ -1483,6 +1486,7 @@ CheckStatus check_align_of(AstAlignOf* ao) {
 CheckStatus check_expression(AstTyped** pexpr) {
     AstTyped* expr = *pexpr;
     if (expr->kind > Ast_Kind_Type_Start && expr->kind < Ast_Kind_Type_End) {
+        expr->type = &basic_types[Basic_Kind_Type_Index];
         return Check_Success;
     }
 
index 90fccfd14db016958454f17490307965de375b5a..e3ecd50333e6d583fe883c4df757f2b092bcdfe8 100644 (file)
@@ -35,6 +35,8 @@ Type basic_types[] = {
     { Type_Kind_Basic, 0, 0, (AstType *) &basic_type_f32x4, { Basic_Kind_F32X4,  Basic_Flag_SIMD,                        16, 16, "f32x4" } },
     { Type_Kind_Basic, 0, 0, (AstType *) &basic_type_f64x2, { Basic_Kind_F64X2,  Basic_Flag_SIMD,                        16, 16, "f64x2" } },
     { Type_Kind_Basic, 0, 0, (AstType *) &basic_type_v128,  { Basic_Kind_V128,   Basic_Flag_SIMD,                        16, 16, "v128"  } },
+
+    { Type_Kind_Basic, 0, 0, NULL,                          { Basic_Kind_Type_Index, Basic_Flag_Type_Index,              4,  4, "Type_Index" } },
 };
 
 // TODO: Document this!!
@@ -463,7 +465,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
         }
 
         case Ast_Kind_Basic_Type: {
-            return ((AstBasicType *) type_node)->type;
+            return ((AstBasicType *) type_node)->basic_type;
         }
 
         case Ast_Kind_Type_Alias:
index bb910401157812ee4a07a9cbc4e1c377f0113458..2eac1ec92b45be22fcda318435dcc009cf357aa2 100644 (file)
@@ -2259,6 +2259,14 @@ EMIT_FUNC(location, AstTyped* expr) {
 EMIT_FUNC(expression, AstTyped* expr) {
     bh_arr(WasmInstruction) code = *pcode;
 
+    if (node_is_type((AstNode *) expr)) {
+        Type* type = type_build_from_ast(context.ast_alloc, (AstType *) expr);
+        WID(WI_I32_CONST, type->id);
+
+        *pcode = code;
+        return;
+    }
+
     switch (expr->kind) {
         case Ast_Kind_Param: {
             AstLocal* param = (AstLocal *) expr;
index 0d89b347920f57778181c76a79fc0585b52188e5..059a3018571e3ceaec786da654f7dab1835e5c87 100644 (file)
@@ -138,6 +138,7 @@ u64 build_type_table(OnyxWasmModule* module) {
                 bh_buffer_write_u64(&table_buffer, 0);                   // TODO: Add member info here. Also, Patching
                 bh_buffer_write_u64(&table_buffer, 0);
                 bh_buffer_write_u32(&table_buffer, type->Enum.is_flags ? 1 : 0);
+                break;
             }
 
             case Type_Kind_Struct: {