OCaml: put macro flag in metadata rather than special type field
[jackhill/mal.git] / ps / step2_eval.ps
index 72a91fa..215fc2e 100644 (file)
@@ -1,7 +1,11 @@
-(types.ps) run
-(reader.ps) run
+/runlibfile where { pop }{ /runlibfile { run } def } ifelse % 
+(types.ps) runlibfile
+(reader.ps) runlibfile
+(printer.ps) runlibfile
 
 % read
+/_readline { print flush (%stdin) (r) file 99 string readline } def
+
 /READ {
     /str exch def
     str read_str
     /env exch def
     /ast exch def
     %(eval_ast: ) print ast ==
-    /nametype ast type eq { %if symbol
-        env ast get
-    }{ /arraytype ast type eq { %elseif list
+    ast _symbol? { %if symbol
+        env ast known {
+            env ast get
+        }{
+            (') ast false _pr_str (' not found)
+            concatenate concatenate _throw
+        } ifelse
+    }{ ast _sequential? { %elseif list or vector
         [
-            ast {
+            ast /data get { %forall items
+                env EVAL
+            } forall
+        ] ast _list? { _list_from_array }{ _vector_from_array } ifelse
+    }{ ast _hash_map? { %elseif list or vector
+        <<
+            ast /data get { %forall entries
                 env EVAL
             } forall
-        ]
+        >> _hash_map_from_dict
     }{ % else
         ast
-    } ifelse } ifelse
+    } ifelse } ifelse } ifelse
 end } def
 
 /EVAL { 3 dict begin
     /env exch def
     /ast exch def
-    %(EVAL: ) print ast ==
-    /arraytype ast type ne { %if not a list
+
+    %(EVAL: ) print ast true _pr_str print (\n) print
+    ast _list? not { %if not a list
         ast env eval_ast
     }{ %else apply the list
         /el ast env eval_ast def
-        el _rest % args array
-        el _first % function
-        %(vvv\n) print pstack (^^^\n) print
+        el _rest el _first % stack: ast function
         exec % apply function to args
     } ifelse
 end } def
@@ -44,34 +58,35 @@ end } def
 
 % print
 /PRINT {
-    /exp exch def
-    %(printing: ) print exp ==
-    exp pr_str
+    true _pr_str
 } def
 
 
 % repl
 /repl_env <<
-    (+) { dup 0 get exch 1 get add }
-    (-) { dup 0 get exch 1 get sub }
-    (*) { dup 0 get exch 1 get mul }
-    (/) { dup 0 get exch 1 get idiv }
+    (+) { dup 0 _nth exch 1 _nth add }
+    (-) { dup 0 _nth exch 1 _nth sub }
+    (*) { dup 0 _nth exch 1 _nth mul }
+    (/) { dup 0 _nth exch 1 _nth idiv }
 >> def
 
 /REP { READ repl_env EVAL PRINT } def
 
-/stdin (%stdin) (r) file def 
-
-{ % loop
-    (user> ) print flush
-
-    %(%lineedit) (r) file 99 string readline
-    stdin 99 string readline
-
+% repl loop
+{ %loop
+    (user> ) _readline
     not { exit } if  % exit if EOF
 
-    %(\ngot line: ) print dup print (\n) print flush
-    REP print (\n) print
+    { %try
+        REP print (\n) print
+    } stopped {
+        (Error: ) print
+        get_error_data false _pr_str print (\n) print
+        $error /newerror false put
+        $error /errorinfo null put
+        clear
+        cleardictstack
+    } if
 } bind loop
 
 (\n) print  % final newline before exit for cleanliness