From: Brendan Hansen Date: Tue, 10 May 2022 01:57:53 +0000 (-0500) Subject: BREAKING renamed type_info to runtime.info X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=7263217c4104e6906d2497725d85363347b20c88;p=onyx.git BREAKING renamed type_info to runtime.info --- diff --git a/core/arg_parse.onyx b/core/arg_parse.onyx index 31e2e2e8..01255cd6 100644 --- a/core/arg_parse.onyx +++ b/core/arg_parse.onyx @@ -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; diff --git a/core/builtin.onyx b/core/builtin.onyx index 068f9803..3146e1fd 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -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 index 00000000..73d35f9d --- /dev/null +++ b/core/container/avl_tree.onyx @@ -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; + } +} + diff --git a/core/conv.onyx b/core/conv.onyx index dfe9871a..e62f35f5 100644 --- a/core/conv.onyx +++ b/core/conv.onyx @@ -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 index 00000000..e1f8f979 --- /dev/null +++ b/core/runtime/info/foreign_blocks.onyx @@ -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 index 00000000..e0aed03a --- /dev/null +++ b/core/runtime/info/helper.onyx @@ -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, ""); + case .Unsized_Float do io.write_str(writer, ""); + } + } + + 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, ""); + } + + 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, ""); + } + + 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 index 00000000..0eb3dfaa --- /dev/null +++ b/core/runtime/info/types.onyx @@ -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]; +} + + diff --git a/core/std.onyx b/core/std.onyx index 83d6aaf9..ec79d75b 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -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 index 47a3ac89..00000000 --- a/core/type_info/helper.onyx +++ /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, ""); - case .Unsized_Float do io.write_str(writer, ""); - } - } - - 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, ""); - } - - 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, ""); - } - - 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 index e16f54f8..00000000 --- a/core/type_info/type_info.onyx +++ /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 diff --git a/docs/builtins.md b/docs/builtins.md index a1d3fb60..3a4defba 100644 --- a/docs/builtins.md +++ b/docs/builtins.md @@ -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 diff --git a/include/astnodes.h b/include/astnodes.h index 2fac9425..740667e1 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -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; }; diff --git a/modules/immediate_mode/immediate_renderer.onyx b/modules/immediate_mode/immediate_renderer.onyx index 127e1e68..41fc4153 100644 --- a/modules/immediate_mode/immediate_renderer.onyx +++ b/modules/immediate_mode/immediate_renderer.onyx @@ -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 diff --git a/scripts/c_binding.onyx b/scripts/c_binding.onyx index 4d577feb..9ac549b4 100644 --- a/scripts/c_binding.onyx +++ b/scripts/c_binding.onyx @@ -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 { diff --git a/src/builtins.c b/src/builtins.c index 7227d9fb..3655d2d6 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -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"); diff --git a/src/checker.c b/src/checker.c index 8a8fd1c7..52b10f94 100644 --- a/src/checker.c +++ b/src/checker.c @@ -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) { diff --git a/src/entities.c b/src/entities.c index c50dd465..e5961e51 100644 --- a/src/entities.c +++ b/src/entities.c @@ -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: { diff --git a/src/onyx.c b/src/onyx.c index f0db9310..9154d8a3 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -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) { diff --git a/src/parser.c b/src/parser.c index d0537d5b..defe9802 100644 --- a/src/parser.c +++ b/src/parser.c @@ -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); diff --git a/src/symres.c b/src/symres.c index 8999a4f2..b5edf7ac 100644 --- a/src/symres.c +++ b/src/symres.c @@ -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); diff --git a/src/wasm_type_table.h b/src/wasm_type_table.h index 4e50e8e1..80ed9df2 100644 --- a/src/wasm_type_table.h +++ b/src/wasm_type_table.h @@ -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 diff --git a/tests/poly_struct_in_type_info.onyx b/tests/poly_struct_in_type_info.onyx index eb321036..6a022568 100644 --- a/tests/poly_struct_in_type_info.onyx +++ b/tests/poly_struct_in_type_info.onyx @@ -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