Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iota command #53

Merged
merged 4 commits into from
Oct 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 79 additions & 0 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{-# LANGUAGE CPP, TemplateHaskell #-}

module Main (main) where

import qualified Data.List as L
import qualified Language.Haskell.Exts as H
import Language.Haskell.TH (runIO)
import System.Directory (getCurrentDirectory)
import System.Environment (getArgs)
import System.IO.Temp (withTempDirectory)
import System.Process (rawSystem)

main :: IO ()
main = do
(name:opts) <- getArgs
let path = modulePath name
code <- readFile path
processed <- withTempDirectory "." "iota-cpp" $ \tmpDir -> do
let originalPath = tmpDir ++ "/define-removed.hs"
let processedPath = tmpDir ++ "/cpp-processed.hs"
writeFile originalPath $ removeDefineMacros code
rawSystem "stack"
["ghc", "--", "-E", originalPath , "-o", processedPath]
removeMacros <$> readFile processedPath
let Just (_, exts) = H.readExtensions processed
let parseOption = H.defaultParseMode
{ H.parseFilename = path
, H.extensions = exts
}
case H.parseModuleWithMode parseOption processed of
H.ParseOk ast -> case opts of
[] -> putStrLn $ pretty ast
[dst] -> do
appendFile dst $ header name
appendFile dst $ pretty ast
failed -> print failed

installPath :: FilePath
installPath = $(do dir <- runIO getCurrentDirectory;[e|dir|])

modulePath :: String -> FilePath
modulePath name = mconcat
[ installPath
, "/src/"
, map convert name
, ".hs"
]
where
convert '.' = '/'
convert c = c

lineWidth :: Int
lineWidth = 80

header :: String -> String
header name = unlines
[ replicate (lineWidth - 1) '-'
, "-- " ++ name
, replicate (lineWidth - 1) '-'
]


#if MIN_VERSION_haskell_src_exts(1,18,0)
pretty :: H.Module l -> String
pretty (H.Module _ _ _ _ decls) = unlines
#else
pretty :: H.Module -> String
pretty (H.Module _ _ _ _ _ _ decls) = unlines
#endif
$ map (H.prettyPrintWithMode pphsMode) decls

removeDefineMacros :: String -> String
removeDefineMacros = unlines . filter (not . L.isPrefixOf "#define") . lines

removeMacros :: String -> String
removeMacros = unlines . filter (not . L.isPrefixOf "#") . lines

pphsMode :: H.PPHsMode
pphsMode = H.defaultMode{ H.layout = H.PPNoLayout }
12 changes: 12 additions & 0 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ dependencies:
library:
source-dirs: src

executables:
iota:
main: Main.hs
source-dirs: app
ghc-options: []
dependencies:
- directory
- haskell-src-exts
- process
- template-haskell
- temporary

tests:
iota-test:
main: Spec.hs
Expand Down