Merge pull request #377 from asarhaddon/fix-runtests-pre-eval
[jackhill/mal.git] / elm / Printer.elm
1 module Printer exposing (..)
2
3 import Array exposing (Array)
4 import Dict exposing (Dict)
5 import Types exposing (Env, MalExpr(..), keywordPrefix, MalFunction(..))
6 import Utils exposing (encodeString, wrap)
7 import Env
8
9
10 printStr : Bool -> MalExpr -> String
11 printStr =
12 printString Env.global
13
14
15 printString : Env -> Bool -> MalExpr -> String
16 printString env readably ast =
17 case ast of
18 MalNil ->
19 "nil"
20
21 MalBool True ->
22 "true"
23
24 MalBool False ->
25 "false"
26
27 MalInt int ->
28 toString int
29
30 MalString str ->
31 printRawString env readably str
32
33 MalSymbol sym ->
34 sym
35
36 MalKeyword kw ->
37 kw
38
39 MalList list ->
40 printList env readably list
41
42 MalVector vec ->
43 printVector env readably vec
44
45 MalMap map ->
46 printMap env readably map
47
48 MalFunction _ ->
49 "#<function>"
50
51 MalAtom atomId ->
52 let
53 value =
54 Env.getAtom atomId env
55 in
56 "(atom " ++ (printString env True value) ++ ")"
57
58 MalApply _ ->
59 "#<apply>"
60
61
62 printBound : Env -> Bool -> List ( String, MalExpr ) -> String
63 printBound env readably =
64 let
65 printEntry name value =
66 name ++ "=" ++ (printString env readably value)
67 in
68 List.map (uncurry printEntry)
69 >> String.join " "
70 >> wrap "(" ")"
71
72
73 printRawString : Env -> Bool -> String -> String
74 printRawString env readably str =
75 if readably then
76 encodeString str
77 else
78 str
79
80
81 printList : Env -> Bool -> List MalExpr -> String
82 printList env readably =
83 List.map (printString env readably)
84 >> String.join " "
85 >> wrap "(" ")"
86
87
88 printVector : Env -> Bool -> Array MalExpr -> String
89 printVector env readably =
90 Array.map (printString env readably)
91 >> Array.toList
92 >> String.join " "
93 >> wrap "[" "]"
94
95
96 printMap : Env -> Bool -> Dict String MalExpr -> String
97 printMap env readably =
98 let
99 -- Strip off the keyword prefix if it is there.
100 printKey k =
101 case String.uncons k of
102 Just ( prefix, rest ) ->
103 if prefix == keywordPrefix then
104 rest
105 else
106 printRawString env readably k
107
108 _ ->
109 printRawString env readably k
110
111 printEntry ( k, v ) =
112 (printKey k) ++ " " ++ (printString env readably v)
113 in
114 Dict.toList
115 >> List.map printEntry
116 >> String.join " "
117 >> wrap "{" "}"
118
119
120 printEnv : Env -> String
121 printEnv env =
122 let
123 printOuterId =
124 Maybe.map toString >> Maybe.withDefault "nil"
125
126 printHeader frameId { outerId, exitId, refCnt } =
127 "#"
128 ++ (toString frameId)
129 ++ " outer="
130 ++ printOuterId outerId
131 ++ " exit="
132 ++ printOuterId exitId
133 ++ " refCnt="
134 ++ (toString refCnt)
135
136 printFrame frameId frame =
137 String.join "\n"
138 ((printHeader frameId frame)
139 :: (Dict.foldr printDatum [] frame.data)
140 )
141
142 printFrameAcc k v acc =
143 printFrame k v :: acc
144
145 printDatum k v acc =
146 (k ++ " = " ++ (printString env False v)) :: acc
147 in
148 "--- Environment ---\n"
149 ++ "Current frame: #"
150 ++ (toString env.currentFrameId)
151 ++ "\n\n"
152 ++ String.join "\n\n" (Dict.foldr printFrameAcc [] env.frames)