--- /dev/null
+\ Integer arithmetic words
+
+: sort-pair
+ 2dup > if
+ swap
+ then
+;
+
+( Find the GCD of n1 and n2 where n2 < n1. )
+: gcd ( n1 n2 -- m )
+ sort-pair
+ over 0= if
+ swap drop
+ else
+ over mod
+ recurse
+ then
+;
+
+: simplify ( n d -- n' d' )
+ swap dup 0< -rot abs swap
+ 2dup gcd
+ swap over ( b n1 c n2 c )
+ / ( b n1 c n2' )
+ -rot / ( b n2' n1' )
+
+ rot if
+ negate
+ then
+
+ swap
+;
;; NUMBERS
+; Rational primitives
+
+(define (numerator x)
+ (if (ratnum? x)
+ (rat:numerator x)
+ x))
+
+(define (denominator x)
+ (if (ratnum? x)
+ (rat:denominator x)
+ (if (fixnum? x)
+ 1
+ 1.0)))
+
+(define (rat:+ x y)
+ (make-rational (fix:+ (fix:* (numerator x) (denominator y))
+ (fix:* (denominator x) (numerator y)))
+ (fix:* (denominator x) (denominator y))))
+
+(define (rat:- x y)
+ (make-rational (fix:- (fix:* (numerator x) (denominator y))
+ (fix:* (denominator x) (numerator y)))
+ (fix:* (denominator x) (denominator y))))
+
+(define (rat:* x y)
+ (make-rational (fix:* (numerator x) (numerator y))
+ (fix:* (denominator x) (denominator y))))
+
+(define (rat:/ x y)
+ (make-rational (fix:* (numerator x) (denominator y))
+ (fix:* (denominator x) (numerator y))))
+
+(define (rat:1/ x)
+ (make-rational (denominator x) (numerator x)))
+
; Type dispatch and promotion
(define (type-dispatch ops x)
flonum-type istype? -rot 2drop boolean-type
; 1 make-fa-primitive flonum?
+:noname ( args -- boolobj )
+ ratnum-type istype? -rot 2drop boolean-type
+; 1 make-fa-primitive ratnum?
+
:noname ( args -- boolobj )
character-type istype? -rot 2drop boolean-type
; 1 make-fa-primitive char?
swap abs swap
; 1 make-fa-primitive fix:abs
-: sort-pair
- 2dup > if
- swap
- then
-;
-
-( Find the GCD of n1 and n2 where n2 < n1. )
-: gcd ( n1 n2 -- m )
- sort-pair
- over 0= if
- swap drop
- else
- over mod
- recurse
- then
-;
-
:noname ( fixnum fixnum -- fixnum' )
drop swap drop gcd fixnum-type
; 2 make-fa-primitive fix:gcd
drop swap drop f/ fatan flonum-type
; 2 make-fa-primitive flo:atan2
+\ --- Rationals ---
+
+' make-rational 2 make-fa-primitive make-rational
+
+:noname ( ratnum -- fixnum )
+ drop pair-type car
+; 1 make-fa-primitive rat:numerator
+
+:noname ( ratnum -- fixnum )
+ drop pair-type cdr
+; 1 make-fa-primitive rat:denominator
\ --- Conversion ---
include term-colours.4th
include defer-is.4th
include catch-throw.4th
+include integer.4th
include float.4th
include debugging.4th
make-type fixnum-type
make-type flonum-type
+make-type ratnum-type
make-type boolean-type
make-type character-type
make-type string-type
pop-parse-idx
;
+: ratnum? ( -- bool )
+ push-parse-idx
+
+ minus? plus? or if
+ inc-parse-idx
+ then
+
+ digit? invert if
+ pop-parse-idx false exit
+ else
+ inc-parse-idx
+ then
+
+ begin digit? while
+ inc-parse-idx
+ repeat
+
+ [char] / nextchar <> if
+ pop-parse-idx false exit
+ else
+ inc-parse-idx
+ then
+
+ digit? invert if
+ pop-parse-idx false exit
+ else
+ inc-parse-idx
+ then
+
+ begin digit? while
+ inc-parse-idx
+ repeat
+
+ delim? pop-parse-idx
+;
+
: boolean? ( -- bool )
nextchar [char] # <> if false exit then
flonum-type
;
+: make-rational ( fixnum fixnum -- ratnum|fixnum )
+ drop swap drop
+ simplify
+
+ dup 1 = if
+ drop fixnum-type
+ else
+ fixnum-type swap fixnum-type
+ cons drop ratnum-type
+ then
+;
+
+: readratnum ( -- ratnum )
+ readfixnum inc-parse-idx readfixnum
+ make-rational
+;
+
: readbool ( -- bool-obj )
inc-parse-idx
exit
then
+ ratnum? if
+ readratnum
+ exit
+ then
+
boolean? if
readbool
exit
boolean-type istype? if true exit then
fixnum-type istype? if true exit then
flonum-type istype? if true exit then
+ ratnum-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
: printflonum ( flonum -- ) drop f. ;
+: printratnum ( ratnum -- )
+ drop pair-type 2dup
+ car print ." /" cdr print
+;
+
: printbool ( bool -- )
drop if
." #t"
:noname ( obj -- )
fixnum-type istype? if printfixnum exit then
flonum-type istype? if printflonum exit then
+ ratnum-type istype? if printratnum exit then
boolean-type istype? if printbool exit then
character-type istype? if printchar exit then
string-type istype? if printstring exit then