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.Helpers as Help
17import qualified AST.Literal as Literal
18import qualified AST.Module.Name as ModuleName
19import qualified AST.Type as T
20import qualified AST.Variable as Var
21import qualified Optimize.DecisionTree as DT
22import qualified Optimize.Environment as Env
29toEncoder :: T.Canonical -> Env.Optimizer Opt.Expr
33 toEncoder (T.dealias args t)
36 error "toEncoder: function"
39 error "toEncoder: type variable"
42 | Var.isPrim "Float" name -> encode "float"
43 | Var.isPrim "Int" name -> encode "int"
44 | Var.isPrim "Bool" name -> encode "bool"
45 | Var.isPrim "String" name -> encode "string"
46 | Var.isJson name -> encode "string"
47 | Var.isTuple name -> encode "null"
48 | otherwise -> error "toEncoder: bad type"
50 T.App (T.Type name) [arg]
51 | Var.isMaybe name -> encodeMaybe arg
52 | Var.isList name -> encodeList arg
53 | Var.isArray name -> encodeArray arg
54 | otherwise -> error "toEncoder: bad union type"
56 T.App (T.Type name) args
57 | Var.isTuple name -> encodeTuple args
60 error "toEncoder: bad union type"
62 T.Record _ (Just _) ->
63 error "toEncoder: bad record"
65 T.Record fields Nothing ->
67 convert (field, typ) =
68 do encoder <- toEncoder typ
71 , Opt.Call encoder [ Opt.Access (Opt.VarLocal "r") field ]
74 do record <- traverse convert fields
75 return $ Opt.Function ["r"] (Opt.Record record)
82encodeMaybe :: T.Canonical -> Env.Optimizer Opt.Expr
84 do null <- encode "null"
85 encoder <- toEncoder tipe
87 let nothing = Var.inCore "Maybe" "Nothing"
88 let test = (DT.Empty, DT.Constructor nothing)
89 let just = Opt.Call encoder [ Opt.CtorAccess (Opt.VarLocal "m") 0 ]
90 let leaf expr = Opt.Leaf (Opt.Inline expr)
92 return $ Opt.Function ["m"] $
93 Opt.Case "m" (Opt.Chain [test] (leaf null) (leaf just)) []
96encodeList :: T.Canonical -> Env.Optimizer Opt.Expr
98 do list <- encode "list"
99 map_ <- core "List" "map"
100 encoder <- toEncoder tipe
102 Opt.Function ["xs"] $
103 Opt.Call list [ Opt.Call map_ [ encoder, Opt.VarLocal "xs" ] ]
106encodeArray :: T.Canonical -> Env.Optimizer Opt.Expr
108 do array <- encode "array"
109 map_ <- core "Array" "map"
110 encoder <- toEncoder tipe
112 Opt.Function ["xs"] $
113 Opt.Call array [ Opt.Call map_ [ encoder, Opt.VarLocal "xs" ] ]
116encodeTuple :: [T.Canonical] -> Env.Optimizer Opt.Expr
120 do encoder <- toEncoder tipe
122 Opt.Call encoder [ Opt.CtorAccess (Opt.VarLocal "t") index ]
124 do list <- encode "list"
125 entries <- zipWithM convert tipes [ 0 .. length tipes ]
126 return $ Opt.Function ["t"] $ Opt.Call list entries
133toDecoder :: T.Canonical -> Env.Optimizer Opt.Expr
137 error "functions should not be allowed through input ports"
140 error "type variables should not be allowed through input ports"
142 T.Aliased _ args t ->
143 toDecoder (T.dealias args t)
146 | Var.isPrim "Float" name -> decode "float"
147 | Var.isPrim "Int" name -> decode "int"
148 | Var.isPrim "Bool" name -> decode "bool"
149 | Var.isPrim "String" name -> decode "string"
150 | Var.isJson name -> decode "value"
151 | Var.isTuple name -> decodeTuple0
152 | otherwise -> error "toDecoder: bad type"
154 T.App (T.Type name) [arg]
155 | Var.isMaybe name -> decodeMaybe arg
156 | Var.isList name -> decodeList arg
157 | Var.isArray name -> decodeArray arg
158 | otherwise -> error "toDecoder: bad union type"
160 T.App (T.Type name) args
161 | Var.isTuple name -> decodeTuple args
164 error "toDecoder: bad union type"
166 T.Record _ (Just _) ->
167 error "toDecoder: bad record"
169 T.Record fields Nothing ->
177decodeMaybe :: T.Canonical -> Env.Optimizer Opt.Expr
179 do let nothing = Var.Global (ModuleName.inCore "Maybe") "Nothing"
180 let just = Var.Global (ModuleName.inCore "Maybe") "Just"
185 oneOf <- decode "oneOf"
186 null <- decode "null"
189 subDecoder <- toDecoder tipe
194 [ Opt.Call null [ Opt.VarGlobal nothing ]
195 , Opt.Call map_ [ Opt.VarGlobal just, subDecoder ]
203decodeList :: T.Canonical -> Env.Optimizer Opt.Expr
205 do list <- decode "list"
206 decoder <- toDecoder tipe
207 return $ Opt.Call list [ decoder ]
214decodeArray :: T.Canonical -> Env.Optimizer Opt.Expr
216 do array <- decode "array"
217 decoder <- toDecoder tipe
218 return $ Opt.Call array [ decoder ]
225decodeTuple0 :: Env.Optimizer Opt.Expr
227 do null <- decode "null"
228 return (Opt.Call null [ Opt.Ctor Help.zeroTuple [] ])
231decodeTuple :: [T.Canonical] -> Env.Optimizer Opt.Expr
238 zip [ 0 .. size - 1] types
242 (Help.makeTuple size)
243 (map (Opt.VarLocal . indexToName . fst) entries)
245 do succeed <- decode "succeed"
246 foldM indexAndThen (Opt.Call succeed [tuple]) entries
249indexToName :: Int -> Text
251 Text.pack ('x' : show index)
254indexAndThen :: Opt.Expr -> (Int, T.Canonical) -> Env.Optimizer Opt.Expr
255indexAndThen decoder (i, tipe) =
256 do andThen <- decode "andThen"
257 index <- decode "index"
258 typeDecoder <- toDecoder tipe
261 [ Opt.Function [indexToName i] decoder
262 , Opt.Call index [ Opt.Literal (Literal.IntNum i), typeDecoder ]
270decodeRecord :: [(Text, T.Canonical)] -> Env.Optimizer Opt.Expr
273 toFieldExpr (key, _) =
274 (key, Opt.VarLocal key)
277 Opt.Record (map toFieldExpr fields)
279 do succeed <- decode "succeed"
280 foldM fieldAndThen (Opt.Call succeed [record]) fields
283fieldAndThen :: Opt.Expr -> (Text, T.Canonical) -> Env.Optimizer Opt.Expr
284fieldAndThen decoder (key, tipe) =
285 do andThen <- decode "andThen"
286 field <- decode "field"
287 typeDecoder <- toDecoder tipe
290 [ Opt.Function [key] decoder
291 , Opt.Call field [ Opt.Literal (Literal.Str key), typeDecoder ]
299core :: Text -> Text -> Env.Optimizer Opt.Expr
301 do let var = Var.Global (ModuleName.inCore home) name
303 return (Opt.VarGlobal var)
306encode :: Text -> Env.Optimizer Opt.Expr
308 core "Json.Encode" name
311decode :: Text -> Env.Optimizer Opt.Expr
313 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