Improved string parser, added license.
[scheme.forth.jl.git] / src / scheme.4th
index c1d42e8..52fcbcc 100644 (file)
@@ -4,6 +4,7 @@ scheme definitions
 include term-colours.4th
 include defer-is.4th
 include catch-throw.4th
+include integer.4th
 include float.4th
 
 include debugging.4th
@@ -25,6 +26,7 @@ variable nexttype
 
 make-type fixnum-type
 make-type flonum-type
+make-type ratnum-type
 make-type boolean-type
 make-type character-type
 make-type string-type
@@ -304,6 +306,9 @@ create-symbol lambda            lambda-symbol
 create-symbol λ                 λ-symbol
 create-symbol begin             begin-symbol
 
+\ Symbol to be bound to welcome message procedure by library
+create-symbol welcome           welcome-symbol
+
 \ }}}
 
 \ ---- Environments ---- {{{
@@ -786,6 +791,42 @@ parse-idx-stack parse-idx-sp !
     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
 
@@ -853,7 +894,7 @@ parse-idx-stack parse-idx-sp !
 : string? ( -- bool )
     nextchar [char] " = ;
 
-: readfixnum ( -- num-atom )
+: readfixnum ( -- fixnum )
     plus? minus? or if
         minus?
         inc-parse-idx
@@ -873,6 +914,56 @@ parse-idx-stack parse-idx-sp !
     fixnum-type
 ;
 
+: readflonum ( -- flonum )
+    readfixnum drop
+    dup 0< swap abs i->f
+
+    [char] . nextchar = if
+        inc-parse-idx
+
+        10.0 ( f exp )
+
+        begin digit? while
+            nextchar [char] 0 - i->f ( f exp d )
+            over f/ rot f+ ( exp f' )
+            swap 10.0 f* ( f' exp' )
+            inc-parse-idx
+        repeat
+
+        drop
+    then
+
+    [char] e nextchar = [char] E nextchar = or if
+        inc-parse-idx
+        10.0
+        readfixnum drop i->f
+        f^ f*
+    then
+
+    swap if
+        -1.0 f*
+    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
     
@@ -901,35 +992,51 @@ parse-idx-stack parse-idx-sp !
 ;
 
 : readstring ( -- charlist )
-    nextchar [char] " = if
-        inc-parse-idx
 
-        delim? false = if
-            bold fg red
-            ." No delimiter following right double quote. Aborting." cr
-            reset-term abort
+    nil nil
+
+    begin
+        nextchar [char] " <>
+    while
+        nextchar [char] \ = if
+            inc-parse-idx
+            nextchar case
+                [char] n of '\n' endof
+                [char] " of [char] " endof
+                [char] \
+            endcase
+        else
+            nextchar
         then
+        inc-parse-idx character-type
+        nil cons
 
-        dec-parse-idx
+        ( firstchar prevchar thischar )
 
-        0 nil-type exit
-    then
+        2swap nil? if
+            2drop 2swap 2drop 2dup  ( thischar thischar )
+        else
+            ( firstchar thischar prevchar )
+            2over 2swap  set-cdr! ( firstchar thischar )
+        then
+    repeat
 
-    nextchar [char] \ = if
-        inc-parse-idx
-        nextchar case
-            [char] n of '\n' endof
-            [char] " of [char] " endof
-            [char] \
-        endcase
-    else
-        nextchar
+    \ Discard previous character
+    2drop
+
+    inc-parse-idx
+    delim? false = if
+        bold fg red
+        ." No delimiter following right double quote. Aborting." cr
+        reset-term abort
     then
-    inc-parse-idx character-type
 
-    recurse
+    dec-parse-idx
 
-    cons
+    nil? if
+        nil cons
+    then
+    drop string-type
 ;
 
 : readsymbol ( -- charlist )
@@ -994,6 +1101,16 @@ parse-idx-stack parse-idx-sp !
         exit
     then
 
+    flonum? if
+        readflonum
+        exit
+    then
+
+    ratnum? if
+        readratnum
+        exit
+    then
+
     boolean? if
         readbool
         exit
@@ -1008,7 +1125,6 @@ parse-idx-stack parse-idx-sp !
         inc-parse-idx
 
         readstring
-        drop string-type
 
         nextchar [char] " <> if
             bold red ." Missing closing double-quote." reset-term cr
@@ -1083,6 +1199,8 @@ parse-idx-stack parse-idx-sp !
 : self-evaluating? ( obj -- obj bool )
     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
@@ -1572,9 +1690,16 @@ hide env
 
 \ ---- Print ---- {{{
 
-: printfixnum ( fixnumobj -- ) drop 0 .R ;
+: printfixnum ( fixnum -- ) drop 0 .R ;
 
-: printbool ( numobj -- )
+: printflonum ( flonum -- ) drop f. ;
+
+: printratnum ( ratnum -- )
+    drop pair-type 2dup
+    car print ." /" cdr print
+;
+
+: printbool ( bool -- )
     drop if
         ." #t"
     else
@@ -1644,6 +1769,8 @@ hide env
 
 :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
@@ -1836,13 +1963,14 @@ variable gc-stack-depth
 ;
 
 : repl
-    cr ." Welcome to scheme.forth.jl!" cr
-       ." Use Ctrl-D to exit." cr
 
     empty-parse-str
 
     enable-gc
 
+    \ Display welcome message
+    welcome-symbol nil cons global-env obj@ eval 2drop
+
     begin
         ['] repl-body catch
         case