{- |
    Module      : $Header$
    Description : Functions for reading and writing FlatCurry files
    Copyright   : (c) 2014        Björn Peemöller
                      2017        Finn Teegen
    License     : BSD-3-clause

    Maintainer  : bjp@informatik.uni-kiel.de
    Stability   : experimental
    Portability : portable

    This module contains functions for reading and writing FlatCurry files.
-}

module Curry.FlatCurry.Files
  ( readTypedFlatCurry, readFlatCurry, readFlatInterface
  , writeFlatCurry, writeBinaryFlatCurry
  ) where

import Data.Binary           (Binary, encode)
import Data.Char             (isSpace)

import Curry.Files.Filenames (typedFlatName, flatName, flatIntName)
import Curry.Files.PathUtils (writeModule, writeBinaryModule, readModule)

import Curry.FlatCurry.Type  (Prog)
import Curry.FlatCurry.Annotated.Type (AProg, TypeExpr)


-- ---------------------------------------------------------------------------
-- Functions for reading and writing FlatCurry terms
-- ---------------------------------------------------------------------------

-- |Reads an typed FlatCurry file (extension ".tfcy") and eventually
-- returns the corresponding FlatCurry program term (type 'AProg').
readTypedFlatCurry :: FilePath -> IO (Maybe (AProg TypeExpr))
readTypedFlatCurry :: FilePath -> IO (Maybe (AProg TypeExpr))
readTypedFlatCurry = FilePath -> IO (Maybe (AProg TypeExpr))
forall a. Read a => FilePath -> IO (Maybe a)
readFlat (FilePath -> IO (Maybe (AProg TypeExpr)))
-> (FilePath -> FilePath)
-> FilePath
-> IO (Maybe (AProg TypeExpr))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
typedFlatName

-- |Reads a FlatCurry file (extension ".fcy") and eventually returns the
-- corresponding FlatCurry program term (type 'Prog').
readFlatCurry :: FilePath -> IO (Maybe Prog)
readFlatCurry :: FilePath -> IO (Maybe Prog)
readFlatCurry = FilePath -> IO (Maybe Prog)
forall a. Read a => FilePath -> IO (Maybe a)
readFlat (FilePath -> IO (Maybe Prog))
-> (FilePath -> FilePath) -> FilePath -> IO (Maybe Prog)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
flatName

-- |Reads a FlatInterface file (extension @.fint@) and returns the
-- corresponding term (type 'Prog') as a value of type 'Maybe'.
readFlatInterface :: FilePath -> IO (Maybe Prog)
readFlatInterface :: FilePath -> IO (Maybe Prog)
readFlatInterface = FilePath -> IO (Maybe Prog)
forall a. Read a => FilePath -> IO (Maybe a)
readFlat (FilePath -> IO (Maybe Prog))
-> (FilePath -> FilePath) -> FilePath -> IO (Maybe Prog)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
flatIntName

-- |Reads a Flat file and returns the corresponding term (type 'Prog' or
-- 'AProg') as a value of type 'Maybe'.
-- Due to compatibility with PAKCS it is allowed to have a commentary
-- at the beginning of the file enclosed in {- ... -}.
readFlat :: Read a => FilePath -> IO (Maybe a)
readFlat :: FilePath -> IO (Maybe a)
readFlat = (Maybe FilePath -> Maybe a) -> IO (Maybe FilePath) -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((FilePath -> a) -> Maybe FilePath -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath -> a
forall a. Read a => FilePath -> a
read (FilePath -> a) -> (FilePath -> FilePath) -> FilePath -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
skipComment)) (IO (Maybe FilePath) -> IO (Maybe a))
-> (FilePath -> IO (Maybe FilePath)) -> FilePath -> IO (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO (Maybe FilePath)
readModule where
  skipComment :: FilePath -> FilePath
skipComment s :: FilePath
s = case (Char -> Bool) -> FilePath -> FilePath
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace FilePath
s of
      '{' : '-' : s' :: FilePath
s' -> FilePath -> FilePath
dropComment FilePath
s'
      s' :: FilePath
s'             -> FilePath
s'
  dropComment :: FilePath -> FilePath
dropComment ('-' : '}' : xs :: FilePath
xs) = FilePath
xs
  dropComment (_ : xs :: FilePath
xs)         = FilePath -> FilePath
dropComment FilePath
xs
  dropComment []               = []

-- |Writes a FlatCurry program term into a file.
writeFlatCurry :: Show a => FilePath -> a -> IO ()
writeFlatCurry :: FilePath -> a -> IO ()
writeFlatCurry fn :: FilePath
fn = FilePath -> FilePath -> IO ()
writeModule FilePath
fn (FilePath -> IO ()) -> (a -> FilePath) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> FilePath
forall a. Show a => a -> FilePath
show

-- |Writes a FlatCurry program term into a normal and a binary file.
writeBinaryFlatCurry :: Binary a => FilePath -> a -> IO ()
writeBinaryFlatCurry :: FilePath -> a -> IO ()
writeBinaryFlatCurry fn :: FilePath
fn = FilePath -> ByteString -> IO ()
writeBinaryModule FilePath
fn (ByteString -> IO ()) -> (a -> ByteString) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ByteString
forall a. Binary a => a -> ByteString
encode