module GOOL.Drasil.AST (Terminator(..), ScopeTag(..), QualifiedName, qualName, 
  FileType(..), isSource, Binding(..), onBinding, BindData(bind, bindDoc), bd, 
  FileData(filePath, fileMod), fileD, updateFileMod, FuncData(fType, funcDoc), 
  fd, ModData(name, modDoc), md, updateMod, MethodData(mthdDoc), mthd, 
  updateMthd, OpData(opPrec, opDoc), od, ParamData(paramVar, paramDoc), pd, 
  paramName, updateParam, ProgData(progName, progPurp, progMods), progD, emptyProg, 
  StateVarData(getStVarScp, stVar, destructSts), svd, 
  TypeData(cType, typeString, typeDoc), td, ValData(valPrec, valType, val), 
  vd, updateValDoc, VarData(varBind, varName, varType, varDoc), vard,
  CommonThunk, pureValue, vectorize, vectorize2, sumComponents, commonVecIndex,
  commonThunkElim, commonThunkDim
) where

import GOOL.Drasil.CodeType (CodeType)

import Prelude hiding ((<>))
import Text.PrettyPrint.HughesPJ (Doc, isEmpty)

-- For how statement endings are printed
data Terminator = Semi | Empty

-- Used for state variables and methods
-- Eq is needed for organizing methods and state variables into public and 
-- private groups for C++ class rendering
data ScopeTag = Pub | Priv deriving ScopeTag -> ScopeTag -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ScopeTag -> ScopeTag -> Bool
$c/= :: ScopeTag -> ScopeTag -> Bool
== :: ScopeTag -> ScopeTag -> Bool
$c== :: ScopeTag -> ScopeTag -> Bool
Eq

-- Used in method exception map and call map. 
-- Qualification first, name second
-- Eq and Ord needed for map lookups
data QualifiedName = QN String String deriving (QualifiedName -> QualifiedName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: QualifiedName -> QualifiedName -> Bool
$c/= :: QualifiedName -> QualifiedName -> Bool
== :: QualifiedName -> QualifiedName -> Bool
$c== :: QualifiedName -> QualifiedName -> Bool
Eq, Eq QualifiedName
QualifiedName -> QualifiedName -> Bool
QualifiedName -> QualifiedName -> Ordering
QualifiedName -> QualifiedName -> QualifiedName
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 :: QualifiedName -> QualifiedName -> QualifiedName
$cmin :: QualifiedName -> QualifiedName -> QualifiedName
max :: QualifiedName -> QualifiedName -> QualifiedName
$cmax :: QualifiedName -> QualifiedName -> QualifiedName
>= :: QualifiedName -> QualifiedName -> Bool
$c>= :: QualifiedName -> QualifiedName -> Bool
> :: QualifiedName -> QualifiedName -> Bool
$c> :: QualifiedName -> QualifiedName -> Bool
<= :: QualifiedName -> QualifiedName -> Bool
$c<= :: QualifiedName -> QualifiedName -> Bool
< :: QualifiedName -> QualifiedName -> Bool
$c< :: QualifiedName -> QualifiedName -> Bool
compare :: QualifiedName -> QualifiedName -> Ordering
$ccompare :: QualifiedName -> QualifiedName -> Ordering
Ord)

qualName :: String -> String -> QualifiedName
qualName :: String -> String -> QualifiedName
qualName = String -> String -> QualifiedName
QN

-- In C++ Source and Header files are separate, other languages have a single 
-- (Combined) file
data FileType = Combined | Source | Header -- deriving Eq

isSource :: FileType -> Bool
isSource :: FileType -> Bool
isSource FileType
Header = Bool
False
isSource FileType
_ = Bool
True

-- Static means bound at compile-time, Dynamic at run-time, used in BindData 
-- and VarData
data Binding = Static | Dynamic

onBinding :: Binding -> a -> a -> a
onBinding :: forall a. Binding -> a -> a -> a
onBinding Binding
Static a
s a
_ = a
s
onBinding Binding
Dynamic a
_ a
d = a
d

-- Used as the underlying data type for Permanence in the C++ renderer
data BindData = BD {BindData -> Binding
bind :: Binding, BindData -> Doc
bindDoc :: Doc}

bd :: Binding -> Doc -> BindData
bd :: Binding -> Doc -> BindData
bd = Binding -> Doc -> BindData
BD

-- Used as the underlying data type for Files in all renderers
data FileData = FileD {FileData -> String
filePath :: FilePath, FileData -> ModData
fileMod :: ModData}

fileD :: FilePath -> ModData -> FileData
fileD :: String -> ModData -> FileData
fileD = String -> ModData -> FileData
FileD

-- Replace a FileData's ModData with a new ModData
updateFileMod :: ModData -> FileData -> FileData
updateFileMod :: ModData -> FileData -> FileData
updateFileMod ModData
m FileData
f = String -> ModData -> FileData
fileD (FileData -> String
filePath FileData
f) ModData
m

