+create-symbol quote quote-symbol
+create-symbol define define-symbol
+create-symbol set! set!-symbol
+create-symbol ok ok-symbol
+create-symbol if if-symbol
+create-symbol lambda lambda-symbol
+create-symbol λ λ-symbol
+
+\ }}}
+
+\ ---- Environments ---- {{{
+
+: enclosing-env ( env -- env )
+ cdr ;
+
+: first-frame ( env -- frame )
+ car ;
+
+: make-frame ( vars vals -- frame )
+ cons ;
+
+: frame-vars ( frame -- vars )
+ car ;
+
+: frame-vals ( frame -- vals )
+ cdr ;
+
+: add-binding ( var val frame -- )
+ 2swap 2over frame-vals cons
+ 2over set-cdr!
+ 2swap 2over frame-vars cons
+ 2swap set-car!
+;
+
+: 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 obj!
+ frame-vals vals obj!
+
+ begin
+ vars obj@ nil objeq? false =
+ while
+ 2dup vars obj@ car objeq? if
+ 2drop true
+ exit
+ then
+
+ vars obj@ cdr vars obj!
+ vals obj@ cdr vals obj!
+ 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 obj@ vals obj@ 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
+;