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.Module.Name as ModuleName
13import qualified AST.Type as T
14import qualified AST.Variable as Var
15import qualified Generate.JavaScript.Builder as JS
16import qualified Generate.JavaScript.Helpers as JS (function, ref)
17import qualified Generate.JavaScript.Variable as Var
18import Generate.JavaScript.Helpers ((<|), (==>))
25encode :: T.Canonical -> JS.Expr
27 JS.function ["v"] [ JS.Return (Just (encodeHelp tipe (JS.ref "v"))) ]
30encodeHelp :: T.Canonical -> JS.Expr -> JS.Expr
34 encodeHelp (T.dealias args t) expr
37 error "encodeHelp: function"
40 error "encodeHelp: type variable"
43 | Var.isPrim "Float" name -> expr
44 | Var.isPrim "Int" name -> expr
45 | Var.isPrim "Bool" name -> expr
46 | Var.isPrim "String" name -> expr
47 | Var.isJson name -> expr
48 | Var.isTuple name -> JS.Null
49 | otherwise -> error "encodeHelp: bad type"
51 T.App (T.Type name) [arg]
52 | Var.isMaybe name -> fromMaybe arg expr
53 | Var.isList name -> fromList arg expr
54 | Var.isArray name -> fromArray arg expr
55 | otherwise -> error "encodeHelp: bad union type"
57 T.App (T.Type name) args
58 | Var.isTuple name -> fromTuple args expr
61 error "encodeHelp: bad union type"
63 T.Record _ (Just _) ->
64 error "encodeHelp: bad record"
66 T.Record fields Nothing ->
69 k ==> encodeHelp t (JS.DotRef expr (JS.Id k))
71 JS.Object (map convert fields)
74fromMaybe :: T.Canonical -> JS.Expr -> JS.Expr
77 (JS.Infix JS.OpStrictEq (JS.DotRef expr (JS.Id "ctor")) (JS.String "Nothing"))
79 (encodeHelp tipe (JS.DotRef expr (JS.Id "_0")))
82fromList :: T.Canonical -> JS.Expr -> JS.Expr
86 Var.coreNative "List" "toArray" <| expr
88 JS.DotRef array (JS.Id "map") <| encode tipe
91fromArray :: T.Canonical -> JS.Expr -> JS.Expr
95 Var.coreNative "Array" "toJSArray" <| expr
97 JS.DotRef array (JS.Id "map") <| encode tipe
100fromTuple :: [T.Canonical] -> JS.Expr -> JS.Expr
101fromTuple types expr =
104 encodeHelp subType $ JS.DotRef expr (JS.Id (Text.pack ('_':show n)))
106 JS.Array (zipWith convert types [ 0 .. length types ])
113decode :: T.Canonical -> Opt.Expr
117 error "functions should not be allowed through input ports"
120 error "type variables should not be allowed through input ports"
122 T.Aliased _ args t ->
123 decode (T.dealias args t)
126 | Var.isPrim "Float" name -> to "float"
127 | Var.isPrim "Int" name -> to "int"
128 | Var.isPrim "Bool" name -> to "bool"
129 | Var.isPrim "String" name -> to "string"
130 | Var.isJson name -> to "value"
131 | Var.isTuple name -> toTuple0
132 | otherwise -> error "decode: bad type"
134 T.App (T.Type name) [arg]
135 | Var.isMaybe name -> toMaybe arg
136 | Var.isList name -> to "list" <== [decode arg]
137 | Var.isArray name -> to "array" <== [decode arg]
138 | otherwise -> error "decode: bad union type"
140 T.App (T.Type name) args
141 | Var.isTuple name -> toTuple args
144 error "decode: bad union type"
146 T.Record _ (Just _) ->
147 error "decode: bad record"
149 T.Record fields Nothing ->
156to :: Text -> Opt.Expr
158 Opt.VarGlobal jsonDecode name
161jsonDecode :: ModuleName.Canonical
163 ModuleName.inCore "Json.Decode"
166field :: Text -> Opt.Expr -> Opt.Expr
168 to "field" <== [ Opt.Literal (Literal.Str name), decoder ]
171index :: Int -> Opt.Expr -> Opt.Expr
173 to "index" <== [ Opt.Literal (Literal.IntNum i), decoder ]
176(<==) :: Opt.Expr -> [Opt.Expr] -> Opt.Expr
182-- COMPLEX DECODE HELPERS
185toMaybe :: T.Canonical -> Opt.Expr
189 Opt.VarGlobal (ModuleName.inCore "Maybe") tag
193 [ to "null" <== [ maybe "Nothing" ]
194 , to "map" <== [ maybe "Just", decode tipe ]
201 to "null" <== [ Opt.Ctor "_Tuple0" [] ]
204toTuple :: [T.Canonical] -> Opt.Expr
211 zipWith (,) [ 0 .. size - 1] types
214 Text.pack ('x' : show i)
219 (Text.pack ("_Tuple" ++ show size))
220 (map (Opt.VarLocal . toVar . fst) pairs)
223 andThen (i, tipe) decoder =
224 to "andThen" <== [ Opt.Function [toVar i] decoder, index i (decode tipe) ]
226 List.foldr andThen makeTuple pairs
229toRecord :: [(Text, T.Canonical)] -> Opt.Expr
232 toFieldExpr (key, _) =
233 (key, Opt.VarLocal key)
236 to "succeed" <== [ Opt.Record (map toFieldExpr fields) ]
238 andThen (key, tipe) decoder =
239 to "andThen" <== [ Opt.Function [key] decoder, field key (decode tipe) ]
241 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