more symbol information for struct fields
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 11 Feb 2023 22:59:52 +0000 (16:59 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 11 Feb 2023 22:59:52 +0000 (16:59 -0600)
compiler/include/types.h
compiler/src/checker.c
compiler/src/symres.c
compiler/src/types.c
compiler/src/utils.c
core/time/date.onyx
core/time/time.onyx
docs/ideas/high_level_goals.md

index d4321cd6be2edb129ba857163cdc67a4186344b8..dc8c979fd879f7077264c005c7186ba6d1e77d00 100644 (file)
@@ -85,6 +85,9 @@ typedef struct StructMember {
     b32 use_processed : 1;
 
     bh_arr(struct AstTyped *) meta_tags;
+
+    // Used in reporting errors and symbol information.
+    struct AstStructMember *member_node;
 } StructMember;
 
 typedef struct TypeWithOffset TypeWithOffset;
index fefc3ba71b4aa0e9d814d9f5a45a572291390a76..a927773494f562da03f60383cbde9589e1f31f06 100644 (file)
@@ -1878,6 +1878,8 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
     field->idx = smem.idx;
     field->type = smem.type;
     field->flags |= Ast_Flag_Has_Been_Checked;
+
+    track_resolution_for_symbol_info((AstNode *) field, (AstNode *) smem.member_node);
     return Check_Success;
 
     // Field access is the general term for "a.b". In the early stages of the language,
@@ -1898,6 +1900,8 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
     if (!n) n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field);
 
     if (n) {
+        track_resolution_for_symbol_info((AstNode *) *pfield, n);
+
         *pfield = (AstFieldAccess *) n;
         return Check_Success;
     }
