structures can have statically bound expressions in their scope
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 29 Jan 2021 15:19:37 +0000 (09:19 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 29 Jan 2021 15:19:37 +0000 (09:19 -0600)
bin/onyx
include/onyxastnodes.h
include/onyxtypes.h
onyx.exe
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c

index 73509c3be59f7b81170b919590eeb58aa3c142a6..6198097d6ff1855671c6970a93122cef522dbd05 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 2ed9744427657a15af143c70fb7134271c5f361e..c4e9d0655cca6da5418a93d2579af6af2ae77f55 100644 (file)
@@ -641,6 +641,9 @@ struct AstStructType {
     // a struct type is kind of complicated and should
     // only happen once.
     Type *stcache;
+    
+    // NOTE: Used to store statically bound expressions in the struct.
+    Scope* scope;
 };
 struct AstStructMember {
     AstTyped_base;
@@ -999,6 +1002,15 @@ extern AstBasicType basic_type_rawptr;
 extern AstBasicType basic_type_int_unsized;
 extern AstBasicType basic_type_float_unsized;
 
+extern AstBasicType basic_type_i8x16;
+extern AstBasicType basic_type_i16x8;
+extern AstBasicType basic_type_i32x4;
+extern AstBasicType basic_type_i64x2;
+extern AstBasicType basic_type_f32x4;
+extern AstBasicType basic_type_f64x2;
+extern AstBasicType basic_type_v128;
+
+
 // :TypeExprHack
 extern AstNode type_expr_symbol;
 
index d34277d37a189cad65745f973ce0a83f781d4d11..daa6d7b00a6e790c4ac7315793c7acbc8f2f5de0 100644 (file)
@@ -137,6 +137,11 @@ struct Type {
     TypeKind kind;
 
     u32 flags;
+    
+    // NOTE(Brendan Hansen): The abstract syntax tree node used to create
+    // the type. Primarily used to look up symbols in scopes that are embedded
+    // in the type.
+    struct AstType* ast_type;
 
     union {
 #define TYPE_KIND(k, ...) Type##k k;
index 13c200b9df504cbde221adeec831bc617227d396..872f78caffa721c40efe8eb693316d0007c52c01 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 3ec011bb4915277eca67099cff663134f20e58b2..c825d36f0727cb4d9c5216e523c370bef92599f0 100644 (file)
@@ -1314,12 +1314,23 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
     }
 
     if (!type_lookup_member(field->expr->type, field->field, &smem)) {
-        onyx_report_error(field->token->pos,
-            "Field '%s' does not exists on '%s'.",
-            field->field,
-            node_get_type_name(field->expr));
-
-        return Check_Error;
+        AstStructType* struct_node = (AstStructType *) field->expr->type->ast_type;
+        assert(struct_node);
+        assert(struct_node->kind == Ast_Kind_Struct_Type);
+        
+        AstNode* n = symbol_raw_resolve(struct_node->scope, field->field);
+        if (n) {
+            *pfield = (AstFieldAccess *) n;
+            return Check_Success;
+            
+        } else {
+            onyx_report_error(field->token->pos,
+                "Field '%s' does not exists on '%s'.",
+                field->field,
+                node_get_type_name(field->expr));
+            
+            return Check_Error;   
+        }
     }
 
     field->offset = smem.offset;
index 7f3b6a67369eca52b359807d67f499ab19bdf67a..3534177f2c204b67514d8657bdef4e68c5ef9856 100644 (file)
@@ -1829,31 +1829,53 @@ static AstStructType* parse_struct(OnyxParser* parser) {
     }
 
     expect_token(parser, '{');
+    b32 member_is_used = 0;
     while (parser->curr->type != '}') {
         if (parser->hit_unexpected_token) return s_node;
-
-        AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member);
+        
+        OnyxToken* member_name;
 
         if (parser->curr->type == Token_Type_Keyword_Use) {
             consume_token(parser);
-            mem->flags |= Ast_Flag_Struct_Mem_Used;
+            member_is_used = 1;
         }
 
-        mem->token = expect_token(parser, Token_Type_Symbol);
+        member_name = expect_token(parser, Token_Type_Symbol);
 
         expect_token(parser, ':');
-        if (parser->curr->type != '=') {
-            mem->type_node = parse_type(parser);
-        }
-
-        if (parser->curr->type == '=') {
+        
+        if (parser->curr->type == ':' && !member_is_used) {
             consume_token(parser);
-            mem->initial_value = parse_expression(parser, 0);
-        }
-
-        expect_token(parser, ';');
+            
+            if (!s_node->scope) {
+                // NOTE: The parent scope will be filled out during symbol resolution.
+                s_node->scope = scope_create(context.ast_alloc, NULL, s_node->token->pos);
+            }
+            
+            AstTyped* expression = parse_top_level_expression(parser);
+            symbol_introduce(s_node->scope, member_name, (AstNode *) expression);
+            
+        } else {
+            AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member);    
+            mem->token = member_name;
+            
+            if (member_is_used) {
+                mem->flags |= Ast_Flag_Struct_Mem_Used;
+                member_is_used = 0;
+            }
+            
+            if (parser->curr->type != '=') {
+                mem->type_node = parse_type(parser);
+            }
 
-        bh_arr_push(s_node->members, mem);
+            if (parser->curr->type == '=') {
+                consume_token(parser);
+                mem->initial_value = parse_expression(parser, 0);
+            }
+            
+            expect_token(parser, ';');
+            bh_arr_push(s_node->members, mem);
+        }
     }
 
     expect_token(parser, '}');
index 54d480b71126b5317ff276a48517176568e218be..ce4b59fba33ac83815cec38c43db2717654264e6 100644 (file)
@@ -95,6 +95,9 @@ AstType* symres_type(AstType* type) {
 
         s_node->flags |= Ast_Flag_Type_Is_Resolved;
         
+        // FIX: This is probably wrong for the long term.
+        if (s_node->scope) s_node->scope->parent = curr_scope;
+        
         {
             bh_table(i32) mem_set;
             bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members));
@@ -296,6 +299,16 @@ static void symres_field_access(AstFieldAccess** fa) {
             return;
         }
     }
