fsharp: step5: Added tail call optimization.
[jackhill/mal.git] / fsharp / printer.fs
CommitLineData
ed3a12f5
PS
1module Printer
2 open System.Text
ed3a12f5
PS
3 open Types
4
6a4627fb
PS
5 type Profile = { Pretty : bool; Separator : string }
6 let pr_str_profile = { Pretty = true; Separator = " " }
7 let str_profile = { Pretty = false; Separator = "" }
8 let prn_profile = { Pretty = true; Separator = " " }
9 let println_profile = { Pretty = false; Separator = " " }
10
11 let print profile nodes =
ed3a12f5 12 let acc = StringBuilder()
327bd967 13 let appendStr (str : string) = acc.Append(str) |> ignore
ed3a12f5 14 let rec pr_node = function
327bd967
PS
15 | Nil -> appendStr "nil"
16 | List(nodes) -> pr_list nodes
17 | Vector(nodes) -> pr_vector nodes
6dcc04db 18 | Map(map) -> pr_map map
327bd967
PS
19 | Symbol(symbol) -> appendStr symbol
20 | Keyword(keyword) -> appendStr ":"; appendStr keyword
ed3a12f5 21 | Number(num) -> acc.Append(num) |> ignore
6a4627fb
PS
22 | String(str) when profile.Pretty -> pr_str_pretty str
23 | String(str) -> appendStr str
327bd967
PS
24 | Bool(true) -> appendStr "true"
25 | Bool(false) -> appendStr "false"
8862f80e 26 | Func(tag, _, _, _, _) -> pr_func tag
ed3a12f5 27
6a4627fb 28 and pr separator prefix node =
327bd967
PS
29 appendStr prefix
30 pr_node node
6a4627fb 31 separator
3b82891f 32
6a4627fb
PS
33 and std_pr = pr " "
34
35 and pr_str_pretty str =
327bd967
PS
36 let appendChar = function
37 | '\t' -> appendStr "\\t"
38 | '\b' -> appendStr "\\b"
39 | '\n' -> appendStr "\\n"
40 | '\r' -> appendStr "\\r"
41 | '\f' -> appendStr "\\f"
42 | '\'' -> appendStr "\\'"
43 | '"' -> appendStr "\\\""
44 | '\\' -> appendStr "\\\\"
45 | ch -> acc.Append(ch) |> ignore
46 appendStr "\""
47 str |> Seq.iter appendChar
48 appendStr "\""
49
a836d8f3
PS
50 and pr_func tag =
51 sprintf "#<func %d>" tag |> appendStr
8f1ee487 52
327bd967
PS
53 and pr_list nodes =
54 appendStr "("
6a4627fb 55 nodes |> List.fold std_pr "" |> ignore
327bd967
PS
56 appendStr ")"
57
58 and pr_vector nodes =
59 appendStr "["
6a4627fb 60 nodes |> Seq.fold std_pr "" |> ignore
327bd967 61 appendStr "]"
6dcc04db
PS
62
63 and pr_map map =
327bd967
PS
64 let pr prefix key value =
65 appendStr prefix
6dcc04db 66 pr_node key
327bd967 67 appendStr " "
6dcc04db
PS
68 pr_node value
69 " "
327bd967
PS
70 appendStr "{"
71 map |> Map.fold pr "" |> ignore
72 appendStr "}"
ed3a12f5 73
6a4627fb 74 nodes |> Seq.fold (pr profile.Separator) "" |> ignore
ed3a12f5 75 acc.ToString()
6a4627fb
PS
76
77 let pr_str : seq<Node> -> string = print pr_str_profile
78 let str : seq<Node> -> string = print str_profile
79 let prn : seq<Node> -> string = print prn_profile
80 let println : seq<Node> -> string = print println_profile