{-# LANGUAGE ConstraintKinds #-}
module SJW.Source (
      CodePath(..)
    , Source(..)
    , HasSource
    , Path(..)
    , source
  ) where

import Control.Monad.Reader (MonadReader)
import Data.List (intercalate)
import Text.ParserCombinators.ReadP (char, munch, sepBy)
import Text.ParserCombinators.ReadPrec (lift)
import Text.Read (readPrec)

newtype Path = Path [String] deriving (Path -> Path -> Bool
(Path -> Path -> Bool) -> (Path -> Path -> Bool) -> Eq Path
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Path -> Path -> Bool
$c/= :: Path -> Path -> Bool
== :: Path -> Path -> Bool
$c== :: Path -> Path -> Bool
Eq, Eq Path
Eq Path
-> (Path -> Path -> Ordering)
-> (Path -> Path -> Bool)
-> (Path -> Path -> Bool)
-> (Path -> Path -> Bool)
-> (Path -> Path -> Bool)
-> (Path -> Path -> Path)
-> (Path -> Path -> Path)
-> Ord Path
Path -> Path -> Bool
Path -> Path -> Ordering
Path -> Path -> Path
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Path -> Path -> Path
$cmin :: Path -> Path -> Path
max :: Path -> Path -> Path
$cmax :: Path -> Path -> Path
>= :: Path -> Path -> Bool
$c>= :: Path -> Path -> Bool
> :: Path -> Path -> Bool
$c> :: Path -> Path -> Bool
<= :: Path -> Path -> Bool
$c<= :: Path -> Path -> Bool
< :: Path -> Path -> Bool
$c< :: Path -> Path -> Bool
compare :: Path -> Path -> Ordering
$ccompare :: Path -> Path -> Ordering
$cp1Ord :: Eq Path
Ord)
newtype CodePath = CodePath [FilePath]

data Source = Source {
      Source -> CodePath
code :: CodePath
    , Source -> Path
mainModule :: Path
  }

type HasSource = MonadReader Source

instance Show Path where
  show :: Path -> String
show (Path [String]
components) = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"." [String]
components

instance Read Path where
  readPrec :: ReadPrec Path
readPrec = ([String] -> Path) -> ReadPrec [String] -> ReadPrec Path
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [String] -> Path
Path (ReadPrec [String] -> ReadPrec Path)
-> (ReadP [String] -> ReadPrec [String])
-> ReadP [String]
-> ReadPrec Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReadP [String] -> ReadPrec [String]
forall a. ReadP a -> ReadPrec a
lift (ReadP [String] -> ReadPrec Path)
-> ReadP [String] -> ReadPrec Path
forall a b. (a -> b) -> a -> b
$
    (Char -> Bool) -> ReadP String
munch (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') ReadP String -> ReadP Char -> ReadP [String]
forall a sep. ReadP a -> ReadP sep -> ReadP [a]
`sepBy` Char -> ReadP Char
char Char
'.'

instance Show CodePath where
  show :: CodePath -> String
show (CodePath [String]
dirs) = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
":" [String]
dirs

source :: [String] -> Source
source :: [String] -> Source
source [String]
paths = Source :: CodePath -> Path -> Source
Source {
      code :: CodePath
code = [String] -> CodePath
CodePath [String]
paths
    , mainModule :: Path
mainModule = [String] -> Path
Path [String
"Main"]
  }