0 constant number-type
1 constant boolean-type
2 constant character-type
-3 constant nil-type
-4 constant pair-type
+3 constant string-type
+4 constant nil-type
+5 constant pair-type
+6 constant symbol-type
: istype? ( obj -- obj b )
over = ;
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
: pair? ( -- bool )
nextchar [char] ( = ;
+: string? ( -- bool )
+ nextchar [char] " = ;
: readnum ( -- num-atom )
minus? dup if
inc-parse-idx
;
+: readstring ( -- str-obj )
+ nextchar [char] " = if
+ inc-parse-idx
+
+ delim? false = if
+ bold fg red
+ ." No delimiter following right double quote. Aborting." cr
+ reset-term abort
+ then
+
+ dec-parse-idx
+
+ 0 nil-type exit
+ then
+
+ nextchar [char] \ = if
+ inc-parse-idx
+ nextchar case
+ [char] n of '\n' endof
+ [char] " of [char] " endof
+ [char] \
+ endcase
+ else
+ nextchar
+ then
+ inc-parse-idx character-type
+
+ recurse
+
+ cons
+;
+
defer read
: readpair ( -- obj )
- inc-parse-idx
eatspaces
\ Empty lists
reset-term abort
then
- nil-type exit
+ dec-parse-idx
+
+ 0 nil-type exit
then
\ Read first pair element
then
eatspaces read
-
else
recurse
then
+ eatspaces
+
cons
;
\ Parse a scheme expression
-: (read) ( -- obj )
+:noname ( -- obj )
eatspaces
exit
then
+ string? if
+ inc-parse-idx
+ readstring
+ drop string-type
+
+ nextchar [char] " <> if
+ bold red ." Missing closing double-quote." reset-term cr
+ abort
+ then
+
+ inc-parse-idx
+ exit
+ then
+
pair? if
+ inc-parse-idx
+
+ eatspaces
+
readpair
+
+ eatspaces
+
+ nextchar [char] ) <> if
+ bold red ." Missing closing paren." reset-term cr
+ abort
+ then
+
+ inc-parse-idx
+
exit
then
nextchar emit
." '. Aborting." reset-term cr
abort
-;
-' (read) is read
+; is read
\ ---- Eval ----
number-type istype? if true exit then
boolean-type istype? if true exit then
character-type istype? if true exit then
+ string-type istype? if true exit then
nil-type istype? if true exit then
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
endcase
;
+: (printstring) ( stringobj -- )
+ nil-type istype? if 2drop exit then
+
+ 2dup car drop dup
+ case
+ '\n' of ." \n" drop endof
+ [char] \ of ." \\" drop endof
+ [char] " of [char] \ emit [char] " emit drop endof
+ emit
+ endcase
+
+ cdr recurse
+;
+: printstring ( stringobj -- )
+ [char] " emit
+ (printstring)
+ [char] " emit ;
+
: printnil ( nilobj -- )
- drop ." ()" ;
+ 2drop ." ()" ;
+
+defer print
+: printpair ( pairobj -- )
+ 2dup
+ car print
+ cdr
+ nil-type istype? if 2drop exit then
+ pair-type istype? if space recurse exit then
+ ." . " print
+;
-: print ( obj -- )
- ." ; "
+:noname ( obj -- )
number-type istype? if printnum exit then
boolean-type istype? if printbool exit then
character-type istype? if printchar exit then
+ string-type istype? if printstring 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
;