1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
10import Prelude hiding (maybe, null)
11import Control.Monad (foldM, zipWithM)
12import qualified Data.Text as Text
13import Data.Text (Text)
15import qualified AST.Expression.Optimized as Opt
16import qualified AST.Literal as Literal
17import qualified AST.Module.Name as ModuleName
18import qualified AST.Type as T
19import qualified AST.Variable as Var
20import qualified Optimize.DecisionTree as DT
21import qualified Optimize.Environment as Env
28toEncoder :: T.Canonical -> Env.Optimizer Opt.Expr
32 toEncoder (T.dealias args t)
35 error "toEncoder: function"
38 error "toEncoder: type variable"
41 | Var.isPrim "Float" name -> encode "float"
42 | Var.isPrim "Int" name -> encode "int"
43 | Var.isPrim "Bool" name -> encode "bool"
44 | Var.isPrim "String" name -> encode "string"
45 | Var.isJson name -> encode "string"
46 | Var.isTuple name -> encode "null"
47 | otherwise -> error "toEncoder: bad type"
49 T.App (T.Type name) [arg]
50 | Var.isMaybe name -> encodeMaybe arg
51 | Var.isList name -> encodeList arg
52 | Var.isArray name -> encodeArray arg
53 | otherwise -> error "toEncoder: bad union type"
55 T.App (T.Type name) args
56 | Var.isTuple name -> encodeTuple args
59 error "toEncoder: bad union type"
61 T.Record _ (Just _) ->
62 error "toEncoder: bad record"
64 T.Record fields Nothing ->
66 convert (field, typ) =
67 do encoder <- toEncoder typ
70 , Opt.Call encoder [ Opt.Access (Opt.VarLocal "r") field ]
73 do record <- traverse convert fields
74 return $ Opt.Function ["r"] (Opt.Record record)
81encodeMaybe :: T.Canonical -> Env.Optimizer Opt.Expr
83 do null <- encode "null"
84 encoder <- toEncoder tipe
86 let nothing = Var.inCore "Maybe" "Nothing"
87 let test = (DT.Empty, DT.Constructor nothing)
88 let just = Opt.Call encoder [ Opt.CtorAccess (Opt.VarLocal "m") 0 ]
89 let leaf expr = Opt.Leaf (Opt.Inline expr)
91 return $ Opt.Function ["m"] $
92 Opt.Case "m" (Opt.Chain [test] (leaf null) (leaf just)) []
95encodeList :: T.Canonical -> Env.Optimizer Opt.Expr
97 do list <- encode "list"
98 map_ <- core "List" "map"
99 encoder <- toEncoder tipe
101 Opt.Function ["xs"] $
102 Opt.Call list [ Opt.Call map_ [ encoder, Opt.VarLocal "xs" ] ]
105encodeArray :: T.Canonical -> Env.Optimizer Opt.Expr
107 do array <- encode "array"
108 map_ <- core "Array" "map"
109 encoder <- toEncoder tipe
111 Opt.Function ["xs"] $
112 Opt.Call array [ Opt.Call map_ [ encoder, Opt.VarLocal "xs" ] ]
115encodeTuple :: [T.Canonical] -> Env.Optimizer Opt.Expr
119 do encoder <- toEncoder tipe
121 Opt.Call encoder [ Opt.CtorAccess (Opt.VarLocal "t") index ]
123 do list <- encode "list"
124 entries <- zipWithM convert tipes [ 0 .. length tipes ]
125 return $ Opt.Function ["t"] $ Opt.Call list entries
132toDecoder :: T.Canonical -> Env.Optimizer Opt.Expr
136 error "functions should not be allowed through input ports"
139 error "type variables should not be allowed through input ports"
141 T.Aliased _ args t ->
142 toDecoder (T.dealias args t)
145 | Var.isPrim "Float" name -> decode "float"
146 | Var.isPrim "Int" name -> decode "int"
147 | Var.isPrim "Bool" name -> decode "bool"
148 | Var.isPrim "String" name -> decode "string"
149 | Var.isJson name -> decode "value"
150 | Var.isTuple name -> decodeTuple0
151 | otherwise -> error "toDecoder: bad type"
153 T.App (T.Type name) [arg]
154 | Var.isMaybe name -> decodeMaybe arg
155 | Var.isList name -> decodeList arg
156 | Var.isArray name -> decodeArray arg
157 | otherwise -> error "toDecoder: bad union type"
159 T.App (T.Type name) args
160 | Var.isTuple name -> decodeTuple args
163 error "toDecoder: bad union type"
165 T.Record _ (Just _) ->
166 error "toDecoder: bad record"
168 T.Record fields Nothing ->
176decodeMaybe :: T.Canonical -> Env.Optimizer Opt.Expr
178 do let nothing = Var.Global (ModuleName.inCore "Maybe") "Nothing"
179 let just = Var.Global (ModuleName.inCore "Maybe") "Just"
184 oneOf <- decode "oneOf"
185 null <- decode "null"
188 subDecoder <- toDecoder tipe
193 [ Opt.Call null [ Opt.VarGlobal nothing ]
194 , Opt.Call map_ [ Opt.VarGlobal just, subDecoder ]
202decodeList :: T.Canonical -> Env.Optimizer Opt.Expr
204 do list <- decode "list"
205 decoder <- toDecoder tipe
206 return $ Opt.Call list [ decoder ]
213decodeArray :: T.Canonical -> Env.Optimizer Opt.Expr
215 do array <- decode "array"
216 decoder <- toDecoder tipe
217 return $ Opt.Call array [ decoder ]
224decodeTuple0 :: Env.Optimizer Opt.Expr
226 do null <- decode "null"
227 return (Opt.Call null [ Opt.Ctor "_Tuple0" [] ])
230decodeTuple :: [T.Canonical] -> Env.Optimizer Opt.Expr
237 zip [ 0 .. size - 1] types
241 (Text.pack ("_Tuple" ++ show size))
242 (map (Opt.VarLocal . indexToName . fst) entries)
244 do succeed <- decode "succeed"
245 foldM indexAndThen (Opt.Call succeed [tuple]) entries
248indexToName :: Int -> Text
250 Text.pack ('x' : show index)
253indexAndThen :: Opt.Expr -> (Int, T.Canonical) -> Env.Optimizer Opt.Expr
254indexAndThen decoder (i, tipe) =
255 do andThen <- decode "andThen"
256 index <- decode "index"
257 typeDecoder <- toDecoder tipe
260 [ Opt.Function [indexToName i] decoder
261 , Opt.Call index [ Opt.Literal (Literal.IntNum i), typeDecoder ]
269decodeRecord :: [(Text, T.Canonical)] -> Env.Optimizer Opt.Expr
272 toFieldExpr (key, _) =
273 (key, Opt.VarLocal key)
276 Opt.Record (map toFieldExpr fields)
278 do succeed <- decode "succeed"
279 foldM fieldAndThen (Opt.Call succeed [record]) fields
282fieldAndThen :: Opt.Expr -> (Text, T.Canonical) -> Env.Optimizer Opt.Expr
283fieldAndThen decoder (key, tipe) =
284 do andThen <- decode "andThen"
285 field <- decode "field"
286 typeDecoder <- toDecoder tipe
289 [ Opt.Function [key] decoder
290 , Opt.Call field [ Opt.Literal (Literal.Str key), typeDecoder ]
298core :: Text -> Text -> Env.Optimizer Opt.Expr
300 do let var = Var.Global (ModuleName.inCore home) name
302 return (Opt.VarGlobal var)
305encode :: Text -> Env.Optimizer Opt.Expr
307 core "Json.Encode" name
310decode :: Text -> Env.Optimizer Opt.Expr
312 core "Json.Decode" name
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list