+    
+    if ((*fa)->expr->kind == Ast_Kind_Struct_Type) {
+        AstStructType* stype = (AstStructType *) (*fa)->expr;
+        AstNode* n = symbol_resolve(stype->scope, (*fa)->token);
+        if (n) {
+            // Note: not field access
+            *fa = (AstFieldAccess *) n;
+            return;
+        }
+    }
 }
 
 static void symres_compound(AstCompound* compound) {
@@ -880,11 +893,15 @@ static void symres_struct_defaults(AstType* t) {
     if (t->kind != Ast_Kind_Struct_Type) return;
     
     AstStructType* st = (AstStructType *) t;
+    if (st->scope) scope_enter(st->scope);
+    
     bh_arr_each(AstStructMember *, smem, st->members) {
         if ((*smem)->initial_value != NULL) {
             symres_expression(&(*smem)->initial_value);
         }
     }
+    
+    if (st->scope) scope_leave();
 }
 
 static void symres_polyproc(AstPolyProc* pp) {
index efa806cf0688c84b4046796e67d9ee570d1b54bd..94ff6094273fa30672e10052f2d817521032fdc7 100644 (file)
@@ -8,33 +8,33 @@ static u32 next_unique_id = 1;
 
 // NOTE: These have to be in the same order as Basic
 Type basic_types[] = {
-    { Type_Kind_Basic, 0, { Basic_Kind_Void,                    0,                       0,  1, "void"   } },
-
-    { Type_Kind_Basic, 0, { Basic_Kind_Bool,   Basic_Flag_Boolean,                       1,  1, "bool"   } },
-
-    { Type_Kind_Basic, 0, { Basic_Kind_Int_Unsized, Basic_Flag_Integer,                  0,  0, "unsized int" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I8,     Basic_Flag_Integer,                       1,  1, "i8"     } },
-    { Type_Kind_Basic, 0, { Basic_Kind_U8,     Basic_Flag_Integer | Basic_Flag_Unsigned, 1,  1, "u8"     } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I16,    Basic_Flag_Integer,                       2,  2, "i16"    } },
-    { Type_Kind_Basic, 0, { Basic_Kind_U16,    Basic_Flag_Integer | Basic_Flag_Unsigned, 2,  2, "u16"    } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I32,    Basic_Flag_Integer,                       4,  4, "i32"    } },
-    { Type_Kind_Basic, 0, { Basic_Kind_U32,    Basic_Flag_Integer | Basic_Flag_Unsigned, 4,  4, "u32"    } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I64,    Basic_Flag_Integer,                       8,  8, "i64"    } },
-    { Type_Kind_Basic, 0, { Basic_Kind_U64,    Basic_Flag_Integer | Basic_Flag_Unsigned, 8,  8, "u64"    } },
-
-    { Type_Kind_Basic, 0, { Basic_Kind_Float_Unsized, Basic_Flag_Float,                  0,  0, "unsized float" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_F32,    Basic_Flag_Float,                         4,  4, "f32"    } },
-    { Type_Kind_Basic, 0, { Basic_Kind_F64,    Basic_Flag_Float,                         8,  4, "f64"    } },
-
-    { Type_Kind_Basic, 0, { Basic_Kind_Rawptr, Basic_Flag_Pointer,                       8,  8, "rawptr" } },
-
-    { Type_Kind_Basic, 0, { Basic_Kind_I8X16,  Basic_Flag_SIMD,                          16, 16, "i8x16" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I16X8,  Basic_Flag_SIMD,                          16, 16, "i16x8" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I32X4,  Basic_Flag_SIMD,                          16, 16, "i32x4" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_I64X2,  Basic_Flag_SIMD,                          16, 16, "i64x2" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_F32X4,  Basic_Flag_SIMD,                          16, 16, "f32x4" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_F64X2,  Basic_Flag_SIMD,                          16, 16, "f64x2" } },
-    { Type_Kind_Basic, 0, { Basic_Kind_V128,   Basic_Flag_SIMD,                          16, 16, "v128"  } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_void, { Basic_Kind_Void,                    0,                       0,  1, "void"   } },
+
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_bool, { Basic_Kind_Bool,   Basic_Flag_Boolean,                       1,  1, "bool"   } },
+
+    { Type_Kind_Basic, 0, NULL,                        { Basic_Kind_Int_Unsized, Basic_Flag_Integer,                  0,  0, "unsized int" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i8,  { Basic_Kind_I8,     Basic_Flag_Integer,                       1,  1, "i8"     } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_u8,  { Basic_Kind_U8,     Basic_Flag_Integer | Basic_Flag_Unsigned, 1,  1, "u8"     } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i16, { Basic_Kind_I16,    Basic_Flag_Integer,                       2,  2, "i16"    } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_u16, { Basic_Kind_U16,    Basic_Flag_Integer | Basic_Flag_Unsigned, 2,  2, "u16"    } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i32, { Basic_Kind_I32,    Basic_Flag_Integer,                       4,  4, "i32"    } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_u32, { Basic_Kind_U32,    Basic_Flag_Integer | Basic_Flag_Unsigned, 4,  4, "u32"    } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i64, { Basic_Kind_I64,    Basic_Flag_Integer,                       8,  8, "i64"    } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_u64, { Basic_Kind_U64,    Basic_Flag_Integer | Basic_Flag_Unsigned, 8,  8, "u64"    } },
+
+    { Type_Kind_Basic, 0, NULL,                        { Basic_Kind_Float_Unsized, Basic_Flag_Float,                  0,  0, "unsized float" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_f32, { Basic_Kind_F32,    Basic_Flag_Float,                         4,  4, "f32"    } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_f64, { Basic_Kind_F64,    Basic_Flag_Float,                         8,  4, "f64"    } },
+
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_rawptr, { Basic_Kind_Rawptr, Basic_Flag_Pointer,                    8,  8, "rawptr" } },
+
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i8x16, { Basic_Kind_I8X16,  Basic_Flag_SIMD,                        16, 16, "i8x16" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i16x8, { Basic_Kind_I16X8,  Basic_Flag_SIMD,                        16, 16, "i16x8" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i32x4, { Basic_Kind_I32X4,  Basic_Flag_SIMD,                        16, 16, "i32x4" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_i64x2, { Basic_Kind_I64X2,  Basic_Flag_SIMD,                        16, 16, "i64x2" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_f32x4, { Basic_Kind_F32X4,  Basic_Flag_SIMD,                        16, 16, "f32x4" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_f64x2, { Basic_Kind_F64X2,  Basic_Flag_SIMD,                        16, 16, "f64x2" } },
+    { Type_Kind_Basic, 0, (AstType *) &basic_type_v128,  { Basic_Kind_V128,   Basic_Flag_SIMD,                        16, 16, "v128"  } },
 };
 
 b32 types_are_surface_compatible(Type* t1, Type* t2) {
@@ -300,7 +300,9 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
 
     switch (type_node->kind) {
         case Ast_Kind_Pointer_Type: {
-            return type_make_pointer(alloc, type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem));
+            Type* ptr_type = type_make_pointer(alloc, type_build_from_ast(alloc, ((AstPointerType *) type_node)->elem));
+            ptr_type->ast_type = type_node;
+            return ptr_type;
         }
 
         case Ast_Kind_Function_Type: {
@@ -310,6 +312,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             Type* func_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * param_count);
 
             func_type->kind = Type_Kind_Function;
+            func_type->ast_type = type_node;
             func_type->Function.param_count = param_count;
             func_type->Function.needed_param_count = param_count;
             func_type->Function.return_type = type_build_from_ast(alloc, ftype_node->return_type);
@@ -327,6 +330,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
 
             Type* a_type = bh_alloc(alloc, sizeof(Type));
             a_type->kind = Type_Kind_Array;
+            a_type->ast_type = type_node;
             a_type->Array.elem = type_build_from_ast(alloc, a_node->elem);
 
             u32 count = 0;
@@ -364,6 +368,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             Type* s_type = bh_alloc(alloc, sizeof(Type));
             s_node->stcache = s_type;
             s_type->kind = Type_Kind_Struct;
+            s_type->ast_type = type_node;
 
             s_type->Struct.unique_id = next_unique_id++;
             s_type->Struct.name = s_node->name;
@@ -476,6 +481,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             enum_node->etcache = enum_type;
 
             enum_type->kind = Type_Kind_Enum;
+            enum_type->ast_type = type_node;
             enum_type->Enum.unique_id = next_unique_id++;
             enum_type->Enum.backing = enum_node->backing_type;
             enum_type->Enum.name = enum_node->name;
@@ -484,18 +490,26 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
         }
 
         case Ast_Kind_Slice_Type: {
-            return type_make_slice(alloc, type_build_from_ast(alloc, ((AstSliceType *) type_node)->elem));
+            Type* slice_type = type_make_slice(alloc, type_build_from_ast(alloc, ((AstSliceType *) type_node)->elem));
+            slice_type->ast_type = type_node;
+            return slice_type;
         }
 
         case Ast_Kind_DynArr_Type: {
-            return type_make_dynarray(alloc, type_build_from_ast(alloc, ((AstDynArrType *) type_node)->elem));
+            Type* dynarr_type = type_make_dynarray(alloc, type_build_from_ast(alloc, ((AstDynArrType *) type_node)->elem));
+            dynarr_type->ast_type = type_node;
+            return dynarr_type;
         }
 
-        case Ast_Kind_VarArg_Type:
-            return type_make_varargs(alloc, type_build_from_ast(alloc, ((AstVarArgType *) type_node)->elem));
+        case Ast_Kind_VarArg_Type: {
+            Type* va_type = type_make_varargs(alloc, type_build_from_ast(alloc, ((AstVarArgType *) type_node)->elem));   
+            va_type->ast_type = type_node;
+            return va_type;
+        }
 
-        case Ast_Kind_Basic_Type:
+        case Ast_Kind_Basic_Type: {
             return ((AstBasicType *) type_node)->type;
+        }
 
         case Ast_Kind_Type_Alias:
             return type_build_from_ast(alloc, ((AstTypeAlias *) type_node)->to);
@@ -504,7 +518,6 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             return ((AstTypeRawAlias *) type_node)->to;
 
         case Ast_Kind_Poly_Struct_Type:
-            // @Cleanup: Replace this with a proper onyx_report_error. - brendanfh 2020/09/14
             onyx_report_error(type_node->token->pos,
                 "This structure is polymorphic, which means you need to provide arguments to it to make it a concrete structure. "
                 "This error message is probably in the wrong place, so look through your code for uses of this struct.");