| 1 | module Printer |
| 2 | open System.Text |
| 3 | open Reader |
| 4 | open Types |
| 5 | |
| 6 | let pr_str data = |
| 7 | let acc = StringBuilder() |
| 8 | let appendStr (str : string) = acc.Append(str) |> ignore |
| 9 | let rec pr_node = function |
| 10 | | Nil -> appendStr "nil" |
| 11 | | List(nodes) -> pr_list nodes |
| 12 | | Vector(nodes) -> pr_vector nodes |
| 13 | | Map(map) -> pr_map map |
| 14 | | Symbol(symbol) -> appendStr symbol |
| 15 | | Keyword(keyword) -> appendStr ":"; appendStr keyword |
| 16 | | Number(num) -> acc.Append(num) |> ignore |
| 17 | | String(str) -> pr_str str |
| 18 | | Bool(true) -> appendStr "true" |
| 19 | | Bool(false) -> appendStr "false" |
| 20 | | Func({ Tag = tag; F = _}) -> pr_func tag |
| 21 | |
| 22 | and pr prefix node = |
| 23 | appendStr prefix |
| 24 | pr_node node |
| 25 | " " |
| 26 | |
| 27 | and pr_str str = |
| 28 | let appendChar = function |
| 29 | | '\t' -> appendStr "\\t" |
| 30 | | '\b' -> appendStr "\\b" |
| 31 | | '\n' -> appendStr "\\n" |
| 32 | | '\r' -> appendStr "\\r" |
| 33 | | '\f' -> appendStr "\\f" |
| 34 | | '\'' -> appendStr "\\'" |
| 35 | | '"' -> appendStr "\\\"" |
| 36 | | '\\' -> appendStr "\\\\" |
| 37 | | ch -> acc.Append(ch) |> ignore |
| 38 | appendStr "\"" |
| 39 | str |> Seq.iter appendChar |
| 40 | appendStr "\"" |
| 41 | |
| 42 | and pr_func tag = |
| 43 | sprintf "#<func %d>" tag |> appendStr |
| 44 | |
| 45 | and pr_list nodes = |
| 46 | appendStr "(" |
| 47 | nodes |> List.fold pr "" |> ignore |
| 48 | appendStr ")" |
| 49 | |
| 50 | and pr_vector nodes = |
| 51 | appendStr "[" |
| 52 | nodes |> Seq.fold pr "" |> ignore |
| 53 | appendStr "]" |
| 54 | |
| 55 | and pr_map map = |
| 56 | let pr prefix key value = |
| 57 | appendStr prefix |
| 58 | pr_node key |
| 59 | appendStr " " |
| 60 | pr_node value |
| 61 | " " |
| 62 | appendStr "{" |
| 63 | map |> Map.fold pr "" |> ignore |
| 64 | appendStr "}" |
| 65 | |
| 66 | pr_node data |
| 67 | acc.ToString() |