: istype? ( obj type -- obj bool )
over = ;
-\ ------ Cons cell memory ------
+\ ------ Cons cell memory ------ {{{
1000 constant N
create car-cells N allot
: objeq? ( obj obj -- bool )
rot = -rot = and ;
-\ ---- Pre-defined symbols ----
+\ }}}
+
+\ ---- Pre-defined symbols ---- {{{
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 ----
+\ ---- Environments ---- {{{
-objvar global-environment
+objvar global-env
: enclosing-env ( env -- env )
cdr ;
cdr ;
: add-binding ( var val frame -- )
+ 2swap 2over frame-vals cons
+ 2over set-car!
+ 2swap 2over frame-vars cons
+ swap set-cdr!
;
-
-\ ---- 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
+ lookup-var-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 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 abort
+ then
+;
+
+objvar env
+
+: define-var ( var val env -- )
+ env objset
+
+ 2over env objfetch ( var val var env )
+ get-vars-vals if
+ 2swap 2drop ( var val vals )
+ set-car!
+ 2drop
+ else
+ env objfetch
+ first-frame ( var val frame )
+ add-binding
+ then
+;
+
+hide env
+
+\ }}}
+
+\ ---- Read ---- {{{
variable parse-idx
variable stored-parse-idx
string? if
inc-parse-idx
+
readstring
drop string-type
then
inc-parse-idx
+
exit
then
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
: 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 ;
+
+: eval-definition ( obj env -- res )
+ 2swap
+ 2over 2over ( env obj env obj )
+ definition-val 2swap ( env obj valexp env )
+ eval ( env obj val )
-: eval
+ 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 )
+
+ 2swap assignment-var 2swap ( env var val )
+
+ >R >R 2swap R> R> 2swap ( var val env )
+ set-var
+
+ ok-symbol
+;
+: eval ( 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
abort
;
-\ ---- Print ----
+\ }}}
+
+\ ---- Print ---- {{{
: printnum ( numobj -- ) drop 0 .R ;
abort
; is print
+\ }}}
+
\ ---- REPL ----
: repl
begin
cr bold fg green ." > " reset-term
read
- eval
+ global-env fetchobj eval
fg cyan ." ; " print reset-term
again
;