scheme definitions
include term-colours.4th
+include defer-is.4th
0 constant number-type
1 constant boolean-type
2 constant character-type
3 constant nil-type
+4 constant pair-type
: istype? ( obj -- obj b )
over = ;
+100 constant N
+create car-cells N allot
+create car-type-cells N allot
+create cdr-cells N allot
+create cdr-type-cells N allot
+
+variable nextfree
+0 nextfree !
+
+: cons ( car-obj cdr-obj -- pair-obj )
+ cdr-type-cells nextfree @ + !
+ cdr-cells nextfree @ + !
+ car-type-cells nextfree @ + !
+ car-cells nextfree @ + !
+
+ nextfree @ pair-type
+
+ 1 nextfree +!
+;
+
+: car ( pair-obj -- car-obj )
+ drop
+ dup car-cells + @ swap
+ car-type-cells + @
+;
+
+: cdr ( pair-obj -- car-obj )
+ drop
+ dup cdr-cells + @ swap
+ cdr-type-cells + @
+;
+
+
\ ---- Read ----
variable parse-idx
pop-parse-idx true
;
-: empty-list? ( -- bool )
- nextchar [char] ( <> if false exit then
- push-parse-idx
- inc-parse-idx
- eatspaces
- nextchar [char] ) <> if pop-parse-idx false exit then
- pop-parse-idx true ;
+: pair? ( -- bool )
+ nextchar [char] ( = ;
: readnum ( -- num-atom )
inc-parse-idx
;
-: readnil ( -- nil-atom )
+defer read
+
+: readpair ( -- obj )
inc-parse-idx
eatspaces
- inc-parse-idx
- nil-type
+ \ Empty lists
+ nextchar [char] ) = if
+ inc-parse-idx
+
+ delim? false = if
+ bold fg red
+ ." No delimiter following right paren. Aborting." cr
+ reset-term abort
+ then
+
+ nil-type exit
+ then
+
+ \ Read first pair element
+ read
+
+ \ Pairs
+ eatspaces
+ nextchar [char] . = if
+ inc-parse-idx
+
+ delim? false = if
+ bold fg red
+ ." No delimiter following '.'. Aborting." cr
+ reset-term abort
+ then
+
+ eatspaces read
+ else
+ recurse
+ then
+
+ eatspaces
+
+ cons
;
\ Parse a scheme expression
-: read ( -- obj )
+:noname ( -- obj )
eatspaces
exit
then
- empty-list? if
- readnil
+ pair? if
+ readpair
exit
then
nextchar emit
." '. Aborting." reset-term cr
abort
-;
+
+; is read
\ ---- Eval ----
false ;
: eval
- self-evaluating? if
- exit
- then
+ \ self-evaluating? if
+ \ exit
+ \ then
+ exit
bold fg red ." Error evaluating expression - unrecognized type. Aborting." reset-term cr
abort
\ ---- Print ----
-: printnum ( numobj -- ) drop . ;
+: printnum ( numobj -- ) drop 0 .R ;
: printbool ( numobj -- )
drop if
: printnil ( nilobj -- )
drop ." ()" ;
-: print ( obj -- )
- ." ; "
+defer print
+: printpair ( pairobj -- )
+ ." ("
+ 2dup
+ car print
+ cdr
+ nil-type istype? if 2drop ." )" exit then
+ pair-type istype? if recurse ." )" exit then
+ ." . " print ." )"
+;
+
+:noname ( obj -- )
number-type istype? if printnum exit then
boolean-type istype? if printbool exit then
character-type istype? if printchar exit then
nil-type istype? if printnil exit then
-;
+ pair-type istype? if printpair exit then
+
+ bold fg red ." Error printing expression - unrecognized type. Aborting" reset-term cr
+ abort
+; is print
\ ---- REPL ----
cr bold fg green ." > " reset-term
read
eval
- fg cyan print reset-term
+ fg cyan ." ; " print reset-term
again
;