Add missing clean targets in 5 impls.
[jackhill/mal.git] / ps / printer.ps
index 956bb18..817bece 100644 (file)
@@ -1,13 +1,10 @@
-(in printer.ps\n) print
-
 % requires types.ps to be included first
 
 % ast print_readably -> _pr_str -> string
 /_pr_str { 4 dict begin
     /print_readably exch def
-    dup
-    /func? exch xcheck def % executable function
-    /obj exch cvlit def
+    dup xcheck { (Cannot print proc: ) print dup == quit } if % assert
+    /obj exch def
     obj _sequential? {
         obj _list? { (\() (\)) }{ ([) (]) } ifelse
         obj /data get ( ) print_readably _pr_str_args
         ( ) print_readably _pr_str_args
         concatenate
         (}) concatenate
-    }{ obj _mal_function? { % if user defined function
+    }{ obj _function? { % if builtin function
+        (<\(builtin_fn* {)
+        obj /data get dup length array copy cvlit
+        ( ) print_readably _pr_str_args
+        (}>)
+        concatenate concatenate
+    }{ obj _mal_function? { % if user defined mal_function
         (<\(fn* )
         obj /params get print_readably _pr_str
         ( )
         concatenate concatenate
     }{ /arraytype obj type eq { % if list or code block
         % accumulate an array of strings
-        func? { (<builtin_fn* { ) }{ (\() } ifelse
+        (\()
         obj ( ) print_readably _pr_str_args
         concatenate
-        func? { ( } >) }{ (\)) } ifelse
+        (\))
         concatenate
     }{ /integertype obj type eq { % if number
-        /slen obj 10 add log ceiling cvi def
+        /slen
+          obj abs 1 max log floor cvi 1 add % positive size
+          obj 0 lt { 1 add } if % account for sign
+        def
         obj 10 slen string cvrs
     }{ /stringtype obj type eq { % if string
-        print_readably {
-            (") obj (") concatenate concatenate
-        }{
-            obj
+        obj length 0 gt { % if string length > 0
+            obj 0 get 127 eq { %if starts with 0x7f (keyword)
+                obj dup length string copy
+                dup 0 58 put % 58 is ':'
+            }{ print_readably {
+                (")
+                obj (\\) (\\\\) replace
+                    (") (\\") replace
+                    (\n) (\\n) replace
+                (") concatenate concatenate
+            }{
+                obj
+            } ifelse } ifelse
+        }{ % else empty string
+            print_readably {
+                ("")
+            }{
+                obj
+            } ifelse
         } ifelse
     }{ null obj eq { % if nil
         (nil)
@@ -57,7 +78,7 @@
         obj dup length string cvs
     }{
         (<unknown>)  
-    } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse
+    } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse } ifelse
 end } def
 
 % array delim print_readably -> _pr_str_args -> new_string
@@ -69,10 +90,26 @@ end } def
     args length 0 gt { %if any elements
         [
             args { %foreach argument in array
-                print_readably _pr_str
+                dup xcheck { %if executable
+                    255 string cvs
+                }{
+                    print_readably _pr_str
+                } ifelse
             } forall 
         ]
         { concatenate delim concatenate } forall
         dup length delim length sub 0 exch getinterval % strip off final delim
     } if
 end } def
+
+% utility function
+/print_dict {
+    (DICT contents:\n) print
+    {
+        (  - ) print
+        exch dup length string cvs print % key
+        (: ) print
+        ==
+    } forall
+} def
+