mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-27 16:01:47 -07:00
Add Quaternions: quaternion128, quaternion256
This commit is contained in:
+4
-4
@@ -4,8 +4,8 @@
|
||||
|
||||
|
||||
main :: proc() {
|
||||
x := 1+2i;
|
||||
y := 3-4i;
|
||||
x = x*y;
|
||||
fmt.printf("%v\n", x);
|
||||
x := 1+2i+3j+4k;
|
||||
y := 3-4i-5j-6k;
|
||||
z := x/y;
|
||||
fmt.println(z, abs(z));
|
||||
}
|
||||
|
||||
+57
-13
@@ -2,9 +2,7 @@
|
||||
|
||||
#import "os.odin";
|
||||
#import "fmt.odin";
|
||||
#import "mem.odin";
|
||||
#import "utf8.odin";
|
||||
#import "hash.odin";
|
||||
|
||||
// IMPORTANT NOTE(bill): `type_info` & `type_info_val` cannot be used within a
|
||||
// #shared_global_scope due to the internals of the compiler.
|
||||
@@ -42,6 +40,7 @@ Type_Info :: union {
|
||||
Integer{size: int, signed: bool},
|
||||
Float{size: int},
|
||||
Complex{size: int},
|
||||
Quaternion{size: int},
|
||||
String{},
|
||||
Boolean{},
|
||||
Any{},
|
||||
@@ -130,8 +129,6 @@ __trap :: proc() #foreign __llvm_core "llvm.trap";
|
||||
read_cycle_counter :: proc() -> u64 #foreign __llvm_core "llvm.readcyclecounter";
|
||||
|
||||
|
||||
|
||||
|
||||
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
||||
Allocator_Mode :: enum u8 {
|
||||
ALLOC,
|
||||
@@ -231,7 +228,7 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
|
||||
return nil;
|
||||
}
|
||||
|
||||
mem.copy(new_memory, old_memory, min(old_size, new_size));;
|
||||
__mem_copy(new_memory, old_memory, min(old_size, new_size));;
|
||||
free(old_memory);
|
||||
return new_memory;
|
||||
}
|
||||
@@ -290,7 +287,7 @@ __string_eq :: proc(a, b: string) -> bool {
|
||||
}
|
||||
|
||||
__string_cmp :: proc(a, b: string) -> int {
|
||||
return mem.compare(cast([]byte)a, cast([]byte)b);
|
||||
return __mem_compare(a.data, b.data, min(a.count, b.count));
|
||||
}
|
||||
|
||||
__string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
|
||||
@@ -300,6 +297,26 @@ __string_le :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) <=
|
||||
__string_ge :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) >= 0; }
|
||||
|
||||
|
||||
__complex64_eq :: proc(a, b: complex64) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
|
||||
__complex64_ne :: proc(a, b: complex64) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
|
||||
__complex128_eq :: proc(a, b: complex128) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
|
||||
__complex128_ne :: proc(a, b: complex128) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
|
||||
|
||||
__quaternion128_eq :: proc(a, b: quaternion128) -> bool #inline {
|
||||
return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b);
|
||||
}
|
||||
__quaternion128_ne :: proc(a, b: quaternion128) -> bool #inline {
|
||||
return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b);
|
||||
}
|
||||
__quaternion256_eq :: proc(a, b: quaternion256) -> bool #inline {
|
||||
return real(a) == real(b) && imag(a) == imag(b) && jmag(a) == jmag(b) && kmag(a) == kmag(b);
|
||||
}
|
||||
__quaternion256_ne :: proc(a, b: quaternion256) -> bool #inline {
|
||||
return real(a) != real(b) || imag(a) != imag(b) || jmag(a) != jmag(b) || kmag(a) != kmag(b);
|
||||
}
|
||||
|
||||
__assert :: proc(file: string, line, column: int, msg: string) #inline {
|
||||
fmt.fprintf(os.stderr, "%s(%d:%d) Runtime assertion: %s\n",
|
||||
file, line, column, msg);
|
||||
@@ -381,6 +398,26 @@ __mem_compare :: proc(a, b: ^byte, n: int) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
__sqrt_f32 :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
||||
__sqrt_f64 :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
||||
__abs_complex64 :: proc(x: complex64) -> f32 #inline {
|
||||
r, i := real(x), imag(x);
|
||||
return __sqrt_f32(r*r + i*i);
|
||||
}
|
||||
__abs_complex128 :: proc(x: complex128) -> f64 #inline {
|
||||
r, i := real(x), imag(x);
|
||||
return __sqrt_f64(r*r + i*i);
|
||||
}
|
||||
__abs_quaternion128 :: proc(x: quaternion128) -> f32 #inline {
|
||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||
return __sqrt_f32(r*r + i*i + j*j + k*k);
|
||||
}
|
||||
__abs_quaternion256 :: proc(x: quaternion256) -> f64 #inline {
|
||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||
return __sqrt_f64(r*r + i*i + j*j + k*k);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Raw_Any :: struct #ordered {
|
||||
type_info: ^Type_Info,
|
||||
@@ -460,7 +497,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
|
||||
}
|
||||
data := cast(^byte)array.data;
|
||||
assert(data != nil);
|
||||
mem.copy(data + (elem_size*array.count), items, elem_size * item_count);
|
||||
__mem_copy(data + (elem_size*array.count), items, elem_size * item_count);
|
||||
array.count += item_count;
|
||||
return array.count;
|
||||
}
|
||||
@@ -479,7 +516,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
|
||||
}
|
||||
data := cast(^byte)array.data;
|
||||
assert(data != nil);
|
||||
mem.zero(data + (elem_size*array.count), elem_size);
|
||||
__mem_zero(data + (elem_size*array.count), elem_size);
|
||||
array.count++;
|
||||
return array.count;
|
||||
}
|
||||
@@ -496,7 +533,7 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
|
||||
if item_count > 0 {
|
||||
data := cast(^byte)slice.data;
|
||||
assert(data != nil);
|
||||
mem.copy(data + (elem_size*slice.count), items, elem_size * item_count);
|
||||
__mem_copy(data + (elem_size*slice.count), items, elem_size * item_count);
|
||||
slice.count += item_count;
|
||||
}
|
||||
return slice.count;
|
||||
@@ -506,7 +543,14 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
|
||||
// Map stuff
|
||||
|
||||
__default_hash :: proc(data: []byte) -> u64 {
|
||||
return hash.fnv64a(data);
|
||||
fnv64a :: proc(data: []byte) -> u64 {
|
||||
h: u64 = 0xcbf29ce484222325;
|
||||
for b in data {
|
||||
h = (h ~ cast(u64)b) * 0x100000001b3;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
return fnv64a(data);
|
||||
}
|
||||
__default_hash_string :: proc(s: string) -> u64 {
|
||||
return __default_hash(cast([]byte)s);
|
||||
@@ -577,7 +621,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int) {
|
||||
e := __dynamic_map_get_entry(new_header, j);
|
||||
e.next = fr.entry_index;
|
||||
ndata := cast(^byte)e;
|
||||
mem.copy(ndata+value_offset, data+value_offset, entry_size-value_offset);
|
||||
__mem_copy(ndata+value_offset, data+value_offset, entry_size-value_offset);
|
||||
if __dynamic_map_full(new_header) {
|
||||
__dynamic_map_grow(new_header);
|
||||
}
|
||||
@@ -618,7 +662,7 @@ __dynamic_map_set :: proc(using h: __Map_Header, key: __Map_Key, value: rawptr)
|
||||
{
|
||||
data := cast(^byte)__dynamic_map_get_entry(h, index);
|
||||
val := data+value_offset;
|
||||
mem.copy(val, value, entry_size-value_offset);
|
||||
__mem_copy(val, value, entry_size-value_offset);
|
||||
}
|
||||
|
||||
if __dynamic_map_full(h) {
|
||||
@@ -698,7 +742,7 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {
|
||||
if fr.entry_index == m.entries.count-1 {
|
||||
m.entries.count--;
|
||||
}
|
||||
mem.copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.count-1), entry_size);
|
||||
__mem_copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.count-1), entry_size);
|
||||
last := __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key);
|
||||
if last.entry_prev >= 0 {
|
||||
__dynamic_map_get_entry(h, last.entry_prev).next = fr.entry_index;
|
||||
|
||||
+45
-10
@@ -115,6 +115,11 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||
case 8: write_string(buf, "complex64");
|
||||
case 16: write_string(buf, "complex128");
|
||||
}
|
||||
case Quaternion:
|
||||
match info.size {
|
||||
case 16: write_string(buf, "quaternion128");
|
||||
case 32: write_string(buf, "quaternion");
|
||||
}
|
||||
case String: write_string(buf, "string");
|
||||
case Boolean: write_string(buf, "bool");
|
||||
case Pointer:
|
||||
@@ -736,11 +741,12 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
fmt_value(fi, any{info.base, v.data}, verb);
|
||||
}
|
||||
|
||||
case Boolean: fmt_arg(fi, v, verb);
|
||||
case Float: fmt_arg(fi, v, verb);
|
||||
case Complex: fmt_arg(fi, v, verb);
|
||||
case Integer: fmt_arg(fi, v, verb);
|
||||
case String: fmt_arg(fi, v, verb);
|
||||
case Boolean: fmt_arg(fi, v, verb);
|
||||
case Integer: fmt_arg(fi, v, verb);
|
||||
case Float: fmt_arg(fi, v, verb);
|
||||
case Complex: fmt_arg(fi, v, verb);
|
||||
case Quaternion: fmt_arg(fi, v, verb);
|
||||
case String: fmt_arg(fi, v, verb);
|
||||
|
||||
case Pointer:
|
||||
if v.type_info == type_info(^Type_Info) {
|
||||
@@ -907,6 +913,33 @@ fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt_quaternion :: proc(fi: ^Fmt_Info, c: quaternion256, bits: int, verb: rune) {
|
||||
match verb {
|
||||
case 'f', 'F', 'v':
|
||||
r := real(c);
|
||||
i := imag(c);
|
||||
j := jmag(c);
|
||||
k := kmag(c);
|
||||
fmt_float(fi, r, bits/4, verb);
|
||||
|
||||
if !fi.plus && i >= 0 { write_rune(fi.buf, '+'); }
|
||||
fmt_float(fi, i, bits/4, verb);
|
||||
write_rune(fi.buf, 'i');
|
||||
|
||||
if !fi.plus && j >= 0 { write_rune(fi.buf, '+'); }
|
||||
fmt_float(fi, j, bits/4, verb);
|
||||
write_rune(fi.buf, 'j');
|
||||
|
||||
if !fi.plus && k >= 0 { write_rune(fi.buf, '+'); }
|
||||
fmt_float(fi, k, bits/4, verb);
|
||||
write_rune(fi.buf, 'k');
|
||||
|
||||
default:
|
||||
fmt_bad_verb(fi, verb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
||||
if arg.data == nil || arg.type_info == nil {
|
||||
write_string(fi.buf, "<nil>");
|
||||
@@ -927,11 +960,13 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
||||
base_arg := arg;
|
||||
base_arg.type_info = type_info_base(base_arg.type_info);
|
||||
match a in base_arg {
|
||||
case bool: fmt_bool(fi, a, verb);
|
||||
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
||||
case f64: fmt_float(fi, a, 64, verb);
|
||||
case complex64: fmt_complex(fi, cast(complex128)a, 64, verb);
|
||||
case complex128: fmt_complex(fi, a, 128, verb);
|
||||
case bool: fmt_bool(fi, a, verb);
|
||||
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
||||
case f64: fmt_float(fi, a, 64, verb);
|
||||
case complex64: fmt_complex(fi, cast(complex128)a, 64, verb);
|
||||
case complex128: fmt_complex(fi, a, 128, verb);
|
||||
case quaternion128: fmt_quaternion(fi, cast(quaternion256)a, 128, verb);
|
||||
case quaternion256: fmt_quaternion(fi, a, 256, verb);
|
||||
|
||||
case int: fmt_int(fi, cast(u64)a, true, 8*size_of(int), verb);
|
||||
case i8: fmt_int(fi, cast(u64)a, true, 8, verb);
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@ pow :: proc(x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
|
||||
lerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t; }
|
||||
lerp :: proc(a, b, t: f64) -> f64 { return a*(1-t) + b*t; }
|
||||
|
||||
sign :: proc(x: f32) -> f32 { if x >= 0 { return +1; } return -1; }
|
||||
sign :: proc(x: f64) -> f64 { if x >= 0 { return +1; } return -1; }
|
||||
sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
|
||||
sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
|
||||
|
||||
bit_reverse :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16";
|
||||
bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32";
|
||||
|
||||
+42
-88
@@ -1,146 +1,100 @@
|
||||
is_signed :: proc(info: ^Type_Info) -> bool {
|
||||
if is_integer(info) {
|
||||
i := union_cast(^Type_Info.Integer)info;
|
||||
info = type_info_base(info);
|
||||
if i, ok := union_cast(^Type_Info.Integer)info; ok {
|
||||
return i.signed;
|
||||
}
|
||||
if is_float(info) {
|
||||
if _, ok := union_cast(^Type_Info.Float)info; ok {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
is_integer :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Integer: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Integer)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_float :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Float: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Float)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_complex :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := union_cast(^Type_Info.Complex)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_any :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Any: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Any)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_string :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.String: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.String)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_boolean :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Boolean: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Boolean)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_pointer :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Pointer: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Pointer)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_procedure :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Procedure: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Procedure)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_array :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Array: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Array)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Dynamic_Array: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Dynamic_Array)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_map :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Map: return i.count == 0;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Map)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_slice :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Slice: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Slice)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_vector :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Vector: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Vector)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_tuple :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Tuple: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Tuple)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_struct :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Struct: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Struct)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_union :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Union: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Union)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Raw_Union: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Raw_Union)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
is_enum :: proc(info: ^Type_Info) -> bool {
|
||||
if info == nil { return false; }
|
||||
|
||||
match i in type_info_base(info) {
|
||||
case Type_Info.Enum: return true;
|
||||
}
|
||||
return false;
|
||||
_, ok := union_cast(^Type_Info.Enum)type_info_base(info);
|
||||
return ok;
|
||||
}
|
||||
|
||||
+288
-87
@@ -1782,10 +1782,41 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
case Basic_UntypedComplex:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (is_type_pointer(type)) {
|
||||
} else if (is_type_quaternion(type)) {
|
||||
ExactValue v = exact_value_to_quaternion(in_value);
|
||||
if (v.kind != ExactValue_Quaternion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_quaternion128:
|
||||
case Basic_quaternion256: {
|
||||
ExactValue real = exact_value_real(v);
|
||||
ExactValue imag = exact_value_imag(v);
|
||||
ExactValue jmag = exact_value_jmag(v);
|
||||
ExactValue kmag = exact_value_kmag(v);
|
||||
if (real.kind != ExactValue_Invalid &&
|
||||
imag.kind != ExactValue_Invalid &&
|
||||
jmag.kind != ExactValue_Invalid &&
|
||||
kmag.kind != ExactValue_Invalid) {
|
||||
ExactValue ov = exact_binary_operator_value(Token_Add, real, exact_value_make_imag(imag));
|
||||
ov = exact_binary_operator_value(Token_Add, ov, exact_value_make_jmag(jmag));
|
||||
ov = exact_binary_operator_value(Token_Add, ov, exact_value_make_kmag(kmag));
|
||||
if (out_value) *out_value = ov;
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
case Basic_UntypedQuaternion:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}else if (is_type_pointer(type)) {
|
||||
if (in_value.kind == ExactValue_Pointer) {
|
||||
return true;
|
||||
}
|
||||
@@ -2213,6 +2244,10 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_quaternion(src) && is_type_quaternion(dst)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Cast between pointers
|
||||
if (is_type_pointer(src) && is_type_pointer(dst)) {
|
||||
Type *s = base_type(type_deref(src));
|
||||
@@ -2613,6 +2648,8 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
|
||||
break;
|
||||
case Basic_UntypedInteger:
|
||||
case Basic_UntypedFloat:
|
||||
case Basic_UntypedComplex:
|
||||
case Basic_UntypedQuaternion:
|
||||
case Basic_UntypedRune:
|
||||
if (!is_type_numeric(target_type)) {
|
||||
operand->mode = Addressing_Invalid;
|
||||
@@ -3605,44 +3642,24 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 flag = 0;
|
||||
if (is_type_untyped(x.type)) {
|
||||
flag |= 1;
|
||||
}
|
||||
if (is_type_untyped(y.type)) {
|
||||
flag |= 2;
|
||||
}
|
||||
switch (flag) {
|
||||
case 0: break;
|
||||
case 1: convert_to_typed(c, &x, y.type, 0); break;
|
||||
case 2: convert_to_typed(c, &y, x.type, 0); break;
|
||||
case 3: {
|
||||
if (x.mode == Addressing_Constant && y.mode == Addressing_Constant) {
|
||||
if (is_type_numeric(x.type) && exact_value_imag(x.value).value_float == 0) {
|
||||
x.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) {
|
||||
y.type = t_untyped_float;
|
||||
}
|
||||
} else {
|
||||
convert_to_typed(c, &x, t_f64, 0);
|
||||
convert_to_typed(c, &y, t_f64, 0);
|
||||
convert_to_typed(c, &x, y.type, 0); if (x.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &y, x.type, 0); if (y.mode == Addressing_Invalid) return false;
|
||||
if (x.mode == Addressing_Constant &&
|
||||
y.mode == Addressing_Constant) {
|
||||
if (is_type_numeric(x.type) && exact_value_imag(x.value).value_float == 0) {
|
||||
x.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) {
|
||||
y.type = t_untyped_float;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
if (x.mode == Addressing_Invalid || y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!are_types_identical(x.type, y.type)) {
|
||||
gbString type_x = type_to_string(x.type);
|
||||
gbString type_y = type_to_string(y.type);
|
||||
error_node(call,
|
||||
"Mismatched types to `complex`, `%s` vs `%s`",
|
||||
type_x, type_y);
|
||||
gb_string_free(type_y);
|
||||
gb_string_free(type_x);
|
||||
gbString tx = type_to_string(x.type);
|
||||
gbString ty = type_to_string(y.type);
|
||||
error_node(call, "Mismatched types to `complex`, `%s` vs `%s`", tx, ty);
|
||||
gb_string_free(ty);
|
||||
gb_string_free(tx);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3669,37 +3686,170 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
}
|
||||
} break;
|
||||
|
||||
case BuiltinProc_quaternion: {
|
||||
// quaternion :: proc(real, imag, jmag, kmag: float_type) -> quaternion_type
|
||||
Operand x = *operand;
|
||||
Operand y = {0};
|
||||
Operand z = {0};
|
||||
Operand w = {0};
|
||||
|
||||
GB_PANIC("BuiltinProc_quaternion");
|
||||
|
||||
// NOTE(bill): Invalid will be the default till fixed
|
||||
operand->type = t_invalid;
|
||||
operand->mode = Addressing_Invalid;
|
||||
|
||||
check_expr(c, &y, ce->args.e[1]); if (y.mode == Addressing_Invalid) return false;
|
||||
check_expr(c, &z, ce->args.e[2]); if (z.mode == Addressing_Invalid) return false;
|
||||
check_expr(c, &w, ce->args.e[3]); if (w.mode == Addressing_Invalid) return false;
|
||||
|
||||
convert_to_typed(c, &x, y.type, 0); if (x.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &x, z.type, 0); if (x.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &x, w.type, 0); if (x.mode == Addressing_Invalid) return false;
|
||||
|
||||
convert_to_typed(c, &y, z.type, 0); if (y.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &y, w.type, 0); if (y.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &y, x.type, 0); if (y.mode == Addressing_Invalid) return false;
|
||||
|
||||
convert_to_typed(c, &z, y.type, 0); if (z.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &z, w.type, 0); if (z.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &z, x.type, 0); if (z.mode == Addressing_Invalid) return false;
|
||||
|
||||
convert_to_typed(c, &w, x.type, 0); if (w.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &w, y.type, 0); if (w.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &w, z.type, 0); if (w.mode == Addressing_Invalid) return false;
|
||||
|
||||
if (x.mode == Addressing_Constant &&
|
||||
y.mode == Addressing_Constant &&
|
||||
z.mode == Addressing_Constant &&
|
||||
w.mode == Addressing_Constant) {
|
||||
if (is_type_numeric(x.type) &&
|
||||
exact_value_imag(x.value).value_float == 0 &&
|
||||
exact_value_jmag(x.value).value_float == 0 &&
|
||||
exact_value_kmag(x.value).value_float == 0) {
|
||||
x.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(y.type) &&
|
||||
exact_value_imag(y.value).value_float == 0 &&
|
||||
exact_value_jmag(y.value).value_float == 0 &&
|
||||
exact_value_kmag(y.value).value_float == 0) {
|
||||
y.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(z.type) &&
|
||||
exact_value_imag(z.value).value_float == 0 &&
|
||||
exact_value_jmag(z.value).value_float == 0 &&
|
||||
exact_value_kmag(z.value).value_float == 0) {
|
||||
z.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(w.type) &&
|
||||
exact_value_imag(w.value).value_float == 0 &&
|
||||
exact_value_jmag(w.value).value_float == 0 &&
|
||||
exact_value_kmag(w.value).value_float == 0) {
|
||||
w.type = t_untyped_float;
|
||||
}
|
||||
}
|
||||
|
||||
if (!are_types_identical(x.type, y.type)) {
|
||||
gbString tx = type_to_string(x.type);
|
||||
gbString ty = type_to_string(y.type);
|
||||
gbString tz = type_to_string(z.type);
|
||||
gbString tw = type_to_string(w.type);
|
||||
error_node(call, "Mismatched types to `complex`, `%s`, `%s` `%s`, `%s`", tx, ty, tz, tw);
|
||||
gb_string_free(tw);
|
||||
gb_string_free(tz);
|
||||
gb_string_free(ty);
|
||||
gb_string_free(tx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_type_float(x.type)) {
|
||||
gbString s = type_to_string(x.type);
|
||||
error_node(call, "Arguments have type `%s`, expected a floating point", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x.mode == Addressing_Constant &&
|
||||
y.mode == Addressing_Constant &&
|
||||
z.mode == Addressing_Constant &&
|
||||
w.mode == Addressing_Constant) {
|
||||
ExactValue v = exact_binary_operator_value(Token_Add, x.value, y.value);
|
||||
v = exact_binary_operator_value(Token_Add, v, z.value);
|
||||
v = exact_binary_operator_value(Token_Add, v, w.value);
|
||||
operand->value = v;
|
||||
operand->mode = Addressing_Constant;
|
||||
} else {
|
||||
operand->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
BasicKind kind = core_type(x.type)->Basic.kind;
|
||||
switch (kind) {
|
||||
case Basic_complex64: x.type = t_f32; break;
|
||||
case Basic_complex128: x.type = t_f64; break;
|
||||
case Basic_UntypedComplex: x.type = t_untyped_float; break;
|
||||
case Basic_quaternion128: x.type = t_f32; break;
|
||||
case Basic_quaternion256: x.type = t_f64; break;
|
||||
case Basic_UntypedQuaternion: x.type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case BuiltinProc_real:
|
||||
case BuiltinProc_imag: {
|
||||
// real :: proc(c: complex_type) -> float_type
|
||||
// imag :: proc(c: complex_type) -> float_type
|
||||
case BuiltinProc_imag:
|
||||
case BuiltinProc_jmag:
|
||||
case BuiltinProc_kmag: {
|
||||
// real :: proc(x: type) -> float_type
|
||||
// imag :: proc(x: type) -> float_type
|
||||
// jmag :: proc(x: type) -> float_type
|
||||
// kmag :: proc(x: type) -> float_type
|
||||
|
||||
Operand *x = operand;
|
||||
if (is_type_untyped(x->type)) {
|
||||
if (x->mode == Addressing_Constant) {
|
||||
if (is_type_numeric(x->type)) {
|
||||
x->type = t_untyped_complex;
|
||||
if (id == BuiltinProc_jmag ||
|
||||
id == BuiltinProc_kmag) {
|
||||
x->type = t_untyped_quaternion;
|
||||
} else {
|
||||
x->type = t_untyped_complex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
convert_to_typed(c, x, t_complex128, 0);
|
||||
if (id == BuiltinProc_jmag ||
|
||||
id == BuiltinProc_kmag) {
|
||||
convert_to_typed(c, x, t_quaternion256, 0);
|
||||
} else {
|
||||
convert_to_typed(c, x, t_complex128, 0);
|
||||
}
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_type_complex(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error_node(call, "Argument has type `%s`, expected a complex type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
if (id == BuiltinProc_jmag ||
|
||||
id == BuiltinProc_kmag) {
|
||||
if (!is_type_quaternion(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error_node(call, "Argument has type `%s`, expected a complex type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!is_type_complex(x->type) && !is_type_quaternion(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error_node(call, "Argument has type `%s`, expected a complex or quaternion type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (x->mode == Addressing_Constant) {
|
||||
if (id == BuiltinProc_real) {
|
||||
x->value = exact_value_real(x->value);
|
||||
} else {
|
||||
x->value = exact_value_imag(x->value);
|
||||
switch (id) {
|
||||
case BuiltinProc_real: x->value = exact_value_real(x->value); break;
|
||||
case BuiltinProc_imag: x->value = exact_value_imag(x->value); break;
|
||||
case BuiltinProc_jmag: x->value = exact_value_jmag(x->value); break;
|
||||
case BuiltinProc_kmag: x->value = exact_value_kmag(x->value); break;
|
||||
}
|
||||
} else {
|
||||
x->mode = Addressing_Value;
|
||||
@@ -3707,13 +3857,50 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
BasicKind kind = core_type(x->type)->Basic.kind;
|
||||
switch (kind) {
|
||||
case Basic_complex64: x->type = t_f32; break;
|
||||
case Basic_complex128: x->type = t_f64; break;
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
case Basic_complex64: x->type = t_f32; break;
|
||||
case Basic_complex128: x->type = t_f64; break;
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
case Basic_quaternion128: x->type = t_f32; break;
|
||||
case Basic_quaternion256: x->type = t_f64; break;
|
||||
case Basic_UntypedQuaternion: x->type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case BuiltinProc_conj: {
|
||||
// conj :: proc(x: type) -> type
|
||||
Operand *x = operand;
|
||||
if (is_type_complex(x->type)) {
|
||||
if (x->mode == Addressing_Constant) {
|
||||
ExactValue v = exact_value_to_complex(x->value);
|
||||
f64 r = v.value_complex.real;
|
||||
f64 i = v.value_complex.imag;
|
||||
x->value = exact_value_complex(r, i);
|
||||
x->mode = Addressing_Constant;
|
||||
} else {
|
||||
x->mode = Addressing_Value;
|
||||
}
|
||||
} else if (is_type_quaternion(x->type)) {
|
||||
if (x->mode == Addressing_Constant) {
|
||||
ExactValue v = exact_value_to_quaternion(x->value);
|
||||
f64 r = v.value_quaternion.real;
|
||||
f64 i = v.value_quaternion.imag;
|
||||
f64 j = v.value_quaternion.jmag;
|
||||
f64 k = v.value_quaternion.kmag;
|
||||
x->value = exact_value_quaternion(r, i, j, k);
|
||||
x->mode = Addressing_Constant;
|
||||
} else {
|
||||
x->mode = Addressing_Value;
|
||||
}
|
||||
} else {
|
||||
gbString s = type_to_string(x->type);
|
||||
error_node(call, "Expected a complex or quaternion, got `%s`", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case BuiltinProc_slice_ptr: {
|
||||
// slice_ptr :: proc(a: ^T, len: int) -> []T
|
||||
// slice_ptr :: proc(a: ^T, len, cap: int) -> []T
|
||||
@@ -3721,16 +3908,13 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
Type *ptr_type = base_type(operand->type);
|
||||
if (!is_type_pointer(ptr_type)) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error_node(call,
|
||||
"Expected a pointer to `slice_ptr`, got `%s`",
|
||||
type_str);
|
||||
error_node(call, "Expected a pointer to `slice_ptr`, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ptr_type == t_rawptr) {
|
||||
error_node(call,
|
||||
"`rawptr` cannot have pointer arithmetic");
|
||||
error_node(call, "`rawptr` cannot have pointer arithmetic");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3775,11 +3959,11 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
} break;
|
||||
|
||||
case BuiltinProc_min: {
|
||||
// min :: proc(a, b: comparable) -> comparable
|
||||
// min :: proc(a, b: ordered) -> ordered
|
||||
Type *type = base_type(operand->type);
|
||||
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error_node(call, "Expected a comparable numeric type to `min`, got `%s`", type_str);
|
||||
error_node(call, "Expected a ordered numeric type to `min`, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
@@ -3791,10 +3975,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
if (b.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (!is_type_comparable(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
|
||||
if (!is_type_ordered(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
|
||||
gbString type_str = type_to_string(b.type);
|
||||
error_node(call,
|
||||
"Expected a comparable numeric type to `min`, got `%s`",
|
||||
"Expected a ordered numeric type to `min`, got `%s`",
|
||||
type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
@@ -3841,12 +4025,12 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
} break;
|
||||
|
||||
case BuiltinProc_max: {
|
||||
// min :: proc(a, b: comparable) -> comparable
|
||||
// min :: proc(a, b: ordered) -> ordered
|
||||
Type *type = base_type(operand->type);
|
||||
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error_node(call,
|
||||
"Expected a comparable numeric or string type to `max`, got `%s`",
|
||||
"Expected a ordered numeric or string type to `max`, got `%s`",
|
||||
type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
@@ -3859,10 +4043,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
if (b.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (!is_type_comparable(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
|
||||
if (!is_type_ordered(b.type) || !(is_type_numeric(b.type) || is_type_string(b.type))) {
|
||||
gbString type_str = type_to_string(b.type);
|
||||
error_node(call,
|
||||
"Expected a comparable numeric or string type to `max`, got `%s`",
|
||||
"Expected a ordered numeric or string type to `max`, got `%s`",
|
||||
type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
@@ -3910,12 +4094,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
|
||||
case BuiltinProc_abs: {
|
||||
// abs :: proc(n: numeric) -> numeric
|
||||
Type *type = base_type(operand->type);
|
||||
if (!is_type_numeric(type)) {
|
||||
if (!is_type_numeric(operand->type) && !is_type_vector(operand->type)) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error_node(call,
|
||||
"Expected a numeric type to `abs`, got `%s`",
|
||||
type_str);
|
||||
error_node(call, "Expected a numeric type to `abs`, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
@@ -3928,6 +4109,18 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
case ExactValue_Float:
|
||||
operand->value.value_float = gb_abs(operand->value.value_float);
|
||||
break;
|
||||
case ExactValue_Complex: {
|
||||
f64 r = operand->value.value_complex.real;
|
||||
f64 i = operand->value.value_complex.imag;
|
||||
operand->value = exact_value_float(gb_sqrt(r*r + i*i));
|
||||
} break;
|
||||
case ExactValue_Quaternion: {
|
||||
f64 r = operand->value.value_complex.real;
|
||||
f64 i = operand->value.value_complex.imag;
|
||||
f64 j = operand->value.value_complex.imag;
|
||||
f64 k = operand->value.value_complex.imag;
|
||||
operand->value = exact_value_float(gb_sqrt(r*r + i*i + j*j + k*k));
|
||||
} break;
|
||||
default:
|
||||
GB_PANIC("Invalid numeric constant");
|
||||
break;
|
||||
@@ -3936,17 +4129,20 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
operand->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
operand->type = type;
|
||||
if (is_type_complex(operand->type)) {
|
||||
operand->type = base_complex_elem_type(operand->type);
|
||||
} else if (is_type_quaternion(operand->type)) {
|
||||
operand->type = base_quaternion_elem_type(operand->type);
|
||||
}
|
||||
GB_ASSERT(!is_type_complex(operand->type) && !is_type_quaternion(operand->type));
|
||||
} break;
|
||||
|
||||
case BuiltinProc_clamp: {
|
||||
// clamp :: proc(a, min, max: comparable) -> comparable
|
||||
// clamp :: proc(a, min, max: ordered) -> ordered
|
||||
Type *type = base_type(operand->type);
|
||||
if (!is_type_comparable(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||
if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
error_node(call,
|
||||
"Expected a comparable numeric or string type to `clamp`, got `%s`",
|
||||
type_str);
|
||||
error_node(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
@@ -3961,11 +4157,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (!is_type_comparable(y.type) || !(is_type_numeric(y.type) || is_type_string(y.type))) {
|
||||
if (!is_type_ordered(y.type) || !(is_type_numeric(y.type) || is_type_string(y.type))) {
|
||||
gbString type_str = type_to_string(y.type);
|
||||
error_node(call,
|
||||
"Expected a comparable numeric or string type to `clamp`, got `%s`",
|
||||
type_str);
|
||||
error_node(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
@@ -3974,11 +4168,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
||||
if (z.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
if (!is_type_comparable(z.type) || !(is_type_numeric(z.type) || is_type_string(z.type))) {
|
||||
if (!is_type_ordered(z.type) || !(is_type_numeric(z.type) || is_type_string(z.type))) {
|
||||
gbString type_str = type_to_string(z.type);
|
||||
error_node(call,
|
||||
"Expected a comparable numeric or string type to `clamp`, got `%s`",
|
||||
type_str);
|
||||
error_node(call, "Expected a ordered numeric or string type to `clamp`, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
return false;
|
||||
}
|
||||
@@ -4551,9 +4743,18 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
switch (bl->kind) {
|
||||
case Token_Integer: t = t_untyped_integer; break;
|
||||
case Token_Float: t = t_untyped_float; break;
|
||||
case Token_Imag: t = t_untyped_complex; break;
|
||||
case Token_String: t = t_untyped_string; break;
|
||||
case Token_Rune: t = t_untyped_rune; break;
|
||||
case Token_Imag: {
|
||||
String s = bl->string;
|
||||
Rune r = s.text[s.len-1];
|
||||
switch (r) {
|
||||
case 'i': t = t_untyped_complex; break;
|
||||
case 'j': case 'k':
|
||||
t = t_untyped_quaternion;
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default: GB_PANIC("Unknown literal"); break;
|
||||
}
|
||||
o->mode = Addressing_Constant;
|
||||
|
||||
+35
-16
@@ -53,8 +53,12 @@ typedef enum BuiltinProcId {
|
||||
BuiltinProc_swizzle,
|
||||
|
||||
BuiltinProc_complex,
|
||||
BuiltinProc_quaternion,
|
||||
BuiltinProc_real,
|
||||
BuiltinProc_imag,
|
||||
BuiltinProc_jmag,
|
||||
BuiltinProc_kmag,
|
||||
BuiltinProc_conj,
|
||||
|
||||
// BuiltinProc_ptr_offset,
|
||||
// BuiltinProc_ptr_sub,
|
||||
@@ -101,8 +105,12 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
||||
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
||||
|
||||
{STR_LIT("complex"), 2, false, Expr_Expr},
|
||||
{STR_LIT("quaternion"), 4, false, Expr_Expr},
|
||||
{STR_LIT("real"), 1, false, Expr_Expr},
|
||||
{STR_LIT("imag"), 1, false, Expr_Expr},
|
||||
{STR_LIT("jmag"), 1, false, Expr_Expr},
|
||||
{STR_LIT("kmag"), 1, false, Expr_Expr},
|
||||
{STR_LIT("conj"), 1, false, Expr_Expr},
|
||||
|
||||
// {STR_LIT("ptr_offset"), 2, false, Expr_Expr},
|
||||
// {STR_LIT("ptr_sub"), 2, false, Expr_Expr},
|
||||
@@ -957,6 +965,15 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
add_type_info_type(c, t_type_info_float);
|
||||
add_type_info_type(c, t_f64);
|
||||
break;
|
||||
|
||||
case Basic_quaternion128:
|
||||
add_type_info_type(c, t_type_info_float);
|
||||
add_type_info_type(c, t_f32);
|
||||
break;
|
||||
case Basic_quaternion256:
|
||||
add_type_info_type(c, t_type_info_float);
|
||||
add_type_info_type(c, t_f64);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -1145,33 +1162,35 @@ void init_preload(Checker *c) {
|
||||
|
||||
|
||||
|
||||
if (record->variant_count != 20) {
|
||||
if (record->variant_count != 21) {
|
||||
compiler_error("Invalid `Type_Info` layout");
|
||||
}
|
||||
t_type_info_named = record->variants[ 1]->type;
|
||||
t_type_info_integer = record->variants[ 2]->type;
|
||||
t_type_info_float = record->variants[ 3]->type;
|
||||
t_type_info_complex = record->variants[ 4]->type;
|
||||
t_type_info_string = record->variants[ 5]->type;
|
||||
t_type_info_boolean = record->variants[ 6]->type;
|
||||
t_type_info_any = record->variants[ 7]->type;
|
||||
t_type_info_pointer = record->variants[ 8]->type;
|
||||
t_type_info_procedure = record->variants[ 9]->type;
|
||||
t_type_info_array = record->variants[10]->type;
|
||||
t_type_info_dynamic_array = record->variants[11]->type;
|
||||
t_type_info_slice = record->variants[12]->type;
|
||||
t_type_info_vector = record->variants[13]->type;
|
||||
t_type_info_tuple = record->variants[14]->type;
|
||||
t_type_info_struct = record->variants[15]->type;
|
||||
t_type_info_raw_union = record->variants[16]->type;
|
||||
t_type_info_union = record->variants[17]->type;
|
||||
t_type_info_enum = record->variants[18]->type;
|
||||
t_type_info_map = record->variants[19]->type;
|
||||
t_type_info_quaternion = record->variants[ 5]->type;
|
||||
t_type_info_string = record->variants[ 6]->type;
|
||||
t_type_info_boolean = record->variants[ 7]->type;
|
||||
t_type_info_any = record->variants[ 8]->type;
|
||||
t_type_info_pointer = record->variants[ 9]->type;
|
||||
t_type_info_procedure = record->variants[10]->type;
|
||||
t_type_info_array = record->variants[11]->type;
|
||||
t_type_info_dynamic_array = record->variants[12]->type;
|
||||
t_type_info_slice = record->variants[13]->type;
|
||||
t_type_info_vector = record->variants[14]->type;
|
||||
t_type_info_tuple = record->variants[15]->type;
|
||||
t_type_info_struct = record->variants[16]->type;
|
||||
t_type_info_raw_union = record->variants[17]->type;
|
||||
t_type_info_union = record->variants[18]->type;
|
||||
t_type_info_enum = record->variants[19]->type;
|
||||
t_type_info_map = record->variants[20]->type;
|
||||
|
||||
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
||||
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
||||
t_type_info_float_ptr = make_type_pointer(c->allocator, t_type_info_float);
|
||||
t_type_info_complex_ptr = make_type_pointer(c->allocator, t_type_info_complex);
|
||||
t_type_info_quaternion_ptr = make_type_pointer(c->allocator, t_type_info_quaternion);
|
||||
t_type_info_string_ptr = make_type_pointer(c->allocator, t_type_info_string);
|
||||
t_type_info_boolean_ptr = make_type_pointer(c->allocator, t_type_info_boolean);
|
||||
t_type_info_any_ptr = make_type_pointer(c->allocator, t_type_info_any);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#define GB_IMPLEMENTATION
|
||||
#include "gb/gb.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
gbAllocator heap_allocator(void) {
|
||||
return gb_heap_allocator();
|
||||
}
|
||||
@@ -104,6 +106,10 @@ i16 f32_to_f16(f32 value) {
|
||||
}
|
||||
}
|
||||
|
||||
f64 gb_sqrt(f64 x) {
|
||||
return sqrt(x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++)
|
||||
|
||||
+191
-16
@@ -5,6 +5,14 @@
|
||||
|
||||
typedef struct AstNode AstNode;
|
||||
|
||||
typedef struct Complex128 {
|
||||
f64 real, imag;
|
||||
} Complex128;
|
||||
|
||||
typedef struct Quaternion256 {
|
||||
f64 real, imag, jmag, kmag;
|
||||
} Quaternion256;
|
||||
|
||||
typedef enum ExactValueKind {
|
||||
ExactValue_Invalid,
|
||||
|
||||
@@ -13,26 +21,24 @@ typedef enum ExactValueKind {
|
||||
ExactValue_Integer,
|
||||
ExactValue_Float,
|
||||
ExactValue_Complex,
|
||||
ExactValue_Quaternion,
|
||||
ExactValue_Pointer,
|
||||
ExactValue_Compound, // TODO(bill): Is this good enough?
|
||||
|
||||
ExactValue_Count,
|
||||
} ExactValueKind;
|
||||
|
||||
typedef struct Complex128 {
|
||||
f64 real, imag;
|
||||
} Complex128;
|
||||
|
||||
typedef struct ExactValue {
|
||||
ExactValueKind kind;
|
||||
union {
|
||||
bool value_bool;
|
||||
String value_string;
|
||||
i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
|
||||
f64 value_float;
|
||||
i64 value_pointer;
|
||||
Complex128 value_complex;
|
||||
AstNode * value_compound;
|
||||
bool value_bool;
|
||||
String value_string;
|
||||
i64 value_integer; // NOTE(bill): This must be an integer and not a pointer
|
||||
f64 value_float;
|
||||
i64 value_pointer;
|
||||
Complex128 value_complex;
|
||||
Quaternion256 value_quaternion;
|
||||
AstNode * value_compound;
|
||||
};
|
||||
} ExactValue;
|
||||
|
||||
@@ -79,6 +85,16 @@ ExactValue exact_value_complex(f64 real, f64 imag) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ExactValue exact_value_quaternion(f64 real, f64 imag, f64 jmag, f64 kmag) {
|
||||
ExactValue result = {ExactValue_Quaternion};
|
||||
result.value_quaternion.real = real;
|
||||
result.value_quaternion.imag = imag;
|
||||
result.value_quaternion.jmag = jmag;
|
||||
result.value_quaternion.kmag = kmag;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ExactValue exact_value_pointer(i64 ptr) {
|
||||
ExactValue result = {ExactValue_Pointer};
|
||||
result.value_pointer = ptr;
|
||||
@@ -216,9 +232,15 @@ ExactValue exact_value_from_basic_literal(Token token) {
|
||||
case Token_Float: return exact_value_float_from_string(token.string);
|
||||
case Token_Imag: {
|
||||
String str = token.string;
|
||||
str.len--; // Ignore the `i`
|
||||
Rune last_rune = cast(Rune)str.text[str.len-1];
|
||||
str.len--; // Ignore the `i|j|k`
|
||||
f64 imag = float_from_string(str);
|
||||
return exact_value_complex(0, imag);
|
||||
|
||||
switch (last_rune) {
|
||||
case 'i': return exact_value_complex(0, imag);
|
||||
case 'j': return exact_value_quaternion(0, 0, imag, 0);
|
||||
case 'k': return exact_value_quaternion(0, 0, 0, imag);
|
||||
}
|
||||
}
|
||||
case Token_Rune: {
|
||||
Rune r = GB_RUNE_INVALID;
|
||||
@@ -278,6 +300,23 @@ ExactValue exact_value_to_complex(ExactValue v) {
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
ExactValue exact_value_to_quaternion(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
return exact_value_quaternion(cast(i64)v.value_integer, 0, 0, 0);
|
||||
case ExactValue_Float:
|
||||
return exact_value_quaternion(v.value_float, 0, 0, 0);
|
||||
case ExactValue_Complex:
|
||||
return exact_value_quaternion(v.value_complex.real, v.value_complex.imag, 0, 0);
|
||||
case ExactValue_Quaternion:
|
||||
return v;
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
ExactValue exact_value_real(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
@@ -285,6 +324,8 @@ ExactValue exact_value_real(ExactValue v) {
|
||||
return v;
|
||||
case ExactValue_Complex:
|
||||
return exact_value_float(v.value_complex.real);
|
||||
case ExactValue_Quaternion:
|
||||
return exact_value_float(v.value_quaternion.real);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
@@ -297,11 +338,39 @@ ExactValue exact_value_imag(ExactValue v) {
|
||||
return exact_value_integer(0);
|
||||
case ExactValue_Complex:
|
||||
return exact_value_float(v.value_complex.imag);
|
||||
case ExactValue_Quaternion:
|
||||
return exact_value_float(v.value_quaternion.imag);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
|
||||
ExactValue exact_value_jmag(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
case ExactValue_Float:
|
||||
case ExactValue_Complex:
|
||||
return exact_value_integer(0);
|
||||
case ExactValue_Quaternion:
|
||||
return exact_value_float(v.value_quaternion.jmag);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
ExactValue exact_value_kmag(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
case ExactValue_Float:
|
||||
case ExactValue_Complex:
|
||||
return exact_value_integer(0);
|
||||
case ExactValue_Quaternion:
|
||||
return exact_value_float(v.value_quaternion.kmag);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
ExactValue exact_value_make_imag(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
@@ -314,6 +383,30 @@ ExactValue exact_value_make_imag(ExactValue v) {
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
ExactValue exact_value_make_jmag(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
return exact_value_quaternion(0, 0, exact_value_to_float(v).value_float, 0);
|
||||
case ExactValue_Float:
|
||||
return exact_value_quaternion(0, 0, v.value_float, 0);
|
||||
default:
|
||||
GB_PANIC("Expected an integer or float type for `exact_value_make_jmag`");
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
ExactValue exact_value_make_kmag(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
return exact_value_quaternion(0, 0, 0, exact_value_to_float(v).value_float);
|
||||
case ExactValue_Float:
|
||||
return exact_value_quaternion(0, 0, 0, v.value_float);
|
||||
default:
|
||||
GB_PANIC("Expected an integer or float type for `exact_value_make_kmag`");
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -325,6 +418,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
case ExactValue_Integer:
|
||||
case ExactValue_Float:
|
||||
case ExactValue_Complex:
|
||||
case ExactValue_Quaternion:
|
||||
return v;
|
||||
}
|
||||
} break;
|
||||
@@ -348,6 +442,13 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
f64 imag = v.value_complex.imag;
|
||||
return exact_value_complex(-real, -imag);
|
||||
}
|
||||
case ExactValue_Quaternion: {
|
||||
f64 real = v.value_quaternion.real;
|
||||
f64 imag = v.value_quaternion.imag;
|
||||
f64 jmag = v.value_quaternion.jmag;
|
||||
f64 kmag = v.value_quaternion.kmag;
|
||||
return exact_value_quaternion(-real, -imag, -jmag, -kmag);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -403,8 +504,10 @@ i32 exact_value_order(ExactValue v) {
|
||||
return 3;
|
||||
case ExactValue_Complex:
|
||||
return 4;
|
||||
case ExactValue_Pointer:
|
||||
case ExactValue_Quaternion:
|
||||
return 5;
|
||||
case ExactValue_Pointer:
|
||||
return 6;
|
||||
|
||||
default:
|
||||
GB_PANIC("How'd you get here? Invalid Value.kind");
|
||||
@@ -426,6 +529,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
||||
case ExactValue_Bool:
|
||||
case ExactValue_String:
|
||||
case ExactValue_Complex:
|
||||
case ExactValue_Quaternion:
|
||||
return;
|
||||
|
||||
case ExactValue_Integer:
|
||||
@@ -439,15 +543,22 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
||||
case ExactValue_Complex:
|
||||
*x = exact_value_complex(cast(f64)x->value_integer, 0);
|
||||
return;
|
||||
case ExactValue_Quaternion:
|
||||
*x = exact_value_quaternion(cast(f64)x->value_integer, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case ExactValue_Float:
|
||||
if (y->kind == ExactValue_Float) {
|
||||
switch (y->kind) {
|
||||
case ExactValue_Float:
|
||||
return;
|
||||
} else if (y->kind == ExactValue_Complex) {
|
||||
case ExactValue_Complex:
|
||||
*x = exact_value_to_complex(*x);
|
||||
return;
|
||||
case ExactValue_Quaternion:
|
||||
*x = exact_value_to_quaternion(*x);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -538,6 +649,53 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
||||
}
|
||||
return exact_value_complex(real, imag);
|
||||
} break;
|
||||
|
||||
case ExactValue_Quaternion: {
|
||||
y = exact_value_to_quaternion(y);
|
||||
f64 a = x.value_quaternion.real;
|
||||
f64 b = x.value_quaternion.imag;
|
||||
f64 c = x.value_quaternion.jmag;
|
||||
f64 d = x.value_quaternion.kmag;
|
||||
|
||||
f64 e = x.value_quaternion.real;
|
||||
f64 f = x.value_quaternion.imag;
|
||||
f64 g = x.value_quaternion.jmag;
|
||||
f64 h = x.value_quaternion.kmag;
|
||||
|
||||
f64 real = 0;
|
||||
f64 imag = 0;
|
||||
f64 jmag = 0;
|
||||
f64 kmag = 0;
|
||||
switch (op) {
|
||||
case Token_Add:
|
||||
real = a + e;
|
||||
imag = b + f;
|
||||
jmag = c + g;
|
||||
kmag = d + h;
|
||||
break;
|
||||
case Token_Sub:
|
||||
real = a - e;
|
||||
imag = b - f;
|
||||
jmag = c - g;
|
||||
kmag = d - h;
|
||||
break;
|
||||
case Token_Mul:
|
||||
real = a*f + b*e + c*h - d*g;
|
||||
imag = a*g - b*h + c*e + d*f;
|
||||
jmag = a*h + b*g - c*f + d*e;
|
||||
kmag = a*e - b*f - c*g - d*h;
|
||||
break;
|
||||
case Token_Quo: {
|
||||
f64 s = e*e + f*f + g*g + h*h;
|
||||
real = (+a*e + b*f + c*g + d*h)/s;
|
||||
imag = (-a*f + b*e - c*h + d*h)/s;
|
||||
jmag = (-a*g + b*h + c*e - d*f)/s;
|
||||
kmag = (-a*h - b*g + c*f + d*e)/s;
|
||||
} break;
|
||||
default: goto error;
|
||||
}
|
||||
return exact_value_quaternion(real, imag, jmag, kmag);
|
||||
} break;
|
||||
}
|
||||
|
||||
error:
|
||||
@@ -609,6 +767,23 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
|
||||
}
|
||||
} break;
|
||||
|
||||
case ExactValue_Quaternion: {
|
||||
f64 a = x.value_quaternion.real;
|
||||
f64 b = x.value_quaternion.imag;
|
||||
f64 c = x.value_quaternion.jmag;
|
||||
f64 d = x.value_quaternion.kmag;
|
||||
|
||||
f64 e = y.value_quaternion.real;
|
||||
f64 f = y.value_quaternion.imag;
|
||||
f64 g = y.value_quaternion.jmag;
|
||||
f64 h = y.value_quaternion.kmag;
|
||||
|
||||
switch (op) {
|
||||
case Token_CmpEq: return cmp_f64(a, e) == 0 && cmp_f64(b, f) == 0 && cmp_f64(c, g) == 0 && cmp_f64(d, h) == 0;
|
||||
case Token_NotEq: return cmp_f64(a, e) != 0 || cmp_f64(b, f) != 0 || cmp_f64(c, g) != 0 || cmp_f64(d, h) != 0;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ExactValue_String: {
|
||||
String a = x.value_string;
|
||||
String b = y.value_string;
|
||||
|
||||
@@ -1351,6 +1351,7 @@ irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
|
||||
return ir_emit(p, ir_instr_store(p, address, value));
|
||||
}
|
||||
irValue *ir_emit_load(irProcedure *p, irValue *address) {
|
||||
GB_ASSERT(address != NULL);
|
||||
return ir_emit(p, ir_instr_load(p, address));
|
||||
}
|
||||
irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) {
|
||||
@@ -1719,11 +1720,7 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
||||
|
||||
if (is_type_complex(t_left)) {
|
||||
ir_emit_comment(proc, str_lit("complex.arith.begin"));
|
||||
Type *tl = core_type(t_left);
|
||||
Type *ft = t_f32;
|
||||
if (tl->Basic.kind == Basic_complex128) {
|
||||
ft = t_f64;
|
||||
}
|
||||
Type *ft = base_complex_elem_type(t_left);
|
||||
|
||||
irValue *res = ir_add_local_generated(proc, type);
|
||||
irValue *a = ir_emit_struct_ev(proc, left, 0);
|
||||
@@ -1773,6 +1770,126 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
||||
|
||||
ir_emit_comment(proc, str_lit("complex.end.begin"));
|
||||
return ir_emit_load(proc, res);
|
||||
} else if (is_type_quaternion(t_left)) {
|
||||
ir_emit_comment(proc, str_lit("quaternion.arith.begin"));
|
||||
Type *ft = base_quaternion_elem_type(t_left);
|
||||
|
||||
irValue *res = ir_add_local_generated(proc, type);
|
||||
irValue *a = ir_emit_struct_ev(proc, left, 0);
|
||||
irValue *b = ir_emit_struct_ev(proc, left, 1);
|
||||
irValue *c = ir_emit_struct_ev(proc, left, 2);
|
||||
irValue *d = ir_emit_struct_ev(proc, left, 3);
|
||||
|
||||
irValue *e = ir_emit_struct_ev(proc, right, 0);
|
||||
irValue *f = ir_emit_struct_ev(proc, right, 1);
|
||||
irValue *g = ir_emit_struct_ev(proc, right, 2);
|
||||
irValue *h = ir_emit_struct_ev(proc, right, 3);
|
||||
|
||||
irValue *real = NULL;
|
||||
irValue *imag = NULL;
|
||||
irValue *jmag = NULL;
|
||||
irValue *kmag = NULL;
|
||||
|
||||
switch (op) {
|
||||
case Token_Add:
|
||||
real = ir_emit_arith(proc, Token_Add, a, e, ft);
|
||||
imag = ir_emit_arith(proc, Token_Add, b, f, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Add, c, g, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Add, d, h, ft);
|
||||
break;
|
||||
case Token_Sub:
|
||||
real = ir_emit_arith(proc, Token_Sub, a, e, ft);
|
||||
imag = ir_emit_arith(proc, Token_Sub, b, f, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Sub, c, g, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Sub, d, h, ft);
|
||||
break;
|
||||
case Token_Mul: {
|
||||
irValue *r0 = ir_emit_arith(proc, Token_Mul, a, e, ft);
|
||||
irValue *r1 = ir_emit_arith(proc, Token_Mul, b, f, ft);
|
||||
irValue *r2 = ir_emit_arith(proc, Token_Mul, c, h, ft);
|
||||
irValue *r3 = ir_emit_arith(proc, Token_Mul, d, g, ft);
|
||||
real = ir_emit_arith(proc, Token_Add, r0, r1, ft);
|
||||
real = ir_emit_arith(proc, Token_Add, real, r2, ft);
|
||||
real = ir_emit_arith(proc, Token_Add, real, r3, ft);
|
||||
|
||||
irValue *i0 = ir_emit_arith(proc, Token_Mul, a, g, ft);
|
||||
irValue *i1 = ir_emit_arith(proc, Token_Mul, b, h, ft);
|
||||
irValue *i2 = ir_emit_arith(proc, Token_Mul, c, e, ft);
|
||||
irValue *i3 = ir_emit_arith(proc, Token_Mul, d, f, ft);
|
||||
imag = ir_emit_arith(proc, Token_Sub, i0, i1, ft);
|
||||
imag = ir_emit_arith(proc, Token_Add, imag, i2, ft);
|
||||
imag = ir_emit_arith(proc, Token_Add, imag, i3, ft);
|
||||
|
||||
irValue *j0 = ir_emit_arith(proc, Token_Mul, a, h, ft);
|
||||
irValue *j1 = ir_emit_arith(proc, Token_Mul, b, g, ft);
|
||||
irValue *j2 = ir_emit_arith(proc, Token_Mul, c, f, ft);
|
||||
irValue *j3 = ir_emit_arith(proc, Token_Mul, d, e, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Add, j0, j1, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Sub, imag, j2, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Sub, imag, j3, ft);
|
||||
|
||||
irValue *k0 = ir_emit_arith(proc, Token_Mul, a, e, ft);
|
||||
irValue *k1 = ir_emit_arith(proc, Token_Mul, b, f, ft);
|
||||
irValue *k2 = ir_emit_arith(proc, Token_Mul, c, g, ft);
|
||||
irValue *k3 = ir_emit_arith(proc, Token_Mul, d, h, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Sub, j0, j1, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Sub, imag, j2, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Sub, imag, j3, ft);
|
||||
} break;
|
||||
case Token_Quo: {
|
||||
irValue *s0 = ir_emit_arith(proc, Token_Mul, e, e, ft);
|
||||
irValue *s1 = ir_emit_arith(proc, Token_Mul, f, f, ft);
|
||||
irValue *s2 = ir_emit_arith(proc, Token_Mul, g, g, ft);
|
||||
irValue *s3 = ir_emit_arith(proc, Token_Mul, h, h, ft);
|
||||
irValue *s = ir_emit_arith(proc, Token_Add, s0, s1, ft);
|
||||
s = ir_emit_arith(proc, Token_Add, s, s2, ft);
|
||||
s = ir_emit_arith(proc, Token_Add, s, s3, ft);
|
||||
|
||||
irValue *r0 = ir_emit_arith(proc, Token_Mul, a, e, ft);
|
||||
irValue *r1 = ir_emit_arith(proc, Token_Mul, b, f, ft);
|
||||
irValue *r2 = ir_emit_arith(proc, Token_Mul, c, h, ft);
|
||||
irValue *r3 = ir_emit_arith(proc, Token_Mul, d, g, ft);
|
||||
real = ir_emit_arith(proc, Token_Add, r0, r1, ft);
|
||||
real = ir_emit_arith(proc, Token_Add, real, r2, ft);
|
||||
real = ir_emit_arith(proc, Token_Add, real, r3, ft);
|
||||
real = ir_emit_arith(proc, Token_Quo, real, s, ft);
|
||||
|
||||
irValue *i0 = ir_emit_arith(proc, Token_Mul, a, f, ft);
|
||||
irValue *i1 = ir_emit_arith(proc, Token_Mul, b, e, ft);
|
||||
irValue *i2 = ir_emit_arith(proc, Token_Mul, c, h, ft);
|
||||
irValue *i3 = ir_emit_arith(proc, Token_Mul, d, g, ft);
|
||||
imag = ir_emit_arith(proc, Token_Sub, i1, i0, ft);
|
||||
imag = ir_emit_arith(proc, Token_Sub, imag, i2, ft);
|
||||
imag = ir_emit_arith(proc, Token_Add, imag, i3, ft);
|
||||
imag = ir_emit_arith(proc, Token_Quo, imag, s, ft);
|
||||
|
||||
irValue *j0 = ir_emit_arith(proc, Token_Mul, a, g, ft);
|
||||
irValue *j1 = ir_emit_arith(proc, Token_Mul, b, h, ft);
|
||||
irValue *j2 = ir_emit_arith(proc, Token_Mul, c, e, ft);
|
||||
irValue *j3 = ir_emit_arith(proc, Token_Mul, d, f, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Sub, j1, j0, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Add, imag, j2, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Sub, imag, j3, ft);
|
||||
jmag = ir_emit_arith(proc, Token_Quo, jmag, s, ft);
|
||||
|
||||
irValue *k0 = ir_emit_arith(proc, Token_Mul, a, h, ft);
|
||||
irValue *k1 = ir_emit_arith(proc, Token_Mul, b, g, ft);
|
||||
irValue *k2 = ir_emit_arith(proc, Token_Mul, c, f, ft);
|
||||
irValue *k3 = ir_emit_arith(proc, Token_Mul, d, e, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Add, k2, k3, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Sub, imag, k0, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Sub, imag, k1, ft);
|
||||
kmag = ir_emit_arith(proc, Token_Quo, kmag, s, ft);
|
||||
} break;
|
||||
}
|
||||
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 2), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 3), kmag);
|
||||
|
||||
ir_emit_comment(proc, str_lit("quaternion.end.begin"));
|
||||
return ir_emit_load(proc, res);
|
||||
}
|
||||
|
||||
|
||||
@@ -1950,14 +2067,19 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||
result_type = make_type_pointer(a, t->Tuple.variables[index]->type);
|
||||
} else if (is_type_complex(t)) {
|
||||
Type *ft = t_f32;
|
||||
if (core_type(t)->Basic.kind == Basic_complex128) {
|
||||
ft = t_f64;
|
||||
}
|
||||
Type *ft = base_complex_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = make_type_pointer(a, ft); break;
|
||||
case 1: result_type = make_type_pointer(a, ft); break;
|
||||
}
|
||||
} else if (is_type_quaternion(t)) {
|
||||
Type *ft = base_quaternion_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = make_type_pointer(a, ft); break;
|
||||
case 1: result_type = make_type_pointer(a, ft); break;
|
||||
case 2: result_type = make_type_pointer(a, ft); break;
|
||||
case 3: result_type = make_type_pointer(a, ft); break;
|
||||
}
|
||||
} else if (is_type_slice(t)) {
|
||||
switch (index) {
|
||||
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break;
|
||||
@@ -2025,14 +2147,19 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
||||
result_type = t->Tuple.variables[index]->type;
|
||||
} else if (is_type_complex(t)) {
|
||||
Type *ft = t_f32;
|
||||
if (core_type(t)->Basic.kind == Basic_complex128) {
|
||||
ft = t_f64;
|
||||
}
|
||||
Type *ft = base_complex_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = ft; break;
|
||||
case 1: result_type = ft; break;
|
||||
}
|
||||
} else if (is_type_quaternion(t)) {
|
||||
Type *ft = base_quaternion_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = ft; break;
|
||||
case 1: result_type = ft; break;
|
||||
case 2: result_type = ft; break;
|
||||
case 3: result_type = ft; break;
|
||||
}
|
||||
} else if (is_type_slice(t)) {
|
||||
switch (index) {
|
||||
case 0: result_type = make_type_pointer(a, t->Slice.elem); break;
|
||||
@@ -2364,6 +2491,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
ev = exact_value_to_float(ev);
|
||||
} else if (is_type_complex(dst)) {
|
||||
ev = exact_value_to_complex(ev);
|
||||
} else if (is_type_quaternion(dst)) {
|
||||
ev = exact_value_to_quaternion(ev);
|
||||
} else if (is_type_string(dst)) {
|
||||
// Handled elsewhere
|
||||
GB_ASSERT(ev.kind == ExactValue_String);
|
||||
@@ -2439,6 +2568,20 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
if (is_type_quaternion(src) && is_type_quaternion(dst)) {
|
||||
Type *ft = base_quaternion_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst);
|
||||
irValue *real = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 0), ft);
|
||||
irValue *imag = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 1), ft);
|
||||
irValue *jmag = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 2), ft);
|
||||
irValue *kmag = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 3), ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 1), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 2), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), kmag);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
// float <-> integer
|
||||
if (is_type_float(src) && is_type_integer(dst)) {
|
||||
irConvKind kind = irConv_fptosi;
|
||||
@@ -3800,29 +3943,88 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *dst = ir_add_local_generated(proc, tv->type);
|
||||
|
||||
Type *ft = base_complex_elem_type(tv->type);
|
||||
irValue *rp = ir_emit_struct_ep(proc, dst, 0);
|
||||
irValue *ip = ir_emit_struct_ep(proc, dst, 1);
|
||||
|
||||
real = ir_emit_conv(proc, real, ft);
|
||||
imag = ir_emit_conv(proc, imag, ft);
|
||||
ir_emit_store(proc, rp, real);
|
||||
ir_emit_store(proc, ip, imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 1), imag);
|
||||
|
||||
return ir_emit_load(proc, dst);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_quaternion: {
|
||||
ir_emit_comment(proc, str_lit("quaternion"));
|
||||
irValue *real = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *imag = ir_build_expr(proc, ce->args.e[1]);
|
||||
irValue *jmag = ir_build_expr(proc, ce->args.e[2]);
|
||||
irValue *kmag = ir_build_expr(proc, ce->args.e[3]);
|
||||
irValue *dst = ir_add_local_generated(proc, tv->type);
|
||||
|
||||
Type *ft = base_complex_elem_type(tv->type);
|
||||
real = ir_emit_conv(proc, real, ft);
|
||||
imag = ir_emit_conv(proc, imag, ft);
|
||||
jmag = ir_emit_conv(proc, jmag, ft);
|
||||
kmag = ir_emit_conv(proc, kmag, ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 1), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 2), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 3), kmag);
|
||||
|
||||
return ir_emit_load(proc, dst);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_real: {
|
||||
ir_emit_comment(proc, str_lit("real"));
|
||||
irValue *complex = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *real = ir_emit_struct_ev(proc, complex, 0);
|
||||
irValue *val = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, real, tv->type);
|
||||
} break;
|
||||
case BuiltinProc_imag: {
|
||||
ir_emit_comment(proc, str_lit("imag"));
|
||||
irValue *complex = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *imag = ir_emit_struct_ev(proc, complex, 1);
|
||||
irValue *val = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv->type);
|
||||
} break;
|
||||
case BuiltinProc_jmag: {
|
||||
ir_emit_comment(proc, str_lit("jmag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *jmag = ir_emit_struct_ev(proc, val, 2);
|
||||
return ir_emit_conv(proc, jmag, tv->type);
|
||||
} break;
|
||||
case BuiltinProc_kmag: {
|
||||
ir_emit_comment(proc, str_lit("kmag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *kmag = ir_emit_struct_ev(proc, val, 3);
|
||||
return ir_emit_conv(proc, kmag, tv->type);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_conj: {
|
||||
ir_emit_comment(proc, str_lit("conj"));
|
||||
irValue *val = ir_build_expr(proc, ce->args.e[0]);
|
||||
irValue *res = NULL;
|
||||
Type *t = ir_type(val);
|
||||
if (is_type_complex(t)) {
|
||||
irValue *res = ir_add_local_generated(proc, tv->type);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
|
||||
} else if (is_type_quaternion(t)) {
|
||||
irValue *res = ir_add_local_generated(proc, tv->type);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
irValue *jmag = ir_emit_struct_ev(proc, val, 2);
|
||||
irValue *kmag = ir_emit_struct_ev(proc, val, 3);
|
||||
imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag));
|
||||
jmag = ir_emit_unary_arith(proc, Token_Sub, jmag, ir_type(jmag));
|
||||
kmag = ir_emit_unary_arith(proc, Token_Sub, kmag, ir_type(kmag));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 2), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 3), kmag);
|
||||
}
|
||||
return ir_emit_load(proc, res);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_slice_ptr: {
|
||||
ir_emit_comment(proc, str_lit("slice_ptr"));
|
||||
@@ -3880,6 +4082,27 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
ir_emit_comment(proc, str_lit("abs"));
|
||||
irValue *x = ir_build_expr(proc, ce->args.e[0]);
|
||||
Type *t = ir_type(x);
|
||||
if (is_type_complex(t)) {
|
||||
gbAllocator a = proc->module->allocator;
|
||||
i64 sz = 8*type_size_of(a, t);
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = x;
|
||||
switch (sz) {
|
||||
case 64: return ir_emit_global_call(proc, "__abs_complex64", args, 1);
|
||||
case 128: return ir_emit_global_call(proc, "__abs_complex128", args, 1);
|
||||
}
|
||||
GB_PANIC("Unknown complex type");
|
||||
} else if (is_type_quaternion(t)) {
|
||||
gbAllocator a = proc->module->allocator;
|
||||
i64 sz = 8*type_size_of(a, t);
|
||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||
args[0] = x;
|
||||
switch (sz) {
|
||||
case 128: return ir_emit_global_call(proc, "__abs_quaternion128", args, 1);
|
||||
case 256: return ir_emit_global_call(proc, "__abs_quaternion256", args, 1);
|
||||
}
|
||||
GB_PANIC("Unknown quaternion type");
|
||||
}
|
||||
irValue *zero = ir_emit_conv(proc, v_zero, t);
|
||||
irValue *cond = ir_emit_comp(proc, Token_Lt, x, zero);
|
||||
irValue *neg = ir_emit(proc, ir_instr_unary_op(proc, Token_Sub, x, t));
|
||||
@@ -6659,21 +6882,25 @@ void ir_gen_tree(irGen *s) {
|
||||
} break;
|
||||
|
||||
case Basic_f32:
|
||||
case Basic_f64:
|
||||
{
|
||||
case Basic_f64: {
|
||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_float_ptr);
|
||||
irValue *bits = ir_const_int(a, type_size_of(a, t));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
||||
} break;
|
||||
|
||||
case Basic_complex64:
|
||||
case Basic_complex128:
|
||||
{
|
||||
case Basic_complex128: {
|
||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_complex_ptr);
|
||||
irValue *bits = ir_const_int(a, type_size_of(a, t));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
||||
} break;
|
||||
|
||||
case Basic_quaternion128:
|
||||
case Basic_quaternion256: {
|
||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_quaternion_ptr);
|
||||
irValue *bits = ir_const_int(a, type_size_of(a, t));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
||||
} break;
|
||||
|
||||
case Basic_rawptr:
|
||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
|
||||
|
||||
+125
-28
@@ -145,28 +145,30 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_bool: ir_fprintf(f, "i1"); return;
|
||||
case Basic_i8: ir_fprintf(f, "i8"); return;
|
||||
case Basic_u8: ir_fprintf(f, "i8"); return;
|
||||
case Basic_i16: ir_fprintf(f, "i16"); return;
|
||||
case Basic_u16: ir_fprintf(f, "i16"); return;
|
||||
case Basic_i32: ir_fprintf(f, "i32"); return;
|
||||
case Basic_u32: ir_fprintf(f, "i32"); return;
|
||||
case Basic_i64: ir_fprintf(f, "i64"); return;
|
||||
case Basic_u64: ir_fprintf(f, "i64"); return;
|
||||
case Basic_bool: ir_fprintf(f, "i1"); return;
|
||||
case Basic_i8: ir_fprintf(f, "i8"); return;
|
||||
case Basic_u8: ir_fprintf(f, "i8"); return;
|
||||
case Basic_i16: ir_fprintf(f, "i16"); return;
|
||||
case Basic_u16: ir_fprintf(f, "i16"); return;
|
||||
case Basic_i32: ir_fprintf(f, "i32"); return;
|
||||
case Basic_u32: ir_fprintf(f, "i32"); return;
|
||||
case Basic_i64: ir_fprintf(f, "i64"); return;
|
||||
case Basic_u64: ir_fprintf(f, "i64"); return;
|
||||
|
||||
case Basic_f32: ir_fprintf(f, "float"); return;
|
||||
case Basic_f64: ir_fprintf(f, "double"); return;
|
||||
case Basic_f32: ir_fprintf(f, "float"); return;
|
||||
case Basic_f64: ir_fprintf(f, "double"); return;
|
||||
|
||||
case Basic_complex64: ir_fprintf(f, "%%..complex64"); return;
|
||||
case Basic_complex128: ir_fprintf(f, "%%..complex128"); return;
|
||||
case Basic_complex64: ir_fprintf(f, "%%..complex64"); return;
|
||||
case Basic_complex128: ir_fprintf(f, "%%..complex128"); return;
|
||||
|
||||
case Basic_quaternion128: ir_fprintf(f, "%%..quaternion128"); return;
|
||||
case Basic_quaternion256: ir_fprintf(f, "%%..quaternion256"); return;
|
||||
|
||||
case Basic_rawptr: ir_fprintf(f, "%%..rawptr"); return;
|
||||
case Basic_string: ir_fprintf(f, "%%..string"); return;
|
||||
case Basic_uint: ir_fprintf(f, "i%lld", word_bits); return;
|
||||
case Basic_int: ir_fprintf(f, "i%lld", word_bits); return;
|
||||
case Basic_any: ir_fprintf(f, "%%..any"); return;
|
||||
case Basic_rawptr: ir_fprintf(f, "%%..rawptr"); return;
|
||||
case Basic_string: ir_fprintf(f, "%%..string"); return;
|
||||
case Basic_uint: ir_fprintf(f, "i%lld", word_bits); return;
|
||||
case Basic_int: ir_fprintf(f, "i%lld", word_bits); return;
|
||||
case Basic_any: ir_fprintf(f, "%%..any"); return;
|
||||
}
|
||||
break;
|
||||
case Type_Pointer:
|
||||
@@ -391,17 +393,42 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
} break;
|
||||
|
||||
case ExactValue_Complex: {
|
||||
GB_ASSERT_MSG(is_type_complex(type), "%s", type_to_string(type));
|
||||
type = core_type(type);
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
ir_fprintf(f, " {");
|
||||
ir_print_type(f, m, ft);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_complex.real), ft);
|
||||
ir_fprintf(f, ", ");
|
||||
ir_print_type(f, m, ft);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_complex.imag), ft);
|
||||
if (is_type_quaternion(type)) {
|
||||
Type *ft = base_quaternion_elem_type(type);
|
||||
ir_fprintf(f, " {"); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_complex.real), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_complex.imag), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(0), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(0), ft);
|
||||
ir_fprintf(f, "}");
|
||||
|
||||
} else {
|
||||
GB_ASSERT_MSG(is_type_complex(type), "%s", type_to_string(type));
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
ir_fprintf(f, " {"); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_complex.real), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_complex.imag), ft);
|
||||
ir_fprintf(f, "}");
|
||||
}
|
||||
} break;
|
||||
|
||||
case ExactValue_Quaternion: {
|
||||
GB_ASSERT_MSG(is_type_quaternion(type), "%s", type_to_string(type));
|
||||
type = core_type(type);
|
||||
Type *ft = base_quaternion_elem_type(type);
|
||||
ir_fprintf(f, " {"); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.real), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.imag), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.jmag), ft);
|
||||
ir_fprintf(f, ", "); ir_print_type(f, m, ft); ir_fprintf(f, " ");
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.kmag), ft);
|
||||
ir_fprintf(f, "}");
|
||||
} break;
|
||||
|
||||
@@ -1008,6 +1035,72 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
case Token_LtEq: ir_fprintf(f, "ole"); break;
|
||||
case Token_GtEq: ir_fprintf(f, "oge"); break;
|
||||
}
|
||||
} else if (is_type_complex(elem_type)) {
|
||||
ir_fprintf(f, "call ");
|
||||
ir_print_calling_convention(f, m, ProcCC_Odin);
|
||||
ir_print_type(f, m, t_bool);
|
||||
char *runtime_proc = "";
|
||||
i64 sz = 8*type_size_of(m->allocator, elem_type);
|
||||
switch (sz) {
|
||||
case 64:
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: runtime_proc = "__complex64_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "__complex64_ne"; break;
|
||||
}
|
||||
break;
|
||||
case 128:
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: runtime_proc = "__complex128_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "__complex128_ne"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_encoded_global(f, make_string_c(runtime_proc), false);
|
||||
ir_fprintf(f, "(");
|
||||
ir_print_type(f, m, type);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, bo->left, type);
|
||||
ir_fprintf(f, ", ");
|
||||
ir_print_type(f, m, type);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, bo->right, type);
|
||||
ir_fprintf(f, ")\n");
|
||||
return;
|
||||
} else if (is_type_quaternion(elem_type)) {
|
||||
ir_fprintf(f, "call ");
|
||||
ir_print_calling_convention(f, m, ProcCC_Odin);
|
||||
ir_print_type(f, m, t_bool);
|
||||
char *runtime_proc = "";
|
||||
i64 sz = 8*type_size_of(m->allocator, elem_type);
|
||||
switch (sz) {
|
||||
case 128:
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: runtime_proc = "__quaternion128_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "__quaternion128_ne"; break;
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: runtime_proc = "__quaternion256_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "__quaternion256_ne"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_encoded_global(f, make_string_c(runtime_proc), false);
|
||||
ir_fprintf(f, "(");
|
||||
ir_print_type(f, m, type);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, bo->left, type);
|
||||
ir_fprintf(f, ", ");
|
||||
ir_print_type(f, m, type);
|
||||
ir_fprintf(f, " ");
|
||||
ir_print_value(f, m, bo->right, type);
|
||||
ir_fprintf(f, ")\n");
|
||||
return;
|
||||
} else {
|
||||
ir_fprintf(f, "icmp ");
|
||||
if (bo->op != Token_CmpEq &&
|
||||
@@ -1420,6 +1513,10 @@ void print_llvm_ir(irGen *ir) {
|
||||
ir_fprintf(f, " = type {float, float} ; Basic_complex64\n");
|
||||
ir_print_encoded_local(f, str_lit("..complex128"));
|
||||
ir_fprintf(f, " = type {double, double} ; Basic_complex128\n");
|
||||
ir_print_encoded_local(f, str_lit("..quaternion128"));
|
||||
ir_fprintf(f, " = type {float, float, float, float} ; Basic_quaternion128\n");
|
||||
ir_print_encoded_local(f, str_lit("..quaternion256"));
|
||||
ir_fprintf(f, " = type {double, double, double, double} ; Basic_quaternion256\n");
|
||||
|
||||
|
||||
ir_print_encoded_local(f, str_lit("..any"));
|
||||
|
||||
+3
-1
@@ -578,9 +578,11 @@ exponent:
|
||||
scan_mantissa(t, 10);
|
||||
}
|
||||
|
||||
if (t->curr_rune == 'i') {
|
||||
switch (t->curr_rune) {
|
||||
case 'i': case 'j': case 'k':
|
||||
token.kind = Token_Imag;
|
||||
advance_to_next_rune(t);
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
+89
-53
@@ -18,6 +18,9 @@ typedef enum BasicKind {
|
||||
Basic_complex64,
|
||||
Basic_complex128,
|
||||
|
||||
Basic_quaternion128,
|
||||
Basic_quaternion256,
|
||||
|
||||
Basic_int,
|
||||
Basic_uint,
|
||||
Basic_rawptr,
|
||||
@@ -28,6 +31,7 @@ typedef enum BasicKind {
|
||||
Basic_UntypedInteger,
|
||||
Basic_UntypedFloat,
|
||||
Basic_UntypedComplex,
|
||||
Basic_UntypedQuaternion,
|
||||
Basic_UntypedString,
|
||||
Basic_UntypedRune,
|
||||
Basic_UntypedNil,
|
||||
@@ -39,18 +43,19 @@ typedef enum BasicKind {
|
||||
} BasicKind;
|
||||
|
||||
typedef enum BasicFlag {
|
||||
BasicFlag_Boolean = GB_BIT(0),
|
||||
BasicFlag_Integer = GB_BIT(1),
|
||||
BasicFlag_Unsigned = GB_BIT(2),
|
||||
BasicFlag_Float = GB_BIT(3),
|
||||
BasicFlag_Complex = GB_BIT(4),
|
||||
BasicFlag_Pointer = GB_BIT(5),
|
||||
BasicFlag_String = GB_BIT(6),
|
||||
BasicFlag_Rune = GB_BIT(7),
|
||||
BasicFlag_Untyped = GB_BIT(8),
|
||||
BasicFlag_Boolean = GB_BIT(0),
|
||||
BasicFlag_Integer = GB_BIT(1),
|
||||
BasicFlag_Unsigned = GB_BIT(2),
|
||||
BasicFlag_Float = GB_BIT(3),
|
||||
BasicFlag_Complex = GB_BIT(4),
|
||||
BasicFlag_Quaternion = GB_BIT(5),
|
||||
BasicFlag_Pointer = GB_BIT(6),
|
||||
BasicFlag_String = GB_BIT(7),
|
||||
BasicFlag_Rune = GB_BIT(8),
|
||||
BasicFlag_Untyped = GB_BIT(9),
|
||||
|
||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex,
|
||||
BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
|
||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex | BasicFlag_Quaternion,
|
||||
BasicFlag_Ordered = BasicFlag_Integer | BasicFlag_Float | BasicFlag_String | BasicFlag_Pointer,
|
||||
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
|
||||
} BasicFlag;
|
||||
|
||||
@@ -198,39 +203,43 @@ void selection_add_index(Selection *s, isize index) {
|
||||
|
||||
|
||||
gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
||||
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
||||
|
||||
{Type_Basic, {Basic_bool, BasicFlag_Boolean, 1, STR_LIT("bool")}},
|
||||
{Type_Basic, {Basic_bool, BasicFlag_Boolean, 1, STR_LIT("bool")}},
|
||||
|
||||
{Type_Basic, {Basic_i8, BasicFlag_Integer, 1, STR_LIT("i8")}},
|
||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("u8")}},
|
||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, 2, STR_LIT("i16")}},
|
||||
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, 2, STR_LIT("u16")}},
|
||||
{Type_Basic, {Basic_i32, BasicFlag_Integer, 4, STR_LIT("i32")}},
|
||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
|
||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
|
||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
|
||||
{Type_Basic, {Basic_i8, BasicFlag_Integer, 1, STR_LIT("i8")}},
|
||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("u8")}},
|
||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, 2, STR_LIT("i16")}},
|
||||
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, 2, STR_LIT("u16")}},
|
||||
{Type_Basic, {Basic_i32, BasicFlag_Integer, 4, STR_LIT("i32")}},
|
||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
|
||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
|
||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
|
||||
|
||||
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
|
||||
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
|
||||
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
|
||||
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
|
||||
|
||||
{Type_Basic, {Basic_complex64, BasicFlag_Complex, 8, STR_LIT("complex64")}},
|
||||
{Type_Basic, {Basic_complex128, BasicFlag_Complex, 16, STR_LIT("complex128")}},
|
||||
{Type_Basic, {Basic_complex64, BasicFlag_Complex, 8, STR_LIT("complex64")}},
|
||||
{Type_Basic, {Basic_complex128, BasicFlag_Complex, 16, STR_LIT("complex128")}},
|
||||
|
||||
{Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
|
||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
|
||||
{Type_Basic, {Basic_quaternion128, BasicFlag_Quaternion, 16, STR_LIT("quaternion128")}},
|
||||
{Type_Basic, {Basic_quaternion256, BasicFlag_Quaternion, 32, STR_LIT("quaternion256")}},
|
||||
|
||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
||||
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
||||
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
|
||||
{Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
|
||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
|
||||
|
||||
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
|
||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
|
||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
|
||||
{Type_Basic, {Basic_UntypedComplex, BasicFlag_Complex | BasicFlag_Untyped, 0, STR_LIT("untyped complex")}},
|
||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
|
||||
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
|
||||
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
|
||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
||||
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
||||
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
|
||||
|
||||
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
|
||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
|
||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
|
||||
{Type_Basic, {Basic_UntypedComplex, BasicFlag_Complex | BasicFlag_Untyped, 0, STR_LIT("untyped complex")}},
|
||||
{Type_Basic, {Basic_UntypedQuaternion, BasicFlag_Quaternion | BasicFlag_Untyped, 0, STR_LIT("untyped quaternion")}},
|
||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
|
||||
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
|
||||
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
|
||||
};
|
||||
|
||||
gb_global Type basic_type_aliases[] = {
|
||||
@@ -255,6 +264,9 @@ gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
gb_global Type *t_complex64 = &basic_types[Basic_complex64];
|
||||
gb_global Type *t_complex128 = &basic_types[Basic_complex128];
|
||||
|
||||
gb_global Type *t_quaternion128 = &basic_types[Basic_quaternion128];
|
||||
gb_global Type *t_quaternion256 = &basic_types[Basic_quaternion256];
|
||||
|
||||
gb_global Type *t_int = &basic_types[Basic_int];
|
||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||
|
||||
@@ -262,15 +274,16 @@ gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
||||
gb_global Type *t_string = &basic_types[Basic_string];
|
||||
gb_global Type *t_any = &basic_types[Basic_any];
|
||||
|
||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||
gb_global Type *t_untyped_complex = &basic_types[Basic_UntypedComplex];
|
||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||
gb_global Type *t_byte = &basic_type_aliases[0];
|
||||
gb_global Type *t_rune = &basic_type_aliases[1];
|
||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||
gb_global Type *t_untyped_complex = &basic_types[Basic_UntypedComplex];
|
||||
gb_global Type *t_untyped_quaternion = &basic_types[Basic_UntypedQuaternion];
|
||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||
gb_global Type *t_byte = &basic_type_aliases[0];
|
||||
gb_global Type *t_rune = &basic_type_aliases[1];
|
||||
|
||||
|
||||
gb_global Type *t_u8_ptr = NULL;
|
||||
@@ -293,6 +306,7 @@ gb_global Type *t_type_info_named = NULL;
|
||||
gb_global Type *t_type_info_integer = NULL;
|
||||
gb_global Type *t_type_info_float = NULL;
|
||||
gb_global Type *t_type_info_complex = NULL;
|
||||
gb_global Type *t_type_info_quaternion = NULL;
|
||||
gb_global Type *t_type_info_any = NULL;
|
||||
gb_global Type *t_type_info_string = NULL;
|
||||
gb_global Type *t_type_info_boolean = NULL;
|
||||
@@ -313,6 +327,7 @@ gb_global Type *t_type_info_named_ptr = NULL;
|
||||
gb_global Type *t_type_info_integer_ptr = NULL;
|
||||
gb_global Type *t_type_info_float_ptr = NULL;
|
||||
gb_global Type *t_type_info_complex_ptr = NULL;
|
||||
gb_global Type *t_type_info_quaternion_ptr = NULL;
|
||||
gb_global Type *t_type_info_any_ptr = NULL;
|
||||
gb_global Type *t_type_info_string_ptr = NULL;
|
||||
gb_global Type *t_type_info_boolean_ptr = NULL;
|
||||
@@ -623,6 +638,13 @@ bool is_type_complex(Type *t) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_type_quaternion(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t->kind == Type_Basic) {
|
||||
return (t->Basic.flags & BasicFlag_Quaternion) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_type_f32(Type *t) {
|
||||
t = core_type(t);
|
||||
if (t->kind == Type_Basic) {
|
||||
@@ -715,6 +737,18 @@ Type *base_complex_elem_type(Type *t) {
|
||||
GB_PANIC("Invalid complex type");
|
||||
return t_invalid;
|
||||
}
|
||||
Type *base_quaternion_elem_type(Type *t) {
|
||||
t = core_type(t);
|
||||
if (is_type_quaternion(t)) {
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_quaternion128: return t_f32;
|
||||
case Basic_quaternion256: return t_f64;
|
||||
case Basic_UntypedQuaternion: return t_untyped_float;
|
||||
}
|
||||
}
|
||||
GB_PANIC("Invalid quaternion type");
|
||||
return t_invalid;
|
||||
}
|
||||
|
||||
|
||||
bool is_type_struct(Type *t) {
|
||||
@@ -971,12 +1005,13 @@ Type *default_type(Type *type) {
|
||||
}
|
||||
if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_UntypedBool: return t_bool;
|
||||
case Basic_UntypedInteger: return t_int;
|
||||
case Basic_UntypedFloat: return t_f64;
|
||||
case Basic_UntypedComplex: return t_complex128;
|
||||
case Basic_UntypedString: return t_string;
|
||||
case Basic_UntypedRune: return t_rune;
|
||||
case Basic_UntypedBool: return t_bool;
|
||||
case Basic_UntypedInteger: return t_int;
|
||||
case Basic_UntypedFloat: return t_f64;
|
||||
case Basic_UntypedComplex: return t_complex128;
|
||||
case Basic_UntypedQuaternion: return t_quaternion256;
|
||||
case Basic_UntypedString: return t_string;
|
||||
case Basic_UntypedRune: return t_rune;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
@@ -1567,8 +1602,9 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
||||
return build_context.word_size;
|
||||
|
||||
case Basic_complex64: case Basic_complex128:
|
||||
// complex{64,128} align as [2]f{32,64}
|
||||
return type_size_of_internal(allocator, t, path) / 2;
|
||||
case Basic_quaternion128: case Basic_quaternion256:
|
||||
return type_size_of_internal(allocator, t, path) / 4;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user