index 7d7860c1c781842f3f145370bfc4f8fa52cd98fd..c8d3640674f2bcfd8db7612d11980fb426a2e834 100644 (file)
@@ -149,6 +149,7 @@ static SymresStatus symres_struct_type(AstStructType* s_node) {
 
     fori (i, 0, bh_arr_length(s_node->members)) {
         AstStructMember *member = s_node->members[i];
+        track_declaration_for_symbol_info(member->token->pos, (AstNode *) member);
 
         if (member->type_node) {
             SymresStatus ss = symres_type(&member->type_node);
index c1dfe372859424893b89980b7a3c51d80006712b..cd1bb199972d6a0fdeb75d095e43f83b39ddb536 100644 (file)
@@ -386,6 +386,10 @@ static Type* type_build_from_ast_inner(bh_allocator alloc, AstType* type_node, b
                     (*member)->type = type_build_from_ast(alloc, (*member)->type_node);
 
                 if ((*member)->type == NULL) {
+                    if (context.cycle_detected) {
+                        onyx_report_error((* member)->token->pos, Error_Critical, "Unable to figure out the type of this structure member.");
+                    }
+
                     s_node->pending_type_is_valid = 0;
                     return accept_partial_types ? s_node->pending_type : NULL;
                 }
@@ -421,6 +425,7 @@ static Type* type_build_from_ast_inner(bh_allocator alloc, AstType* type_node, b
                 smem->token = (*member)->token;
                 smem->initial_value = &(*member)->initial_value;
                 smem->meta_tags = (*member)->meta_tags;
+                smem->member_node = *member;
 
                 smem->included_through_use = 0;
                 smem->used = (*member)->is_used;
@@ -596,7 +601,7 @@ static Type* type_build_from_ast_inner(bh_allocator alloc, AstType* type_node, b
 
         case Ast_Kind_Alias: {
             AstAlias* alias = (AstAlias *) type_node;
-            return type_build_from_ast(alloc, (AstType *) alias->alias);
+            return type_build_from_ast_inner(alloc, (AstType *) alias->alias, accept_partial_types);
         }
 
         case Ast_Kind_Typeof: {
@@ -777,6 +782,7 @@ Type* type_build_implicit_type_of_struct_literal(bh_allocator alloc, AstStructLi
         smem->included_through_use = 0;
         smem->used = 0;
         smem->use_through_pointer_index = -1;
+        smem->member_node = NULL;
 
         // Having this present caused more issues than its
         // worth. I don't think this is necessary, and it allows
@@ -981,6 +987,7 @@ b32 type_struct_member_apply_use(bh_allocator alloc, Type *s_type, StructMember
         new_smem->meta_tags = nsmem->meta_tags;
         new_smem->used = nsmem->used;
         new_smem->included_through_use = 1;
+        new_smem->member_node = nsmem->member_node;
 
         if (type_is_pointer) {
             new_smem->offset = nsmem->offset;
index 37a3383036393b72a8cd53fe501e7d5848c57386..d7016b3af0284f90f026ff615374eab31d849161 100644 (file)
@@ -1382,6 +1382,7 @@ void track_declaration_for_symbol_info(OnyxFilePos pos, AstNode *node) {
 
 void track_resolution_for_symbol_info(AstNode *original, AstNode *resolved) {
     if (!context.options->generate_symbol_info_file) return;
+    if (!resolved) return;
 
     SymbolInfoTable *syminfo = context.symbol_info;
     assert(syminfo);
index 8d83c3a73e02ab13f5df78c8ac2aef2663ae8bf6..74bc824918d940607b42e562188137b8ed882fba 100644 (file)
@@ -2,12 +2,10 @@ package core.time
 
 use core
 
-@conv.Custom_Format.{_format}
-@conv.Custom_Parse.{_parse}
 Date :: struct {
     year: i32;
 
-    // Note that `month` and `day` are 0-based.
+    // Note that `month` is 0-based.
     month, day: i32;
 }
 
@@ -15,7 +13,11 @@ Date :: struct {
     month_durations := u32.[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
 
     make :: (year, month, day: i32) -> Date {
-        return .{ year, month - 1, day - 1 };
+        return .{ year, month - 1, day };
+    }
+
+    today :: () -> Date {
+        return now()->as_date();
     }
 
     add_months :: (d: Date, days: i32) -> Date {
@@ -34,7 +36,7 @@ Date :: struct {
         nd := d;
         nd.day += days;
 
-        while nd.day >= Date.month_durations[nd.month] {
+        while nd.day > Date.month_durations[nd.month] {
             nd.day -= Date.month_durations[nd.month];
 
             // February leap year case
@@ -54,35 +56,39 @@ Date :: struct {
         return nd;
     }
 
-    before :: (d1, d2: Date) -> bool {
+    is_before :: (d1, d2: Date) -> bool {
         if d1.year  != d2.year  do return d1.year  < d2.year;
         if d1.month != d2.month do return d1.month < d2.month;
         return d1.day < d2.day;
     }
 
-    after :: (d1, d2: Date) -> bool {
+    is_after :: (d1, d2: Date) -> bool {
         if d1.year  != d2.year  do return d1.year  > d2.year;
         if d1.month != d2.month do return d1.month > d2.month;
         return d1.day > d2.day;
     }
 
-    _parse :: (d: ^Date, text: str, _: Allocator) -> bool {
-        year,  t  := string.bisect(text, #char "-");
-        month, t' := string.bisect(t,    #char "-");
-        day,   t' := string.bisect(t,    #char "-");
+}
+
+@conv.Custom_Format_Proc.{ Date }
+(output: ^conv.Format_Output, format: ^conv.Format, date: ^Date) {
+    conv.format(output, "{}-{w2}-{w2}", date.year, date.month + 1, date.day);
+}
 
-        d.year  = ~~  conv.str_to_i64(year);
-        d.month = ~~ (conv.str_to_i64(month) - 1);
-        d.day   = ~~ (conv.str_to_i64(day) - 1);
+@conv.Custom_Parse_Proc.{ Date }
+(d: ^Date, text: str, _: Allocator) -> bool {
+    year,  t  := string.bisect(text, #char "-");
+    month, t' := string.bisect(t,    #char "-");
+    day,   t' := string.bisect(t,    #char "-");
 
-        return true;
-    }
+    d.year  = ~~  conv.str_to_i64(year);
+    d.month = ~~ (conv.str_to_i64(month) - 1);
+    d.day   = ~~  conv.str_to_i64(day);
 
-    _format :: (output: ^conv.Format_Output, format: ^conv.Format, date: ^Date) {
-        conv.format(output, "{}-{w2}-{w2}", date.year, date.month + 1, date.day + 1);
-    }
+    return true;
 }
 
+
 #operator  + macro (d: Date, days: i32) => d->add_days(days);
 #operator  - macro (d: Date, days: i32) => d->add_days(-days);
 
index afe27d98013bbefb7a1687d4611689de3ab024ed..b61975d05e32949283058c9b9863314c8290fa11 100644 (file)
@@ -301,30 +301,31 @@ strptime :: (buf_: [] u8, format_: [] u8, tm: ^Timestamp) -> bool {
     }
 
     return working;
-}
 
-#local
-parse_number_and_advance :: (buf: ^[] u8, result: ^i32, low, high, offset: i32) -> bool {
-    use core {string}
+    //
+    // Helper function used above
+    parse_number_and_advance :: (buf: ^[] u8, result: ^i32, low, high, offset: i32) -> bool {
+        use core {string}
+
+        n := 0;
+        while buf.count > 0 {
+            c := buf.data[0];
+            if c < #char "0" || c > #char "9" {
+                break;
+            }
 
-    n := 0;
-    while buf.count > 0 {
-        c := buf.data[0];
-        if c < #char "0" || c > #char "9" {
-            break;
+            n *= 10;
+            n += ~~(c - #char "0");
+            string.advance(buf);
         }
 
-        n *= 10;
-        n += ~~(c - #char "0");
-        string.advance(buf);
-    }
+        if n >= low && n <= high {
+            *result = n + offset;
+            return true;
+        }
 
-    if n >= low && n <= high {
-        *result = n + offset;
-        return true;
+        return false;
     }
-
-    return false;
 }
 
 #local {
index b4c3ffb96a27ef4f89cbfb3ba4d1802ce0d0928c..ee2e184fe2056f46e7461a63e89c317123a36602 100644 (file)
@@ -35,6 +35,11 @@ documentation.
 
 
 [Core Library Cleanup](./core_libraries.md)
+- [ ] Add improved time functionality
+  - [ ] clock_gettime
+  - [ ] clock_settime
+  - [ ] clock_getres
+  - [ ] clock
 --------------------