diff options
author | pommicket <pommicket@gmail.com> | 2022-01-11 22:29:00 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-01-11 22:29:00 -0500 |
commit | 06ebaf043b97b9de6bd096f062e7954609748a67 (patch) | |
tree | 5b808896fd438a147fcb3fc900c628354b95b873 /05 | |
parent | 343129a61099f74ab746905a693d7b18ced6b269 (diff) |
untested first stab at floats
Diffstat (limited to '05')
-rw-r--r-- | 05/main.b | 6 | ||||
-rw-r--r-- | 05/tokenize.b | 55 | ||||
-rw-r--r-- | 05/util.b | 23 |
3 files changed, 82 insertions, 2 deletions
@@ -152,6 +152,7 @@ function normalize_float local exponent significand = *8p_significand + if significand == 0 goto normalize_0 exponent = *8p_exponent :float_reduce_loop @@ -169,7 +170,10 @@ function normalize_float *8p_significand = significand *8p_exponent = exponent return - + :normalize_0 + *8p_exponent = 0 + return + function fill_in_powers_of_10 local i local p diff --git a/05/tokenize.b b/05/tokenize.b index 1c197a7..e6bd48e 100644 --- a/05/tokenize.b +++ b/05/tokenize.b @@ -122,6 +122,11 @@ function tokenize local data local significand local exponent + local pow10 + local integer + local fraction + local lower + local upper in = pptokens :tokenize_loop @@ -263,8 +268,51 @@ function tokenize :tokenize_float significand = 0 exponent = 0 - ; @TODO + pow10 = 0 + integer = strtoi(&in, 10) + fraction = 0 + if *1in != '. goto float_no_fraction + in += 1 + p = in + fraction = strtoi(&in, 10) + ; e.g. to turn 35 into .35, multiply by 10^-2 + pow10 = p - in + if pow10 < -400 goto bad_float + :float_no_fraction + ; construct the number integer + fraction*10^pow10 + ; first, deal with the fractional part + p = powers_of_10 + p += pow10 < 4 + full_multiply_signed(fraction, *8p, &upper, &lower) + ; effectively we want the upper 58 bits of this multiplication + significand = lower > 58 + significand |= upper < 6 + p += 8 + significand >= 0 - *8p + if integer == 0 goto float_no_integer + ; we now have significand / 2^58 = fraction*10^pow10 + ; now deal with the integer part + exponent = leftmost_1bit(integer) + significand >= exponent + n = 58 - exponent + significand += integer < n + if *1in != 'e goto float_no_exponent + + :float_no_exponent + if significand == 0 goto float_zero + ; reduce to 52-bit significant + significand >= 6 + exponent += 6 + exponent += 51 ; 1001010111... => 1.001010111... + n = leftmost_1bit(significand) + b = 1 < n + significand &= ~b + data = significand + exponent += 1023 ; float format + data |= exponent < 52 + :float_no_integer byte 0xcc + :float_zero :tokenize_loop_end return 0 @@ -293,6 +341,11 @@ function tokenize :str_bad_token string Bad token. byte 0 + :bad_float + compile_error(file, line_number, .str_bad_float) + :str_bad_float + string Bad floating-point number. + byte 0 ; return character or escaped character from *p_in, advancing accordingly ; returns -1 on bad character @@ -477,6 +477,29 @@ function exit argument status_code syscall(0x3c, status_code) +; return index of leftmost bit +; error on 0 +function leftmost_1bit + argument x + local i + local b + if x == 0 goto leftmost1bit_0 + + i = 63 + :leftmost1bit_loop + b = 1 < i + b &= x + if b != 0 goto leftmost1bit_found + i -= 1 + goto leftmost1bit_loop + :leftmost1bit_found + return i + :leftmost1bit_0 + fputs(2, .str_leftmost1bit_0) + exit(1) + :str_leftmost1bit_0 + string 0 passed to leftmost_1bit. + byte 0 :return_0 return 0 :return_1 |