authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-23 14:04:52-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-23 14:04:52-04:00
log3e9697bb35267973554155cedc2e593bd4519dd8
tree86868b584d74643e091c2858bfd3f4425264ae26
parent14d416f83b4dabeb714d7001f6efa4fcbac180d5
signaturelock-open Commit is signed but in an unrecognized format.

remove octal and hex floats from the language

closes #2093 This is technically a breaking change but I would be surprised if anyone was actually using this feature.

3 files changed, 9 insertions(+), 92 deletions(-)

src/tokenizer.cpp+9-77
...@@ -293,85 +293,11 @@ static void cancel_token(Tokenize *t) {...@@ -293,85 +293,11 @@ static void cancel_token(Tokenize *t) {
293}293}
294294
295static void end_float_token(Tokenize *t) {295static void end_float_token(Tokenize *t) {
296 if (t->radix == 10 || t->radix == 16) {296 uint8_t *ptr_buf = (uint8_t*)buf_ptr(t->buf) + t->cur_tok->start_pos;
297 uint8_t *ptr_buf = (uint8_t*)buf_ptr(t->buf) + t->cur_tok->start_pos;297 size_t buf_len = t->cur_tok->end_pos - t->cur_tok->start_pos;
298 size_t buf_len = t->cur_tok->end_pos - t->cur_tok->start_pos;298 if (bigfloat_init_buf(&t->cur_tok->data.float_lit.bigfloat, ptr_buf, buf_len)) {
299 if (bigfloat_init_buf(&t->cur_tok->data.float_lit.bigfloat, ptr_buf, buf_len)) {
300 t->cur_tok->data.float_lit.overflow = true;
301 }
302 return;
303 }
304
305 BigInt int_max;
306 bigint_init_unsigned(&int_max, INT_MAX);
307
308 if (bigint_cmp(&t->specified_exponent, &int_max) != CmpLT) {
309 t->cur_tok->data.float_lit.overflow = true;
310 return;
311 }
312
313 if (!bigint_fits_in_bits(&t->specified_exponent, 128, true)) {
314 t->cur_tok->data.float_lit.overflow = true;
315 return;
316 }
317
318 int64_t specified_exponent = bigint_as_signed(&t->specified_exponent);
319 if (t->is_exp_negative) {
320 specified_exponent = -specified_exponent;
321 }
322 t->exponent_in_bin_or_dec = (int)(t->exponent_in_bin_or_dec + specified_exponent);
323
324 if (!bigint_fits_in_bits(&t->significand, 128, false)) {
325 t->cur_tok->data.float_lit.overflow = true;299 t->cur_tok->data.float_lit.overflow = true;
326 return;
327 }300 }
328
329 // A SoftFloat-3e float128 is represented internally as a standard
330 // quad-precision float with 15bit exponent and 112bit fractional.
331 union { uint64_t repr[2]; float128_t actual; } f_bits;
332
333 if (bigint_cmp_zero(&t->significand) == CmpEQ) {
334 f_bits.repr[0] = 0;
335 f_bits.repr[1] = 0;
336 } else {
337 int significand_magnitude_in_bin = 127 - bigint_clz(&t->significand, 128);
338 t->exponent_in_bin_or_dec += significand_magnitude_in_bin;
339 if (!(-16382 <= t->exponent_in_bin_or_dec && t->exponent_in_bin_or_dec <= 16383)) {
340 t->cur_tok->data.float_lit.overflow = true;
341 return;
342 }
343
344 // Shift bits of significand so they are left-justified at the 112-bit
345 // mark. We truncate excess bits and lose precision. No rounding.
346 //
347 // -16 <= shift <= 112
348 //
349 // NOTE: The loss of precision could be considered a limitation of using
350 // 128-bit floats. In stage2 we should use an arbitrary precision
351 // float/rational type to represent these and avoid this.
352 const int shift = 112 - significand_magnitude_in_bin;
353 bigint_write_twos_complement(&t->significand, (uint8_t*) f_bits.repr, 128, false);
354
355 if (shift >= 64) {
356 f_bits.repr[1] = f_bits.repr[0] << (shift - 64);
357 f_bits.repr[0] = 0;
358 } else if (shift > 0) {
359 f_bits.repr[1] = (f_bits.repr[1] << shift) | (f_bits.repr[0] >> (64 - shift));
360 f_bits.repr[0] = f_bits.repr[0] << shift;
361 } else if (shift < 0) {
362 int positive_shift = -shift;
363 assert(positive_shift <= 16);
364 f_bits.repr[0] = (f_bits.repr[0] >> positive_shift) | (f_bits.repr[1] << (64 - positive_shift));
365 f_bits.repr[1] = f_bits.repr[1] >> positive_shift;
366 }
367
368 // Lexer separates negative sign from value so this is always non-negative.
369 const uint64_t exp_mask = 0xffffull << 48;
370 f_bits.repr[1] &= ~exp_mask;
371 f_bits.repr[1] |= (uint64_t)(t->exponent_in_bin_or_dec + 16383) << 48;
372 }
373
374 bigfloat_init_128(&t->cur_tok->data.float_lit.bigfloat, f_bits.actual);
375}301}
376302
377static void end_token(Tokenize *t) {303static void end_token(Tokenize *t) {
...@@ -1265,10 +1191,16 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1265,10 +1191,16 @@ void tokenize(Buf *buf, Tokenization *out) {
1265 case TokenizeStateNumber:1191 case TokenizeStateNumber:
1266 {1192 {
1267 if (c == '.') {1193 if (c == '.') {
1194 if (t.radix != 16 && t.radix != 10) {
1195 invalid_char_error(&t, c);
1196 }
1268 t.state = TokenizeStateNumberDot;1197 t.state = TokenizeStateNumberDot;
1269 break;1198 break;
1270 }1199 }
1271 if (is_exponent_signifier(c, t.radix)) {1200 if (is_exponent_signifier(c, t.radix)) {
1201 if (t.radix != 16 && t.radix != 10) {
1202 invalid_char_error(&t, c);
1203 }
1272 t.state = TokenizeStateFloatExponentUnsigned;1204 t.state = TokenizeStateFloatExponentUnsigned;
1273 assert(t.cur_tok->id == TokenIdIntLiteral);1205 assert(t.cur_tok->id == TokenIdIntLiteral);
1274 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);1206 bigint_init_bigint(&t.significand, &t.cur_tok->data.int_lit.bigint);
test/compare_output.zig-10
...@@ -215,13 +215,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -215,13 +215,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
215 \\ _ = c.printf(c"0x103.70p-5: %.013a\n",215 \\ _ = c.printf(c"0x103.70p-5: %.013a\n",
216 \\ f64(0x103.70p-5));216 \\ f64(0x103.70p-5));
217 \\217 \\
218 \\ _ = c.printf(c"\n");
219 \\
220 \\ _ = c.printf(c"0b10100.00010e0: %.013a\n",
221 \\ f64(0b10100.00010e0));
222 \\ _ = c.printf(c"0o10700.00010e0: %.013a\n",
223 \\ f64(0o10700.00010e0));
224 \\
225 \\ return 0;218 \\ return 0;
226 \\}219 \\}
227 ,220 ,
...@@ -260,9 +253,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -260,9 +253,6 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
260 \\0x103.70p+5: 0x1.0370000000000p+13253 \\0x103.70p+5: 0x1.0370000000000p+13
261 \\0x103.70p-5: 0x1.0370000000000p+3254 \\0x103.70p-5: 0x1.0370000000000p+3
262 \\255 \\
263 \\0b10100.00010e0: 0x1.4100000000000p+4
264 \\0o10700.00010e0: 0x1.1c00010000000p+12
265 \\
266 );256 );
267257
268 cases.add("order-independent declarations",258 cases.add("order-independent declarations",
test/stage1/behavior/math.zig-5
...@@ -597,8 +597,3 @@ test "vector integer addition" {...@@ -597,8 +597,3 @@ test "vector integer addition" {
597 S.doTheTest();597 S.doTheTest();
598 comptime S.doTheTest();598 comptime S.doTheTest();
599}599}
600
601test "binary and octal float literals" {
602 expect(0b10100.00010e0 == 0x1.4100000000000p+4);
603 expect(0o10700.00010e0 == 0x1.1c00010000000p+12);
604}