\ ------ Types ------
-0 constant number-type
+0 constant fixnum-type
1 constant boolean-type
2 constant character-type
3 constant string-type
4 constant nil-type
5 constant pair-type
6 constant symbol-type
-7 constant primitive-type
+7 constant primitive-proc-type
+8 constant compound-proc-type
: istype? ( obj type -- obj bool )
over = ;
objvar symbol-table
+: duplicate-charlist ( charlist -- copy )
+ 2dup nil objeq? false = if
+ 2dup car 2swap cdr recurse cons
+ then ;
+
+: charlist-equiv ( charlist charlist -- bool )
+
+ 2over 2over
+
+ \ One or both nil
+ nil? -rot 2drop
+ if
+ nil? -rot 2drop
+ if
+ 2drop 2drop true exit
+ else
+ 2drop 2drop false exit
+ then
+ else
+ nil? -rot 2drop
+ if
+ 2drop 2drop false exit
+ then
+ then
+
+ 2over 2over
+
+ \ Neither nil
+ car drop -rot car drop = if
+ cdr 2swap cdr recurse
+ else
+ 2drop 2drop false
+ then
+;
+
+: charlist>symbol ( charlist -- symbol-obj )
+
+ symbol-table fetchobj
+
+ begin
+ nil? false =
+ while
+ 2over 2over
+ car drop pair-type
+ charlist-equiv if
+ 2swap 2drop
+ car
+ exit
+ else
+ cdr
+ then
+ repeat
+
+ 2drop
+ drop symbol-type 2dup
+ symbol-table fetchobj cons
+ symbol-table setobj
+;
+
+
: (create-symbol) ( addr n -- symbol-obj )
dup 0= if
2drop nil
create-symbol set! set!-symbol
create-symbol ok ok-symbol
create-symbol if if-symbol
+create-symbol lambda lambda-symbol
\ }}}
cons
symbol-table setobj
- rot primitive-type ( var prim )
+ rot primitive-proc-type ( var prim )
global-env fetchobj define-var
;
-: add-prim ( args -- )
- nil objeq? if
- 0 number-type
+: arg-count-error
+ bold fg red ." Incorrect argument count." reset-term cr
+ abort
+;
+
+: ensure-arg-count ( args n -- )
+ dup 0= if
+ drop nil objeq? false = if
+ arg-count-error
+ then
else
- 2dup cdr recurse drop
- -rot car drop
- + number-type
+ -rot 2dup nil objeq? if
+ arg-count-error
+ then
+
+ cdr rot 1- recurse
then
;
-' add-prim make-primitive +
+: arg-type-error
+ bold fg red ." Incorrect argument type." reset-term cr
+ abort
+;
+
+: ensure-arg-type ( arg type -- arg )
+ istype? false = if
+ arg-type-error
+ then
+;
+
+include scheme-primitives.4th
\ }}}
nextchar [char] ) = or
;
+: commentstart? ( -- bool )
+ nextchar [char] ; = ;
+
: eatspaces
+
+ false \ Indicates whether or not we're eating a comment
+
begin
- whitespace?
+ dup whitespace? or commentstart? or
while
+ dup nextchar '\n' = and if
+ invert \ Stop eating comment
+ else
+ dup false = commentstart? and if
+ invert \ Begin eating comment
+ then
+ then
+
inc-parse-idx
repeat
+ drop
;
: digit? ( -- bool )
: minus? ( -- bool )
nextchar [char] - = ;
-: number? ( -- bool )
- digit? minus? or false = if
- false
- exit
+: plus? ( -- bool )
+ nextchar [char] + = ;
+
+: fixnum? ( -- bool )
+ minus? plus? or if
+ inc-parse-idx
+
+ delim? if
+ dec-parse-idx
+ false exit
+ else
+ dec-parse-idx
+ then
+ else
+ digit? false = if
+ false exit
+ then
then
push-parse-idx
nextchar [char] " = ;
: readnum ( -- num-atom )
- minus? dup if
+ plus? minus? or if
+ minus?
inc-parse-idx
+ else
+ false
then
0
swap if negate then
- number-type
+ fixnum-type
;
: readbool ( -- bool-atom )
cons
;
-: charlist-equiv ( charlist charlist -- bool )
-
- 2over 2over
-
- \ One or both nil
- nil? -rot 2drop
- if
- nil? -rot 2drop
- if
- 2drop 2drop true exit
- else
- 2drop 2drop false exit
- then
- else
- nil? -rot 2drop
- if
- 2drop 2drop false exit
- then
- then
-
- 2over 2over
-
- \ Neither nil
- car drop -rot car drop = if
- cdr 2swap cdr recurse
- else
- 2drop 2drop false
- then
-;
-
-: charlist>symbol ( charlist -- symbol-obj )
-
- symbol-table fetchobj
-
- begin
- nil? false =
- while
- 2over 2over
- car drop pair-type
- charlist-equiv if
- 2swap 2drop
- car
- exit
- else
- cdr
- then
- repeat
-
- 2drop
- drop symbol-type 2dup
- symbol-table fetchobj cons
- symbol-table setobj
-;
-
: readpair ( -- pairobj )
eatspaces
eatspaces
- number? if
+ fixnum? if
readnum
exit
then
then
eof? if
+ inc-parse-idx
bold fg blue ." Moriturus te saluto." reset-term ." ok" cr
quit
then
: self-evaluating? ( obj -- obj bool )
boolean-type istype? if true exit then
- number-type istype? if true exit then
+ fixnum-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
: true? ( boolobj -- bool )
false? invert ;
-: applicaion? ( obj -- obj bool)
+: application? ( obj -- obj bool)
pair-type istype? ;
: operator ( obj -- operator )
then
;
+: apply ( proc args )
+ 2swap dup case
+ primitive-proc-type of
+ drop execute
+ endof
+
+ compound-proc-type of
+ ." Compound procedures not yet implemented."
+ endof
+
+ bold fg red ." Object not applicable. Aboring." reset-term cr
+ abort
+ endcase
+;
+
:noname ( obj env -- result )
2swap
application? if
2over 2over
operator 2swap eval
-
- primitive-type istype? false = if
- bold fg red ." Object not applicable. Aboring." reset-term cr
- abort
- then
-
-2rot
operands 2swap list-of-vals
- 2swap drop execute
+ apply
exit
then
2drop ." <primitive procedure>" ;
:noname ( obj -- )
- number-type istype? if printnum exit then
+ fixnum-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
symbol-type istype? if printsymbol exit then
nil-type istype? if printnil exit then
pair-type istype? if ." (" printpair ." )" exit then
- primitive-type istype? if printprim exit then
+ primitive-proc-type istype? if printprim exit then
bold fg red ." Error printing expression - unrecognized type. Aborting" reset-term cr
abort