1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Foreign (encode, decode) where
5import Prelude hiding (maybe)
6import qualified Data.List as List
7import qualified Data.Text as Text
10import qualified AST.Expression.Optimized as Opt
11import qualified AST.Literal as Literal
12import qualified AST.Type as T
13import qualified AST.Variable as Var
14import qualified Generate.JavaScript.Builder as JS
15import qualified Generate.JavaScript.Helpers as JS (function, ref)
16import qualified Generate.JavaScript.Variable as Var
17import Generate.JavaScript.Helpers ((<|), (==>))
24encode :: T.Canonical -> JS.Expr
26 JS.function ["v"] [ JS.Return (Just (encodeHelp tipe (JS.ref "v"))) ]
29encodeHelp :: T.Canonical -> JS.Expr -> JS.Expr
33 encodeHelp (T.dealias args t) expr
36 error "encodeHelp: function"
39 error "encodeHelp: type variable"
42 | Var.isPrim "Float" name -> expr
43 | Var.isPrim "Int" name -> expr
44 | Var.isPrim "Bool" name -> expr
45 | Var.isPrim "String" name -> expr
46 | Var.isJson name -> expr
47 | Var.isTuple name -> JS.Null
48 | otherwise -> error "encodeHelp: bad type"
50 T.App (T.Type name) [arg]
51 | Var.isMaybe name -> fromMaybe arg expr
52 | Var.isList name -> fromList arg expr
53 | Var.isArray name -> fromArray arg expr
54 | otherwise -> error "encodeHelp: bad union type"
56 T.App (T.Type name) args
57 | Var.isTuple name -> fromTuple args expr
60 error "encodeHelp: bad union type"
62 T.Record _ (Just _) ->
63 error "encodeHelp: bad record"
65 T.Record fields Nothing ->
68 k ==> encodeHelp t (JS.DotRef expr (JS.Id k))
70 JS.Object (map convert fields)
73fromMaybe :: T.Canonical -> JS.Expr -> JS.Expr
76 (JS.Infix JS.OpStrictEq (JS.DotRef expr (JS.Id "ctor")) (JS.String "Nothing"))
78 (encodeHelp tipe (JS.DotRef expr (JS.Id "_0")))
81fromList :: T.Canonical -> JS.Expr -> JS.Expr
85 Var.coreNative "List" "toArray" <| expr
87 JS.DotRef array (JS.Id "map") <| encode tipe
90fromArray :: T.Canonical -> JS.Expr -> JS.Expr
94 Var.coreNative "Array" "toJSArray" <| expr
96 JS.DotRef array (JS.Id "map") <| encode tipe
99fromTuple :: [T.Canonical] -> JS.Expr -> JS.Expr
100fromTuple types expr =
103 encodeHelp subType $ JS.DotRef expr (JS.Id (Text.pack ('_':show n)))
105 JS.Array (zipWith convert types [ 0 .. length types ])
112decode :: T.Canonical -> Opt.Expr
116 error "functions should not be allowed through input ports"
119 error "type variables should not be allowed through input ports"
121 T.Aliased _ args t ->
122 decode (T.dealias args t)
125 | Var.isPrim "Float" name -> to "float"
126 | Var.isPrim "Int" name -> to "int"
127 | Var.isPrim "Bool" name -> to "bool"
128 | Var.isPrim "String" name -> to "string"
129 | Var.isJson name -> to "value"
130 | Var.isTuple name -> toTuple0
131 | otherwise -> error "decode: bad type"
133 T.App (T.Type name) [arg]
134 | Var.isMaybe name -> toMaybe arg
135 | Var.isList name -> to "list" <== [decode arg]
136 | Var.isArray name -> to "array" <== [decode arg]
137 | otherwise -> error "decode: bad union type"
139 T.App (T.Type name) args
140 | Var.isTuple name -> toTuple args
143 error "decode: bad union type"
145 T.Record _ (Just _) ->
146 error "decode: bad record"
148 T.Record fields Nothing ->
155inJsonDecode :: Text -> Var.Canonical
157 Var.inCore "Json.Decode" name
160to :: Text -> Opt.Expr
162 Opt.Var (inJsonDecode name)
165field :: Text -> Opt.Expr -> Opt.Expr
167 to "field" <== [ Opt.Literal (Literal.Str name), decoder ]
170index :: Int -> Opt.Expr -> Opt.Expr
172 to "index" <== [ Opt.Literal (Literal.IntNum i), decoder ]
175(<==) :: Opt.Expr -> [Opt.Expr] -> Opt.Expr
181-- COMPLEX DECODE HELPERS
184toMaybe :: T.Canonical -> Opt.Expr
188 Opt.Var (Var.inCore "Maybe" tag)
192 [ to "null" <== [ maybe "Nothing" ]
193 , to "map" <== [ maybe "Just", decode tipe ]
200 to "null" <== [ Opt.Ctor "_Tuple0" [] ]
203toTuple :: [T.Canonical] -> Opt.Expr
210 zipWith (,) [ 0 .. size - 1] types
213 Text.pack ('x' : show i)
218 (Text.pack ("_Tuple" ++ show size))
219 (map (Opt.Var . Var.local . toVar . fst) pairs)
222 andThen (i, tipe) decoder =
223 to "andThen" <== [ Opt.Function [toVar i] decoder, index i (decode tipe) ]
225 List.foldr andThen makeTuple pairs
228toRecord :: [(Text, T.Canonical)] -> Opt.Expr
231 toFieldExpr (key, _) =
232 (key, Opt.Var (Var.local key))
235 to "succeed" <== [ Opt.Record (map toFieldExpr fields) ]
237 andThen (key, tipe) decoder =
238 to "andThen" <== [ Opt.Function [key] decoder, field key (decode tipe) ]
240 List.foldr andThen finalDecoder fields
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