packages feed

kempe-0.2.0.9: src/Language/C/AST.hs

{-# LANGUAGE OverloadedStrings #-}

module Language.C.AST ( CType (..)
                      , CFunc (..)
                      , prettyHeaders
                      , cSettings
                      ) where

import           Data.Semigroup    ((<>))
import qualified Data.Set          as S
import qualified Data.Text         as T
import           Prettyprinter     (Doc, LayoutOptions (..), PageWidth (..), Pretty (..), tupled, (<+>))
import           Prettyprinter.Ext

cSettings :: LayoutOptions
cSettings = LayoutOptions $ AvailablePerLine 180 0.8

data CHeader = StdBool -- ^ @stdbool.h@
             | StdInt -- ^ @stdint.h@
             deriving (Eq, Ord)

prettyInclude :: CHeader -> Doc ann
prettyInclude StdBool = "#include <stdbool.h>"
prettyInclude StdInt  = "#include <stdint.h>"

data CType = CInt
           | CBool
           | CUInt64
           | CInt8
           | CVoid
           | CVoidPtr
           -- ADTs etc.

data CFunc = CFunc !T.Text [CType] CType

prettyHeaders :: [CFunc] -> Doc ann
prettyHeaders es =
    let hs = foldMap mentionedFunc es
        in prettyLines (fmap prettyInclude (S.toList hs))
            <#> prettyLines (fmap pretty es)

mentioned :: CType -> S.Set CHeader
mentioned CInt     = mempty
mentioned CBool    = S.singleton StdBool
mentioned CUInt64  = S.singleton StdInt
mentioned CVoid    = mempty
mentioned CVoidPtr = mempty
mentioned CInt8    = S.singleton StdInt

mentionedFunc :: CFunc -> S.Set CHeader
mentionedFunc (CFunc _ args ret) = foldMap mentioned (ret : args)

instance Pretty CType where
    pretty CInt     = "int"
    pretty CBool    = "bool"
    pretty CUInt64  = "uint64_t"
    pretty CVoid    = "void"
    pretty CVoidPtr = "void*"
    pretty CInt8    = "int8_t"

instance Pretty CFunc where
    pretty (CFunc fname args retType) = "extern" <+> pretty retType <+> pretty fname <+> tupled (pretty <$> args) <> ";"