Updated README.
[scheme.forth.jl.git] / scheme.4th
index 4ccf7d8..f8dd089 100644 (file)
@@ -52,7 +52,7 @@ variable nextexception
 make-exception recoverable-exception
 make-exception unrecoverable-exception
 
-: display-warning ( addr count -- )
+: display-exception-msg ( addr count -- )
     bold fg red
     ." Exception: "
     type
@@ -65,7 +65,7 @@ make-exception unrecoverable-exception
 
     [compile] if
         ['] -rot ,
-        ['] display-warning ,
+        ['] display-exception-msg ,
     [compile] then
 
     ['] throw ,
@@ -139,11 +139,6 @@ variable nextfree
     cdr-cells + !
 ;
 
-: caar car car ;
-: cadr cdr car ;
-: cdar car cdr ;
-: cddr cdr cdr ;
-
 : nil 0 nil-type ;
 : nil? nil-type istype? ;
 
@@ -1058,7 +1053,96 @@ parse-idx-stack parse-idx-sp !
     quote-symbol tagged-list?  ;
 
 : quote-body ( quote-obj -- quote-body-obj )
-    cadr ;
+    cdr car ;
+
+: quasiquote? ( obj -- obj bool )
+    quasiquote-symbol tagged-list? ;
+
+: unquote? ( obj -- obj bool )
+    unquote-symbol tagged-list? ;
+
+: unquote-splicing? ( obj -- obj bool )
+    unquote-splicing-symbol tagged-list? ;
+
+: eval-unquote ( env obj -- res )
+    cdr ( env args )
+
+    nil? if
+        recoverable-exception throw" no arguments to unquote."
+    then
+
+    2dup cdr
+    nil? false = if
+        recoverable-exception throw" too many arguments to unquote."
+    then
+
+    2drop car 2swap eval
+;
+
+( Create a new list from elements of l1 consed on to l2 )
+: join-lists ( l2 l1 -- l3 )
+    nil? if 2drop exit then
+
+    2dup car
+    -2rot cdr
+    recurse cons
+;
+
+defer eval-quasiquote-item
+: eval-quasiquote-pair ( env obj -- res )
+    2over 2over ( env obj env obj )
+
+    cdr eval-quasiquote-item
+
+    -2rot car ( cdritem env objcar )
+
+    unquote-splicing? if
+        eval-unquote ( cdritems caritem )
+
+        2swap nil? if
+            2drop
+        else
+            2swap join-lists
+        then
+    else
+        eval-quasiquote-item ( cdritems caritem )
+        2swap cons
+    then
+
+;
+
+:noname ( env obj )
+    nil? if
+        2swap 2drop exit
+    then
+
+    unquote? if
+        eval-unquote exit
+    then
+
+    pair-type istype? if
+        eval-quasiquote-pair exit
+    then
+
+    2swap 2drop
+; is eval-quasiquote-item
+
+: eval-quasiquote ( obj env -- res )
+    2swap cdr ( env args )
+
+    nil? if
+        recoverable-exception throw" no arguments to quasiquote."
+    then
+
+    2dup cdr ( env args args-cdr )
+    nil? false = if
+        recoverable-exception throw" too many arguments to quasiquote."
+    then
+
+    2drop car ( env arg )
+
+    eval-quasiquote-item
+;
 
 : variable? ( obj -- obj bool )
     symbol-type istype? ;
@@ -1159,10 +1243,10 @@ hide env
 : if-consequent ( ifobj -- conseq )
     cdr cdr car ;
 
-: if-alternative ( ifobj -- alt|false )
+: if-alternative ( ifobj -- alt|none )
     cdr cdr cdr
     nil? if
-        2drop false
+        2drop none
     else
         car
     then ;
@@ -1319,6 +1403,7 @@ hide env
         endcase
 ;
 
+( Simply evaluates the given procedure with expbody as its argument. )
 : macro-expand ( proc expbody -- result )
     2swap
     2dup procedure-body ( expbody proc procbody )
@@ -1346,6 +1431,11 @@ hide env
         exit
     then
 
+    quasiquote? if
+        2swap eval-quasiquote
+        exit
+    then
+
     variable? if
         2swap lookup-var
         exit
@@ -1456,7 +1546,7 @@ hide env
 ;
 
 : (printstring) ( stringobj -- )
-    nil-type istype? if 2drop exit then
+    nil? if 2drop exit then
 
     2dup car drop dup
     case
@@ -1501,6 +1591,9 @@ hide env
 : printnone ( noneobj -- )
     2drop ." Unspecified return value" ;
 
+: printport ( port -- )
+    2drop ." <port>" ;
+
 :noname ( obj -- )
     fixnum-type istype? if printfixnum exit then
     realnum-type istype? if printrealnum exit then
@@ -1709,11 +1802,7 @@ variable gc-stack-depth
             recoverable-exception of false endof
             unrecoverable-exception of true endof
 
-            \ Rethrow anything else:
-            throw
-
-            \ If we're still here, loop again
-            false
+            throw false
         endcase
     until
 ;