BREAKING renamed type_info to runtime.info
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 10 May 2022 01:57:53 +0000 (20:57 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 10 May 2022 01:57:53 +0000 (20:57 -0500)
22 files changed:
core/arg_parse.onyx
core/builtin.onyx
core/container/avl_tree.onyx [new file with mode: 0644]
core/conv.onyx
core/runtime/info/foreign_blocks.onyx [new file with mode: 0644]
core/runtime/info/helper.onyx [new file with mode: 0644]
core/runtime/info/types.onyx [new file with mode: 0644]
core/std.onyx
core/type_info/helper.onyx [deleted file]
core/type_info/type_info.onyx [deleted file]
docs/builtins.md
include/astnodes.h
modules/immediate_mode/immediate_renderer.onyx
scripts/c_binding.onyx
src/builtins.c
src/checker.c
src/entities.c
src/onyx.c
src/parser.c
src/symres.c
src/wasm_type_table.h
tests/poly_struct_in_type_info.onyx

index 31e2e2e8f9d1255082cc9837bd530e62011f6224..01255cd633ace539e6eb4881e65dc732a739425e 100644 (file)
@@ -7,7 +7,7 @@ arg_parse :: (c_args: [] cstr, output: any) -> bool {
              |> iter.map((x) => string.from_cstr(*x));
     defer arg_iter.close(arg_iter.data);
 
-    use type_info;
+    use package runtime.info;
 
     ptr_type := cast(^Type_Info_Pointer) get_type_info(output.type);
     if ptr_type.kind != .Pointer do return false;
index 068f9803cc75cd8085ed50e3c2406abdc5474452..3146e1fd505ab30eb3b37a6f67d1bfcfcda6a910 100644 (file)
@@ -148,6 +148,7 @@ new :: #match {
 
     (T: type_expr, allocator := context.allocator) -> rawptr {
         memory :: package core.memory
+        type_info :: package runtime.info
 
         info := type_info.get_type_info(T);
         size := type_info.size_of(T);
diff --git a/core/container/avl_tree.onyx b/core/container/avl_tree.onyx
new file mode 100644 (file)
index 0000000..73d35f9
--- /dev/null
@@ -0,0 +1,14 @@
+package core.avl_tree
+
+AVL_Tree :: struct (T: type_expr) {
+    data: T;
+    left, right: ^AVL_Tree(T);
+
+    insert :: (tree: ^AVL_Tree, data: tree.T) {
+        node := new(typeof *tree);
+        node.data = data;
+        node.left = null;
+        node.right = null;
+    }
+}
+
index dfe9871a4dafa18781fc125026dfefff86067ce6..e62f35f500f5b09a58f391dfed9af50887af2130 100644 (file)
@@ -15,7 +15,7 @@ custom_formatters_initialized :: #init () {
     map.init(^custom_parsers,    default=null_proc);
 
     #if Enable_Custom_Formatters {
-        use type_info;
+        use package runtime.info;
 
         for type_idx: type_table.count {
             type := type_table[type_idx];
@@ -466,7 +466,7 @@ format_va :: #match {}
 }
 
 format_any :: (output: ^Format_Output, formatting: ^Format, v: any) {
-    use package builtin.type_info
+    use package runtime.info
     array :: package core.array;
 
     if formatting.dereference {
@@ -579,7 +579,7 @@ format_any :: (output: ^Format_Output, formatting: ^Format, v: any) {
             // 256 bytes is enough for the name of a type but I'm not entirely sure...
             stream := io.string_stream_make(~~buf);
             writer := io.writer_make(^stream);
-            type_info.write_type_name(^writer, value);
+            write_type_name(^writer, value);
 
             output->write(io.string_stream_to_str(^stream));
         }
@@ -772,7 +772,7 @@ format_any :: (output: ^Format_Output, formatting: ^Format, v: any) {
 //      parse_any(^x, "12.34");
 parse_any :: #match {}
 #match parse_any (v: any, to_parse: str, string_allocator := context.allocator) -> bool {
-    use type_info;
+    use package runtime.info;
 
     info := get_type_info(v.type);
     if info.kind != .Pointer do return false;
@@ -787,7 +787,7 @@ parse_any :: #match {}
         return custom_parsers[data_type](target, to_parse, string_allocator);
     }
 
-    use type_info;
+    use package runtime.info;
     info := get_type_info(data_type);
 
     switch data_type {
diff --git a/core/runtime/info/foreign_blocks.onyx b/core/runtime/info/foreign_blocks.onyx
new file mode 100644 (file)
index 0000000..e1f8f97
--- /dev/null
@@ -0,0 +1,29 @@
+
+package runtime.info
+
+//
+// Foreign Blocks
+// Because foreign blocks can generate a lot of data, and their data is only
+// really helpful in a handful of cases, you need to pass "--generate-foreign-bindings"
+// to have these arrays filled out.
+//
+
+foreign_block :: #distinct u32
+
+foreign_blocks: [] ^Foreign_Block;
+
+Foreign_Block :: struct {
+    module_name: str;
+    funcs: [] Foreign_Function;
+
+    Foreign_Function :: struct {
+        name: str;
+        type: type_expr;
+    }
+}
+
+get_foreign_block :: (f: foreign_block) -> ^Foreign_Block {
+    if ~~f < cast(i32) 0 || ~~f >= cast(i32) foreign_blocks.count do return null;
+
+    return foreign_blocks[cast(i32) f];
+}
\ No newline at end of file
diff --git a/core/runtime/info/helper.onyx b/core/runtime/info/helper.onyx
new file mode 100644 (file)
index 0000000..e0aed03
--- /dev/null
@@ -0,0 +1,325 @@
+package runtime.info
+
+#local io :: package core.io
+
+write_type_name :: (writer: ^io.Writer, t: type_expr) {
+    info := get_type_info(t);
+    if info == null do return;
+
+    switch info.kind {
+        case .Basic {
+            basic := cast(^Type_Info_Basic) info;
+
+            switch basic.basic_kind {
+                case .Void do io.write_str(writer, "void");
+                case .Bool do io.write_str(writer, "bool");
+                case .U8   do io.write_str(writer, "u8");
+                case .I8   do io.write_str(writer, "i8");
+                case .U16  do io.write_str(writer, "u16");
+                case .I16  do io.write_str(writer, "i16");
+                case .U32  do io.write_str(writer, "u32");
+                case .I32  do io.write_str(writer, "i32");
+                case .U64  do io.write_str(writer, "u64");
+                case .I64  do io.write_str(writer, "i64");
+
+                case .F32  do io.write_str(writer, "f32");
+                case .F64  do io.write_str(writer, "f64");
+
+                case .Rawptr do return io.write_str(writer, "rawptr");
+
+                case .I8X16 do return io.write_str(writer, "i8x16");
+                case .I16X8 do return io.write_str(writer, "i16x8");
+                case .I32X4 do return io.write_str(writer, "i32x4");
+                case .I64X2 do return io.write_str(writer, "i64x2");
+                case .F32X4 do return io.write_str(writer, "f32x4");
+                case .F64X2 do return io.write_str(writer, "f64x2");
+                case .V128  do return io.write_str(writer, "v128");
+
+                case .Type_Index do io.write_str(writer, "type_expr");
+                case .Unsized_Int do io.write_str(writer, "<unsized int>");
+                case .Unsized_Float do io.write_str(writer, "<unsized float>");
+            }
+        }
+
+        case .Pointer {
+            pointer := cast(^Type_Info_Pointer) info;
+            io.write_str(writer, "^");
+            write_type_name(writer, pointer.to);
+        }
+
+        case .Array {
+            arr := cast(^Type_Info_Array) info;
+            io.write_format(writer, "[{}] ", arr.count);
+            write_type_name(writer, arr.of);
+        }
+
+        case .Slice {
+            slice := cast(^Type_Info_Slice) info;
+            io.write_str(writer, "[] ");
+            write_type_name(writer, slice.of);
+        }
+
+        case .Dynamic_Array {
+            dyn := cast(^Type_Info_Dynamic_Array) info;
+            io.write_str(writer, "[..] ");
+            write_type_name(writer, dyn.of);
+        }
+
+        case .Variadic_Argument {
+            va := cast(^Type_Info_Variadic_Argument) info;
+            io.write_str(writer, "..");
+            write_type_name(writer, va.of);
+        }
+
+        case .Enum {
+            e := cast(^Type_Info_Enum) info;
+            io.write_str(writer, e.name);
+        }
+
+        case .Struct {
+            s := cast(^Type_Info_Struct) info;
+            if s.name.count > 0 do io.write_str(writer, s.name);
+            else                do io.write_str(writer, "<anonymous struct>");
+        }
+
+        case .Polymorphic_Struct {
+            s := cast(^Type_Info_Polymorphic_Struct) info;
+            if s.name.count > 0 do io.write_str(writer, s.name);
+            else                do io.write_str(writer, "<anonymous polymorphic struct>");
+        }
+
+        case .Compound {
+            comp := cast(^Type_Info_Compound) info;
+            io.write_str(writer, "(");
+
+            i := 0;
+            for type: comp.components {
+                if i != 0 do io.write_str(writer, ", ");
+
+                write_type_name(writer, type);
+                i += 1;
+            }
+            io.write_str(writer, ")");
+        }
+
+        case .Function {
+            f := cast(^Type_Info_Function) info;
+            io.write_str(writer, "(");
+
+            i := 0;
+            for type: f.parameter_types {
+                if i != 0 do io.write_str(writer, ", ");
+
+                write_type_name(writer, type);
+                i += 1;
+            }
+            io.write_str(writer, ") -> ");
+
+            write_type_name(writer, f.return_type);
+        }            
+
+        case .Distinct {
+            d := cast(^Type_Info_Distinct) info;
+            io.write_str(writer, d.name);
+        }
+    }
+}
+
+is_pointer :: (t: type_expr) -> bool {
+    if t == rawptr do return true;
+    info := get_type_info(t);
+    return info.kind == .Pointer;
+}
+
+size_of :: (t: type_expr) -> u32 {
+    info := get_type_info(t);
+    if info == null do return 0;
+
+    switch info.kind {
+        case .Basic {
+            basic := cast(^Type_Info_Basic) info;
+
+            switch basic.basic_kind {
+                case .Void do return 0;
+                case .Bool, .U8, .I8 do return 1;
+                case .U16, .I16 do return 2;
+                case .U32, .I32, .F32, .Type_Index do return 4;
+                case .U64, .I64, .F64 do return 8;
+                case .I8X16, .I16X8, .I32X4, .I64X2, .F32X4, .F64X2, .V128 do return 16;
+                case .Rawptr do return sizeof rawptr;
+
+                case .Unsized_Int do return 0;
+                case .Unsized_Float do return 0;
+            }
+        }
+
+        case .Pointer do return sizeof rawptr;
+
+        case .Array {
+            arr := cast(^Type_Info_Array) info;
+            return size_of(arr.of) * arr.count;
+        }
+
+        case .Slice do return sizeof str;
+        case .Dynamic_Array do return sizeof [..] void;
+        case .Variadic_Argument do return sizeof str;
+        case .Enum {
+            e := cast(^Type_Info_Enum) info;
+            return e.size;
+        }
+
+        case .Struct {
+            s := cast(^Type_Info_Struct) info;
+            return s.size;
+        }
+
+        case .Polymorphic_Struct do return 0;
+
+        case .Compound do return 0;
+
+        case .Function do return 4;
+
+        case .Distinct {
+            d := cast(^Type_Info_Distinct) info;
+            return size_of(d.base_type);
+        }
+    }
+
+    return 0;
+}
+
+offset_of :: (T: type_expr, member: str) -> u32 {
+    info := get_type_info(T);
+    if info == null         do return 0;
+    if info.kind != .Struct do return 0;
+
+    struct_info := cast(^Type_Info_Struct) info;
+    for ^m: struct_info.members {
+        if m.name == member do return m.offset;
+    }
+
+    // Should this return something else if the member was not found?
+    return 0;
+}
+
+get_tags_for_member :: (S: type_expr, member_name: str) -> [] any {
+    ti := get_type_info(S);
+    if ti.kind != .Struct do return .[];
+    
+    for ^ (cast(^Type_Info_Struct) ti).members {
+        if it.name == member_name {
+            return it.tags;
+        }
+    }
+    
+    return .[];
+}
+
+struct_constructed_from :: (struct_type: type_expr, base_type: type_expr) -> bool {
+    struct_info := get_type_info(struct_type);
+    if struct_info.kind != .Struct do return false;
+
+    return (cast(^Type_Info_Struct) struct_info).constructed_from == base_type;
+}
+
+struct_inherits :: (struct_type: type_expr, base_type: type_expr) -> bool {
+    struct_info := cast(^Type_Info_Struct) get_type_info(struct_type);
+    if struct_info.kind != .Struct do return false;
+
+    first_member := ^struct_info.members[0];
+    return first_member.used && first_member.type == base_type;
+}
+
+#operator == (t1: Type_Info_Function, t2: Type_Info_Function) -> bool {
+    if t1.parameter_types.count != t2.parameter_types.count do return false;
+    if t1.return_type           != t2.return_type           do return false;
+    if t1.is_variadic           != t2.is_variadic           do return false;
+
+    while i := 0; i < t1.parameter_types.count {
+        @Robustness // This does not handle nested procedure types
+        if t1.parameter_types[i] != t2.parameter_types[i] do return false;
+    }
+
+    return true;
+}
+
+enum_name :: (value: $Backing_Type) -> str {
+    info := get_type_info(Backing_Type);
+    if info.kind != .Enum do return null_str;
+
+    etype := cast(^Type_Info_Enum) info;
+    for ^member: etype.members {
+        if member.value == ~~value do return member.name;
+    }
+    
+    return null_str;
+}
+
+enum_value :: ($E: type_expr, name: str) -> E {
+    info := get_type_info(E); 
+    if info.kind != .Enum do return ~~0;
+
+    etype := cast(^Type_Info_Enum) info;
+    for ^member: etype.members {
+        if member.name == name do return ~~member.value;
+    }
+
+    return ~~0;
+}
+
+enum_values :: (E: type_expr) -> [] Type_Info_Enum.Member {
+    info := cast(^Type_Info_Enum) get_type_info(E);
+    if info.kind != .Enum do return .[];
+
+    return info.members;
+}
+
+get_struct_by_name :: (name: str) -> type_expr {
+    index := 0;
+    for type_table {
+        defer index += 1;
+        if it.kind != .Struct do continue;
+
+        if (cast(^Type_Info_Struct) it).name == name do return cast(type_expr) index;
+    }
+
+    return void;
+}
+
+get_struct_method :: (type: type_expr, method_name: str) -> ^any {
+    info := cast(^Type_Info_Struct) get_type_info(type);
+    if info.kind != .Struct do return null;
+
+    for ^method: info.methods {
+        if method.name == method_name {
+            return ^method.func;
+        }
+    }
+
+    return null;
+}
+
+populate_struct_vtable :: (table: ^$Table_Type, struct_type: type_expr, safe := true) {
+    v_info := cast(^Type_Info_Struct) get_type_info(Table_Type);
+    if v_info.kind != .Struct do return;
+
+    for^ member: v_info.members {
+        if get_type_info(member.type).kind != .Function do continue;
+
+        struct_method := get_struct_method(struct_type, member.name);
+        if struct_method == null do continue;
+        if safe && struct_method.type != member.type do continue;
+
+        dest := cast(^()->void) (cast(^u8) table + member.offset);
+        *dest = *cast(^()->void) struct_method.data;
+    }
+}
+
+for_all_types :: macro (body: Code) {
+    for (package runtime.info).type_table.count {
+        type_info := (package runtime.info).type_table[it];
+        type_idx  : type_expr = ~~ it;
+
+        #unquote body;
+    }
+}
diff --git a/core/runtime/info/types.onyx b/core/runtime/info/types.onyx
new file mode 100644 (file)
index 0000000..0eb3dfa
--- /dev/null
@@ -0,0 +1,191 @@
+// A lot of these names have been copied from JAI's introspection system. This is just because
+// I don't want to mentally bike-shed about the names; I just want to get something working.
+
+package runtime.info
+
+type_table : [] ^Type_Info;
+
+Type_Info :: struct {
+    // This must match the order of the elements in onyxtypes.h
+    Kind :: enum {
+        Invalid            :: 0x00; // Unused
+        Basic              :: 0x01;
+        Pointer            :: 0x02;
+        Function           :: 0x03;
+        Struct             :: 0x04;
+        Polymorphic_Struct :: 0x05;
+        Compound           :: 0x06;
+        Array              :: 0x07;
+        Slice              :: 0x08;
+        Dynamic_Array      :: 0x09;
+        Variadic_Argument  :: 0x0a;
+        Enum               :: 0x0b;
+        Distinct           :: 0x0c;
+    }
+
+    kind := Kind.Invalid;
+    size: u32;
+
+    // Does this need to know alignment? Probably?
+    alignment: u32;
+}
+
+Type_Info_Basic :: struct {
+    use base : Type_Info;
+
+    // This must match the order of the elements in BasicKind in onyxtypes.h
+    Kind :: enum {
+        Void  :: 0x00;
+        Bool  :: 0x01;
+
+        Unsized_Int :: 0x02;
+        I8    :: 0x03;
+        U8    :: 0x04;
+        I16   :: 0x05;
+        U16   :: 0x06;
+        I32   :: 0x07;
+        U32   :: 0x08;
+        I64   :: 0x09;
+        U64   :: 0x0a;
+
+        Unsized_Float :: 0x0b;
+        F32   :: 0x0c;
+        F64   :: 0x0d;
+
+        Rawptr :: 0x0e;
+
+        I8X16 :: 0x0f;
+        I16X8 :: 0x10;
+        I32X4 :: 0x11;
+        I64X2 :: 0x12;
+        F32X4 :: 0x13;
+        F64X2 :: 0x14;
+        V128  :: 0x15;
+
+        Type_Index :: 0x16;
+    }
+
+    basic_kind: Kind;
+}
+
+Type_Info_Pointer :: struct {
+    use base : Type_Info;
+
+    @Rename
+    to: type_expr;
+}
+
+Type_Info_Function :: struct {
+    use base : Type_Info;
+
+    return_type:        type_expr;
+    parameter_types: [] type_expr;
+
+    is_variadic: bool;
+}
+
+Type_Info_Array :: struct {
+    use base : Type_Info;
+
+    @Rename
+    of: type_expr;
+    count: u32;
+}
+
+Type_Info_Slice :: struct {
+    use base : Type_Info;
+
+    @Rename
+    of: type_expr;
+}
+
+Type_Info_Dynamic_Array :: struct {
+    use base : Type_Info;
+
+    @Rename
+    of: type_expr;
+}
+
+Type_Info_Variadic_Argument :: struct {
+    use base : Type_Info;
+
+    @Rename
+    of: type_expr;
+}
+
+Type_Info_Enum :: struct {
+    use base : Type_Info;
+
+    Member :: struct {
+        name: str;
+        value: u64; // This assumes enums are always represented as ints.
+    }
+
+    // This is first for better alignment
+    backing_type: type_expr;
+    name: str;
+    members: [] Member;
+
+    is_flags: bool;
+}
+
+Type_Info_Struct :: struct {
+    use base : Type_Info;
+
+    Member :: struct {
+        name: str;
+        offset: u32;
+        type: type_expr;
+
+        used: bool;
+        default: rawptr; // Pointer to the initial value of the same type as the member.
+                         // null if no default value is given, or if it is not compile time known.
+
+                         // As another thought. This could become a thunk that get the default value
+                         // at runtime or returns the value.
+
+        tags: [] any;
+    }
+
+    constructed_from: type_expr;
+    name: str;
+    members: [] Member;
+    parameters: [] any;
+    tags: [] any;
+
+    Method :: struct {
+        name: str;
+        func: any;
+    }
+    methods: [] Method;
+}
+
+Type_Info_Polymorphic_Struct :: struct {
+    use base : Type_Info;
+
+    name: str;
+    tags: [] any;
+}
+
+Type_Info_Compound :: struct {
+    use base : Type_Info;
+
+    components : [] type_expr;
+}
+
+Type_Info_Distinct :: struct {
+    use base : Type_Info;
+
+    base_type: type_expr;
+    name: str;
+}
+
+get_type_info :: (t: type_expr) -> ^Type_Info {
+    // Grossness to get around the fact that type_exprs are not technically comparable, because in most
+    // cases you should not compare them as the number assigned to them is arbitrary.
+    if ~~t < cast(i32) 0 || ~~t >= cast(i32) type_table.count do return null;
+
+    return type_table[cast(i32) t];
+}
+
+
index 83d6aaf95824f36da53d436cce0ad402d314af03..ec79d75bdb12a74436b89555b55162fa80f66187 100644 (file)
@@ -35,7 +35,9 @@ package core
 #load "./runtime/build_opts"
 #load "./runtime/common"
 
-#load "./type_info/helper"
+#load "./runtime/info/helper"
+#load "./runtime/info/types"
+#load "./runtime/info/foreign_blocks"
 
 #load "./arg_parse"
 
diff --git a/core/type_info/helper.onyx b/core/type_info/helper.onyx
deleted file mode 100644 (file)
index 47a3ac8..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-package builtin.type_info
-
-#local io :: package core.io
-
-write_type_name :: (writer: ^io.Writer, t: type_expr) {
-    info := get_type_info(t);
-    if info == null do return;
-
-    switch info.kind {
-        case .Basic {
-            basic := cast(^Type_Info_Basic) info;
-
-            switch basic.basic_kind {
-                case .Void do io.write_str(writer, "void");
-                case .Bool do io.write_str(writer, "bool");
-                case .U8   do io.write_str(writer, "u8");
-                case .I8   do io.write_str(writer, "i8");
-                case .U16  do io.write_str(writer, "u16");
-                case .I16  do io.write_str(writer, "i16");
-                case .U32  do io.write_str(writer, "u32");
-                case .I32  do io.write_str(writer, "i32");
-                case .U64  do io.write_str(writer, "u64");
-                case .I64  do io.write_str(writer, "i64");
-
-                case .F32  do io.write_str(writer, "f32");
-                case .F64  do io.write_str(writer, "f64");
-
-                case .Rawptr do return io.write_str(writer, "rawptr");
-
-                case .I8X16 do return io.write_str(writer, "i8x16");
-                case .I16X8 do return io.write_str(writer, "i16x8");
-                case .I32X4 do return io.write_str(writer, "i32x4");
-                case .I64X2 do return io.write_str(writer, "i64x2");
-                case .F32X4 do return io.write_str(writer, "f32x4");
-                case .F64X2 do return io.write_str(writer, "f64x2");
-                case .V128  do return io.write_str(writer, "v128");
-
-                case .Type_Index do io.write_str(writer, "type_expr");
-                case .Unsized_Int do io.write_str(writer, "<unsized int>");
-                case .Unsized_Float do io.write_str(writer, "<unsized float>");
-            }
-        }
-
-        case .Pointer {
-            pointer := cast(^Type_Info_Pointer) info;
-            io.write_str(writer, "^");
-            write_type_name(writer, pointer.to);
-        }
-
-        case .Array {
-            arr := cast(^Type_Info_Array) info;
-            io.write_format(writer, "[{}] ", arr.count);
-            write_type_name(writer, arr.of);
-        }
-
-        case .Slice {
-            slice := cast(^Type_Info_Slice) info;
-            io.write_str(writer, "[] ");
-            write_type_name(writer, slice.of);
-        }
-
-        case .Dynamic_Array {
-            dyn := cast(^Type_Info_Dynamic_Array) info;
-            io.write_str(writer, "[..] ");
-            write_type_name(writer, dyn.of);
-        }
-
-        case .Variadic_Argument {
-            va := cast(^Type_Info_Variadic_Argument) info;
-            io.write_str(writer, "..");
-            write_type_name(writer, va.of);
-        }
-
-        case .Enum {
-            e := cast(^Type_Info_Enum) info;
-            io.write_str(writer, e.name);
-        }
-
-        case .Struct {
-            s := cast(^Type_Info_Struct) info;
-            if s.name.count > 0 do io.write_str(writer, s.name);
-            else                do io.write_str(writer, "<anonymous struct>");
-        }
-
-        case .Polymorphic_Struct {
-            s := cast(^Type_Info_Polymorphic_Struct) info;
-            if s.name.count > 0 do io.write_str(writer, s.name);
-            else                do io.write_str(writer, "<anonymous polymorphic struct>");
-        }
-
-        case .Compound {
-            comp := cast(^Type_Info_Compound) info;
-            io.write_str(writer, "(");
-
-            i := 0;
-            for type: comp.components {
-                if i != 0 do io.write_str(writer, ", ");
-
-                write_type_name(writer, type);
-                i += 1;
-            }
-            io.write_str(writer, ")");
-        }
-
-        case .Function {
-            f := cast(^Type_Info_Function) info;
-            io.write_str(writer, "(");
-
-            i := 0;
-            for type: f.parameter_types {
-                if i != 0 do io.write_str(writer, ", ");
-
-                write_type_name(writer, type);
-                i += 1;
-            }
-            io.write_str(writer, ") -> ");
-
-            write_type_name(writer, f.return_type);
-        }            
-
-        case .Distinct {
-            d := cast(^Type_Info_Distinct) info;
-            io.write_str(writer, d.name);
-        }
-    }
-}
-
-is_pointer :: (t: type_expr) -> bool {
-    if t == rawptr do return true;
-    info := get_type_info(t);
-    return info.kind == .Pointer;
-}
-
-size_of :: (t: type_expr) -> u32 {
-    info := get_type_info(t);
-    if info == null do return 0;
-
-    switch info.kind {
-        case .Basic {
-            basic := cast(^Type_Info_Basic) info;
-
-            switch basic.basic_kind {
-                case .Void do return 0;
-                case .Bool, .U8, .I8 do return 1;
-                case .U16, .I16 do return 2;
-                case .U32, .I32, .F32, .Type_Index do return 4;
-                case .U64, .I64, .F64 do return 8;
-                case .I8X16, .I16X8, .I32X4, .I64X2, .F32X4, .F64X2, .V128 do return 16;
-                case .Rawptr do return sizeof rawptr;
-
-                case .Unsized_Int do return 0;
-                case .Unsized_Float do return 0;
-            }
-        }
-
-        case .Pointer do return sizeof rawptr;
-
-        case .Array {
-            arr := cast(^Type_Info_Array) info;
-            return size_of(arr.of) * arr.count;
-        }
-
-        case .Slice do return sizeof str;
-        case .Dynamic_Array do return sizeof [..] void;
-        case .Variadic_Argument do return sizeof str;
-        case .Enum {
-            e := cast(^Type_Info_Enum) info;
-            return e.size;
-        }
-
-        case .Struct {
-            s := cast(^Type_Info_Struct) info;
-            return s.size;
-        }
-
-        case .Polymorphic_Struct do return 0;
-
-        case .Compound do return 0;
-
-        case .Function do return 4;
-
-        case .Distinct {
-            d := cast(^Type_Info_Distinct) info;
-            return size_of(d.base_type);
-        }
-    }
-
-    return 0;
-}
-
-offset_of :: (T: type_expr, member: str) -> u32 {
-    info := get_type_info(T);
-    if info == null         do return 0;
-    if info.kind != .Struct do return 0;
-
-    struct_info := cast(^Type_Info_Struct) info;
-    for ^m: struct_info.members {
-        if m.name == member do return m.offset;
-    }
-
-    // Should this return something else if the member was not found?
-    return 0;
-}
-
-get_tags_for_member :: (S: type_expr, member_name: str) -> [] any {
-    use type_info;
-    
-    ti := get_type_info(S);
-    if ti.kind != .Struct do return .[];
-    
-    for ^ (cast(^Type_Info_Struct) ti).members {
-        if it.name == member_name {
-            return it.tags;
-        }
-    }
-    
-    return .[];
-}
-
-struct_constructed_from :: (struct_type: type_expr, base_type: type_expr) -> bool {
-    struct_info := get_type_info(struct_type);
-    if struct_info.kind != .Struct do return false;
-
-    return (cast(^Type_Info_Struct) struct_info).constructed_from == base_type;
-}
-
-struct_inherits :: (struct_type: type_expr, base_type: type_expr) -> bool {
-    struct_info := cast(^Type_Info_Struct) get_type_info(struct_type);
-    if struct_info.kind != .Struct do return false;
-
-    first_member := ^struct_info.members[0];
-    return first_member.used && first_member.type == base_type;
-}
-
-#operator == (t1: Type_Info_Function, t2: Type_Info_Function) -> bool {
-    if t1.parameter_types.count != t2.parameter_types.count do return false;
-    if t1.return_type           != t2.return_type           do return false;
-    if t1.is_variadic           != t2.is_variadic           do return false;
-
-    while i := 0; i < t1.parameter_types.count {
-        @Robustness // This does not handle nested procedure types
-        if t1.parameter_types[i] != t2.parameter_types[i] do return false;
-    }
-
-    return true;
-}
-
-enum_name :: (value: $Backing_Type) -> str {
-    info := get_type_info(Backing_Type);
-    if info.kind != .Enum do return null_str;
-
-    etype := cast(^Type_Info_Enum) info;
-    for ^member: etype.members {
-        if member.value == ~~value do return member.name;
-    }
-    
-    return null_str;
-}
-
-enum_value :: ($E: type_expr, name: str) -> E {
-    info := get_type_info(E); 
-    if info.kind != .Enum do return ~~0;
-
-    etype := cast(^Type_Info_Enum) info;
-    for ^member: etype.members {
-        if member.name == name do return ~~member.value;
-    }
-
-    return ~~0;
-}
-
-enum_values :: (E: type_expr) -> [] Type_Info_Enum.Member {
-    info := cast(^Type_Info_Enum) get_type_info(E);
-    if info.kind != .Enum do return .[];
-
-    return info.members;
-}
-
-get_struct_by_name :: (name: str) -> type_expr {
-    index := 0;
-    for type_table {
-        defer index += 1;
-        if it.kind != .Struct do continue;
-
-        if (cast(^Type_Info_Struct) it).name == name do return cast(type_expr) index;
-    }
-
-    return void;
-}
-
-get_struct_method :: (type: type_expr, method_name: str) -> ^any {
-    info := cast(^Type_Info_Struct) get_type_info(type);
-    if info.kind != .Struct do return null;
-
-    for ^method: info.methods {
-        if method.name == method_name {
-            return ^method.func;
-        }
-    }
-
-    return null;
-}
-
-populate_struct_vtable :: (table: ^$Table_Type, struct_type: type_expr, safe := true) {
-    v_info := cast(^Type_Info_Struct) get_type_info(Table_Type);
-    if v_info.kind != .Struct do return;
-
-    for^ member: v_info.members {
-        if get_type_info(member.type).kind != .Function do continue;
-
-        struct_method := get_struct_method(struct_type, member.name);
-        if struct_method == null do continue;
-        if safe && struct_method.type != member.type do continue;
-
-        dest := cast(^()->void) (cast(^u8) table + member.offset);
-        *dest = *cast(^()->void) struct_method.data;
-    }
-}
-
-for_all_types :: macro (body: Code) {
-    for (package builtin.type_info).type_table.count {
-        type_info := (package builtin.type_info).type_table[it];
-        type_idx  : type_expr = ~~ it;
-
-        #unquote body;
-    }
-}
diff --git a/core/type_info/type_info.onyx b/core/type_info/type_info.onyx
deleted file mode 100644 (file)
index e16f54f..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-// A lot of these names have been copied from JAI's introspection system. This is just because
-// I don't want to mentally bike-shed about the names; I just want to get something working.
-
-package builtin.type_info
-
-type_table : [] ^Type_Info;
-
-Type_Info :: struct {
-    // This must match the order of the elements in onyxtypes.h
-    Kind :: enum {
-        Invalid            :: 0x00; // Unused
-        Basic              :: 0x01;
-        Pointer            :: 0x02;
-        Function           :: 0x03;
-        Struct             :: 0x04;
-        Polymorphic_Struct :: 0x05;
-        Compound           :: 0x06;
-        Array              :: 0x07;
-        Slice              :: 0x08;
-        Dynamic_Array      :: 0x09;
-        Variadic_Argument  :: 0x0a;
-        Enum               :: 0x0b;
-        Distinct           :: 0x0c;
-    }
-
-    kind := Kind.Invalid;
-    size: u32;
-
-    // Does this need to know alignment? Probably?
-    alignment: u32;
-}
-
-Type_Info_Basic :: struct {
-    use base : Type_Info;
-
-    // This must match the order of the elements in BasicKind in onyxtypes.h
-    Kind :: enum {
-        Void  :: 0x00;
-        Bool  :: 0x01;
-
-        Unsized_Int :: 0x02;
-        I8    :: 0x03;
-        U8    :: 0x04;
-        I16   :: 0x05;
-        U16   :: 0x06;
-        I32   :: 0x07;
-        U32   :: 0x08;
-        I64   :: 0x09;
-        U64   :: 0x0a;
-
-        Unsized_Float :: 0x0b;
-        F32   :: 0x0c;
-        F64   :: 0x0d;
-
-        Rawptr :: 0x0e;
-
-        I8X16 :: 0x0f;
-        I16X8 :: 0x10;
-        I32X4 :: 0x11;
-        I64X2 :: 0x12;
-        F32X4 :: 0x13;
-        F64X2 :: 0x14;
-        V128  :: 0x15;
-
-        Type_Index :: 0x16;
-    }
-
-    basic_kind: Kind;
-}
-
-Type_Info_Pointer :: struct {
-    use base : Type_Info;
-
-    @Rename
-    to: type_expr;
-}
-
-Type_Info_Function :: struct {
-    use base : Type_Info;
-
-    return_type:        type_expr;
-    parameter_types: [] type_expr;
-
-    is_variadic: bool;
-}
-
-Type_Info_Array :: struct {
-    use base : Type_Info;
-
-    @Rename
-    of: type_expr;
-    count: u32;
-}
-
-Type_Info_Slice :: struct {
-    use base : Type_Info;
-
-    @Rename
-    of: type_expr;
-}
-
-Type_Info_Dynamic_Array :: struct {
-    use base : Type_Info;
-
-    @Rename
-    of: type_expr;
-}
-
-Type_Info_Variadic_Argument :: struct {
-    use base : Type_Info;
-
-    @Rename
-    of: type_expr;
-}
-
-Type_Info_Enum :: struct {
-    use base : Type_Info;
-
-    Member :: struct {
-        name: str;
-        value: u64; // This assumes enums are always represented as ints.
-    }
-
-    // This is first for better alignment
-    backing_type: type_expr;
-    name: str;
-    members: [] Member;
-
-    is_flags: bool;
-}
-
-Type_Info_Struct :: struct {
-    use base : Type_Info;
-
-    Member :: struct {
-        name: str;
-        offset: u32;
-        type: type_expr;
-
-        used: bool;
-        default: rawptr; // Pointer to the initial value of the same type as the member.
-                         // null if no default value is given, or if it is not compile time known.
-
-                         // As another thought. This could become a thunk that get the default value
-                         // at runtime or returns the value.
-
-        tags: [] any;
-    }
-
-    constructed_from: type_expr;
-    name: str;
-    members: [] Member;
-    parameters: [] any;
-    tags: [] any;
-
-    Method :: struct {
-        name: str;
-        func: any;
-    }
-    methods: [] Method;
-}
-
-Type_Info_Polymorphic_Struct :: struct {
-    use base : Type_Info;
-
-    name: str;
-    tags: [] any;
-}
-
-Type_Info_Compound :: struct {
-    use base : Type_Info;
-
-    components : [] type_expr;
-}
-
-Type_Info_Distinct :: struct {
-    use base : Type_Info;
-
-    base_type: type_expr;
-    name: str;
-}
-
-get_type_info :: (t: type_expr) -> ^Type_Info {
-    // Grossness to get around the fact that type_exprs are not technically comparable, because in most
-    // cases you should not compare them as the number assigned to them is arbitrary.
-    if ~~t < cast(i32) 0 || ~~t >= cast(i32) type_table.count do return null;
-
-    return type_table[cast(i32) t];
-}
-
-
-
-
-//
-// I have a small feeling I am going to rename "type_info" at some point soon,
-// which makes including this here make even more sense.
-//
-// Alternate names for "type_info" could be:
-//
-//    - reflect
-//    - introspect
-//    - runtime.info   I kind of like this so then things are in the runtime package.
-//                     runtime can be for things defined in the language, whil core
-//                     core can be for standard library like functionality.
-
-
-//
-// Foreign Blocks
-// Because foreign blocks can generate a lot of data, and their data is only
-// really helpful in a handful of cases, you need to pass "--generate-foreign-bindings"
-// to have these arrays filled out.
-//
-
-foreign_block :: #distinct u32
-
-foreign_blocks: [] ^Foreign_Block;
-
-Foreign_Block :: struct {
-    module_name: str;
-    funcs: [] Foreign_Function;
-
-    Foreign_Function :: struct {
-        name: str;
-        type: type_expr;
-    }
-}
-
-get_foreign_block :: (f: foreign_block) -> ^Foreign_Block {
-    if ~~f < cast(i32) 0 || ~~f >= cast(i32) foreign_blocks.count do return null;
-
-    return foreign_blocks[cast(i32) f];
-}
\ No newline at end of file
index a1d3fb603f3952554a34146d56b6c7c37696407e..3a4defba7f90aae6e0007e8d782d7026187b60b0 100644 (file)
@@ -67,7 +67,7 @@ This type represents a custom iterator that can be iterated over using a `for` l
 This type represents the value given by the `#callsite` expression. In practice, you will never use this type because you will just do something like: `f :: (site := #callsite)`
 
 - `any` -
-This type represents any value. It does this by using a data pointer and a type expression. Using the `builtin.type_info` package, you can introspect that type expression to retrieve data about the type, and from there reconstruct how to use the data pointer. See `conv.onyx` for how this works with `printf`.
+This type represents any value. It does this by using a data pointer and a type expression. Using the `runtime.info` package, you can introspect that type expression to retrieve data about the type, and from there reconstruct how to use the data pointer. See `conv.onyx` for how this works with `printf`.
 
 - `Code` -
 This is a dummy type that represents the type of a `#unquote {}` block. It is used when passing code around to macros or procedures, i.e. `f :: macro (body: Code)`
\ No newline at end of file
index 2fac9425015f8530ed460345ef0b3c6122417ac8..740667e140dbefeb8ecf9595fa34b7f8c94c75f1 100644 (file)
@@ -39,7 +39,6 @@
     NODE(DirectiveOperator)    \
     NODE(DirectiveExport)      \
     NODE(DirectiveDefined)     \
-    NODE(DirectiveTag)         \
     NODE(DirectiveInit)        \
     NODE(DirectiveLibrary)     \
     NODE(DirectiveRemove)      \
@@ -211,7 +210,6 @@ typedef enum AstKind {
     Ast_Kind_Directive_Operator,
     Ast_Kind_Directive_Export,
     Ast_Kind_Directive_Defined,
-    Ast_Kind_Directive_Tag,
     Ast_Kind_Directive_Init,
     Ast_Kind_Directive_Library,
     Ast_Kind_Directive_Remove,
@@ -1267,13 +1265,6 @@ struct AstDirectiveDefined {
     b32 is_defined: 1;
 };
 
-struct AstDirectiveTag {
-    AstNode_base;
-
-    AstTyped* expr;
-    AstTyped* tag;
-};
-
 struct AstDirectiveRemove {
     AstNode_base;
 };
index 127e1e68ce62265d984ba2177bc48f4e66d0a0a7..41fc415320f1c829aceb7beeb125f827453e37c2 100644 (file)
@@ -111,7 +111,7 @@ Immediate_Renderer :: struct {
 
         gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
 
-        offset_of :: (package builtin.type_info).offset_of;
+        offset_of :: (package runtime.info).offset_of;
         IV :: Immediate_Vertex;
 
         // Position
index 4d577febde5cc704f30e3e9e2c9685e32e7997fe..9ac549b45d57e7d39b20f2abc17c401ddfbfcffe 100644 (file)
@@ -2,6 +2,7 @@ package c_binding
 
 use package core
 use package simd
+#local info :: package runtime.info
 
 #if !#defined((package runtime).Generated_Foreign_Info) {
     #error "Please run this script with the '--generate-foreign-info' flag."
@@ -18,7 +19,7 @@ Impl_Mapping :: struct {
 }
 
 Binding_Config :: struct {
-    foreign_block: type_info.foreign_block;
+    foreign_block: info.foreign_block;
     preamble: [] str;
     output_file: str;
     cast_map: [] Cast_Mapping;
@@ -28,7 +29,7 @@ Binding_Config :: struct {
 build_c_binding :: (use binding_config: Binding_Config) -> bool {
     for file: os.with_file(output_file, .Write) {
         writer := io.writer_make(file);
-        fb := type_info.get_foreign_block(foreign_block);
+        fb := info.get_foreign_block(foreign_block);
 
         write_file_introduction(^writer, preamble, fb.module_name);
 
@@ -69,7 +70,7 @@ write_file_introduction :: (writer: ^io.Writer, preamble: [] str, name: str) {
 }
 
 write_function_body :: (writer, ff, cast_map) => {
-    use type_info;
+    use info;
 
     method_type := ff.type;
     method_info := cast (^Type_Info_Function) get_type_info(method_type);
@@ -104,7 +105,7 @@ write_library_block :: (writer, funcs) => {
 }
 
 print_body :: (writer, method_name, method_info, cast_map) => {
-    use type_info;
+    use info;
     call := io.dynamic_string_stream_make();
     defer io.dynamic_string_stream_free(^call);
     callw := io.writer_make(^call);
@@ -149,7 +150,7 @@ print_body :: (writer, method_name, method_info, cast_map) => {
 }
 
 type_to_wasm_type :: (t: type_expr) -> str {
-    use type_info;
+    use info;
 
     param_info := get_type_info(t);
     switch param_info.kind {
@@ -195,7 +196,7 @@ type_to_wasm_type :: (t: type_expr) -> str {
 }
 
 type_encoding :: (t: type_expr) -> str {
-    use type_info;
+    use info;
 
     param_info := get_type_info(t);
     switch param_info.kind {
index 7227d9fb1a3ef0683adb2db57c1c1ae7477baec3..3655d2d611a8b61720adf2463f40b67de06945b9 100644 (file)
@@ -457,7 +457,7 @@ void initialize_builtins(bh_allocator a) {
 
     bh_arr_new(global_heap_allocator, init_procedures, 4);
 
-    p = package_lookup("builtin.type_info");
+    p = package_lookup("runtime.info");
     if (p != NULL) {
         type_table_node     = (AstTyped *) symbol_raw_resolve(p->scope, "type_table");
         foreign_blocks_node = (AstTyped *) symbol_raw_resolve(p->scope, "foreign_blocks");
index 8a8fd1c75e6cd08fed4d2a032b581dfc2ee20536..52b10f94ce06143d38b1999607ee48515449ed30 100644 (file)
@@ -2610,67 +2610,6 @@ CheckStatus check_process_directive(AstNode* directive) {
         export->export_name = export->export_name_expr->token;
     }
 
-    if (directive->kind == Ast_Kind_Directive_Tag) {
-        AstDirectiveTag *tag = (AstDirectiveTag *) directive;
-
-        CHECK(expression, &tag->tag);
-
-        switch (tag->expr->kind) {
-            case Ast_Kind_Struct_Type: {
-                AstStructType* st = (AstStructType *) tag->expr;
-
-                bh_arr(AstTyped *) tags = st->meta_tags;
-
-                if (tags == NULL) bh_arr_new(global_heap_allocator, tags, 1);
-                bh_arr_push(tags, tag->tag);
-
-                st->meta_tags = tags;
-
-                return Check_Complete;
-            }
-
-            case Ast_Kind_Field_Access: {
-                AstFieldAccess* fa = (AstFieldAccess *) tag->expr;
-
-                if (fa->expr->kind == Ast_Kind_Struct_Type) {
-                    // CLEANUP: Everything in this case is handled very poorly.
-                    AstStructType* st = (AstStructType *) fa->expr;
-                    Type* s_type = type_build_from_ast(context.ast_alloc, (AstType *) st);
-
-                    bh_arr_each(AstStructMember *, smem, st->members) {
-                        if (token_equals((*smem)->token, fa->token)) {
-                            bh_arr(AstTyped *) tags = (*smem)->meta_tags;
-
-                            if (tags == NULL) bh_arr_new(global_heap_allocator, tags, 1);
-                            bh_arr_push(tags, tag->tag);
-
-                            (*smem)->meta_tags = tags;
-
-                            bh_arr_each(StructMember *, smem_type, s_type->Struct.memarr) {
-                                if (token_text_equals((*smem)->token, (*smem_type)->name)) {
-                                    (*smem_type)->meta_tags = tags;
-                                    break;
-                                }
-                            }
-
-                            return Check_Complete;
-                        }
-                    }
-
-                    onyx_report_error(fa->token->pos, Error_Critical, "'%b' is not a member of '%s'.",
-                        fa->token->text, fa->token->length,
-                        st->name);
-                    return Check_Error;
-                }
-            }
-
-            default: {
-                onyx_report_error(tag->token->pos, Error_Critical, "Cannot tag this.");
-                return Check_Error;
-            }
-        }
-    }
-
     if (directive->kind == Ast_Kind_Directive_Init) {
         AstDirectiveInit *init = (AstDirectiveInit *) directive;
         if ((init->flags & Ast_Flag_Has_Been_Checked) == 0) {
index c50dd4650f011c59c3310b59e38e63cb3c598013..e5961e5111ed366e27eb222c170dc32a8b03a47b 100644 (file)
@@ -352,7 +352,6 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s
 
         case Ast_Kind_Directive_Export:
         case Ast_Kind_Directive_Add_Overload:
-        case Ast_Kind_Directive_Tag:
         case Ast_Kind_Directive_Operator:
         case Ast_Kind_Directive_Init:
         case Ast_Kind_Directive_Library: {
index f0db93104fde8bc9d822fdf32e7ebd5bf20a3a3f..9154d8a32884caec00482df95d06515e2f71310a 100644 (file)
@@ -262,7 +262,13 @@ static void context_init(CompileOptions* opts) {
         .state = Entity_State_Parse_Builtin,
         .type = Entity_Type_Load_File,
         .package = NULL,
-        .include = create_load(context.ast_alloc, "core/type_info/type_info"),
+        .include = create_load(context.ast_alloc, "core/runtime/info/types"),
+    }));
+    entity_heap_insert(&context.entities, ((Entity) {
+        .state = Entity_State_Parse_Builtin,
+        .type = Entity_Type_Load_File,
+        .package = NULL,
+        .include = create_load(context.ast_alloc, "core/runtime/info/foreign_blocks"),
     }));
 
     entity_heap_insert(&context.entities, ((Entity) {
index d0537d5b80cd04c2517a45fbffc3ce9d0fe88673..defe98024c3a5382f8f2faf6142db661d3b29f81 100644 (file)
@@ -3172,17 +3172,6 @@ static void parse_top_level_statement(OnyxParser* parser) {
                 ENTITY_SUBMIT(export);
                 return;
             }
-            else if (parse_possible_directive(parser, "tag")) {
-                AstDirectiveTag *tag = make_node(AstDirectiveTag, Ast_Kind_Directive_Tag);
-                tag->token = dir_token;
-
-                tag->expr = parse_expression(parser, 0);
-                expect_token(parser, ',');
-                tag->tag = parse_expression(parser, 0);
-
-                ENTITY_SUBMIT(tag);
-                return;
-            }
             else if (parse_possible_directive(parser, "thread_local")) {
                 OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
                 AstMemRes* memres = parse_memory_reservation(parser, symbol, 1);
index 8999a4f2a4f48d2d8997aeef78a50c6d908a03e5..b5edf7ac08a9b2bb067cf8c5da6c8d29f72cbf74 100644 (file)
@@ -1400,13 +1400,6 @@ static SymresStatus symres_process_directive(AstNode* directive) {
             break;
         }
 
-        case Ast_Kind_Directive_Tag: {
-            AstDirectiveTag *tag = (AstDirectiveTag *) directive;
-            SYMRES(expression, &tag->tag);
-            SYMRES(expression, &tag->expr);
-            break;
-        }
-
         case Ast_Kind_Directive_Init: {
             AstDirectiveInit *init = (AstDirectiveInit *) directive;
             SYMRES(expression, &init->init_proc);
index 4e50e8e148be349f328dc770aef4305165fe3653..80ed9df21e3bcdb37aaca21018a9d51ceb0298c6 100644 (file)
@@ -24,7 +24,7 @@ u64 build_type_table(OnyxWasmModule* module) {
     if (POINTER_SIZE == 4) bh_buffer_write_u32(&table_buffer, count); \
     if (POINTER_SIZE == 8) bh_buffer_write_u64(&table_buffer, count); 
 
-    // This is the data behind the "type_table" slice in type_info.onyx
+    // This is the data behind the "type_table" slice in runtime/info/types.onyx
     #if (POINTER_SIZE == 4)
         #define Table_Info_Type u32
     #else
index eb32103661921ea5e44976e45e480ca87aeec108..6a02256899fdda6058ef518855b95436442445ab 100644 (file)
@@ -1,5 +1,6 @@
 #load "core/std"
 use package core
+info :: package runtime.info
 
 Base :: struct (T: type_expr) {
     const: i32;
@@ -11,8 +12,8 @@ main :: (args) => {
 
     x := Base(str).{ 10, "Hello" };
     printf("{}\n", x);
-    printf("{}\n", type_info.struct_constructed_from(typeof x, Base));
+    printf("{}\n", info.struct_constructed_from(typeof x, Base));
 
     y: Allocator;
-    printf("{}\n", type_info.struct_constructed_from(typeof y, Base));
+    printf("{}\n", info.struct_constructed_from(typeof y, Base));
 }
\ No newline at end of file