packages feed

jacinda-3.0.0.0: src/Jacinda/Backend/Printf.hs

{-# LANGUAGE OverloadedStrings #-}

module Jacinda.Backend.Printf ( sprintf
                              ) where

import           A
import qualified Data.ByteString                   as BS
import           Data.ByteString.Builder           (toLazyByteString)
import           Data.ByteString.Builder.RealFloat (doubleDec)
import qualified Data.ByteString.Lazy              as BSL
import qualified Data.Text                         as T
import           Data.Text.Encoding                (decodeUtf8, encodeUtf8)

sprintf :: BS.ByteString -- ^ Format string
        -> E a
        -> BS.ByteString
sprintf fmt e = encodeUtf8 (sprintf' (decodeUtf8 fmt) e)

pf :: Double -> T.Text
pf = decodeUtf8 . BSL.toStrict . toLazyByteString . doubleDec

-- TODO: interpret precision, like %0.6f %.6

sprintf' :: T.Text -> E a -> T.Text
sprintf' fmt (Lit _ (FLit f)) =
    let (prefix, fmt') = T.breakOn "%f" fmt
        in prefix <> pf f <> T.drop 2 fmt'
sprintf' fmt (Lit _ (ILit i)) =
    let (prefix, fmt') = T.breakOn "%i" fmt
        in prefix <> T.pack (show i) <> T.drop 2 fmt'
sprintf' fmt (Lit _ (StrLit bs)) =
    let (prefix, fmt') = T.breakOn "%s" fmt
        in prefix <> decodeUtf8 bs <> T.drop 2 fmt'
sprintf' fmt (Tup _ [e]) = sprintf' fmt e
sprintf' fmt (Tup l (e:es)) =
    let nextFmt = sprintf' fmt e
        in sprintf' nextFmt (Tup l es)
sprintf' fmt (Lit _ (BLit b)) =
    let (prefix, fmt') = T.breakOn "%b" fmt
        in prefix <> showBool b <> T.drop 2 fmt'
    where showBool True  = "true"
          showBool False = "false"