\ Floating point arithmetic
-: lshift 2* ;
-: rshift 2/ ;
+( Cheating for now by using forth.jl CODE/END-CODE to
+ access Julia's floating point support. This isn't
+ at all portable. That said, the year is 2016 and most
+ CPUs implement these operations - even the trig functions,
+ so I don't feel too bad! )
-: nlshift 0 do lshift loop ;
-: nrshift 0 do rshift loop ;
+CODE f+
+ b = reinterpret(Float64, popPS())
+ a = reinterpret(Float64, popPS())
+ pushPS(reinterpret(Int64, a+b))
+END-CODE
-1 52 nlshift 1- constant frac-mask
-1 11 nlshift 1- 52 nlshift constant exp-mask
+CODE f-
+ b = reinterpret(Float64, popPS())
+ a = reinterpret(Float64, popPS())
+ pushPS(reinterpret(Int64, a-b))
+END-CODE
-: fraction
- frac-mask and ;
+CODE f*
+ b = reinterpret(Float64, popPS())
+ a = reinterpret(Float64, popPS())
+ pushPS(reinterpret(Int64, a*b))
+END-CODE
-: exponent
- exp-mask and 52 nrshift ;
+CODE f/
+ b = reinterpret(Float64, popPS())
+ a = reinterpret(Float64, popPS())
+ pushPS(reinterpret(Int64, a/b))
+END-CODE
-: sign ( float -- sign )
- 0> ;
+( addr len -- float )
+CODE float-parse
+ len = popPS()
+ addr = popPS()
+ val = parse(Float64, getString(addr, len))
+ pushPS(reinterpret(Int64, val))
+END-CODE
-: make-float ( sign exponent fraction -- float )
- swap 52 nlshift or
- swap false = if
- negate
- then
-;
+( float -- )
+CODE float-print
+ print(reinterpret(Float64, popPS()))
+END-CODE
\ No newline at end of file
include term-colours.4th
include defer-is.4th
include throw-catch.4th
+include float.4th
defer read
defer eval
does> @ ;
make-type fixnum-type
-make-type real-type
+make-type realnum-type
make-type boolean-type
make-type character-type
make-type string-type
inc-parse-idx
repeat
- delim? if
- pop-parse-idx
- true
- else
- pop-parse-idx
- false
+ delim? pop-parse-idx
+;
+
+: realnum? ( -- bool )
+ \ Record starting parse idx:
+ \ Want to detect whether any characters were eaten.
+ parse-idx @
+
+ push-parse-idx
+
+ minus? plus? or if
+ inc-parse-idx
+ then
+
+ begin digit? while
+ inc-parse-idx
+ repeat
+
+ [char] . nextchar = if
+ inc-parse-idx
+ begin digit? while
+ inc-parse-idx
+ repeat
then
+
+ [char] e nextchar = [char] E nextchar = or if
+ inc-parse-idx
+
+ minus? plus? or if
+ inc-parse-idx
+ then
+
+ begin digit? while
+ inc-parse-idx
+ repeat
+ then
+
+ \ This is a real number if characters were
+ \ eaten and the next characer is a delimiter.
+ parse-idx @ < delim? and
+
+ pop-parse-idx
;
: boolean? ( -- bool )
: string? ( -- bool )
nextchar [char] " = ;
-: readnum ( -- num-atom )
+: readfixnum ( -- num-atom )
plus? minus? or if
minus?
inc-parse-idx
fixnum-type
;
+: readrealnum ( -- realnum )
+
+ \ Remember that at this point we're guaranteed to
+ \ have a parsable real on this line.
+
+ parse-str parse-idx @ +
+
+ begin delim? false = while
+ inc-parse-idx
+ repeat
+
+ parse-str parse-idx @ + over -
+
+ float-parse
+
+ realnum-type
+;
+
: readbool ( -- bool-atom )
inc-parse-idx
eatspaces
fixnum? if
- readnum
+ readfixnum
+ exit
+ then
+
+ realnum? if
+ readrealnum
exit
then
: self-evaluating? ( obj -- obj bool )
boolean-type istype? if true exit then
fixnum-type istype? if true exit then
+ realnum-type istype? if true exit then
character-type istype? if true exit then
string-type istype? if true exit then
nil-type istype? if true exit then
\ ---- Print ---- {{{
-: printnum ( numobj -- ) drop 0 .R ;
+: printfixnum ( fixnumobj -- ) drop 0 .R ;
+
+: printrealnum ( realnumobj -- ) drop float-print ;
: printbool ( numobj -- )
drop if
2drop ." <compound procedure>" ;
:noname ( obj -- )
- fixnum-type istype? if printnum exit then
+ fixnum-type istype? if printfixnum exit then
+ realnum-type istype? if printrealnum exit then
boolean-type istype? if printbool exit then
character-type istype? if printchar exit then
string-type istype? if printstring exit then