untested first stab at floats

This commit is contained in:
pommicket 2022-01-11 22:29:00 -05:00
parent 343129a610
commit 06ebaf043b
3 changed files with 82 additions and 2 deletions

View file

@ -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

View file

@ -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

View file

@ -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