{-# LANGUAGE OverloadedStrings #-} module Elm.Encoder ( toElmEncoderRef , toElmEncoderRefWith , toElmEncoderSource , toElmEncoderSourceWith ) where import Control.Monad.Reader import Data.Text import Elm.Common import Elm.Type import Formatting class HasEncoder a where render :: a -> Reader Options Text class HasEncoderRef a where renderRef :: a -> Reader Options Text instance HasEncoder ElmDatatype where render d@(ElmDatatype name constructor) = do fnName <- renderRef d sformat (stext % " : " % stext % " -> Json.Encode.Value" % cr % stext % " x =" % stext) fnName name fnName <$> render constructor render (ElmPrimitive primitive) = renderRef primitive instance HasEncoderRef ElmDatatype where renderRef (ElmDatatype name _) = pure $ sformat ("encode" % stext) name renderRef (ElmPrimitive primitive) = renderRef primitive instance HasEncoder ElmConstructor where render (RecordConstructor _ value) = sformat (cr % " Json.Encode.object" % cr % " [ " % stext % cr % " ]") <$> render value instance HasEncoder ElmValue where render (ElmField name value) = do fieldModifier <- asks fieldLabelModifier valueBody <- render value pure $ sformat ("( \"" % stext % "\", " % stext % " x." % stext % " )") (fieldModifier name) valueBody name render (ElmPrimitiveRef primitive) = renderRef primitive render (ElmRef name) = pure $ sformat ("encode" % stext) name render (Values x y) = sformat (stext % cr % " , " % stext) <$> render x <*> render y instance HasEncoderRef ElmPrimitive where renderRef EDate = pure "(Json.Encode.string << toISOString)" renderRef EUnit = pure "Json.Encode.null" renderRef EInt = pure "Json.Encode.int" renderRef EChar = pure "Json.Encode.char" renderRef EBool = pure "Json.Encode.bool" renderRef EFloat = pure "Json.Encode.float" renderRef EString = pure "Json.Encode.string" renderRef (EList (ElmPrimitive EChar)) = pure "Json.Encode.string" renderRef (EList datatype) = sformat ("(Json.Encode.list << List.map " % stext % ")") <$> renderRef datatype renderRef (EMaybe datatype) = sformat ("(Maybe.withDefault Json.Encode.null << Maybe.map " % stext % ")") <$> renderRef datatype renderRef (ETuple2 x y) = sformat ("(tuple2 " % stext % " " % stext % ")") <$> renderRef x <*> renderRef y renderRef (EDict k datatype) = sformat ("(dict " % stext % " " % stext % ")") <$> renderRef k <*> renderRef datatype toElmEncoderRefWith :: ElmType a => Options -> a -> Text toElmEncoderRefWith options x = runReader (renderRef (toElmType x)) options toElmEncoderRef :: ElmType a => a -> Text toElmEncoderRef = toElmEncoderRefWith defaultOptions toElmEncoderSourceWith :: ElmType a => Options -> a -> Text toElmEncoderSourceWith options x = runReader (render (toElmType x)) options toElmEncoderSource :: ElmType a => a -> Text toElmEncoderSource = toElmEncoderSourceWith defaultOptions