{-# LANGUAGE OverloadedStrings #-}

-- | Main module for the library
module Language.ATS ( -- * Functions for working with syntax
                      lexATS
                    , parse
                    , printATS
                    , printATSCustom
                    , printATSFast
                    , printErr
                    -- * Library functions
                    , getDependencies
                    -- * Syntax Tree
                    , ATS (..)
                    , Declaration (..)
                    , Expression (..)
                    , Type (..)
                    , Function (..)
                    , Implementation (..)
                    , Pattern (..)
                    , Name (..)
                    , UnOp (..)
                    , BinOp (..)
                    , DataPropLeaf (..)
                    , Leaf (..)
                    , Arg (..)
                    , Addendum (..)
                    , LambdaType (..)
                    , Universal (..)
                    , Existential (..)
                    , PreFunction (..)
                    , StaticExpression (..)
                    , StackFunction (..)
                    , Paired (..)
                    , Fixity (..)
                    , SortArg (..)
                    , Sort (..)
                    , SortArgs
                    -- * Lexical types
                    , Token (..)
                    , AlexPosn (..)
                    , Keyword (..)
                    -- * Error types
                    , ATSError
                    -- * Lenses
                    , preF
                    , expression
                    , fun
                    , leaves
                    , constructorUniversals
                    , typeCall
                    , typeCallArgs
                    ) where

import           Control.Lens
import           Control.Monad
import           Control.Monad.IO.Class
import           Data.Maybe                   (catMaybes)
import           GHC.IO.Handle.FD             (stderr)
import           Language.ATS.Lexer
import           Language.ATS.Parser
import           Language.ATS.PrettyPrint
import           Language.ATS.Types
import           Text.PrettyPrint.ANSI.Leijen hiding ((<$>))

rewriteATS' :: ATS -> ATS
rewriteATS' (ATS ds) = ATS (rewriteDecl <$> ds)

printErr :: MonadIO m => ATSError String -> m ()
printErr = liftIO . hPutDoc stderr . (<> "\n") . pretty

-- | Parse a string containing ATS source.
parse :: String -> Either (ATSError String) ATS
parse = fmap rewriteATS' . (parseATS <=< (over _Left LexError . lexATS))

-- TODO use prepocessing?? here?
getDependencies :: ATS -> [FilePath]
getDependencies (ATS ds) = join $ catMaybes (g <$> ds)
    where g (Staload _ _ s)  = Just [s]
          g (Include s)      = Just [s]
          g (Local _ as as') = Just $ getDependencies as <> getDependencies as'
          g _                = Nothing