module Language.Sexp.Encode
( encode
) where
import Data.List (intersperse)
import Data.Monoid as Monoid
import Data.Scientific
import Data.Text.Encoding (encodeUtf8)
import Data.ByteString.Lazy (ByteString)
import Data.ByteString.Lazy.Builder.ASCII
import Language.Sexp.Types
bAtom :: Atom -> Builder
bAtom (AtomBool a) = char8 '#' <> if a then char8 't' else char8 'f'
bAtom (AtomInt a) = integerDec a
bAtom (AtomReal a) = string8 . formatScientific Generic Nothing $ a
bAtom (AtomString a) = stringUtf8 (show a)
bAtom (AtomSymbol a) = byteString (encodeUtf8 a)
bAtom (AtomKeyword a) = char8 ':' <> byteString (encodeUtf8 (unKw a))
sep :: [Builder] -> Builder
sep = mconcat . intersperse (char8 ' ')
bSexp :: Sexp -> Builder
bSexp (Atom _ a) = bAtom a
bSexp (List _ ss) = char8 '(' <> sep (map bSexp ss) <> char8 ')'
bSexp (Vector _ ss) = char8 '[' <> sep (map bSexp ss) <> char8 ']'
bSexp (Quoted _ a) = char8 '\'' Monoid.<> bSexp a
encode :: Sexp -> ByteString
encode = toLazyByteString . bSexp