module Elm.Decoder ( decoder , listDecoder ) where import Elm.Helpers import Elm.Types elmDecoder :: Expr -> String elmDecoder (Primitive t) = case t of String -> "Json.Decode.string" Int -> "Json.Decode.int" Float -> "Json.Decode.float" Date -> "Json.Decode.Extra.date" Bool -> "Json.Decode.bool" p -> error $ "No decoder for Primitive known: " ++ show p elmDecoder (Field f) = elmDecoder f elmDecoder (DataType name _) = "decode" ++ name elmDecoder (Product (Primitive List) (Primitive Char)) = elmDecoder $ Primitive String elmDecoder (Product (Primitive List) t) = "Json.Decode.list " ++ if isProduct t then "(" ++ elmDecoder t ++ ")" else elmDecoder t elmDecoder (Product (Primitive Maybe) t) = "Json.Decode.maybe " ++ if isProduct t then "(" ++ elmDecoder t ++ ")" else elmDecoder t elmDecoder d = error $ "No decoder for definition known: " ++ show d decoderFunction :: String -> String decoderFunction = (++) "decode" decoder :: Expr -> String decoder (DataType name (Record _ expr)) = format [ func ++ " : Json.Decode.Decoder " ++ name , func ++ " =" , tab 4 "Json.Decode.succeed " ++ name , format $ map (tab 8) $ build expr ] where func = decoderFunction name build (Product s1 s2) = build s1 ++ build s2 build (Selector _ selector t) = [ concat $ surround "|: (" " := " ")" [ show selector , elmDecoder t ] ] build d = error $ "Unsupported Record decoder Selector definition: " ++ show d decoder (DataType name s) = format [ func ++ " : Json.Decode.Decoder " ++ name , func ++ " =" , tab 4 "let" , tab 8 "resolver c = case c of" , format $ map (tab 12 . toCase) $ flatten s , tab 12 "_ -> Json.Decode.fail (\"Unable to resolve \" ++ c ++ \" to a " ++ name ++ "\")" , tab 4 "in" , tab 8 $ elmDecoder (Primitive String) ++ " `Json.Decode.andThen` resolver" ] where func = decoderFunction name flatten (Sum a b) = flatten a ++ flatten b flatten (Constructor constructor _) = [constructor] flatten d = error $ "Unsupported Sum decoder Constructor definition: " ++ show d toCase constructor = "\"" ++ constructor ++ "\" -> Json.Decode.succeed " ++ constructor decoder d = error $ "Unsupported decoder definition: " ++ show d listDecoder :: Expr -> String listDecoder (DataType name _) = format [ func ++ " : Json.Decode.Decoder (List " ++ name ++ ")" , func ++ " =" , tab 4 "Json.Decode.list " ++ decoderFunction name ] where func = "decode" ++ name ++ "List" listDecoder d = error $ "Unsupported list decoder definition: " ++ show d