-- Used as the underlying data type for Functions in all renderers
data FuncData = FD {FuncData -> TypeData
fType :: TypeData, FuncData -> Doc
funcDoc :: Doc}

fd :: TypeData -> Doc -> FuncData
fd :: TypeData -> Doc -> FuncData
fd = TypeData -> Doc -> FuncData
FD

-- Used as the underlying data type for Modules in all renderers
data ModData = MD {ModData -> String
name :: String, ModData -> Doc
modDoc :: Doc}

md :: String -> Doc -> ModData
md :: String -> Doc -> ModData
md = String -> Doc -> ModData
MD

updateMod :: (Doc -> Doc) -> ModData -> ModData
updateMod :: (Doc -> Doc) -> ModData -> ModData
updateMod Doc -> Doc
f ModData
m = String -> Doc -> ModData
md (ModData -> String
name ModData
m) (Doc -> Doc
f forall a b. (a -> b) -> a -> b
$ ModData -> Doc
modDoc ModData
m)

-- Used as the underlying data type for Methods in all renderers except C++
newtype MethodData = MthD {MethodData -> Doc
mthdDoc :: Doc}

mthd :: Doc -> MethodData
mthd :: Doc -> MethodData
mthd = Doc -> MethodData
MthD 

updateMthd :: MethodData -> (Doc -> Doc) -> MethodData
updateMthd :: MethodData -> (Doc -> Doc) -> MethodData
updateMthd MethodData
m Doc -> Doc
f = Doc -> MethodData
mthd ((Doc -> Doc
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. MethodData -> Doc
mthdDoc) MethodData
m)

-- Used as the underlying data type for UnaryOp and BinaryOp in all renderers
data OpData = OD {OpData -> Int
opPrec :: Int, OpData -> Doc
opDoc :: Doc}

od :: Int -> Doc -> OpData
od :: Int -> Doc -> OpData
od = Int -> Doc -> OpData
OD

-- Used as the underlying data type for Parameters in all renderers
data ParamData = PD {ParamData -> VarData
paramVar :: VarData, ParamData -> Doc
paramDoc :: Doc}

pd :: VarData -> Doc -> ParamData
pd :: VarData -> Doc -> ParamData
pd = VarData -> Doc -> ParamData
PD 

paramName :: ParamData -> String
paramName :: ParamData -> String
paramName = VarData -> String
varName forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParamData -> VarData
paramVar

updateParam :: (Doc -> Doc) -> ParamData -> ParamData
updateParam :: (Doc -> Doc) -> ParamData -> ParamData
updateParam Doc -> Doc
f ParamData
v = VarData -> Doc -> ParamData
pd (ParamData -> VarData
paramVar ParamData
v) ((Doc -> Doc
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParamData -> Doc
paramDoc) ParamData
v)

-- Used as the underlying data type for Programs in all renderers
data ProgData = ProgD {ProgData -> String
progName :: String, ProgData -> String
progPurp :: String, ProgData -> [FileData]
progMods :: [FileData]}

progD :: String -> String -> [FileData] -> ProgData
progD :: String -> String -> [FileData] -> ProgData
progD String
n String
st [FileData]
fs = String -> String -> [FileData] -> ProgData
ProgD String
n String
st (forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> Bool
isEmpty forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModData -> Doc
modDoc forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileData -> ModData
fileMod) [FileData]
fs)

emptyProg :: ProgData
emptyProg :: ProgData
emptyProg = String -> String -> [FileData] -> ProgData
progD String
"" String
"" []

-- Used as the underlying data type for StateVars in the C++ renderer
data StateVarData = SVD {StateVarData -> ScopeTag
getStVarScp :: ScopeTag, StateVarData -> Doc
stVar :: Doc, 
  StateVarData -> (Doc, Terminator)
destructSts :: (Doc, Terminator)}

svd :: ScopeTag -> Doc -> (Doc, Terminator) -> StateVarData
svd :: ScopeTag -> Doc -> (Doc, Terminator) -> StateVarData
svd = ScopeTag -> Doc -> (Doc, Terminator) -> StateVarData
SVD

-- Used as the underlying data type for Types in all renderers
data TypeData = TD {TypeData -> CodeType
cType :: CodeType, TypeData -> String
typeString :: String, TypeData -> Doc
typeDoc :: Doc}

td :: CodeType -> String -> Doc -> TypeData
td :: CodeType -> String -> Doc -> TypeData
td = CodeType -> String -> Doc -> TypeData
TD

-- Used as the underlying data type for Values in all renderers
data ValData = VD {ValData -> Maybe Int
valPrec :: Maybe Int, ValData -> TypeData
valType :: TypeData, ValData -> Doc
val :: Doc}

vd :: Maybe Int -> TypeData -> Doc -> ValData
vd :: Maybe Int -> TypeData -> Doc -> ValData
vd = Maybe Int -> TypeData -> Doc -> ValData
VD

updateValDoc :: (Doc -> Doc) -> ValData -> ValData
updateValDoc :: (Doc -> Doc) -> ValData -> ValData
updateValDoc Doc -> Doc
f ValData
v = Maybe Int -> TypeData -> Doc -> ValData
vd (ValData -> Maybe Int
valPrec ValData
v) (ValData -> TypeData
valType ValData
v) ((Doc -> Doc
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. ValData -> Doc
val) ValData
v)

-- Used as the underlying data type for Variables in all renderers
data VarData = VarD {VarData -> Binding
varBind :: Binding, VarData -> String
varName :: String, 
  VarData -> TypeData
varType :: TypeData, VarData -> Doc
varDoc :: Doc}

vard :: Binding -> String -> TypeData -> Doc -> VarData
vard :: Binding -> String -> TypeData -> Doc -> VarData
vard = Binding -> String -> TypeData -> Doc -> VarData
VarD

-- Used as the underlying data type for Thunks in all renderers
data CommonThunk s
  = PureValue (s ValData)
  | Vectorize (s ValData -> s ValData) (CommonThunk s)
  | Vectorize2 (s ValData -> s ValData -> s ValData) (CommonThunk s) (CommonThunk s)
  | SumComponents (CommonThunk s)

pureValue :: s ValData -> CommonThunk s
pureValue :: forall (s :: * -> *). s ValData -> CommonThunk s
pureValue = forall (s :: * -> *). s ValData -> CommonThunk s
PureValue

vectorize :: (s ValData -> s ValData) -> CommonThunk s -> CommonThunk s
vectorize :: forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> CommonThunk s
vectorize = forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> CommonThunk s
Vectorize

vectorize2 :: (s ValData -> s ValData -> s ValData) -> CommonThunk s -> CommonThunk s -> CommonThunk s
vectorize2 :: forall (s :: * -> *).
(s ValData -> s ValData -> s ValData)
-> CommonThunk s -> CommonThunk s -> CommonThunk s
vectorize2 = forall (s :: * -> *).
(s ValData -> s ValData -> s ValData)
-> CommonThunk s -> CommonThunk s -> CommonThunk s
Vectorize2

sumComponents :: CommonThunk s -> CommonThunk s
sumComponents :: forall (s :: * -> *). CommonThunk s -> CommonThunk s
sumComponents = forall (s :: * -> *). CommonThunk s -> CommonThunk s
SumComponents

commonVecIndex :: (s ValData -> s ValData) -> CommonThunk s -> s ValData
commonVecIndex :: forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonVecIndex s ValData -> s ValData
index (PureValue s ValData
v) = s ValData -> s ValData
index s ValData
v
commonVecIndex s ValData -> s ValData
index (Vectorize s ValData -> s ValData
op CommonThunk s
v) = s ValData -> s ValData
op (forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonVecIndex s ValData -> s ValData
index CommonThunk s
v)
commonVecIndex s ValData -> s ValData
index (Vectorize2 s ValData -> s ValData -> s ValData
op CommonThunk s
v1 CommonThunk s
v2) = forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonVecIndex s ValData -> s ValData
index CommonThunk s
v1 s ValData -> s ValData -> s ValData
`op` forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonVecIndex s ValData -> s ValData
index CommonThunk s
v2
commonVecIndex s ValData -> s ValData
_ (SumComponents CommonThunk s
_) = forall a. HasCallStack => String -> a
error String
"Indexing into a scalar thunk"

commonThunkElim :: (CommonThunk s -> a) -> (CommonThunk s -> a) -> CommonThunk s -> a
commonThunkElim :: forall (s :: * -> *) a.
(CommonThunk s -> a) -> (CommonThunk s -> a) -> CommonThunk s -> a
commonThunkElim CommonThunk s -> a
_ CommonThunk s -> a
sumF (SumComponents CommonThunk s
v) = CommonThunk s -> a
sumF CommonThunk s
v
commonThunkElim CommonThunk s -> a
vectorF CommonThunk s -> a
_ CommonThunk s
v = CommonThunk s -> a
vectorF CommonThunk s
v

-- The dimension of a vector or the vector underlying a dot product
-- Used to generate thunkAssign loops
commonThunkDim :: (s ValData -> s ValData) -> CommonThunk s -> s ValData
commonThunkDim :: forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonThunkDim s ValData -> s ValData
dim (PureValue s ValData
v) = s ValData -> s ValData
dim s ValData
v
commonThunkDim s ValData -> s ValData
dim (Vectorize s ValData -> s ValData
_ CommonThunk s
v) = forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonThunkDim s ValData -> s ValData
dim CommonThunk s
v
commonThunkDim s ValData -> s ValData
dim (Vectorize2 s ValData -> s ValData -> s ValData
_ CommonThunk s
v1 CommonThunk s
_) = forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonThunkDim s ValData -> s ValData
dim CommonThunk s
v1
commonThunkDim s ValData -> s ValData
dim (SumComponents CommonThunk s
v) = forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonThunkDim s ValData -> s ValData
dim CommonThunk s
v