def/set/lookup are working!
[scheme.forth.jl.git] / scheme.4th
index 825ba58..8581893 100644 (file)
@@ -16,7 +16,7 @@ include defer-is.4th
 : istype? ( obj type -- obj bool )
     over = ;
 
-\ ------ Cons cell memory ------
+\ ------ Cons cell memory ------ {{{
 
 1000 constant N
 create car-cells N allot
@@ -82,7 +82,9 @@ variable nextfree
 : objeq? ( obj obj -- bool )
     rot = -rot = and ;
 
-\ ---- Pre-defined symbols ----
+\ }}}
+
+\ ---- Pre-defined symbols ---- {{{
 
 objvar symbol-table
 
@@ -115,13 +117,14 @@ objvar symbol-table
     does> dup @ swap 1+ @
 ;
 
-create-symbol quote quote-symbol
-create-symbol define define-symbol
-create-symbol set! set!-symbol
+create-symbol quote     quote-symbol
+create-symbol define    define-symbol
+create-symbol set!      set!-symbol
+create-symbol ok        ok-symbol
 
-\ ---- Environments ----
+\ }}}
 
-objvar global-environment
+\ ---- Environments ---- {{{
 
 : enclosing-env ( env -- env )
     cdr ;
@@ -139,10 +142,107 @@ objvar global-environment
     cdr ;
 
 : add-binding ( var val frame -- )
+    2swap 2over frame-vals cons
+    2over set-cdr!
+    2swap 2over frame-vars cons
+    2swap set-car!
 ;
-    
 
-\ ---- Read ----
+: extend-env ( vars vals env -- env )
+    >R >R
+    make-frame
+    R> R>
+    cons
+;
+
+objvar vars
+objvar vals
+
+: get-vars-vals-frame ( var frame -- bool )
+    2dup frame-vars vars setobj
+    frame-vals vals setobj
+
+    begin
+        vars fetchobj nil objeq? false =
+    while
+        2dup vars fetchobj car objeq? if
+            2drop true
+            exit
+        then
+
+        vars fetchobj cdr vars setobj
+        vals fetchobj cdr vals setobj
+    repeat
+
+    2drop false
+;
+
+: get-vars-vals ( var env -- vars? vals? bool )
+
+    begin
+        2dup nil objeq? false =
+    while
+        2over 2over first-frame
+        get-vars-vals-frame if
+            2drop 2drop
+            vars fetchobj vals fetchobj true
+            exit
+        then
+
+        enclosing-env
+    repeat
+
+    2drop 2drop
+    false
+;
+
+hide vars
+hide vals
+
+: lookup-var ( var env -- val )
+    get-vars-vals if
+        2swap 2drop car
+    else
+        bold fg red ." Tried to read unbound variable." reset-term cr abort
+    then
+;
+
+: set-var ( var val env -- )
+    >R >R 2swap R> R> ( val var env )
+    get-vars-vals if
+        2swap 2drop ( val vals )
+        set-car!
+    else
+        bold fg red ." Tried to set unbound variable." reset-term cr abort
+    then
+;
+
+objvar env
+
+: define-var ( var val env -- )
+    env setobj 
+
+    2over env fetchobj ( var val var env )
+    get-vars-vals if
+        2swap 2drop ( var val vals )
+        set-car!
+        2drop
+    else
+        env fetchobj
+        first-frame ( var val frame )
+        add-binding
+    then
+;
+
+hide env
+
+objvar global-env
+nil nil nil extend-env
+global-env setobj
+
+\ }}}
+
+\ ---- Read ---- {{{
 
 variable parse-idx
 variable stored-parse-idx
@@ -517,6 +617,7 @@ defer read
 
     string? if
         inc-parse-idx
+
         readstring
         drop string-type
 
@@ -526,6 +627,7 @@ defer read
         then
 
         inc-parse-idx
+
         exit
     then
 
@@ -558,12 +660,14 @@ defer read
         quit
     then
 
-    \ Anything else is assumed to be a symbol
+    \ Anything else is parsed as a symbol
     readsymbol charlist>symbol
 
 ; is read
 
-\ ---- Eval ----
+\ }}}
+
+\ ---- Eval ---- {{{
 
 : self-evaluating? ( obj -- obj bool )
     boolean-type istype? if true exit then
@@ -588,22 +692,94 @@ defer read
 
 : quote-body ( quote-obj -- quote-body-obj )
     cadr ;
+
+: variable? ( obj -- obj bool )
+    symbol-type istype? ;
+
+: definition? ( obj -- obj bool )
+    define-symbol tagged-list? ;
+
+: definition-var ( obj -- var )
+    cdr car ;
+
+: definition-val ( obj -- val )
+    cdr cdr car ;
+
+: assignment? ( obj -- obj bool )
+    set!-symbol tagged-list? ;
+
+: assignment-var ( obj -- var )
+    cdr car ;
+    
+: assignment-val ( obj -- val )
+    cdr cdr car ;
+
+defer eval
+
+: eval-definition ( obj env -- res )
+    2swap 
+    2over 2over ( env obj env obj )
+    definition-val 2swap ( env obj valexp env )
+    eval  ( env obj val )
+    
+    2swap definition-var 2swap ( env var val )
+
+    >R >R 2swap R> R> 2swap ( var val env )
+    define-var
+
+    ok-symbol
+;
+    
+: eval-assignment ( obj env -- res )
+    2swap 
+    2over 2over ( env obj env obj )
+    assignment-val 2swap ( env obj valexp env )
+    eval  ( env obj val )
     
-: eval
+    2swap assignment-var 2swap ( env var val )
+
+    >R >R 2swap R> R> 2swap ( var val env )
+    set-var
+
+    ok-symbol
+;
+
+:noname ( obj env -- result )
+    2swap
+
     self-evaluating? if
+        2swap 2drop
         exit
     then
 
     quote? if
         quote-body
+        2swap 2drop
+        exit
+    then
+
+    variable? if
+        2swap lookup-var
+        exit
+    then
+
+    definition? if
+        2swap eval-definition
+        exit
+    then
+
+    assignment? if
+        2swap eval-assignment
         exit
     then
 
     bold fg red ." Error evaluating expression - unrecognized type. Aborting." reset-term cr
     abort
-;
+; is eval
+
+\ }}}
 
-\ ---- Print ----
+\ ---- Print ---- {{{
 
 : printnum ( numobj -- ) drop 0 .R ;
 
@@ -677,6 +853,8 @@ defer print
     abort
 ; is print
 
+\ }}}
+
 \ ---- REPL ----
 
 : repl
@@ -688,9 +866,11 @@ defer print
     begin
         cr bold fg green ." > " reset-term
         read
-        eval
+        global-env fetchobj eval
         fg cyan ." ; " print reset-term
     again
 ;
 
 forth definitions
+
+\ vim:fdm=marker