packages feed

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

{-# LANGUAGE OverloadedStrings #-}

module Jacinda.Backend.Printf ( sprintf
                              , isReady
                              ) where

import qualified Data.ByteString    as BS
import           Data.Semigroup     ((<>))
import qualified Data.Text          as T
import           Data.Text.Encoding (decodeUtf8, encodeUtf8)
import           Jacinda.AST

isReady :: E a -> Bool
isReady FloatLit{} = True
isReady StrLit{}   = True
isReady IntLit{}   = True
isReady BoolLit{}  = True
isReady (Tup _ es) = all isReady es
isReady _          = False

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

-- TODO: https://hackage.haskell.org/package/floatshow
--
-- TODO: interpret precision, like %0.6f %.6

sprintf' :: T.Text -> E a -> T.Text
sprintf' fmt (FloatLit _ f) =
    let (prefix, fmt') = T.breakOn "%f" fmt
        in prefix <> T.pack (show f) <> T.drop 2 fmt'
sprintf' fmt (IntLit _ i) =
    let (prefix, fmt') = T.breakOn "%i" fmt
        in prefix <> T.pack (show i) <> T.drop 2 fmt'
sprintf' fmt (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 (BoolLit _ b) =
    let (prefix, fmt') = T.breakOn "%b" fmt
        in prefix <> showBool b <> T.drop 2 fmt'
    where showBool True  = "true"
          showBool False = "false"