mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-29 19:00:06 +00:00
Built-in Quaternions (Not just an April Fool's Joke any more)
This commit is contained in:
+235
-7
@@ -497,6 +497,14 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
||||
if (is_type_complex(dst)) {
|
||||
return 1;
|
||||
}
|
||||
if (is_type_quaternion(dst)) {
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case Basic_UntypedQuaternion:
|
||||
if (is_type_quaternion(dst)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1438,7 +1446,7 @@ bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Typ
|
||||
ExactValue imag = exact_value_imag(v);
|
||||
if (real.kind != ExactValue_Invalid &&
|
||||
imag.kind != ExactValue_Invalid) {
|
||||
if (out_value) *out_value = exact_binary_operator_value(Token_Add, real, exact_value_make_imag(imag));
|
||||
if (out_value) *out_value = exact_value_complex(exact_value_to_f64(real), exact_value_to_f64(imag));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -1449,6 +1457,36 @@ bool check_representable_as_constant(CheckerContext *c, ExactValue in_value, Typ
|
||||
default: GB_PANIC("Compiler error: Unknown complex type!"); break;
|
||||
}
|
||||
|
||||
return false;
|
||||
} 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) {
|
||||
if (out_value) *out_value = exact_value_quaternion(exact_value_to_f64(real), exact_value_to_f64(imag), exact_value_to_f64(jmag), exact_value_to_f64(kmag));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Basic_UntypedComplex:
|
||||
if (out_value) *out_value = exact_value_to_quaternion(*out_value);
|
||||
return true;
|
||||
case Basic_UntypedQuaternion:
|
||||
return true;
|
||||
|
||||
default: GB_PANIC("Compiler error: Unknown complex type!"); break;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (is_type_pointer(type)) {
|
||||
if (in_value.kind == ExactValue_Pointer) {
|
||||
@@ -1481,10 +1519,14 @@ void check_is_expressible(CheckerContext *c, Operand *o, Type *type) {
|
||||
if (!is_type_integer(o->type) && is_type_integer(type)) {
|
||||
error(o->expr, "'%s' truncated to '%s'", a, b);
|
||||
} else {
|
||||
#if 0
|
||||
gbAllocator ha = heap_allocator();
|
||||
String str = big_int_to_string(ha, &o->value.value_integer);
|
||||
defer (gb_free(ha, str.text));
|
||||
error(o->expr, "'%s = %.*s' overflows '%s'", a, LIT(str), b);
|
||||
#else
|
||||
error(o->expr, "Cannot convert '%s' to '%s'", a, b);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
error(o->expr, "Cannot convert '%s' to '%s'", a, b);
|
||||
@@ -1759,6 +1801,21 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (is_type_quaternion(x->type) || is_type_quaternion(y->type)) {
|
||||
switch (op) {
|
||||
case Token_CmpEq:
|
||||
switch (8*size) {
|
||||
case 128: add_package_dependency(c, "runtime", "quaternion128_eq"); break;
|
||||
case 256: add_package_dependency(c, "runtime", "quaternion256_eq"); break;
|
||||
}
|
||||
break;
|
||||
case Token_NotEq:
|
||||
switch (8*size) {
|
||||
case 128: add_package_dependency(c, "runtime", "quaternion128_ne"); break;
|
||||
case 256: add_package_dependency(c, "runtime", "quaternion256_ne"); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1978,6 +2035,14 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_complex(src) && is_type_quaternion(dst)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_quaternion(src) && is_type_quaternion(dst)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_type_bit_field_value(src) && is_type_integer(dst)) {
|
||||
return true;
|
||||
}
|
||||
@@ -2557,6 +2622,8 @@ ExactValue convert_exact_value_for_type(ExactValue v, Type *type) {
|
||||
v = exact_value_to_integer(v);
|
||||
} else if (is_type_complex(t)) {
|
||||
v = exact_value_to_complex(v);
|
||||
} else if (is_type_quaternion(t)) {
|
||||
v = exact_value_to_quaternion(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
@@ -2652,6 +2719,7 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
|
||||
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;
|
||||
@@ -3769,10 +3837,98 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_quaternion: {
|
||||
// quaternion :: proc(real, imag, jmag, kmag: float_type) -> complex_type
|
||||
Operand x = *operand;
|
||||
Operand y = {};
|
||||
Operand z = {};
|
||||
Operand w = {};
|
||||
|
||||
// NOTE(bill): Invalid will be the default till fixed
|
||||
operand->type = t_invalid;
|
||||
operand->mode = Addressing_Invalid;
|
||||
|
||||
check_expr(c, &y, ce->args[1]);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
check_expr(c, &z, ce->args[2]);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
check_expr(c, &w, ce->args[3]);
|
||||
if (y.mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
convert_to_typed(c, &x, y.type); if (x.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &z, x.type); if (z.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &w, x.type); 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) {
|
||||
x.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(y.type) && exact_value_imag(y.value).value_float == 0) {
|
||||
y.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(z.type) && exact_value_imag(z.value).value_float == 0) {
|
||||
z.type = t_untyped_float;
|
||||
}
|
||||
if (is_type_numeric(w.type) && exact_value_imag(w.value).value_float == 0) {
|
||||
w.type = t_untyped_float;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(are_types_identical(x.type, y.type) && are_types_identical(x.type, z.type) && are_types_identical(x.type, w.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(call, "Mismatched types to 'quaternion', '%s' vs '%s' vs '%s' vs '%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(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) {
|
||||
f64 r = exact_value_to_float(x.value).value_float;
|
||||
f64 i = exact_value_to_float(y.value).value_float;
|
||||
f64 j = exact_value_to_float(z.value).value_float;
|
||||
f64 k = exact_value_to_float(w.value).value_float;
|
||||
operand->value = exact_value_quaternion(r, i, j, k);
|
||||
operand->mode = Addressing_Constant;
|
||||
} else {
|
||||
operand->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
BasicKind kind = core_type(x.type)->Basic.kind;
|
||||
switch (kind) {
|
||||
case Basic_f32: operand->type = t_quaternion128; break;
|
||||
case Basic_f64: operand->type = t_quaternion256; break;
|
||||
case Basic_UntypedFloat: operand->type = t_untyped_quaternion; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_real:
|
||||
case BuiltinProc_imag: {
|
||||
// real :: proc(x: type) -> float_type
|
||||
// proc imag(x: type) -> float_type
|
||||
// imag :: proc(x: type) -> float_type
|
||||
|
||||
Operand *x = operand;
|
||||
if (is_type_untyped(x->type)) {
|
||||
@@ -3780,7 +3936,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
if (is_type_numeric(x->type)) {
|
||||
x->type = t_untyped_complex;
|
||||
}
|
||||
} else {
|
||||
} else if (is_type_quaternion(x->type)) {
|
||||
convert_to_typed(c, x, t_quaternion256);
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
} else{
|
||||
convert_to_typed(c, x, t_complex128);
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
@@ -3788,9 +3949,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_type_complex(x->type)) {
|
||||
if (!is_type_complex(x->type) && !is_type_quaternion(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error(call, "Argument has type '%s', expected a complex type", s);
|
||||
error(call, "Argument has type '%s', expected a complex or quaternion type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
@@ -3808,7 +3969,57 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
switch (kind) {
|
||||
case Basic_complex64: x->type = t_f32; break;
|
||||
case Basic_complex128: x->type = t_f64; break;
|
||||
case Basic_quaternion128: x->type = t_f32; break;
|
||||
case Basic_quaternion256: x->type = t_f64; break;
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
case Basic_UntypedQuaternion: x->type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_jmag:
|
||||
case BuiltinProc_kmag: {
|
||||
// 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;
|
||||
}
|
||||
} else{
|
||||
convert_to_typed(c, x, t_quaternion256);
|
||||
if (x->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_type_quaternion(x->type)) {
|
||||
gbString s = type_to_string(x->type);
|
||||
error(call, "Argument has type '%s', expected a quaternion type", s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x->mode == Addressing_Constant) {
|
||||
switch (id) {
|
||||
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;
|
||||
}
|
||||
|
||||
BasicKind kind = core_type(x->type)->Basic.kind;
|
||||
switch (kind) {
|
||||
case Basic_quaternion128: x->type = t_f32; break;
|
||||
case Basic_quaternion256: x->type = t_f64; break;
|
||||
case Basic_UntypedComplex: x->type = t_untyped_float; break;
|
||||
case Basic_UntypedQuaternion: x->type = t_untyped_float; break;
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
@@ -3822,12 +4033,24 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
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;
|
||||
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(call, "Expected a complex or quaternion, got '%s'", s);
|
||||
@@ -4226,6 +4449,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
if (are_types_identical(bt, t_f64)) add_package_dependency(c, "runtime", "abs_f64");
|
||||
if (are_types_identical(bt, t_complex64)) add_package_dependency(c, "runtime", "abs_complex64");
|
||||
if (are_types_identical(bt, t_complex128)) add_package_dependency(c, "runtime", "abs_complex128");
|
||||
if (are_types_identical(bt, t_quaternion128)) add_package_dependency(c, "runtime", "abs_quaternion128");
|
||||
if (are_types_identical(bt, t_quaternion256)) add_package_dependency(c, "runtime", "abs_quaternion256");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6232,8 +6457,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
case Token_Imag: {
|
||||
String s = bl->token.string;
|
||||
Rune r = s[s.len-1];
|
||||
// NOTE(bill, 2019-08-25): Allow for quaternions by having j and k imaginary numbers
|
||||
switch (r) {
|
||||
case 'i': t = t_untyped_complex; break;
|
||||
case 'i': t = t_untyped_complex; break;
|
||||
case 'j': t = t_untyped_quaternion; break;
|
||||
case 'k': t = t_untyped_quaternion; break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -1610,6 +1610,10 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
|
||||
str_lit("quo_complex64"),
|
||||
str_lit("quo_complex128"),
|
||||
str_lit("mul_quaternion128"),
|
||||
str_lit("mul_quaternion256"),
|
||||
str_lit("quo_quaternion128"),
|
||||
str_lit("quo_quaternion256"),
|
||||
|
||||
str_lit("umodti3"),
|
||||
str_lit("udivti3"),
|
||||
@@ -1891,6 +1895,7 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_integer = find_core_type(c, str_lit("Type_Info_Integer"));
|
||||
t_type_info_rune = find_core_type(c, str_lit("Type_Info_Rune"));
|
||||
t_type_info_float = find_core_type(c, str_lit("Type_Info_Float"));
|
||||
t_type_info_quaternion = find_core_type(c, str_lit("Type_Info_Quaternion"));
|
||||
t_type_info_complex = find_core_type(c, str_lit("Type_Info_Complex"));
|
||||
t_type_info_string = find_core_type(c, str_lit("Type_Info_String"));
|
||||
t_type_info_boolean = find_core_type(c, str_lit("Type_Info_Boolean"));
|
||||
@@ -1915,6 +1920,7 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
|
||||
t_type_info_rune_ptr = alloc_type_pointer(t_type_info_rune);
|
||||
t_type_info_float_ptr = alloc_type_pointer(t_type_info_float);
|
||||
t_type_info_quaternion_ptr = alloc_type_pointer(t_type_info_quaternion);
|
||||
t_type_info_complex_ptr = alloc_type_pointer(t_type_info_complex);
|
||||
t_type_info_string_ptr = alloc_type_pointer(t_type_info_string);
|
||||
t_type_info_boolean_ptr = alloc_type_pointer(t_type_info_boolean);
|
||||
|
||||
@@ -16,8 +16,11 @@ enum BuiltinProcId {
|
||||
BuiltinProc_swizzle,
|
||||
|
||||
BuiltinProc_complex,
|
||||
BuiltinProc_quaternion,
|
||||
BuiltinProc_real,
|
||||
BuiltinProc_imag,
|
||||
BuiltinProc_jmag,
|
||||
BuiltinProc_kmag,
|
||||
BuiltinProc_conj,
|
||||
|
||||
BuiltinProc_expand_to_tuple,
|
||||
@@ -172,8 +175,11 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("swizzle"), 1, true, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
{STR_LIT("complex"), 2, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("quaternion"), 4, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("real"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("imag"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("jmag"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("kmag"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("conj"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
{STR_LIT("expand_to_tuple"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
+178
-6
@@ -12,6 +12,19 @@ bool are_types_identical(Type *x, Type *y);
|
||||
struct Complex128 {
|
||||
f64 real, imag;
|
||||
};
|
||||
struct Quaternion256 {
|
||||
f64 imag, jmag, kmag, real;
|
||||
};
|
||||
|
||||
Quaternion256 quaternion256_inverse(Quaternion256 x) {
|
||||
f64 invmag2 = 1.0 / (x.real*x.real + x.imag*x.imag + x.jmag*x.jmag + x.kmag*x.kmag);
|
||||
x.real = +x.real * invmag2;
|
||||
x.imag = -x.imag * invmag2;
|
||||
x.jmag = -x.jmag * invmag2;
|
||||
x.kmag = -x.kmag * invmag2;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
enum ExactValueKind {
|
||||
ExactValue_Invalid,
|
||||
@@ -21,6 +34,7 @@ enum ExactValueKind {
|
||||
ExactValue_Integer,
|
||||
ExactValue_Float,
|
||||
ExactValue_Complex,
|
||||
ExactValue_Quaternion,
|
||||
ExactValue_Pointer,
|
||||
ExactValue_Compound, // TODO(bill): Is this good enough?
|
||||
ExactValue_Procedure, // TODO(bill): Is this good enough?
|
||||
@@ -37,6 +51,7 @@ struct ExactValue {
|
||||
f64 value_float;
|
||||
i64 value_pointer;
|
||||
Complex128 value_complex;
|
||||
Quaternion256 value_quaternion;
|
||||
Ast * value_compound;
|
||||
Ast * value_procedure;
|
||||
};
|
||||
@@ -61,7 +76,8 @@ HashKey hash_exact_value(ExactValue v) {
|
||||
return hash_integer(v.value_pointer);
|
||||
case ExactValue_Complex:
|
||||
return hashing_proc(&v.value_complex, gb_size_of(Complex128));
|
||||
|
||||
case ExactValue_Quaternion:
|
||||
return hashing_proc(&v.value_quaternion, gb_size_of(Quaternion256));
|
||||
case ExactValue_Compound:
|
||||
return hash_pointer(v.value_compound);
|
||||
case ExactValue_Procedure:
|
||||
@@ -116,6 +132,15 @@ 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;
|
||||
@@ -253,8 +278,10 @@ ExactValue exact_value_from_basic_literal(Token token) {
|
||||
str.len--; // Ignore the 'i|j|k'
|
||||
f64 imag = float_from_string(str);
|
||||
|
||||
if (last_rune == 'i') {
|
||||
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: {
|
||||
@@ -318,11 +345,26 @@ ExactValue exact_value_to_complex(ExactValue v) {
|
||||
return exact_value_complex(v.value_float, 0);
|
||||
case ExactValue_Complex:
|
||||
return v;
|
||||
// case ExactValue_Quaternion:
|
||||
// return exact_value_complex(v.value_quaternion.real, v.value_quaternion.imag);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
ExactValue exact_value_to_quaternion(ExactValue v) {
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
return exact_value_quaternion(big_int_to_f64(&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) {
|
||||
@@ -331,6 +373,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;
|
||||
@@ -343,6 +387,34 @@ ExactValue exact_value_imag(ExactValue v) {
|
||||
return exact_value_i64(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_i64(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_i64(0);
|
||||
case ExactValue_Quaternion:
|
||||
return exact_value_float(v.value_quaternion.kmag);
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
@@ -361,6 +433,32 @@ ExactValue exact_value_make_imag(ExactValue v) {
|
||||
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_imag'");
|
||||
}
|
||||
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_imag'");
|
||||
}
|
||||
ExactValue r = {ExactValue_Invalid};
|
||||
return r;
|
||||
}
|
||||
|
||||
i64 exact_value_to_i64(ExactValue v) {
|
||||
v = exact_value_to_integer(v);
|
||||
if (v.kind == ExactValue_Integer) {
|
||||
@@ -389,6 +487,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;
|
||||
@@ -413,6 +512,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;
|
||||
}
|
||||
@@ -463,8 +569,10 @@ i32 exact_value_order(ExactValue const &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");
|
||||
@@ -485,7 +593,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:
|
||||
@@ -499,6 +607,9 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
||||
case ExactValue_Complex:
|
||||
*x = exact_value_complex(big_int_to_f64(&x->value_integer), 0);
|
||||
return;
|
||||
case ExactValue_Quaternion:
|
||||
*x = exact_value_quaternion(big_int_to_f64(&x->value_integer), 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -509,6 +620,17 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
||||
case ExactValue_Complex:
|
||||
*x = exact_value_to_complex(*x);
|
||||
return;
|
||||
case ExactValue_Quaternion:
|
||||
*x = exact_value_to_quaternion(*x);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case ExactValue_Complex:
|
||||
switch (y->kind) {
|
||||
case ExactValue_Quaternion:
|
||||
*x = exact_value_to_quaternion(*x);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -606,6 +728,56 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Quaternion: {
|
||||
y = exact_value_to_quaternion(y);
|
||||
f64 xr = x.value_quaternion.real;
|
||||
f64 xi = x.value_quaternion.imag;
|
||||
f64 xj = x.value_quaternion.jmag;
|
||||
f64 xk = x.value_quaternion.kmag;
|
||||
f64 yr = y.value_quaternion.real;
|
||||
f64 yi = y.value_quaternion.imag;
|
||||
f64 yj = y.value_quaternion.jmag;
|
||||
f64 yk = y.value_quaternion.kmag;
|
||||
|
||||
|
||||
f64 real = 0;
|
||||
f64 imag = 0;
|
||||
f64 jmag = 0;
|
||||
f64 kmag = 0;
|
||||
|
||||
switch (op) {
|
||||
case Token_Add:
|
||||
real = xr + yr;
|
||||
imag = xi + yi;
|
||||
jmag = xj + yj;
|
||||
kmag = xk + yk;
|
||||
break;
|
||||
case Token_Sub:
|
||||
real = xr - yr;
|
||||
imag = xi - yi;
|
||||
jmag = xj - yj;
|
||||
kmag = xk - yk;
|
||||
break;
|
||||
case Token_Mul:
|
||||
imag = xr * yi + xi * yr + xj * yk - xk * yj;
|
||||
jmag = xr * yj - xi * yk + xj * yr + xk * yi;
|
||||
kmag = xr * yk + xi * yj - xj * yi + xk * yr;
|
||||
real = xr * yr - xi * yi - xj * yj - xk * yk;
|
||||
break;
|
||||
case Token_Quo: {
|
||||
f64 invmag2 = 1.0 / (yr*yr + yi*yi + yj*yj + yk*yk);
|
||||
imag = (xr * -yi + xi * +yr + xj * -yk - xk * -yj) * invmag2;
|
||||
jmag = (xr * -yj - xi * -yk + xj * +yr + xk * -yi) * invmag2;
|
||||
kmag = (xr * -yk + xi * -yj - xj * -yi + xk * +yr) * invmag2;
|
||||
real = (xr * +yr - xi * -yi - xj * -yj - xk * -yk) * invmag2;
|
||||
break;
|
||||
}
|
||||
default: goto error;
|
||||
}
|
||||
return exact_value_quaternion(real, imag, jmag, kmag);
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_String: {
|
||||
if (op != Token_Add) goto error;
|
||||
|
||||
|
||||
+238
-7
@@ -3853,6 +3853,60 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
||||
return ir_emit_load(proc, res);
|
||||
}
|
||||
|
||||
if (is_type_quaternion(t_left)) {
|
||||
ir_emit_comment(proc, str_lit("complex.arith.begin"));
|
||||
defer (ir_emit_comment(proc, str_lit("complex.arith.end")));
|
||||
|
||||
right = ir_emit_conv(proc, right, t_left);
|
||||
|
||||
Type *ft = base_complex_elem_type(t_left);
|
||||
|
||||
if (op == Token_Add || op == Token_Sub) {
|
||||
irValue *res = ir_add_local_generated(proc, type, false); // NOTE: initialized in full later
|
||||
irValue *x0 = ir_emit_struct_ev(proc, left, 0);
|
||||
irValue *x1 = ir_emit_struct_ev(proc, left, 1);
|
||||
irValue *x2 = ir_emit_struct_ev(proc, left, 2);
|
||||
irValue *x3 = ir_emit_struct_ev(proc, left, 3);
|
||||
|
||||
irValue *y0 = ir_emit_struct_ev(proc, right, 0);
|
||||
irValue *y1 = ir_emit_struct_ev(proc, right, 1);
|
||||
irValue *y2 = ir_emit_struct_ev(proc, right, 2);
|
||||
irValue *y3 = ir_emit_struct_ev(proc, right, 3);
|
||||
|
||||
irValue *z0 = ir_emit_arith(proc, op, x0, y0, ft);
|
||||
irValue *z1 = ir_emit_arith(proc, op, x1, y1, ft);
|
||||
irValue *z2 = ir_emit_arith(proc, op, x2, y2, ft);
|
||||
irValue *z3 = ir_emit_arith(proc, op, x3, y3, ft);
|
||||
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), z0);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), z1);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 2), z2);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 3), z3);
|
||||
|
||||
return ir_emit_load(proc, res);
|
||||
} else if (op == Token_Mul) {
|
||||
auto args = array_make<irValue *>(heap_allocator(), 2);
|
||||
args[0] = left;
|
||||
args[1] = right;
|
||||
|
||||
switch (8*type_size_of(ft)) {
|
||||
case 32: return ir_emit_runtime_call(proc, "mul_quaternion128", args);
|
||||
case 64: return ir_emit_runtime_call(proc, "mul_quaternion256", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
} else if (op == Token_Quo) {
|
||||
auto args = array_make<irValue *>(heap_allocator(), 2);
|
||||
args[0] = left;
|
||||
args[1] = right;
|
||||
|
||||
switch (8*type_size_of(ft)) {
|
||||
case 32: return ir_emit_runtime_call(proc, "quo_quaternion128", args);
|
||||
case 64: return ir_emit_runtime_call(proc, "quo_quaternion256", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if (op == Token_Add) {
|
||||
@@ -4188,7 +4242,7 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
||||
}
|
||||
|
||||
if (is_type_complex(a)) {
|
||||
char *runtime_proc = "";
|
||||
char const *runtime_proc = "";
|
||||
i64 sz = 8*type_size_of(a);
|
||||
switch (sz) {
|
||||
case 64:
|
||||
@@ -4212,6 +4266,31 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
||||
return ir_emit_runtime_call(proc, runtime_proc, args);
|
||||
}
|
||||
|
||||
if (is_type_quaternion(a)) {
|
||||
char const *runtime_proc = "";
|
||||
i64 sz = 8*type_size_of(a);
|
||||
switch (sz) {
|
||||
case 128:
|
||||
switch (op_kind) {
|
||||
case Token_CmpEq: runtime_proc = "quaternion128_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "quaternion128_ne"; break;
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
switch (op_kind) {
|
||||
case Token_CmpEq: runtime_proc = "quaternion256_eq"; break;
|
||||
case Token_NotEq: runtime_proc = "quaternion256_ne"; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
GB_ASSERT(runtime_proc != nullptr);
|
||||
|
||||
auto args = array_make<irValue *>(ir_allocator(), 2);
|
||||
args[0] = left;
|
||||
args[1] = right;
|
||||
return ir_emit_runtime_call(proc, runtime_proc, args);
|
||||
}
|
||||
|
||||
if (is_type_bit_set(a)) {
|
||||
switch (op_kind) {
|
||||
case Token_Lt:
|
||||
@@ -4295,11 +4374,18 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
||||
case 0: result_type = alloc_type_pointer(ft); break;
|
||||
case 1: result_type = alloc_type_pointer(ft); break;
|
||||
}
|
||||
} else if (is_type_quaternion(t)) {
|
||||
Type *ft = base_complex_elem_type(t);
|
||||
switch (index) {
|
||||
case 0: result_type = alloc_type_pointer(ft); break;
|
||||
case 1: result_type = alloc_type_pointer(ft); break;
|
||||
case 2: result_type = alloc_type_pointer(ft); break;
|
||||
case 3: result_type = alloc_type_pointer(ft); break;
|
||||
}
|
||||
} else if (is_type_slice(t)) {
|
||||
switch (index) {
|
||||
case 0: result_type = alloc_type_pointer(alloc_type_pointer(t->Slice.elem)); break;
|
||||
case 1: result_type = alloc_type_pointer(t_int); break;
|
||||
case 2: result_type = alloc_type_pointer(t_int); break;
|
||||
}
|
||||
} else if (is_type_string(t)) {
|
||||
switch (index) {
|
||||
@@ -4370,6 +4456,17 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Basic_quaternion128: case Basic_quaternion256:
|
||||
{
|
||||
Type *ft = base_complex_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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type_Struct:
|
||||
@@ -4752,6 +4849,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_MSG(ev.kind == ExactValue_String, "%d", ev.kind);
|
||||
@@ -4875,6 +4974,49 @@ 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)) {
|
||||
// @QuaternionLayout
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, false);
|
||||
irValue *q0 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 0), ft);
|
||||
irValue *q1 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 1), ft);
|
||||
irValue *q2 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 2), ft);
|
||||
irValue *q3 = ir_emit_conv(proc, ir_emit_struct_ev(proc, value, 3), ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), q0);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 1), q1);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 2), q2);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), q3);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
if (is_type_float(src) && is_type_complex(dst)) {
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, true);
|
||||
irValue *real = ir_emit_conv(proc, value, ft);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), real);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
if (is_type_float(src) && is_type_quaternion(dst)) {
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, true);
|
||||
irValue *real = ir_emit_conv(proc, value, ft);
|
||||
// @QuaternionLayout
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), real);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
if (is_type_complex(src) && is_type_quaternion(dst)) {
|
||||
Type *ft = base_complex_elem_type(dst);
|
||||
irValue *gen = ir_add_local_generated(proc, dst, true);
|
||||
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);
|
||||
// @QuaternionLayout
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 3), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), imag);
|
||||
return ir_emit_load(proc, gen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// float <-> integer
|
||||
if (is_type_float(src) && is_type_integer(dst)) {
|
||||
irConvKind kind = irConv_fptosi;
|
||||
@@ -5315,6 +5457,7 @@ enum Typeid_Kind : u8 {
|
||||
Typeid_Rune,
|
||||
Typeid_Float,
|
||||
Typeid_Complex,
|
||||
Typeid_Quaternion,
|
||||
Typeid_String,
|
||||
Typeid_Boolean,
|
||||
Typeid_Any,
|
||||
@@ -6067,17 +6210,77 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
||||
return ir_emit_load(proc, dst);
|
||||
}
|
||||
|
||||
case BuiltinProc_quaternion: {
|
||||
ir_emit_comment(proc, str_lit("quaternion"));
|
||||
irValue *real = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *imag = ir_build_expr(proc, ce->args[1]);
|
||||
irValue *jmag = ir_build_expr(proc, ce->args[2]);
|
||||
irValue *kmag = ir_build_expr(proc, ce->args[3]);
|
||||
|
||||
// @QuaternionLayout
|
||||
irValue *dst = ir_add_local_generated(proc, tv.type, false);
|
||||
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, 3), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 1), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 2), kmag);
|
||||
|
||||
return ir_emit_load(proc, dst);
|
||||
}
|
||||
|
||||
case BuiltinProc_real: {
|
||||
ir_emit_comment(proc, str_lit("real"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
if (is_type_complex(ir_type(val))) {
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
} else if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 3);
|
||||
return ir_emit_conv(proc, real, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for real");
|
||||
return nullptr;
|
||||
}
|
||||
case BuiltinProc_imag: {
|
||||
ir_emit_comment(proc, str_lit("imag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
if (is_type_complex(ir_type(val))) {
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
} else if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 0);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for imag");
|
||||
return nullptr;
|
||||
}
|
||||
case BuiltinProc_jmag: {
|
||||
ir_emit_comment(proc, str_lit("jmag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 1);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for jmag");
|
||||
return nullptr;
|
||||
}
|
||||
case BuiltinProc_kmag: {
|
||||
ir_emit_comment(proc, str_lit("kmag"));
|
||||
irValue *val = ir_build_expr(proc, ce->args[0]);
|
||||
if (is_type_quaternion(ir_type(val))) {
|
||||
// @QuaternionLayout
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 2);
|
||||
return ir_emit_conv(proc, imag, tv.type);
|
||||
}
|
||||
GB_PANIC("invalid type for kmag");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case BuiltinProc_conj: {
|
||||
@@ -6092,6 +6295,20 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
||||
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)) {
|
||||
// @QuaternionLayout
|
||||
res = ir_add_local_generated(proc, tv.type, false);
|
||||
irValue *real = ir_emit_struct_ev(proc, val, 3);
|
||||
irValue *imag = ir_emit_struct_ev(proc, val, 0);
|
||||
irValue *jmag = ir_emit_struct_ev(proc, val, 1);
|
||||
irValue *kmag = ir_emit_struct_ev(proc, val, 2);
|
||||
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, 3), real);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), imag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), jmag);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, res, 2), kmag);
|
||||
}
|
||||
return ir_emit_load(proc, res);
|
||||
}
|
||||
@@ -6162,7 +6379,16 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
|
||||
return x;
|
||||
}
|
||||
ir_emit_comment(proc, str_lit("abs"));
|
||||
if (is_type_complex(t)) {
|
||||
if (is_type_quaternion(t)) {
|
||||
i64 sz = 8*type_size_of(t);
|
||||
auto args = array_make<irValue *>(ir_allocator(), 1);
|
||||
args[0] = x;
|
||||
switch (sz) {
|
||||
case 128: return ir_emit_runtime_call(proc, "abs_quaternion128", args);
|
||||
case 256: return ir_emit_runtime_call(proc, "abs_quaternion256", args);
|
||||
}
|
||||
GB_PANIC("Unknown complex type");
|
||||
} else if (is_type_complex(t)) {
|
||||
i64 sz = 8*type_size_of(t);
|
||||
auto args = array_make<irValue *>(ir_allocator(), 1);
|
||||
args[0] = x;
|
||||
@@ -9876,6 +10102,11 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_complex_ptr);
|
||||
break;
|
||||
|
||||
case Basic_quaternion128:
|
||||
case Basic_quaternion256:
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_quaternion_ptr);
|
||||
break;
|
||||
|
||||
case Basic_rawptr:
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_pointer_ptr);
|
||||
break;
|
||||
|
||||
+42
-11
@@ -418,20 +418,23 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
|
||||
}
|
||||
return;
|
||||
|
||||
// case Basic_f16: ir_write_str_lit(f, "half"); return;
|
||||
case Basic_f32: ir_write_str_lit(f, "float"); return;
|
||||
case Basic_f64: ir_write_str_lit(f, "double"); return;
|
||||
// case Basic_f16: ir_write_str_lit(f, "half"); return;
|
||||
case Basic_f32: ir_write_str_lit(f, "float"); return;
|
||||
case Basic_f64: ir_write_str_lit(f, "double"); return;
|
||||
|
||||
// case Basic_complex32: ir_write_str_lit(f, "%%..complex32"); return;
|
||||
case Basic_complex64: ir_write_str_lit(f, "%..complex64"); return;
|
||||
case Basic_complex128: ir_write_str_lit(f, "%..complex128"); return;
|
||||
// case Basic_complex32: ir_write_str_lit(f, "%%..complex32"); return;
|
||||
case Basic_complex64: ir_write_str_lit(f, "%..complex64"); return;
|
||||
case Basic_complex128: ir_write_str_lit(f, "%..complex128"); return;
|
||||
|
||||
case Basic_any: ir_write_str_lit(f, "%..any"); return;
|
||||
case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return;
|
||||
case Basic_string: ir_write_str_lit(f, "%..string"); return;
|
||||
case Basic_cstring: ir_write_str_lit(f, "i8*"); return;
|
||||
case Basic_quaternion128: ir_write_str_lit(f, "%..quaternion128"); return;
|
||||
case Basic_quaternion256: ir_write_str_lit(f, "%..quaternion256"); return;
|
||||
|
||||
case Basic_typeid: ir_write_str_lit(f, "%..typeid"); return;
|
||||
case Basic_any: ir_write_str_lit(f, "%..any"); return;
|
||||
case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return;
|
||||
case Basic_string: ir_write_str_lit(f, "%..string"); return;
|
||||
case Basic_cstring: ir_write_str_lit(f, "i8*"); return;
|
||||
|
||||
case Basic_typeid: ir_write_str_lit(f, "%..typeid"); return;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -811,6 +814,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
break;
|
||||
}
|
||||
case ExactValue_Complex: {
|
||||
// xy/ri format
|
||||
type = core_type(type);
|
||||
GB_ASSERT_MSG(is_type_complex(type), "%s", type_to_string(type));
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
@@ -823,6 +827,26 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
ir_write_byte(f, '}');
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Quaternion: {
|
||||
// xyzw/ijkr format
|
||||
type = core_type(type);
|
||||
GB_ASSERT_MSG(is_type_quaternion(type), "%s", type_to_string(type));
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
ir_write_byte(f, ' ');
|
||||
ir_write_byte(f, '{');
|
||||
ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.imag), ft);
|
||||
ir_write_str_lit(f, ", "); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.jmag), ft);
|
||||
ir_write_str_lit(f, ", "); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.kmag), ft);
|
||||
ir_write_str_lit(f, ", "); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
|
||||
ir_print_exact_value(f, m, exact_value_float(value.value_quaternion.real), ft);
|
||||
ir_write_byte(f, '}');
|
||||
break;
|
||||
}
|
||||
|
||||
case ExactValue_Pointer:
|
||||
if (value.value_pointer == 0) {
|
||||
if (is_type_typeid(type)) {
|
||||
@@ -2246,6 +2270,13 @@ void print_llvm_ir(irGen *ir) {
|
||||
ir_print_encoded_local(f, str_lit("..complex128"));
|
||||
ir_write_str_lit(f, " = type {double, double} ; Basic_complex128\n");
|
||||
|
||||
ir_print_encoded_local(f, str_lit("..quaternion64"));
|
||||
ir_write_str_lit(f, " = type {half, half, half, half} ; Basic_quaternion64\n");
|
||||
ir_print_encoded_local(f, str_lit("..quaternion128"));
|
||||
ir_write_str_lit(f, " = type {float, float, float, float} ; Basic_quaternion128\n");
|
||||
ir_print_encoded_local(f, str_lit("..quaternion256"));
|
||||
ir_write_str_lit(f, " = type {double, double, double, double} ; Basic_quaternion256\n");
|
||||
|
||||
ir_print_encoded_local(f, str_lit("..typeid"));
|
||||
ir_write_str_lit(f, " = type ");
|
||||
ir_print_type(f, m, t_uintptr);
|
||||
|
||||
+4
-1
@@ -745,7 +745,10 @@ 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);
|
||||
}
|
||||
|
||||
+39
-11
@@ -32,6 +32,9 @@ enum BasicKind {
|
||||
Basic_complex64,
|
||||
Basic_complex128,
|
||||
|
||||
Basic_quaternion128,
|
||||
Basic_quaternion256,
|
||||
|
||||
Basic_int,
|
||||
Basic_uint,
|
||||
Basic_uintptr,
|
||||
@@ -66,6 +69,7 @@ enum BasicKind {
|
||||
Basic_UntypedInteger,
|
||||
Basic_UntypedFloat,
|
||||
Basic_UntypedComplex,
|
||||
Basic_UntypedQuaternion,
|
||||
Basic_UntypedString,
|
||||
Basic_UntypedRune,
|
||||
Basic_UntypedNil,
|
||||
@@ -82,17 +86,18 @@ enum BasicFlag {
|
||||
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_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_LLVM = GB_BIT(10),
|
||||
BasicFlag_LLVM = GB_BIT(11),
|
||||
|
||||
BasicFlag_EndianLittle = GB_BIT(13),
|
||||
BasicFlag_EndianBig = GB_BIT(14),
|
||||
|
||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex,
|
||||
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex | BasicFlag_Quaternion,
|
||||
BasicFlag_Ordered = BasicFlag_Integer | BasicFlag_Float | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
|
||||
BasicFlag_OrderedNumeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Rune,
|
||||
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
|
||||
@@ -342,6 +347,9 @@ gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_complex64, BasicFlag_Complex, 8, STR_LIT("complex64")}},
|
||||
{Type_Basic, {Basic_complex128, BasicFlag_Complex, 16, STR_LIT("complex128")}},
|
||||
|
||||
{Type_Basic, {Basic_quaternion128, BasicFlag_Quaternion, 16, STR_LIT("quaternion128")}},
|
||||
{Type_Basic, {Basic_quaternion256, BasicFlag_Quaternion, 32, STR_LIT("quaternion256")}},
|
||||
|
||||
{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_uintptr, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uintptr")}},
|
||||
@@ -377,6 +385,7 @@ gb_global Type basic_types[] = {
|
||||
{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")}},
|
||||
@@ -412,6 +421,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];
|
||||
gb_global Type *t_uintptr = &basic_types[Basic_uintptr];
|
||||
@@ -446,6 +458,7 @@ 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];
|
||||
@@ -472,6 +485,7 @@ gb_global Type *t_type_info_integer = nullptr;
|
||||
gb_global Type *t_type_info_rune = nullptr;
|
||||
gb_global Type *t_type_info_float = nullptr;
|
||||
gb_global Type *t_type_info_complex = nullptr;
|
||||
gb_global Type *t_type_info_quaternion = nullptr;
|
||||
gb_global Type *t_type_info_any = nullptr;
|
||||
gb_global Type *t_type_info_typeid = nullptr;
|
||||
gb_global Type *t_type_info_string = nullptr;
|
||||
@@ -496,6 +510,7 @@ gb_global Type *t_type_info_integer_ptr = nullptr;
|
||||
gb_global Type *t_type_info_rune_ptr = nullptr;
|
||||
gb_global Type *t_type_info_float_ptr = nullptr;
|
||||
gb_global Type *t_type_info_complex_ptr = nullptr;
|
||||
gb_global Type *t_type_info_quaternion_ptr = nullptr;
|
||||
gb_global Type *t_type_info_any_ptr = nullptr;
|
||||
gb_global Type *t_type_info_typeid_ptr = nullptr;
|
||||
gb_global Type *t_type_info_string_ptr = nullptr;
|
||||
@@ -924,6 +939,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) {
|
||||
@@ -1063,12 +1085,15 @@ bool is_type_simple_compare(Type *t) {
|
||||
|
||||
Type *base_complex_elem_type(Type *t) {
|
||||
t = core_type(t);
|
||||
if (is_type_complex(t)) {
|
||||
if (t->kind == Type_Basic) {
|
||||
switch (t->Basic.kind) {
|
||||
// case Basic_complex32: return t_f16;
|
||||
case Basic_complex64: return t_f32;
|
||||
case Basic_complex128: return t_f64;
|
||||
case Basic_UntypedComplex: return t_untyped_float;
|
||||
// case Basic_complex32: return t_f16;
|
||||
case Basic_complex64: return t_f32;
|
||||
case Basic_complex128: return t_f64;
|
||||
case Basic_quaternion128: return t_f32;
|
||||
case Basic_quaternion256: return t_f64;
|
||||
case Basic_UntypedComplex: return t_untyped_float;
|
||||
case Basic_UntypedQuaternion: return t_untyped_float;
|
||||
}
|
||||
}
|
||||
GB_PANIC("Invalid complex type");
|
||||
@@ -1818,6 +1843,7 @@ Type *default_type(Type *type) {
|
||||
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;
|
||||
}
|
||||
@@ -2358,6 +2384,8 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
|
||||
case Basic_complex64: case Basic_complex128:
|
||||
return type_size_of_internal(t, path) / 2;
|
||||
case Basic_quaternion128: case Basic_quaternion256:
|
||||
return type_size_of_internal(t, path) / 4;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user