aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZachary Pierson <zacpiersonhehe@gmail.com>2017-04-02 03:29:51 -0500
committerZachary Pierson <zacpiersonhehe@gmail.com>2017-04-02 03:29:51 -0500
commitce0d874efd3bdd2cbfd24ca5b10c9326774c1530 (patch)
tree9f3b6ce4c83a7c7e45506b17cd36363c06f978e7 /src
parent24b33374b7830fae01be1915adb14b4e45ff9550 (diff)
parent2c8b99337bb33d0f713026c5c38e05428cc52143 (diff)
Merge https://github.com/gingerBill/Odin
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c424
-rw-r--r--src/checker.c74
-rw-r--r--src/common.c6
-rw-r--r--src/exact_value.c332
-rw-r--r--src/ir.c364
-rw-r--r--src/ir_print.c180
-rw-r--r--src/main.c2
-rw-r--r--src/parser.c2
-rw-r--r--src/tokenizer.c14
-rw-r--r--src/types.c206
10 files changed, 1414 insertions, 190 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index db1bbd135..55dcdb941 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -1754,19 +1754,69 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
if (v.kind != ExactValue_Float) {
return false;
}
+ if (out_value) *out_value = v;
+
switch (type->Basic.kind) {
- // case Basic_f16:
case Basic_f32:
case Basic_f64:
- // case Basic_f128:
- if (out_value) *out_value = v;
return true;
case Basic_UntypedFloat:
return true;
}
- } else if (is_type_pointer(type)) {
+ } else if (is_type_complex(type)) {
+ ExactValue v = exact_value_to_complex(in_value);
+ if (v.kind != ExactValue_Complex) {
+ return false;
+ }
+
+ switch (type->Basic.kind) {
+ case Basic_complex64:
+ case Basic_complex128: {
+ ExactValue real = exact_value_real(v);
+ 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));
+ return true;
+ }
+ } break;
+ case Basic_UntypedComplex:
+ return true;
+ }
+
+ 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 &&
+ 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;
}
@@ -2190,6 +2240,14 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
}
}
+ if (is_type_complex(src) && is_type_complex(dst)) {
+ 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));
@@ -2590,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;
@@ -3568,6 +3628,279 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
operand->mode = Addressing_Value;
} break;
+ case BuiltinProc_complex: {
+ // complex :: proc(real, imag: float_type) -> complex_type
+ Operand x = *operand;
+ Operand y = {0};
+
+ // 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;
+ }
+
+ 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;
+ }
+ }
+
+ if (!are_types_identical(x.type, y.type)) {
+ 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;
+ }
+
+ 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) {
+ operand->value = exact_binary_operator_value(Token_Add, x.value, y.value);
+ 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_complex64; break;
+ case Basic_f64: operand->type = t_complex128; break;
+ case Basic_UntypedFloat: operand->type = t_untyped_complex; break;
+ default: GB_PANIC("Invalid type"); break;
+ }
+ } 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:
+ 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)) {
+ if (id == BuiltinProc_jmag ||
+ id == BuiltinProc_kmag) {
+ x->type = t_untyped_quaternion;
+ } else {
+ x->type = t_untyped_complex;
+ }
+ }
+ } else {
+ 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 (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) {
+ 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;
+ }
+
+ 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_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
@@ -3575,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;
}
@@ -3629,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;
}
@@ -3645,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;
@@ -3695,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;
@@ -3713,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;
@@ -3764,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;
}
@@ -3782,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;
@@ -3790,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;
}
@@ -3815,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;
}
@@ -3828,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;
}
@@ -4407,6 +4745,16 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
case Token_Float: t = t_untyped_float; 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;
diff --git a/src/checker.c b/src/checker.c
index e942916df..3a458d099 100644
--- a/src/checker.c
+++ b/src/checker.c
@@ -52,6 +52,14 @@ 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,
BuiltinProc_slice_ptr,
@@ -87,8 +95,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("type_info"), 1, false, Expr_Expr},
{STR_LIT("type_info_of_val"), 1, false, Expr_Expr},
- {STR_LIT("compile_assert"), 1, false, Expr_Stmt},
- {STR_LIT("assert"), 1, false, Expr_Stmt},
+ {STR_LIT("compile_assert"), 1, false, Expr_Expr},
+ {STR_LIT("assert"), 1, false, Expr_Expr},
{STR_LIT("panic"), 1, false, Expr_Stmt},
{STR_LIT("copy"), 2, false, Expr_Expr},
@@ -96,6 +104,14 @@ 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},
{STR_LIT("slice_ptr"), 2, true, Expr_Expr},
@@ -940,6 +956,24 @@ void add_type_info_type(Checker *c, Type *t) {
add_type_info_type(c, t_type_info_ptr);
add_type_info_type(c, t_rawptr);
break;
+
+ case Basic_complex64:
+ add_type_info_type(c, t_type_info_float);
+ add_type_info_type(c, t_f32);
+ break;
+ case Basic_complex128:
+ 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;
@@ -1128,31 +1162,35 @@ void init_preload(Checker *c) {
- if (record->variant_count != 19) {
+ 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_string = record->variants[ 4]->type;
- t_type_info_boolean = record->variants[ 5]->type;
- t_type_info_any = record->variants[ 6]->type;
- t_type_info_pointer = record->variants[ 7]->type;
- t_type_info_procedure = record->variants[ 8]->type;
- t_type_info_array = record->variants[ 9]->type;
- t_type_info_dynamic_array = record->variants[10]->type;
- t_type_info_slice = record->variants[11]->type;
- t_type_info_vector = record->variants[12]->type;
- t_type_info_tuple = record->variants[13]->type;
- t_type_info_struct = record->variants[14]->type;
- t_type_info_raw_union = record->variants[15]->type;
- t_type_info_union = record->variants[16]->type;
- t_type_info_enum = record->variants[17]->type;
- t_type_info_map = record->variants[18]->type;
+ t_type_info_complex = record->variants[ 4]->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);
diff --git a/src/common.c b/src/common.c
index 2c40e22ed..fe07dc175 100644
--- a/src/common.c
+++ b/src/common.c
@@ -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_++)
diff --git a/src/exact_value.c b/src/exact_value.c
index 7e8e69f50..eec5d157a 100644
--- a/src/exact_value.c
+++ b/src/exact_value.c
@@ -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,
@@ -12,6 +20,8 @@ typedef enum ExactValueKind {
ExactValue_String,
ExactValue_Integer,
ExactValue_Float,
+ ExactValue_Complex,
+ ExactValue_Quaternion,
ExactValue_Pointer,
ExactValue_Compound, // TODO(bill): Is this good enough?
@@ -21,12 +31,14 @@ typedef enum ExactValueKind {
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;
- 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;
@@ -66,6 +78,23 @@ ExactValue exact_value_float(f64 f) {
return result;
}
+ExactValue exact_value_complex(f64 real, f64 imag) {
+ ExactValue result = {ExactValue_Complex};
+ result.value_complex.real = real;
+ result.value_complex.imag = 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;
@@ -113,9 +142,7 @@ ExactValue exact_value_integer_from_string(String string) {
return exact_value_integer(result);
}
-
-
-ExactValue exact_value_float_from_string(String string) {
+f64 float_from_string(String string) {
isize i = 0;
u8 *str = string.text;
isize len = string.len;
@@ -190,8 +217,11 @@ ExactValue exact_value_float_from_string(String string) {
while (exp > 0) { scale *= 10.0; exp -= 1; }
}
- f64 result = sign * (frac ? (value / scale) : (value * scale));
- return exact_value_float(result);
+ return sign * (frac ? (value / scale) : (value * scale));
+}
+
+ExactValue exact_value_float_from_string(String string) {
+ return exact_value_float(float_from_string(string));
}
@@ -200,6 +230,18 @@ ExactValue exact_value_from_basic_literal(Token token) {
case Token_String: return exact_value_string(token.string);
case Token_Integer: return exact_value_integer_from_string(token.string);
case Token_Float: return exact_value_float_from_string(token.string);
+ case Token_Imag: {
+ String str = token.string;
+ Rune last_rune = cast(Rune)str.text[str.len-1];
+ str.len--; // Ignore the `i|j|k`
+ f64 imag = float_from_string(str);
+
+ 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;
gb_utf8_decode(token.string.text, token.string.len, &r);
@@ -245,6 +287,128 @@ ExactValue exact_value_to_float(ExactValue v) {
return r;
}
+ExactValue exact_value_to_complex(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ return exact_value_complex(cast(i64)v.value_integer, 0);
+ case ExactValue_Float:
+ return exact_value_complex(v.value_float, 0);
+ case ExactValue_Complex:
+ return v;
+ }
+ ExactValue r = {ExactValue_Invalid};
+ 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:
+ case ExactValue_Float:
+ 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;
+}
+
+ExactValue exact_value_imag(ExactValue v) {
+ switch (v.kind) {
+ case ExactValue_Integer:
+ case ExactValue_Float:
+ 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:
+ return exact_value_complex(0, exact_value_to_float(v).value_float);
+ case ExactValue_Float:
+ return exact_value_complex(0, v.value_float);
+ default:
+ GB_PANIC("Expected an integer or float type for `exact_value_make_imag`");
+ }
+ 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;
+}
+
+
ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision) {
switch (op) {
@@ -253,6 +417,8 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
case ExactValue_Invalid:
case ExactValue_Integer:
case ExactValue_Float:
+ case ExactValue_Complex:
+ case ExactValue_Quaternion:
return v;
}
} break;
@@ -271,6 +437,18 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
i.value_float = -i.value_float;
return i;
}
+ case ExactValue_Complex: {
+ f64 real = v.value_complex.real;
+ 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;
@@ -324,8 +502,12 @@ i32 exact_value_order(ExactValue v) {
return 2;
case ExactValue_Float:
return 3;
- case ExactValue_Pointer:
+ case ExactValue_Complex:
return 4;
+ case ExactValue_Quaternion:
+ return 5;
+ case ExactValue_Pointer:
+ return 6;
default:
GB_PANIC("How'd you get here? Invalid Value.kind");
@@ -346,6 +528,8 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
case ExactValue_Bool:
case ExactValue_String:
+ case ExactValue_Complex:
+ case ExactValue_Quaternion:
return;
case ExactValue_Integer:
@@ -356,16 +540,30 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
// TODO(bill): Is this good enough?
*x = exact_value_float(cast(f64)x->value_integer);
return;
+ 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;
+ case ExactValue_Complex:
+ *x = exact_value_to_complex(*x);
return;
+ case ExactValue_Quaternion:
+ *x = exact_value_to_quaternion(*x);
+ return;
+ }
break;
}
- compiler_error("How'd you get here? Invalid ExactValueKind");
+ compiler_error("match_exact_values: How'd you get here? Invalid ExactValueKind %d", x->kind);
}
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
@@ -420,6 +618,84 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
default: goto error;
}
} break;
+
+ case ExactValue_Complex: {
+ y = exact_value_to_complex(y);
+ f64 a = x.value_complex.real;
+ f64 b = x.value_complex.imag;
+ f64 c = y.value_complex.real;
+ f64 d = y.value_complex.imag;
+ f64 real = 0;
+ f64 imag = 0;
+ switch (op) {
+ case Token_Add:
+ real = a + c;
+ imag = b + d;
+ break;
+ case Token_Sub:
+ real = a - c;
+ imag = b - d;
+ break;
+ case Token_Mul:
+ real = (a*c - b*d);
+ imag = (b*c + a*d);
+ break;
+ case Token_Quo: {
+ f64 s = c*c + d*d;
+ real = (a*c + b*d)/s;
+ imag = (b*c - a*d)/s;
+ } break;
+ default: goto error;
+ }
+ 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:
@@ -480,6 +756,34 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
}
} break;
+ case ExactValue_Complex: {
+ f64 a = x.value_complex.real;
+ f64 b = x.value_complex.imag;
+ f64 c = y.value_complex.real;
+ f64 d = y.value_complex.imag;
+ switch (op) {
+ case Token_CmpEq: return cmp_f64(a, c) == 0 && cmp_f64(b, d) == 0;
+ case Token_NotEq: return cmp_f64(a, c) != 0 || cmp_f64(b, d) != 0;
+ }
+ } 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;
diff --git a/src/ir.c b/src/ir.c
index fb638fb27..bfe4f3781 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -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) {
@@ -1653,6 +1654,7 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
}
irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index);
+irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index);
irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset) {
offset = ir_emit_conv(proc, offset, t_int);
@@ -1716,6 +1718,180 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
return ir_emit_load(proc, res);
}
+ if (is_type_complex(t_left)) {
+ ir_emit_comment(proc, str_lit("complex.arith.begin"));
+ 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);
+ irValue *b = ir_emit_struct_ev(proc, left, 1);
+ irValue *c = ir_emit_struct_ev(proc, right, 0);
+ irValue *d = ir_emit_struct_ev(proc, right, 1);
+
+ irValue *real = NULL;
+ irValue *imag = NULL;
+
+ switch (op) {
+ case Token_Add:
+ real = ir_emit_arith(proc, Token_Add, a, c, ft);
+ imag = ir_emit_arith(proc, Token_Add, b, d, ft);
+ break;
+ case Token_Sub:
+ real = ir_emit_arith(proc, Token_Sub, a, c, ft);
+ imag = ir_emit_arith(proc, Token_Sub, b, d, ft);
+ break;
+ case Token_Mul: {
+ irValue *x = ir_emit_arith(proc, Token_Mul, a, c, ft);
+ irValue *y = ir_emit_arith(proc, Token_Mul, b, d, ft);
+ real = ir_emit_arith(proc, Token_Sub, x, y, ft);
+ irValue *z = ir_emit_arith(proc, Token_Mul, b, c, ft);
+ irValue *w = ir_emit_arith(proc, Token_Mul, a, d, ft);
+ imag = ir_emit_arith(proc, Token_Add, z, w, ft);
+ } break;
+ case Token_Quo: {
+ irValue *s1 = ir_emit_arith(proc, Token_Mul, c, c, ft);
+ irValue *s2 = ir_emit_arith(proc, Token_Mul, d, d, ft);
+ irValue *s = ir_emit_arith(proc, Token_Add, s1, s2, ft);
+
+ irValue *x = ir_emit_arith(proc, Token_Mul, a, c, ft);
+ irValue *y = ir_emit_arith(proc, Token_Mul, b, d, ft);
+ real = ir_emit_arith(proc, Token_Add, x, y, ft);
+ real = ir_emit_arith(proc, Token_Quo, real, s, ft);
+
+ irValue *z = ir_emit_arith(proc, Token_Mul, b, c, ft);
+ irValue *w = ir_emit_arith(proc, Token_Mul, a, d, ft);
+ imag = ir_emit_arith(proc, Token_Sub, z, w, ft);
+ imag = ir_emit_arith(proc, Token_Quo, imag, 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_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);
+ }
+
if (op == Token_Add) {
if (is_type_pointer(t_left)) {
@@ -1890,6 +2066,20 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
GB_ASSERT(t->Tuple.variable_count > 0);
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 = 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;
@@ -1956,6 +2146,20 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
GB_ASSERT(t->Tuple.variable_count > 0);
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 = 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;
@@ -2285,6 +2489,10 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
ExactValue ev = value->Constant.value;
if (is_type_float(dst)) {
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);
@@ -2350,6 +2558,30 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
return ir_emit(proc, ir_instr_conv(proc, kind, value, src, dst));
}
+ if (is_type_complex(src) && is_type_complex(dst)) {
+ Type *ft = base_complex_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);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 0), real);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, gen, 1), imag);
+ 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;
@@ -3704,6 +3936,96 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
// return ir_emit(proc, ir_instr_vector_shuffle(proc, vector, indices, index_count));
} break;
+ case BuiltinProc_complex: {
+ ir_emit_comment(proc, str_lit("complex"));
+ irValue *real = ir_build_expr(proc, ce->args.e[0]);
+ irValue *imag = ir_build_expr(proc, ce->args.e[1]);
+ 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);
+ 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 *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 *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)) {
+ 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)) {
+ 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"));
irValue *ptr = ir_build_expr(proc, ce->args.e[0]);
@@ -3760,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));
@@ -6528,8 +6871,6 @@ void ir_gen_tree(irGen *s) {
case Basic_u32:
case Basic_i64:
case Basic_u64:
- // case Basic_i128:
- // case Basic_u128:
case Basic_int:
case Basic_uint: {
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
@@ -6540,16 +6881,27 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), is_signed);
} break;
- // case Basic_f16:
case Basic_f32:
- case Basic_f64:
- // case Basic_f128:
- {
+ 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: {
+ 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);
break;
diff --git a/src/ir_print.c b/src/ir_print.c
index beae020db..ab5926bd0 100644
--- a/src/ir_print.c
+++ b/src/ir_print.c
@@ -145,26 +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_i128: ir_fprintf(f, "i128"); return;
- // case Basic_u128: ir_fprintf(f, "i128"); return;
- // case Basic_f16: ir_fprintf(f, "half"); return;
- case Basic_f32: ir_fprintf(f, "float"); return;
- case Basic_f64: ir_fprintf(f, "double"); return;
- // case Basic_f128: ir_fprintf(f, "fp128"); 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_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_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;
}
break;
case Type_Pointer:
@@ -365,7 +369,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
} break;
case ExactValue_Float: {
GB_ASSERT_MSG(is_type_float(type), "%s", type_to_string(type));
- type = base_type(type);
+ type = core_type(type);
u64 u = *cast(u64*)&value.value_float;
switch (type->Basic.kind) {
case Basic_f32:
@@ -382,28 +386,52 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
switch (type->Basic.kind) {
case 0: break;
-#if 0
- case Basic_f16:
- ir_fprintf(f, "bitcast (");
- ir_print_type(f, m, t_u16);
- ir_fprintf(f, " %u to ", cast(u16)f32_to_f16(cast(f32)value.value_float));
- ir_print_type(f, m, t_f16);
- ir_fprintf(f, ")");
- break;
- case Basic_f128:
- ir_fprintf(f, "bitcast (");
- ir_fprintf(f, "i128");
- // TODO(bill): Actually support f128
- ir_fprintf(f, " %llu to ", u);
- ir_print_type(f, m, t_f128);
- ir_fprintf(f, ")");
- break;
-#endif
default:
ir_fprintf(f, "0x%016llx", u);
break;
}
} break;
+
+ case ExactValue_Complex: {
+ type = core_type(type);
+ 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;
+
case ExactValue_Pointer:
if (value.value_pointer == 0) {
ir_fprintf(f, "null");
@@ -1007,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 &&
@@ -1415,6 +1509,16 @@ void print_llvm_ir(irGen *ir) {
ir_print_encoded_local(f, str_lit("..rawptr"));
ir_fprintf(f, " = type i8* ; Basic_rawptr\n");
+ ir_print_encoded_local(f, str_lit("..complex64"));
+ 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"));
ir_fprintf(f, " = type {");
ir_print_type(f, m, t_type_info_ptr);
diff --git a/src/main.c b/src/main.c
index ccc2b4c3b..6c2167802 100644
--- a/src/main.c
+++ b/src/main.c
@@ -261,7 +261,7 @@ int main(int argc, char **argv) {
#if defined(GB_SYSTEM_WINDOWS)
// For more passes arguments: http://llvm.org/docs/Passes.html
exit_code = system_exec_command_line_app("llvm-opt", false,
- "\"%.*sbin/opt\" \"%s\" -o \"%.*s\".bc "
+ "\"%.*sbin/opt\" \"%s\" -o \"%.*s.bc\" "
"-mem2reg "
"-memcpyopt "
"-die "
diff --git a/src/parser.c b/src/parser.c
index fbedb3855..5169bd7bf 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1735,6 +1735,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
case Token_Integer:
case Token_Float:
+ case Token_Imag:
case Token_Rune:
operand = ast_basic_lit(f, f->curr_token);
next_token(f);
@@ -3238,6 +3239,7 @@ AstNode *parse_stmt(AstFile *f) {
case Token_Ident:
case Token_Integer:
case Token_Float:
+ case Token_Imag:
case Token_Rune:
case Token_String:
case Token_OpenParen:
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 6c7f76c02..398f39f98 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -7,6 +7,7 @@ TOKEN_KIND(Token__LiteralBegin, "_LiteralBegin"), \
TOKEN_KIND(Token_Ident, "identifier"), \
TOKEN_KIND(Token_Integer, "integer"), \
TOKEN_KIND(Token_Float, "float"), \
+ TOKEN_KIND(Token_Imag, "imaginary"), \
TOKEN_KIND(Token_Rune, "rune"), \
TOKEN_KIND(Token_String, "string"), \
TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \
@@ -547,18 +548,18 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
}
}
- token.string.len = t->curr - token.string.text;
- return token;
+ goto end;
}
scan_mantissa(t, 10);
+
fraction:
if (t->curr_rune == '.') {
// HACK(bill): This may be inefficient
TokenizerState state = save_tokenizer_state(t);
advance_to_next_rune(t);
- if (digit_value(t->curr_rune) >= 10) {
+ if (t->curr_rune == '.') {
// TODO(bill): Clean up this shit
restore_tokenizer_state(t, &state);
goto end;
@@ -577,6 +578,13 @@ exponent:
scan_mantissa(t, 10);
}
+ switch (t->curr_rune) {
+ case 'i': case 'j': case 'k':
+ token.kind = Token_Imag;
+ advance_to_next_rune(t);
+ break;
+ }
+
end:
token.string.len = t->curr - token.string.text;
return token;
diff --git a/src/types.c b/src/types.c
index eee10dd45..ebbce3e39 100644
--- a/src/types.c
+++ b/src/types.c
@@ -12,25 +12,15 @@ typedef enum BasicKind {
Basic_i64,
Basic_u64,
-/* Basic_i16le,
- Basic_i16be,
- Basic_u16le,
- Basic_u16be,
- Basic_i32le,
- Basic_i32be,
- Basic_u32le,
- Basic_u32be,
- Basic_i64le,
- Basic_i64be,
- Basic_u64le,
- Basic_u64be, */
-
- // Basic_i128,
- // Basic_u128,
- // Basic_f16,
Basic_f32,
Basic_f64,
- // Basic_f128,
+
+ Basic_complex64,
+ Basic_complex128,
+
+ Basic_quaternion128,
+ Basic_quaternion256,
+
Basic_int,
Basic_uint,
Basic_rawptr,
@@ -40,6 +30,8 @@ typedef enum BasicKind {
Basic_UntypedBool,
Basic_UntypedInteger,
Basic_UntypedFloat,
+ Basic_UntypedComplex,
+ Basic_UntypedQuaternion,
Basic_UntypedString,
Basic_UntypedRune,
Basic_UntypedNil,
@@ -51,17 +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_Pointer = GB_BIT(4),
- BasicFlag_String = GB_BIT(5),
- BasicFlag_Rune = GB_BIT(6),
- BasicFlag_Untyped = GB_BIT(7),
-
- BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float,
- BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
+ 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_Quaternion,
+ BasicFlag_Ordered = BasicFlag_Integer | BasicFlag_Float | BasicFlag_String | BasicFlag_Pointer,
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
} BasicFlag;
@@ -209,33 +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_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_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
- // {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
- // {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}},
- {Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
- {Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
- // {Type_Basic, {Basic_f128, BasicFlag_Float, 16, STR_LIT("f128")}},
- {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_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_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_Invalid, 0, 0, STR_LIT("invalid type")}},
+
+ {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_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_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_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[] = {
@@ -253,25 +257,33 @@ gb_global Type *t_i32 = &basic_types[Basic_i32];
gb_global Type *t_u32 = &basic_types[Basic_u32];
gb_global Type *t_i64 = &basic_types[Basic_i64];
gb_global Type *t_u64 = &basic_types[Basic_u64];
-// gb_global Type *t_i128 = &basic_types[Basic_i128];
-// gb_global Type *t_u128 = &basic_types[Basic_u128];
-// gb_global Type *t_f16 = &basic_types[Basic_f16];
+
gb_global Type *t_f32 = &basic_types[Basic_f32];
gb_global Type *t_f64 = &basic_types[Basic_f64];
-// gb_global Type *t_f128 = &basic_types[Basic_f128];
+
+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_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_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 +305,8 @@ gb_global Type *t_type_info_enum_value_ptr = NULL;
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;
@@ -312,6 +326,8 @@ gb_global Type *t_type_info_map = NULL;
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;
@@ -615,6 +631,20 @@ bool is_type_float(Type *t) {
}
return false;
}
+bool is_type_complex(Type *t) {
+ t = core_type(t);
+ if (t->kind == Type_Basic) {
+ return (t->Basic.flags & BasicFlag_Complex) != 0;
+ }
+ 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) {
@@ -695,6 +725,31 @@ Type *base_vector_type(Type *t) {
return t;
}
+Type *base_complex_elem_type(Type *t) {
+ t = core_type(t);
+ if (is_type_complex(t)) {
+ switch (t->Basic.kind) {
+ case Basic_complex64: return t_f32;
+ case Basic_complex128: return t_f64;
+ case Basic_UntypedComplex: return t_untyped_float;
+ }
+ }
+ 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) {
t = base_type(t);
@@ -950,11 +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_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;
@@ -1542,6 +1599,11 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
case Basic_int: case Basic_uint: case Basic_rawptr:
return build_context.word_size;
+
+ case Basic_complex64: case Basic_complex128:
+ 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;