imperative-edsl-0.4.1: src/Language/Embedded/Backend/C.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE QuasiQuotes #-}
-- | C code generation for 'Program'
module Language.Embedded.Backend.C where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
import Data.Loc (noLoc)
import qualified Language.C.Syntax as C
import Control.Monad.Operational.Higher
import Language.C.Monad
import Text.PrettyPrint.Mainland (pretty)
--------------------------------------------------------------------------------
-- * Utilities
--------------------------------------------------------------------------------
-- | Create a named type
namedType :: String -> C.Type
namedType t = C.Type
(C.DeclSpec [] [] (C.Tnamed (C.Id t noLoc) [] noLoc) noLoc)
(C.DeclRoot noLoc)
noLoc
-- | Return the argument of a boolean negation expression
viewNotExp :: C.Exp -> Maybe C.Exp
viewNotExp (C.UnOp C.Lnot a _) = Just a
viewNotExp (C.FnCall (C.Var (C.Id "!" _) _) [a] _) = Just a
-- Apparently this is what `!` parses to
viewNotExp _ = Nothing
--------------------------------------------------------------------------------
-- * Code generation user interface
--------------------------------------------------------------------------------
-- | Compile a program to C code represented as a string
--
-- For programs that make use of the primitives in
-- "Language.Embedded.Concurrent", the resulting C code can be compiled as
-- follows:
--
-- > gcc -Iinclude csrc/chan.c -lpthread YOURPROGRAM.c
compile :: (Interp instr CGen, HFunctor instr) => Program instr a -> String
compile = pretty 80 . prettyCGen . liftSharedLocals . wrapMain . interpret
-- | Compile a program to C code and print it on the screen
--
-- For programs that make use of the primitives in
-- "Language.Embedded.Concurrent", the resulting C code can be compiled as
-- follows:
--
-- > gcc -Iinclude csrc/chan.c -lpthread YOURPROGRAM.c
icompile :: (Interp instr CGen, HFunctor instr) => Program instr a -> IO ()
icompile = putStrLn . compile