authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-07 15:57:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-07 15:57:41-04:00
log2234788fa80dfaf1e58df51ff576701f8161b0df
treec544704e7d4981e2cae1c54abb4e6b17bc872268
parent38b47d8aca57efbb10b8000cb726eb24b1f37ccb

add ability to explicitly cast float to integer

closes #414

7 files changed, 58 insertions(+), 12 deletions(-)

src/bigfloat.cpp+4
......@@ -150,3 +150,7 @@ Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) {
150150 return CmpEQ;
151151 }
152152}
153
154bool bigfloat_has_fraction(const BigFloat *bigfloat) {
155 return floorl(bigfloat->value) != bigfloat->value;
156}
src/bigfloat.hpp+1
......@@ -43,5 +43,6 @@ void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count,
4343
4444// convenience functions
4545Cmp bigfloat_cmp_zero(const BigFloat *bigfloat);
46bool bigfloat_has_fraction(const BigFloat *bigfloat);
4647
4748#endif
src/ir.cpp+37-9
......@@ -6206,7 +6206,9 @@ static bool const_val_fits_in_num_lit(ConstExprValue *const_val, TypeTableEntry
62066206 (const_val->type->id == TypeTableEntryIdInt || const_val->type->id == TypeTableEntryIdNumLitInt)));
62076207}
62086208
6209static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
6209static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type,
6210 bool explicit_cast)
6211{
62106212 if (type_is_invalid(other_type)) {
62116213 return false;
62126214 }
......@@ -6243,6 +6245,32 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
62436245 return true;
62446246 }
62456247 }
6248 if (explicit_cast && (other_type->id == TypeTableEntryIdInt || other_type->id == TypeTableEntryIdNumLitInt) &&
6249 const_val_is_float)
6250 {
6251 if (bigfloat_has_fraction(&const_val->data.x_bigfloat)) {
6252 Buf *val_buf = buf_alloc();
6253 bigfloat_write_buf(val_buf, &const_val->data.x_bigfloat);
6254
6255 ir_add_error(ira, instruction,
6256 buf_sprintf("fractional component prevents float value %s from being casted to type '%s'",
6257 buf_ptr(val_buf),
6258 buf_ptr(&other_type->name)));
6259 return false;
6260 } else {
6261 BigInt bigint;
6262 bigint_init_bigfloat(&bigint, &const_val->data.x_bigfloat);
6263 if (other_type->id == TypeTableEntryIdNumLitInt) {
6264 return true;
6265 } else {
6266 if (bigint_fits_in_bits(&bigint, other_type->data.integral.bit_count,
6267 other_type->data.integral.is_signed))
6268 {
6269 return true;
6270 }
6271 }
6272 }
6273 }
62466274
62476275 const char *num_lit_str;
62486276 Buf *val_buf = buf_alloc();
......@@ -6425,12 +6453,12 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
64256453 if (expected_type->id == TypeTableEntryIdPointer &&
64266454 expected_type->data.pointer.is_const)
64276455 {
6428 if (ir_num_lit_fits_in_other_type(ira, value, expected_type->data.pointer.child_type)) {
6456 if (ir_num_lit_fits_in_other_type(ira, value, expected_type->data.pointer.child_type, false)) {
64296457 return ImplicitCastMatchResultYes;
64306458 } else {
64316459 return ImplicitCastMatchResultReportedError;
64326460 }
6433 } else if (ir_num_lit_fits_in_other_type(ira, value, expected_type)) {
6461 } else if (ir_num_lit_fits_in_other_type(ira, value, expected_type, false)) {
64346462 return ImplicitCastMatchResultYes;
64356463 } else {
64366464 return ImplicitCastMatchResultReportedError;
......@@ -6542,7 +6570,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
65426570 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||
65436571 prev_type->id == TypeTableEntryIdNumLitFloat)
65446572 {
6545 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type)) {
6573 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
65466574 prev_inst = cur_inst;
65476575 continue;
65486576 } else {
......@@ -6551,7 +6579,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
65516579 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||
65526580 cur_type->id == TypeTableEntryIdNumLitFloat)
65536581 {
6554 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) {
6582 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
65556583 continue;
65566584 } else {
65576585 return ira->codegen->builtin_types.entry_invalid;
......@@ -7636,7 +7664,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
76367664 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
76377665 actual_type->id == TypeTableEntryIdNumLitFloat)
76387666 {
7639 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) {
7667 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type, true)) {
76407668 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
76417669 } else {
76427670 return ira->codegen->invalid_instruction;
......@@ -7658,7 +7686,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
76587686 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
76597687 actual_type->id == TypeTableEntryIdNumLitFloat)
76607688 {
7661 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) {
7689 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type, true)) {
76627690 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
76637691 } else {
76647692 return ira->codegen->invalid_instruction;
......@@ -7736,7 +7764,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
77367764 return ira->codegen->invalid_instruction;
77377765
77387766 return cast2;
7739 } else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type)) {
7767 } else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
77407768 CastOp op;
77417769 if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
77427770 wanted_type->id == TypeTableEntryIdFloat) ||
......@@ -8630,7 +8658,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
86308658 return ira->codegen->builtin_types.entry_invalid;
86318659 }
86328660
8633 ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, resolved_type);
8661 ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, resolved_type, false);
86348662 return resolved_type;
86358663 }
86368664
std/fmt/errol/index.zig+1-2
......@@ -43,8 +43,7 @@ fn errol3u(val: f64, buffer: []u8) -> FloatDecimal {
4343
4444 // normalize the midpoint
4545
46 var e: i32 = undefined;
47 _ = math.frexp(val, &e);
46 const e = math.frexp(val).exponent;
4847 var exp = i16(math.floor(307 + f64(e) * 0.30103));
4948 if (exp < 20) {
5049 exp = 20;
std/math/index.zig+1-1
......@@ -95,7 +95,7 @@ pub const isSignalNan = @import("isnan.zig").isSignalNan;
9595pub const fabs = @import("fabs.zig").fabs;
9696pub const ceil = @import("ceil.zig").ceil;
9797pub const floor = @import("floor.zig").floor;
98pub const trunc = @import("floor.zig").trunc;
98pub const trunc = @import("trunc.zig").trunc;
9999pub const round = @import("round.zig").round;
100100pub const frexp = @import("frexp.zig").frexp;
101101pub const frexp32_result = @import("frexp.zig").frexp32_result;
test/cases/cast.zig+7
......@@ -251,3 +251,10 @@ fn testPeerErrorAndArray2(x: u8) -> %[]const u8 {
251251 else => error.BadValue,
252252 }
253253}
254
255test "explicit cast float number literal to integer if no fraction component" {
256 const x = i32(1e4);
257 assert(x == 10000);
258 const y = i32(f32(1e4));
259 assert(y == 10000);
260}
test/compile_errors.zig+7
......@@ -1945,4 +1945,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
19451945 \\}
19461946 ,
19471947 ".tmp_source.zig:2:15: error: float literal out of range of any type");
1948
1949 cases.add("explicit cast float literal to integer when there is a fraction component",
1950 \\export fn entry() -> i32 {
1951 \\ i32(12.34)
1952 \\}
1953 ,
1954 ".tmp_source.zig:2:9: error: fractional component prevents float value 12.340000 from being casted to type 'i32'");
19481955}