Skip to content

Instantly share code, notes, and snippets.

@chpatrick
Last active August 29, 2015 14:15
Show Gist options
  • Save chpatrick/9803687aaf1b3def85d4 to your computer and use it in GitHub Desktop.
Save chpatrick/9803687aaf1b3def85d4 to your computer and use it in GitHub Desktop.
Anonymous foreign import
{-# LANGUAGE RecordWildCards, LambdaCase #-}
module AnonForeign(foreignImport) where
import Control.Applicative
import Control.Monad
import Language.Haskell.Meta.Parse
import Language.Haskell.TH.Quote
import Language.Haskell.TH.Syntax
import System.Random
import Text.ParserCombinators.Parsec as P hiding ((<|>))
import Text.ParserCombinators.Parsec.Language (haskellDef)
import qualified Text.ParserCombinators.Parsec.Token as PT
PT.TokenParser { .. } = PT.makeTokenParser haskellDef
foreignImport :: QuasiQuoter
foreignImport = QuasiQuoter { quoteExp = quoteForeign }
where
quoteForeign s = case parse parseForeign "" s of
Left err -> fail (show err)
Right ( cconv, safety, spec, type_ ) -> do
nameSuf <- runIO $ replicateM 16 $ randomRIO ( 'a', 'z' ) -- hack hack hack
name <- newName ("foreign_anon_" ++ nameSuf)
addTopDecls [ ForeignD $ ImportF cconv safety spec name type_ ]
return $ VarE name
parseForeign :: Parser ( Callconv, Safety, String, Type )
parseForeign = do
whiteSpace
cconv <- CCall <$ reserved "ccall"
<|> StdCall <$ reserved "stdcall"
safety <- Unsafe <$ reserved "unsafe"
<|> Interruptible <$ reserved "interruptible"
<|> Safe <$ reserved "safe"
<|> pure Safe
spec <- stringLiteral
reservedOp "::"
typeString <- P.many anyToken
type_ <- case parseType typeString of
Left err -> fail err
Right t -> return t
return ( cconv, safety, spec, type_ )
{- TEST
import AnonForeign
import qualified Data.ByteString as BS
import Foreign.C
test = BS.useAsCString "oh baby" [foreignImport|ccall safe "stdio.h puts" :: CString -> IO CInt |]
test2 = BS.useAsCString "kaching" [foreignImport| ccall safe "stdio.h puts" :: CString -> IO CInt |]
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment