module Language.Drasil.Code.Imperative.ReadInput (
sampleInputDD, readWithDataDesc
) where
import Control.Lens ((^.))
import Data.List (intersperse, isPrefixOf, transpose)
import Data.List.Split (splitOn)
import Data.List.NonEmpty (NonEmpty(..), toList)
import Language.Drasil hiding (Data, Matrix)
import Language.Drasil.Expr.Development (Expr(Matrix))
import Language.Drasil.Code.DataDesc (DataDesc'(..), Data'(..), DataItem'(..),
Delimiter, dataDesc, junk, list, singleton')
import Language.Drasil.Chunk.Code (CodeVarChunk)
readWithDataDesc :: FilePath -> DataDesc' -> IO [Expr]
readWithDataDesc :: FilePath -> DataDesc' -> IO [Expr]
readWithDataDesc FilePath
fp DataDesc'
ddsc = do
FilePath
ins <- FilePath -> IO FilePath
readFile FilePath
fp
let readDD :: DataDesc' -> String -> [Expr]
readDD :: DataDesc' -> FilePath -> [Expr]
readDD (DD Data'
ds FilePath
dlm DataDesc'
dd) FilePath
s = let (FilePath
dat,FilePath
rest) = FilePath -> FilePath -> (FilePath, FilePath)
splitAtFirst FilePath
s FilePath
dlm in
Data' -> FilePath -> [Expr]
readData Data'
ds FilePath
dat [Expr] -> [Expr] -> [Expr]
forall a. [a] -> [a] -> [a]
++ DataDesc' -> FilePath -> [Expr]
readDD DataDesc'
dd FilePath
rest
readDD (End Data'
d) FilePath
s = Data' -> FilePath -> [Expr]
readData Data'
d FilePath
s
readData :: Data' -> String -> [Expr]
readData :: Data' -> FilePath -> [Expr]
readData Data'
Junk FilePath
_ = []
readData (Datum DataItem'
d) FilePath
s = [DataItem' -> FilePath -> Expr
readDataItem DataItem'
d FilePath
s]
readData (Data NonEmpty DataItem'
dis Integer
0 FilePath
d) FilePath
s = (DataItem' -> FilePath -> Expr)
-> [DataItem'] -> [FilePath] -> [Expr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith DataItem' -> FilePath -> Expr
readDataItem (NonEmpty DataItem' -> [DataItem']
forall a. NonEmpty a -> [a]
toList NonEmpty DataItem'
dis) (FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
d FilePath
s)
readData (Data ((DI CodeVarChunk
c [FilePath
dlm1]):|[DataItem']
_) Integer
1 FilePath
dlm2) FilePath
s = ([FilePath] -> Expr) -> [[FilePath]] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (([[Expr]] -> Expr
Matrix ([[Expr]] -> Expr) -> ([Expr] -> [[Expr]]) -> [Expr] -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Expr] -> [[Expr]] -> [[Expr]]
forall a. a -> [a] -> [a]
:[])) ([Expr] -> Expr) -> ([FilePath] -> [Expr]) -> [FilePath] -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(FilePath -> Expr) -> [FilePath] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Space -> FilePath -> Expr
strAsExpr (Space -> Space
getInnerSpace (Space -> Space) -> Space -> Space
forall a b. (a -> b) -> a -> b
$ CodeVarChunk
c CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ))) ([[FilePath]] -> [Expr]) -> [[FilePath]] -> [Expr]
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [[FilePath]]
forall a. [[a]] -> [[a]]
transpose ([[FilePath]] -> [[FilePath]]) -> [[FilePath]] -> [[FilePath]]
forall a b. (a -> b) -> a -> b
$
(FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm2) ([FilePath] -> [[FilePath]]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm1 FilePath
s
readData (Data ((DI CodeVarChunk
c [FilePath
dlm1, FilePath
dlm3]):|[DataItem']
_) Integer
1 FilePath
dlm2) FilePath
s = ([[FilePath]] -> Expr) -> [[[FilePath]]] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map ([[Expr]] -> Expr
Matrix ([[Expr]] -> Expr)
-> ([[FilePath]] -> [[Expr]]) -> [[FilePath]] -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
([FilePath] -> [Expr]) -> [[FilePath]] -> [[Expr]]
forall a b. (a -> b) -> [a] -> [b]
map ((FilePath -> Expr) -> [FilePath] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Space -> FilePath -> Expr
strAsExpr (Space -> Space
getInnerSpace (Space -> Space) -> Space -> Space
forall a b. (a -> b) -> a -> b
$ CodeVarChunk
c CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ)))) ([[[FilePath]]] -> [Expr]) -> [[[FilePath]]] -> [Expr]
forall a b. (a -> b) -> a -> b
$ [[[FilePath]]] -> [[[FilePath]]]
forall a. [[a]] -> [[a]]
transpose ([[[FilePath]]] -> [[[FilePath]]])
-> [[[FilePath]]] -> [[[FilePath]]]
forall a b. (a -> b) -> a -> b
$
(FilePath -> [[FilePath]]) -> [FilePath] -> [[[FilePath]]]
forall a b. (a -> b) -> [a] -> [b]
map ((FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm3) ([FilePath] -> [[FilePath]])
-> (FilePath -> [FilePath]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm2) ([FilePath] -> [[[FilePath]]]) -> [FilePath] -> [[[FilePath]]]
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm1 FilePath
s
readData (Data ((DI CodeVarChunk
c [FilePath
dlm1, FilePath
dlm2]):|[DataItem']
_) Integer
2 FilePath
dlm3) FilePath
s = ([[FilePath]] -> Expr) -> [[[FilePath]]] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map ([[Expr]] -> Expr
Matrix ([[Expr]] -> Expr)
-> ([[FilePath]] -> [[Expr]]) -> [[FilePath]] -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
([FilePath] -> [Expr]) -> [[FilePath]] -> [[Expr]]
forall a b. (a -> b) -> [a] -> [b]
map ((FilePath -> Expr) -> [FilePath] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Space -> FilePath -> Expr
strAsExpr (Space -> Space
getInnerSpace (Space -> Space) -> Space -> Space
forall a b. (a -> b) -> a -> b
$ CodeVarChunk
c CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ))) ([[FilePath]] -> [[Expr]])
-> ([[FilePath]] -> [[FilePath]]) -> [[FilePath]] -> [[Expr]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[FilePath]] -> [[FilePath]]
forall a. [[a]] -> [[a]]
transpose) ([[[FilePath]]] -> [Expr]) -> [[[FilePath]]] -> [Expr]
forall a b. (a -> b) -> a -> b
$
[[[FilePath]]] -> [[[FilePath]]]
forall a. [[a]] -> [[a]]
transpose ([[[FilePath]]] -> [[[FilePath]]])
-> [[[FilePath]]] -> [[[FilePath]]]
forall a b. (a -> b) -> a -> b
$ (FilePath -> [[FilePath]]) -> [FilePath] -> [[[FilePath]]]
forall a b. (a -> b) -> [a] -> [b]
map ((FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm3) ([FilePath] -> [[FilePath]])
-> (FilePath -> [FilePath]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm2) ([FilePath] -> [[[FilePath]]]) -> [FilePath] -> [[[FilePath]]]
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm1 FilePath
s
readData Data'
_ FilePath
_ = FilePath -> [Expr]
forall a. HasCallStack => FilePath -> a
error FilePath
"Invalid degree of intermixing in DataDesc or list with more than 2 dimensions (not yet supported)"
readDataItem :: DataItem' -> String -> Expr
readDataItem :: DataItem' -> FilePath -> Expr
readDataItem (DI CodeVarChunk
c []) FilePath
s = Space -> FilePath -> Expr
strAsExpr (CodeVarChunk
c CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ) FilePath
s
readDataItem (DI CodeVarChunk
c [FilePath
dlm]) FilePath
s = Space -> [FilePath] -> Expr
strListAsExpr (CodeVarChunk
c CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ) (FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm FilePath
s)
readDataItem (DI CodeVarChunk
c [FilePath
dlm1, FilePath
dlm2]) FilePath
s = Space -> [[FilePath]] -> Expr
strList2DAsExpr (CodeVarChunk
c CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ)
((FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm2) ([FilePath] -> [[FilePath]]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> [FilePath]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn FilePath
dlm1 FilePath
s)
readDataItem (DI CodeVarChunk
_ [FilePath]
_) FilePath
_ = FilePath -> Expr
forall a. HasCallStack => FilePath -> a
error FilePath
"readWithDataDesc does not yet support lists with 3 or more dimensions"
[Expr] -> IO [Expr]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Expr] -> IO [Expr]) -> [Expr] -> IO [Expr]
forall a b. (a -> b) -> a -> b
$ DataDesc' -> FilePath -> [Expr]
readDD DataDesc'
ddsc FilePath
ins
sampleInputDD :: [CodeVarChunk] -> DataDesc'
sampleInputDD :: [CodeVarChunk] -> DataDesc'
sampleInputDD [CodeVarChunk]
ds = [Data'] -> FilePath -> DataDesc'
dataDesc (Data'
junk Data' -> [Data'] -> [Data']
forall a. a -> [a] -> [a]
: Data' -> [Data'] -> [Data']
forall a. a -> [a] -> [a]
intersperse Data'
junk ((CodeVarChunk -> Data') -> [CodeVarChunk] -> [Data']
forall a b. (a -> b) -> [a] -> [b]
map CodeVarChunk -> Data'
toData [CodeVarChunk]
ds)) FilePath
"\n"
where toData :: CodeVarChunk -> Data'
toData CodeVarChunk
d = Space -> CodeVarChunk -> Data'
toData' (CodeVarChunk
d CodeVarChunk -> Getting Space CodeVarChunk Space -> Space
forall s a. s -> Getting a s a -> a
^. Getting Space CodeVarChunk Space
forall c. HasSpace c => Getter c Space
Getter CodeVarChunk Space
typ) CodeVarChunk
d
toData' :: Space -> CodeVarChunk -> Data'
toData' t :: Space
t@(Vect Space
_) CodeVarChunk
d = CodeVarChunk -> [FilePath] -> Data'
list CodeVarChunk
d
(Int -> [FilePath] -> [FilePath]
forall a. Int -> [a] -> [a]
take (Space -> Int
getDimension Space
t) ([FilePath
", ", FilePath
"; "] [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ (FilePath -> FilePath) -> FilePath -> [FilePath]
forall a. (a -> a) -> a -> [a]
iterate (Char
':'Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
:) FilePath
":"))
toData' Space
_ CodeVarChunk
d = CodeVarChunk -> Data'
singleton' CodeVarChunk
d
strAsExpr :: Space -> String -> Expr
strAsExpr :: Space -> FilePath -> Expr
strAsExpr Space
Integer FilePath
s = Integer -> Expr
forall r. LiteralC r => Integer -> r
int (FilePath -> Integer
forall a. Read a => FilePath -> a
read FilePath
s :: Integer)
strAsExpr Space
Natural FilePath
s = Integer -> Expr
forall r. LiteralC r => Integer -> r
int (FilePath -> Integer
forall a. Read a => FilePath -> a
read FilePath
s :: Integer)
strAsExpr Space
Real FilePath
s = Double -> Expr
forall r. LiteralC r => Double -> r
dbl (FilePath -> Double
forall a. Read a => FilePath -> a
read FilePath
s :: Double)
strAsExpr Space
Rational FilePath
s = Double -> Expr
forall r. LiteralC r => Double -> r
dbl (FilePath -> Double
forall a. Read a => FilePath -> a
read FilePath
s :: Double)
strAsExpr Space
String FilePath
s = FilePath -> Expr
forall r. LiteralC r => FilePath -> r
str FilePath
s
strAsExpr Space
_ FilePath
_ = FilePath -> Expr
forall a. HasCallStack => FilePath -> a
error FilePath
"strAsExpr should only be numeric space or string"
getDimension :: Space -> Int
getDimension :: Space -> Int
getDimension (Vect Space
t) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Space -> Int
getDimension Space
t
getDimension Space
_ = Int
0
splitAtFirst :: String -> Delimiter -> (String, String)
splitAtFirst :: FilePath -> FilePath -> (FilePath, FilePath)
splitAtFirst = FilePath -> FilePath -> FilePath -> (FilePath, FilePath)
forall {a}. Eq a => [a] -> [a] -> [a] -> ([a], [a])
splitAtFirst' []
where splitAtFirst' :: [a] -> [a] -> [a] -> ([a], [a])
splitAtFirst' [a]
acc [] [a]
_ = ([a]
acc, [])
splitAtFirst' [a]
acc s :: [a]
s@(a
h:[a]
t) [a]
d = if [a]
d [a] -> [a] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [a]
s then
([a]
acc, [a] -> [a] -> [a]
forall {a}. Eq a => [a] -> [a] -> [a]
dropDelim [a]
d [a]
s) else [a] -> [a] -> [a] -> ([a], [a])
splitAtFirst' ([a]
acc[a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++[a
h]) [a]
t [a]
d
dropDelim :: [a] -> [a] -> [a]
dropDelim (a
d:[a]
ds) (a
s:[a]
ss) = if a
d a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
s then [a] -> [a] -> [a]
dropDelim [a]
ds [a]
ss
else FilePath -> [a]
forall a. HasCallStack => FilePath -> a
error FilePath
"impossible"
dropDelim [] [a]
s = [a]
s
dropDelim [a]
_ [] = FilePath -> [a]
forall a. HasCallStack => FilePath -> a
error FilePath
"impossible"
strListAsExpr :: Space -> [String] -> Expr
strListAsExpr :: Space -> [FilePath] -> Expr
strListAsExpr (Vect Space
t) [FilePath]
ss = [[Expr]] -> Expr
Matrix [(FilePath -> Expr) -> [FilePath] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Space -> FilePath -> Expr
strAsExpr Space
t) [FilePath]
ss]
strListAsExpr Space
_ [FilePath]
_ = FilePath -> Expr
forall a. HasCallStack => FilePath -> a
error FilePath
"strListsAsExpr called on non-vector space"
strList2DAsExpr :: Space -> [[String]] -> Expr
strList2DAsExpr :: Space -> [[FilePath]] -> Expr
strList2DAsExpr (Vect (Vect Space
t)) [[FilePath]]
sss = [[Expr]] -> Expr
Matrix ([[Expr]] -> Expr) -> [[Expr]] -> Expr
forall a b. (a -> b) -> a -> b
$ ([FilePath] -> [Expr]) -> [[FilePath]] -> [[Expr]]
forall a b. (a -> b) -> [a] -> [b]
map ((FilePath -> Expr) -> [FilePath] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Space -> FilePath -> Expr
strAsExpr Space
t)) [[FilePath]]
sss
strList2DAsExpr Space
_ [[FilePath]]
_ = FilePath -> Expr
forall a. HasCallStack => FilePath -> a
error FilePath
"strLists2DAsExprs called on non-2D-vector space"