mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 22:28:46 +00:00
union type allow for any types and removes common fields
This commit is contained in:
+73
-48
@@ -34,59 +34,54 @@ CallingConvention :: enum {
|
||||
}
|
||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||
// The compiler relies upon this _exact_ order
|
||||
TypeInfo :: struct #ordered {
|
||||
// Core Types
|
||||
EnumValue :: raw_union {
|
||||
f: f64;
|
||||
i: i128;
|
||||
}
|
||||
Record :: struct #ordered {
|
||||
types: []^TypeInfo;
|
||||
names: []string;
|
||||
offsets: []int; // offsets may not be used in tuples
|
||||
usings: []bool; // usings may not be used in tuples
|
||||
packed: bool;
|
||||
ordered: bool;
|
||||
custom_align: bool;
|
||||
}
|
||||
|
||||
|
||||
TypeInfoEnumValue :: raw_union {
|
||||
f: f64;
|
||||
i: i128;
|
||||
}
|
||||
|
||||
TypeInfoRecord :: struct #ordered {
|
||||
types: []^TypeInfo;
|
||||
names: []string;
|
||||
offsets: []int; // offsets may not be used in tuples
|
||||
usings: []bool; // usings may not be used in tuples
|
||||
packed: bool;
|
||||
ordered: bool;
|
||||
custom_align: bool;
|
||||
}
|
||||
|
||||
|
||||
TypeInfo :: union {
|
||||
size: int;
|
||||
align: int;
|
||||
|
||||
Named{name: string; base: ^TypeInfo};
|
||||
Integer{signed: bool};
|
||||
Rune{};
|
||||
Float{};
|
||||
Complex{};
|
||||
String{};
|
||||
Boolean{};
|
||||
Any{};
|
||||
Pointer{
|
||||
// Variant Types
|
||||
Named :: struct #ordered {name: string; base: ^TypeInfo};
|
||||
Integer :: struct #ordered {signed: bool};
|
||||
Rune :: struct{};
|
||||
Float :: struct{};
|
||||
Complex :: struct{};
|
||||
String :: struct{};
|
||||
Boolean :: struct{};
|
||||
Any :: struct{};
|
||||
Pointer :: struct #ordered {
|
||||
elem: ^TypeInfo; // nil -> rawptr
|
||||
};
|
||||
Atomic{elem: ^TypeInfo};
|
||||
Procedure{
|
||||
Atomic :: struct #ordered {elem: ^TypeInfo};
|
||||
Procedure :: struct #ordered {
|
||||
params: ^TypeInfo; // TypeInfo.Tuple
|
||||
results: ^TypeInfo; // TypeInfo.Tuple
|
||||
variadic: bool;
|
||||
convention: CallingConvention;
|
||||
};
|
||||
Array{
|
||||
Array :: struct #ordered {
|
||||
elem: ^TypeInfo;
|
||||
elem_size: int;
|
||||
count: int;
|
||||
};
|
||||
DynamicArray{elem: ^TypeInfo; elem_size: int};
|
||||
Slice {elem: ^TypeInfo; elem_size: int};
|
||||
Vector {elem: ^TypeInfo; elem_size, count: int};
|
||||
Tuple {using record: TypeInfoRecord}; // Only really used for procedures
|
||||
Struct {using record: TypeInfoRecord};
|
||||
RawUnion {using record: TypeInfoRecord};
|
||||
Union{
|
||||
common_fields: struct {
|
||||
DynamicArray :: struct #ordered {elem: ^TypeInfo; elem_size: int};
|
||||
Slice :: struct #ordered {elem: ^TypeInfo; elem_size: int};
|
||||
Vector :: struct #ordered {elem: ^TypeInfo; elem_size, count: int};
|
||||
Tuple :: Record; // Only really used for procedures
|
||||
Struct :: Record;
|
||||
RawUnion :: Record;
|
||||
Union :: struct #ordered {
|
||||
common_fields: struct #ordered {
|
||||
types: []^TypeInfo;
|
||||
names: []string;
|
||||
offsets: []int; // offsets may not be used in tuples
|
||||
@@ -94,22 +89,52 @@ TypeInfo :: union {
|
||||
variant_names: []string;
|
||||
variant_types: []^TypeInfo;
|
||||
};
|
||||
Enum{
|
||||
Enum :: struct #ordered {
|
||||
base: ^TypeInfo;
|
||||
names: []string;
|
||||
values: []TypeInfoEnumValue;
|
||||
values: []EnumValue;
|
||||
};
|
||||
Map{
|
||||
Map :: struct #ordered {
|
||||
key: ^TypeInfo;
|
||||
value: ^TypeInfo;
|
||||
generated_struct: ^TypeInfo;
|
||||
count: int; // == 0 if dynamic
|
||||
};
|
||||
BitField{
|
||||
BitField :: struct #ordered {
|
||||
names: []string;
|
||||
bits: []i32;
|
||||
offsets: []i32;
|
||||
};
|
||||
|
||||
|
||||
// Fields
|
||||
size: int;
|
||||
align: int;
|
||||
|
||||
variant: union {
|
||||
Named,
|
||||
Integer,
|
||||
Rune,
|
||||
Float,
|
||||
Complex,
|
||||
String,
|
||||
Boolean,
|
||||
Any,
|
||||
Pointer,
|
||||
Atomic,
|
||||
Procedure,
|
||||
Array,
|
||||
DynamicArray,
|
||||
Slice,
|
||||
Vector,
|
||||
Tuple,
|
||||
Struct,
|
||||
RawUnion,
|
||||
Union,
|
||||
Enum,
|
||||
Map,
|
||||
BitField,
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE(bill): only the ones that are needed (not all types)
|
||||
@@ -147,7 +172,7 @@ Context :: struct #ordered {
|
||||
|
||||
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
||||
|
||||
SourceCodeLocation :: struct {
|
||||
SourceCodeLocation :: struct #ordered {
|
||||
fully_pathed_filename: string;
|
||||
line, column: i64;
|
||||
procedure: string;
|
||||
@@ -190,7 +215,7 @@ type_info_base :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
match i in base {
|
||||
match i in base.variant {
|
||||
case TypeInfo.Named: base = i.base;
|
||||
}
|
||||
return base;
|
||||
@@ -201,7 +226,7 @@ type_info_base_without_enum :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
if info == nil do return nil;
|
||||
|
||||
base := info;
|
||||
match i in base {
|
||||
match i in base.variant {
|
||||
case TypeInfo.Named: base = i.base;
|
||||
case TypeInfo.Enum: base = i.base;
|
||||
}
|
||||
|
||||
+36
-50
@@ -10,8 +10,8 @@ import (
|
||||
_BUFFER_SIZE :: 1<<12;
|
||||
|
||||
StringBuffer :: union {
|
||||
Static {buf: []u8;};
|
||||
Dynamic{buf: [dynamic]u8;};
|
||||
[]u8,
|
||||
[dynamic]u8,
|
||||
}
|
||||
|
||||
FmtInfo :: struct {
|
||||
@@ -34,28 +34,18 @@ FmtInfo :: struct {
|
||||
}
|
||||
|
||||
|
||||
make_string_buffer_from_slice :: proc(b: []u8) -> StringBuffer {
|
||||
return StringBuffer.Static{b};
|
||||
}
|
||||
|
||||
make_string_dynamic_buffer :: proc() -> StringBuffer {
|
||||
return StringBuffer.Dynamic{make([dynamic]u8)};
|
||||
}
|
||||
string_buffer_data :: proc(buf: ^StringBuffer) -> []u8 {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
return b.buf[..];
|
||||
case StringBuffer.Dynamic:
|
||||
return b.buf[..];
|
||||
case []u8: return b[..];
|
||||
case [dynamic]u8: return b[..];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
string_buffer_data :: proc(buf: StringBuffer) -> []u8 {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
return b.buf[..];
|
||||
case StringBuffer.Dynamic:
|
||||
return b.buf[..];
|
||||
case []u8: return b[..];
|
||||
case [dynamic]u8: return b[..];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
@@ -69,18 +59,14 @@ write_string :: proc(buf: ^StringBuffer, s: string) {
|
||||
}
|
||||
write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
append(&b.buf, ...data);
|
||||
case StringBuffer.Dynamic:
|
||||
append(&b.buf, ...data);
|
||||
case []u8: append(b, ...data);
|
||||
case [dynamic]u8: append(b, ...data);
|
||||
}
|
||||
}
|
||||
write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
append(&b.buf, data);
|
||||
case StringBuffer.Dynamic:
|
||||
append(&b.buf, data);
|
||||
case []u8: append(b, data);
|
||||
case [dynamic]u8: append(b, data);
|
||||
}
|
||||
}
|
||||
write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
||||
@@ -108,7 +94,7 @@ write_int :: proc(buf: ^StringBuffer, i: i64, base: int) {
|
||||
|
||||
fprint :: proc(fd: os.Handle, args: ...any) -> int {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[..0]);
|
||||
buf := StringBuffer(data[..0]);
|
||||
sbprint(&buf, ...args);
|
||||
res := string_buffer_data(buf);
|
||||
os.write(fd, res);
|
||||
@@ -117,7 +103,7 @@ fprint :: proc(fd: os.Handle, args: ...any) -> int {
|
||||
|
||||
fprintln :: proc(fd: os.Handle, args: ...any) -> int {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[..0]);
|
||||
buf := StringBuffer(data[..0]);
|
||||
sbprintln(&buf, ...args);
|
||||
res := string_buffer_data(buf);
|
||||
os.write(fd, res);
|
||||
@@ -125,7 +111,7 @@ fprintln :: proc(fd: os.Handle, args: ...any) -> int {
|
||||
}
|
||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[..0]);
|
||||
buf := StringBuffer(data[..0]);
|
||||
sbprintf(&buf, fmt, ...args);
|
||||
res := string_buffer_data(buf);
|
||||
os.write(fd, res);
|
||||
@@ -145,17 +131,17 @@ printf_err :: proc(fmt: string, args: ...any) -> int { return fprintf(os.stderr
|
||||
// aprint* procedures return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
aprint :: proc(args: ...any) -> string {
|
||||
buf := make_string_dynamic_buffer();
|
||||
buf := StringBuffer(make([dynamic]u8));
|
||||
sbprint(&buf, ...args);
|
||||
return to_string(buf);
|
||||
}
|
||||
aprintln :: proc(args: ...any) -> string {
|
||||
buf := make_string_dynamic_buffer();
|
||||
buf := StringBuffer(make([dynamic]u8));
|
||||
sbprintln(&buf, ...args);
|
||||
return to_string(buf);
|
||||
}
|
||||
aprintf :: proc(fmt: string, args: ...any) -> string {
|
||||
buf := make_string_dynamic_buffer();
|
||||
buf := StringBuffer(make([dynamic]u8));
|
||||
sbprintf(&buf, fmt, ...args);
|
||||
return to_string(buf);
|
||||
}
|
||||
@@ -164,15 +150,15 @@ aprintf :: proc(fmt: string, args: ...any) -> string {
|
||||
// bprint* procedures return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
bprint :: proc(buf: []u8, args: ...any) -> string {
|
||||
sb := make_string_buffer_from_slice(buf[..0..len(buf)]);
|
||||
sb := StringBuffer(buf[..0..len(buf)]);
|
||||
return sbprint(&sb, ...args);
|
||||
}
|
||||
bprintln :: proc(buf: []u8, args: ...any) -> string {
|
||||
sb := make_string_buffer_from_slice(buf[..0..len(buf)]);
|
||||
sb := StringBuffer(buf[..0..len(buf)]);
|
||||
return sbprintln(&sb, ...args);
|
||||
}
|
||||
bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
|
||||
sb := make_string_buffer_from_slice(buf[..0..len(buf)]);
|
||||
sb := StringBuffer(buf[..0..len(buf)]);
|
||||
return sbprintf(&sb, fmt, ...args);
|
||||
}
|
||||
|
||||
@@ -183,7 +169,7 @@ bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
|
||||
|
||||
fprint_type :: proc(fd: os.Handle, info: ^TypeInfo) {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[..0]);
|
||||
buf := StringBuffer(data[..0]);
|
||||
write_type(&buf, info);
|
||||
os.write(fd, string_buffer_data(buf));
|
||||
}
|
||||
@@ -192,7 +178,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
if ti == nil do return;
|
||||
|
||||
using TypeInfo;
|
||||
match info in ti {
|
||||
match info in ti.variant {
|
||||
case Named:
|
||||
write_string(buf, info.name);
|
||||
case Integer:
|
||||
@@ -201,18 +187,18 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
case ti == type_info(uint): write_string(buf, "uint");
|
||||
case:
|
||||
write_string(buf, info.signed ? "i" : "u");
|
||||
write_int(buf, i64(8*info.size), 10);
|
||||
write_int(buf, i64(8*ti.size), 10);
|
||||
}
|
||||
case Rune:
|
||||
write_string(buf, "rune");
|
||||
case Float:
|
||||
match info.size {
|
||||
match ti.size {
|
||||
case 2: write_string(buf, "f16");
|
||||
case 4: write_string(buf, "f32");
|
||||
case 8: write_string(buf, "f64");
|
||||
}
|
||||
case Complex:
|
||||
match info.size {
|
||||
match ti.size {
|
||||
case 4: write_string(buf, "complex32");
|
||||
case 8: write_string(buf, "complex64");
|
||||
case 16: write_string(buf, "complex128");
|
||||
@@ -237,7 +223,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
if info.params == nil {
|
||||
write_string(buf, "()");
|
||||
} else {
|
||||
t := info.params.(^Tuple);
|
||||
t := info.params.variant.(Tuple);
|
||||
write_string(buf, "(");
|
||||
for t, i in t.types {
|
||||
if i > 0 do write_string(buf, ", ");
|
||||
@@ -295,7 +281,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
if info.ordered do write_string(buf, "#ordered ");
|
||||
if info.custom_align {
|
||||
write_string(buf, "#align ");
|
||||
write_int(buf, i64(info.align), 10);
|
||||
write_int(buf, i64(ti.align), 10);
|
||||
write_byte(buf, ' ');
|
||||
}
|
||||
write_byte(buf, '{');
|
||||
@@ -324,8 +310,8 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
write_byte(buf, '{');
|
||||
defer write_byte(buf, '}');
|
||||
|
||||
variant_type := type_info_base(info.variant_types[i]);
|
||||
variant := variant_type.(^Struct);
|
||||
variant_type := type_info_base(info.variant_types[i]).variant;
|
||||
variant := (&variant_type).(Struct);
|
||||
|
||||
vc := len(variant.names)-len(cf.names);
|
||||
for j in 0..vc {
|
||||
@@ -359,9 +345,9 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
write_string(buf, "}");
|
||||
case BitField:
|
||||
write_string(buf, "bit_field ");
|
||||
if info.align != 1 {
|
||||
if ti.align != 1 {
|
||||
write_string(buf, "#align ");
|
||||
write_int(buf, i64(info.align), 10);
|
||||
write_int(buf, i64(ti.align), 10);
|
||||
write_rune(buf, ' ');
|
||||
}
|
||||
write_string(buf, " {");
|
||||
@@ -697,7 +683,7 @@ fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
|
||||
using TypeInfo;
|
||||
match e in v.type_info {
|
||||
match e in v.type_info.variant {
|
||||
case:
|
||||
fmt_bad_verb(fi, verb);
|
||||
return;
|
||||
@@ -768,9 +754,9 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
|
||||
using TypeInfo;
|
||||
match info in v.type_info {
|
||||
match info in v.type_info.variant {
|
||||
case Named:
|
||||
match b in info.base {
|
||||
match b in info.base.variant {
|
||||
case Struct:
|
||||
if verb != 'v' {
|
||||
fmt_bad_verb(fi, verb);
|
||||
@@ -866,9 +852,9 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
defer write_byte(fi.buf, ']');
|
||||
|
||||
entries := &(^raw.DynamicMap(v.data).entries);
|
||||
gs := type_info_base(info.generated_struct).(^Struct);
|
||||
ed := type_info_base(gs.types[1]).(^DynamicArray);
|
||||
entry_type := ed.elem.(^Struct);
|
||||
gs := type_info_base(info.generated_struct).variant.(Struct);
|
||||
ed := type_info_base(gs.types[1]).variant.(DynamicArray);
|
||||
entry_type := ed.elem.variant.(Struct);
|
||||
entry_size := ed.elem_size;
|
||||
|
||||
for i in 0..entries.len {
|
||||
|
||||
+15
-15
@@ -208,15 +208,15 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
WORD_SIZE :: size_of(int);
|
||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||
using TypeInfo;
|
||||
match info in type_info {
|
||||
match info in type_info.variant {
|
||||
case Named:
|
||||
return align_of_type_info(info.base);
|
||||
case Integer:
|
||||
return info.size;
|
||||
return type_info.align;
|
||||
case Rune:
|
||||
return info.size;
|
||||
return type_info.align;
|
||||
case Float:
|
||||
return info.size;
|
||||
return type_info.align;
|
||||
case String:
|
||||
return WORD_SIZE;
|
||||
case Boolean:
|
||||
@@ -239,13 +239,13 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
total := size * count;
|
||||
return clamp(total, 1, MAX_ALIGN);
|
||||
case Tuple:
|
||||
return info.align;
|
||||
return type_info.align;
|
||||
case Struct:
|
||||
return info.align;
|
||||
return type_info.align;
|
||||
case Union:
|
||||
return info.align;
|
||||
return type_info.align;
|
||||
case RawUnion:
|
||||
return info.align;
|
||||
return type_info.align;
|
||||
case Enum:
|
||||
return align_of_type_info(info.base);
|
||||
case Map:
|
||||
@@ -263,15 +263,15 @@ align_formula :: proc(size, align: int) -> int {
|
||||
size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
WORD_SIZE :: size_of(int);
|
||||
using TypeInfo;
|
||||
match info in type_info {
|
||||
match info in type_info.variant {
|
||||
case Named:
|
||||
return size_of_type_info(info.base);
|
||||
case Integer:
|
||||
return info.size;
|
||||
return type_info.size;
|
||||
case Rune:
|
||||
return info.size;
|
||||
return type_info.size;
|
||||
case Float:
|
||||
return info.size;
|
||||
return type_info.size;
|
||||
case String:
|
||||
return 2*WORD_SIZE;
|
||||
case Boolean:
|
||||
@@ -301,11 +301,11 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
alignment := align_formula(size, align);
|
||||
return alignment*(count-1) + size;
|
||||
case Struct:
|
||||
return info.size;
|
||||
return type_info.size;
|
||||
case Union:
|
||||
return info.size;
|
||||
return type_info.size;
|
||||
case RawUnion:
|
||||
return info.size;
|
||||
return type_info.size;
|
||||
case Enum:
|
||||
return size_of_type_info(info.base);
|
||||
case Map:
|
||||
|
||||
+20
-20
@@ -1,6 +1,6 @@
|
||||
is_signed :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
match i in type_info_base(info) {
|
||||
match i in type_info_base(info).variant {
|
||||
case TypeInfo.Integer: return i.signed;
|
||||
case TypeInfo.Float: return true;
|
||||
}
|
||||
@@ -8,96 +8,96 @@ is_signed :: proc(info: ^TypeInfo) -> bool {
|
||||
}
|
||||
is_integer :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Integer);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Integer);
|
||||
return ok;
|
||||
}
|
||||
is_rune :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Rune);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Rune);
|
||||
return ok;
|
||||
}
|
||||
is_float :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Float);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Float);
|
||||
return ok;
|
||||
}
|
||||
is_complex :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Complex);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Complex);
|
||||
return ok;
|
||||
}
|
||||
is_any :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Any);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Any);
|
||||
return ok;
|
||||
}
|
||||
is_string :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.String);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.String);
|
||||
return ok;
|
||||
}
|
||||
is_boolean :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Boolean);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Boolean);
|
||||
return ok;
|
||||
}
|
||||
is_pointer :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Pointer);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Pointer);
|
||||
return ok;
|
||||
}
|
||||
is_procedure :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Procedure);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Procedure);
|
||||
return ok;
|
||||
}
|
||||
is_array :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Array);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Array);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_array :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.DynamicArray);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.DynamicArray);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_map :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Map);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Map);
|
||||
return ok;
|
||||
}
|
||||
is_slice :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Slice);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Slice);
|
||||
return ok;
|
||||
}
|
||||
is_vector :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Vector);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Vector);
|
||||
return ok;
|
||||
}
|
||||
is_tuple :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Tuple);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Tuple);
|
||||
return ok;
|
||||
}
|
||||
is_struct :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Struct);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Struct);
|
||||
return ok;
|
||||
}
|
||||
is_union :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Union);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Union);
|
||||
return ok;
|
||||
}
|
||||
is_raw_union :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.RawUnion);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.RawUnion);
|
||||
return ok;
|
||||
}
|
||||
is_enum :: proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := type_info_base(info).(^TypeInfo.Enum);
|
||||
_, ok := type_info_base(info).variant.(TypeInfo.Enum);
|
||||
return ok;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user