Completed draft of primitive application.
[scheme.forth.jl.git] / scheme.4th
index d075e81..fa53d67 100644 (file)
@@ -13,6 +13,7 @@ include defer-is.4th
 4 constant nil-type
 5 constant pair-type
 6 constant symbol-type
+7 constant primitive-type
 : istype? ( obj type -- obj bool )
     over = ;
 
@@ -82,6 +83,20 @@ variable nextfree
 : objeq? ( obj obj -- bool )
     rot = -rot = and ;
 
+: 2rot ( a1 a2 b1 b2 c1 c2 -- b1 b2 c1 c2 a1 a2 )
+    >R >R ( a1 a2 b1 b2 )
+    2swap ( b1 b2 a1 a2 )
+    R> R> ( b1 b2 a1 a2 c1 c2 )
+    2swap
+;
+
+: -2rot ( a1 a2 b1 b2 c1 c2 -- c1 c2 a1 a2 b1 b2 )
+    2swap ( a1 a2 c1 c2 b1 b2 )
+    >R >R ( a1 a2 c1 c2 )
+    2swap ( c1 c2 a1 a2 )
+    R> R>
+;
+
 \ }}}
 
 \ ---- Pre-defined symbols ---- {{{
@@ -121,13 +136,12 @@ 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
 
 \ }}}
 
 \ ---- Environments ---- {{{
 
-objvar global-env
-
 : enclosing-env ( env -- env )
     cdr ;
 
@@ -145,9 +159,9 @@ objvar global-env
 
 : add-binding ( var val frame -- )
     2swap 2over frame-vals cons
-    2over set-car!
+    2over set-cdr!
     2swap 2over frame-vars cons
-    swap set-cdr!
+    2swap set-car!
 ;
 
 : extend-env ( vars vals env -- env )
@@ -205,7 +219,7 @@ hide vals
     get-vars-vals if
         2swap 2drop car
     else
-        bold fg red ." Tried to read unbound variable." reset-term abort
+        bold fg red ." Tried to read unbound variable." reset-term cr abort
     then
 ;
 
@@ -215,7 +229,7 @@ hide vals
         2swap 2drop ( val vals )
         set-car!
     else
-        bold fg red ." Tried to set unbound variable." reset-term abort
+        bold fg red ." Tried to set unbound variable." reset-term cr abort
     then
 ;
 
@@ -238,10 +252,49 @@ objvar env
 
 hide env
 
+objvar global-env
+nil nil nil extend-env
+global-env setobj
+
+\ }}}
+
+\ ---- Primitives ---- {{{
+
+: make-primitive ( cfa -- )
+    bl word
+    count
+
+    (create-symbol)
+    drop symbol-type
+    
+    2dup
+
+    symbol-table fetchobj
+    cons
+    symbol-table setobj
+
+    rot primitive-type ( var prim )
+    global-env fetchobj define-var
+;
+
+: add-prim ( args -- )
+    nil objeq? if
+        0 number-type
+    else
+        2dup cdr recurse drop
+        -rot car drop
+        + number-type
+    then
+;
+
+' add-prim make-primitive +
+
 \ }}}
 
 \ ---- Read ---- {{{
 
+defer read
+
 variable parse-idx
 variable stored-parse-idx
 create parse-str 161 allot
@@ -549,8 +602,6 @@ parse-idx-stack parse-idx-sp !
     symbol-table setobj
 ;
 
-defer read
-
 : readpair ( -- pairobj )
     eatspaces
 
@@ -667,6 +718,8 @@ defer read
 
 \ ---- Eval ---- {{{
 
+defer eval
+
 : self-evaluating? ( obj -- obj bool )
     boolean-type istype? if true exit then
     number-type istype? if true exit then
@@ -712,8 +765,6 @@ defer read
 : assignment-val ( obj -- val )
     cdr cdr car ;
 
-defer eval
-
 : eval-definition ( obj env -- res )
     2swap 
     2over 2over ( env obj env obj )
@@ -722,7 +773,7 @@ defer eval
     
     2swap definition-var 2swap ( env var val )
 
-    >R >R 2swap R> R> 2swap ( var val env )
+    2rot ( var val env )
     define-var
 
     ok-symbol
@@ -736,12 +787,70 @@ defer eval
     
     2swap assignment-var 2swap ( env var val )
 
-    >R >R 2swap R> R> 2swap ( var val env )
+    2rot ( var val env )
     set-var
 
     ok-symbol
 ;
 
+: if? ( obj -- obj bool )
+    if-symbol tagged-list? ;
+
+: if-predicate ( ifobj -- pred )
+    cdr car ;
+
+: if-consequent ( ifobj -- conseq )
+    cdr cdr car ;
+
+: if-alternative ( ifobj -- alt|false )
+    cdr cdr cdr
+    2dup nil objeq? if
+        2drop false
+    else
+        car
+    then ;
+
+: false? ( boolobj -- boolean )
+    boolean-type istype? if
+        false boolean-type objeq?
+    else
+        2drop false
+    then
+;
+
+: true? ( boolobj -- bool )
+    false? invert ;
+
+: applicaion? ( obj -- obj bool)
+    pair-type istype? ;
+
+: operator ( obj -- operator )
+    car ;
+
+: operands ( obj -- operands )
+    cdr ;
+
+: nooperands? ( operands -- bool )
+    nil objeq? ;
+
+: first-operand ( operands -- operand )
+    car ;
+
+: rest-operands ( operands -- other-operands )
+    cdr ;
+
+: list-of-vals ( args env -- vals )
+    2swap
+
+    2dup nooperands? if
+        2swap 2drop
+    else
+        2over 2over first-operand 2swap eval
+        -2rot rest-operands 2swap recurse
+        cons
+    then
+;
+
 :noname ( obj env -- result )
     2swap
 
@@ -771,6 +880,36 @@ defer eval
         exit
     then
 
+    if? if
+        2over 2over
+        if-predicate
+        2swap eval 
+
+        true? if
+            if-consequent
+        else
+            if-alternative
+        then
+
+        2swap ['] eval goto
+    then
+
+    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
+        exit
+    then
+
     bold fg red ." Error evaluating expression - unrecognized type. Aborting." reset-term cr
     abort
 ; is eval
@@ -779,6 +918,8 @@ defer eval
 
 \ ---- Print ---- {{{
 
+defer print
+
 : printnum ( numobj -- ) drop 0 .R ;
 
 : printbool ( numobj -- )
@@ -828,7 +969,6 @@ defer eval
 : printnil ( nilobj -- )
     2drop ." ()" ;
 
-defer print
 : printpair ( pairobj -- )
     2dup
     car print
@@ -838,6 +978,9 @@ defer print
     ."  . " print
 ;
 
+: printprim ( primobj -- )
+    2drop ." <primitive procedure>" ;
+
 :noname ( obj -- )
     number-type istype? if printnum exit then
     boolean-type istype? if printbool exit then
@@ -846,6 +989,7 @@ defer print
     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
 
     bold fg red ." Error printing expression - unrecognized type. Aborting" reset-term cr
     abort
@@ -870,3 +1014,5 @@ defer print
 ;
 
 forth definitions
+
+\ vim:fdm=marker