Fixed another define-var bug.
[scheme.forth.jl.git] / src / scheme.4th
index 7b1da05..68c3b67 100644 (file)
@@ -62,7 +62,7 @@ variable nextexception
 make-exception recoverable-exception
 make-exception unrecoverable-exception
 
-: throw reset-term throw ;
+: throw reset-term cr throw ;
 
 \ }}}
 
@@ -75,6 +75,12 @@ create car-type-cells scheme-memsize allot
 create cdr-cells scheme-memsize allot
 create cdr-type-cells scheme-memsize allot
 
+variable gc-enabled
+false gc-enabled !
+
+: gc-enabled?
+    gc-enabled @ ;
+
 create nextfrees scheme-memsize allot
 :noname
     scheme-memsize 0 do
@@ -90,7 +96,9 @@ variable nextfree
     nextfree !
 
     nextfree @ scheme-memsize >= if
-        collect-garbage
+        gc-enabled? if
+            collect-garbage
+        then
     then
 
     nextfree @ scheme-memsize >= if
@@ -402,6 +410,9 @@ variable read-line-buffer-offset
 : make-frame ( vars vals -- frame )
     cons ;
 
+: add-frame-to-env ( frame env -- env )
+    cons ;
+
 : frame-vars ( frame -- vars )
     car ;
 
@@ -416,99 +427,89 @@ variable read-line-buffer-offset
 ;
 
 : extend-env ( vars vals env -- env )
-    >R >R
-    make-frame
-    R> R>
-    cons
+    -2rot make-frame
+    2swap add-frame-to-env
 ;
 
-objvar vars
-objvar vals
-
-: get-vars-vals-frame ( var frame -- bool )
-    2dup frame-vars vars obj!
-    frame-vals vals obj!
+: get-vals-frame ( var frame -- vals | nil )
+    2dup frame-vars 
+    2swap frame-vals ( var vars vals )
 
     begin
-        vars obj@ nil objeq? false =
+        nil? false =
     while
-        2dup vars obj@ car objeq? if
-            2drop true
+
+        -2rot ( vals var vars )
+        2over 2over car objeq? if
+            2drop 2drop
             exit
         then
 
-        vars obj@ cdr vars obj!
-        vals obj@ cdr vals obj!
+        cdr 2rot cdr
     repeat
 
-    2drop false
+    2drop 2drop 2drop
+    nil
 ;
 
-: get-vars-vals ( var env -- vars? vals? bool )
+: get-vals ( var env -- vals | nil )
 
     begin
         nil? false =
     while
         2over 2over first-frame
-        get-vars-vals-frame if
-            2drop 2drop
-            vars obj@ vals obj@ true
+        get-vals-frame nil? false = if
+            2swap 2drop 2swap 2drop
             exit
         then
 
+        2drop
+
         enclosing-env
     repeat
 
-    2drop 2drop
-    false
+    2swap 2drop
 ;
 
-hide vars
-hide vals
-
-objvar var
-
+objvar var \ Used only for error messages
 : lookup-var ( var env -- val )
     2over var obj!
-    get-vars-vals if
-        2swap 2drop car
-    else
-        except-message: ." tried to read unbound variable '" var obj@ print ." '." recoverable-exception  throw
+    
+    get-vals nil? if
+        except-message: ." tried to read unbound variable '" var obj@ print ." '."
+        recoverable-exception throw
     then
+
+    car
 ;
 
 : set-var ( var val env -- )
-    >R >R 2swap R> R> ( val var env )
-    2over var obj!
-    get-vars-vals if
-        2swap 2drop ( val vals )
-        set-car!
+    2rot 2dup var obj! ( val env var )
+    get-vals nil? if
+        except-message: ." tried to set unbound variable '" var obj@ print ." '."
+        recoverable-exception throw
     else
-        except-message: ." tried to set unbound variable '" var obj@ print ." '." recoverable-exception throw
+        ( val vals )
+        set-car!
     then
 ;
-
 hide var
 
-objvar env
-
 : define-var ( var val env -- )
-    env obj! 
+    first-frame ( var val frame )
+    2rot 2swap 2over 2over ( val var frame var frame )
 
-    2over env obj@ ( var val var env )
-    get-vars-vals if
-        2swap 2drop ( var val vals )
-        set-car!
+    get-vals-frame nil? if
         2drop
-    else
-        env obj@
-        first-frame ( var val frame )
+        -2rot 2swap 2rot
         add-binding
