module Curry.Files.Unlit (isLiterate, unlit) where
import Control.Monad (when, zipWithM)
import Data.Char (isSpace)
import Curry.Base.Monad (CYM, failMessageAt)
import Curry.Base.Position (Position (..), first)
import Curry.Files.Filenames (lcurryExt, takeExtension)
isLiterate :: FilePath -> Bool
isLiterate = (== lcurryExt) . takeExtension
data Line
= Program !Int String
| Blank
| Comment
unlit :: FilePath -> String -> CYM String
unlit fn cy
| isLiterate fn = do
ls <- progLines fn $ zipWith classify [1 .. ] $ lines cy
when (all null ls) $ failMessageAt (first fn) "No code in literate script"
return (unlines ls)
| otherwise = return cy
classify :: Int -> String -> Line
classify l ('>' : cs) = Program l cs
classify _ cs | all isSpace cs = Blank
| otherwise = Comment
progLines :: FilePath -> [Line] -> CYM [String]
progLines fn cs = zipWithM checkAdjacency (Blank : cs) cs where
checkAdjacency (Program p _) Comment = report fn p "followed"
checkAdjacency Comment (Program p _) = report fn p "preceded"
checkAdjacency _ (Program _ s) = return s
checkAdjacency _ _ = return ""
report :: String -> Int -> String -> CYM a
report f l cause = failMessageAt (Position f l 1) msg
where msg = concat [ "When reading literate source: "
, "Program line is " ++ cause ++ " by comment line."
]