diff options
| author | Zachary Pierson <zacpiersonhehe@gmail.com> | 2017-04-02 03:29:51 -0500 |
|---|---|---|
| committer | Zachary Pierson <zacpiersonhehe@gmail.com> | 2017-04-02 03:29:51 -0500 |
| commit | ce0d874efd3bdd2cbfd24ca5b10c9326774c1530 (patch) | |
| tree | 9f3b6ce4c83a7c7e45506b17cd36363c06f978e7 /src/check_expr.c | |
| parent | 24b33374b7830fae01be1915adb14b4e45ff9550 (diff) | |
| parent | 2c8b99337bb33d0f713026c5c38e05428cc52143 (diff) | |
Merge https://github.com/gingerBill/Odin
Diffstat (limited to 'src/check_expr.c')
| -rw-r--r-- | src/check_expr.c | 424 |
1 files changed, 386 insertions, 38 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; |