+    else
+        ( val var frame vals )
+        2swap 2drop 2swap 2drop
+        set-car!
     then
 ;
 
-hide env
-
 : make-procedure ( params body env -- proc )
     nil
     cons cons cons
@@ -1273,6 +1274,11 @@ parse-idx-stack parse-idx-sp !
         exit
     then
 
+    nextchar [char] ) = if
+        inc-parse-idx
+        except-message: ." unmatched closing parenthesis." recoverable-exception throw
+    then
+
     \ Anything else is parsed as a symbol
     readsymbol charlist>symbol
 
@@ -1286,7 +1292,7 @@ parse-idx-stack parse-idx-sp !
 
 \ }}}
 
-\ ---- Eval ---- {{{
+\ ---- Syntax ---- {{{
 
 : self-evaluating? ( obj -- obj bool )
     boolean-type istype? if true exit then
@@ -1449,7 +1455,7 @@ parse-idx-stack parse-idx-sp !
 
 \ }}}
 
-\ ---- Analyze ----
+\ ---- Analyze ---- {{{
 
 : evaluate-eproc ( eproc env --- res )
 
@@ -1636,15 +1642,7 @@ parse-idx-stack parse-idx-sp !
     then
 ;
 
-: application-executor ( operator-proc arg-procs env -- res )
-    2rot 2over ( aprocs env fproc env )
-    evaluate-eproc ( aprocs env proc )
-
-    -2rot 2swap ( proc env aprocs )
-    evaluate-operand-eprocs ( proc vals )
-
-    2swap ( vals proc )
-    
+: apply ( vals proc )
     dup case
         primitive-proc-type of
             drop execute
@@ -1668,6 +1666,18 @@ parse-idx-stack parse-idx-sp !
     endcase
 ;
 
+: application-executor ( operator-proc arg-procs env -- res )
+    2rot 2over ( aprocs env fproc env )
+    evaluate-eproc ( aprocs env proc )
+
+    -2rot 2swap ( proc env aprocs )
+    evaluate-operand-eprocs ( proc vals )
+
+    2swap ( vals proc )
+
+    ['] apply goto
+;
+
 : analyze-application ( exp -- eproc )
     2dup operator analyze
     2swap operands operand-eproc-list
@@ -1700,6 +1710,7 @@ parse-idx-stack parse-idx-sp !
 
 ; is analyze
 
+\ }}}
 
 \ ---- Macro Expansion ---- {{{
 
@@ -1923,12 +1934,24 @@ parse-idx-stack parse-idx-sp !
     except-message: ." tried to print object with unknown type." recoverable-exception throw
 ; is print
 
+xxxx
 \ }}}
 
 \ ---- Garbage Collection ---- {{{
 
-variable gc-enabled
-false gc-enabled !
+( Notes on garbage collection:
+  This is a mark-sweep garbage collector, invoked by cons.
+  The roots of the object tree used by the marking routine 
+  include all objects in the parameter stack, and several
+  other fixed roots such as global-env, symbol-table, macro-table,
+  and the console-i/o-port.
+
+  NO OTHER OBJECTS WILL BE MARKED!
+
+  This places implicit restrictions on when cons can be invoked.
+  Invoking cons when live objects are stored on the return stack
+  or in other variables than the above will result in possible
+  memory corruption if the cons triggers the GC. )
 
 variable gc-stack-depth
 
@@ -1939,9 +1962,6 @@ variable gc-stack-depth
 : disable-gc
     false gc-enabled ! ;
 
-: gc-enabled?
-    gc-enabled @ ;
-
 : pairlike? ( obj -- obj bool )
     pair-type istype? if true exit then
     string-type istype? if true exit then
@@ -2041,8 +2061,14 @@ variable gc-stack-depth
     ok-symbol ( port res )
 
     begin
+        \ DEBUG
+        \ bold fg blue ." READ from " 2over drop . ." ==> " reset-term
+
         2over read-port ( port res obj )
 
+        \ DEBUG
+        \ 2dup print cr
+
         2dup EOF character-type objeq? if
             2drop 2swap close-port
             exit
@@ -2060,7 +2086,11 @@ variable gc-stack-depth
 
     include scheme-primitives.4th
 
+    enable-gc
+
     s" scheme-library.scm" load 2drop
+
+    disable-gc
     
 \ }}}
 
@@ -2102,6 +2132,8 @@ variable gc-stack-depth
             throw false
         endcase
     until
+
+    disable-gc
 ;
 
 forth definitions