module Drasil.GOOL.AST (Terminator(..), VisibilityTag(..), ScopeTag(..),
  ScopeData(..), sd, 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, valInt, valType, val), vd,
  updateValDoc, VarData(varBind, varName, varType, varDoc), vard, CommonThunk,
  pureValue, vectorize, vectorize2, sumComponents, commonVecIndex,
  commonThunkElim, commonThunkDim
) where

import Drasil.GOOL.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 VisibilityTag = Pub | Priv deriving VisibilityTag -> VisibilityTag -> Bool
(VisibilityTag -> VisibilityTag -> Bool)
-> (VisibilityTag -> VisibilityTag -> Bool) -> Eq VisibilityTag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VisibilityTag -> VisibilityTag -> Bool
== :: VisibilityTag -> VisibilityTag -> Bool
$c/= :: VisibilityTag -> VisibilityTag -> Bool
/= :: VisibilityTag -> VisibilityTag -> 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
(QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool) -> Eq QualifiedName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: QualifiedName -> QualifiedName -> Bool
== :: QualifiedName -> QualifiedName -> Bool
$c/= :: QualifiedName -> QualifiedName -> Bool
/= :: QualifiedName -> QualifiedName -> Bool
Eq, Eq QualifiedName
Eq QualifiedName =>
(QualifiedName -> QualifiedName -> Ordering)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> QualifiedName)
-> (QualifiedName -> QualifiedName -> QualifiedName)
-> Ord 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
$ccompare :: QualifiedName -> QualifiedName -> Ordering
compare :: QualifiedName -> QualifiedName -> Ordering
$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
>= :: QualifiedName -> QualifiedName -> Bool
$cmax :: QualifiedName -> QualifiedName -> QualifiedName
max :: QualifiedName -> QualifiedName -> QualifiedName
$cmin :: QualifiedName -> QualifiedName -> QualifiedName
min :: QualifiedName -> QualifiedName -> QualifiedName
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 (Doc -> Doc) -> Doc -> Doc
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 (Doc -> Doc) -> (MethodData -> Doc) -> MethodData -> Doc
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 (VarData -> String)
-> (ParamData -> VarData) -> ParamData -> String
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 (Doc -> Doc) -> (ParamData -> Doc) -> ParamData -> Doc
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 ((FileData -> Bool) -> [FileData] -> [FileData]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (FileData -> Bool) -> FileData -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> Bool
isEmpty (Doc -> Bool) -> (FileData -> Doc) -> FileData -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModData -> Doc
modDoc (ModData -> Doc) -> (FileData -> ModData) -> FileData -> Doc
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 -> VisibilityTag
getStVarScp :: VisibilityTag, StateVarData -> Doc
stVar :: Doc, 
  StateVarData -> (Doc, Terminator)
destructSts :: (Doc, Terminator)}

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

-- Used as the underlying data type for Scopes in all renderers
data ScopeTag = Local | Global deriving ScopeTag -> ScopeTag -> Bool
(ScopeTag -> ScopeTag -> Bool)
-> (ScopeTag -> ScopeTag -> Bool) -> Eq ScopeTag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ScopeTag -> ScopeTag -> Bool
== :: ScopeTag -> ScopeTag -> Bool
$c/= :: ScopeTag -> ScopeTag -> Bool
/= :: ScopeTag -> ScopeTag -> Bool
Eq

newtype ScopeData = SD {ScopeData -> ScopeTag
scopeTag :: ScopeTag}

sd :: ScopeTag -> ScopeData
sd :: ScopeTag -> ScopeData
sd = ScopeTag -> ScopeData
SD

-- 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
-- valPrec is the precedence of the operator involved if the value is an expression,
-- valInt is the int the value is holding if the value is a litInt,
-- valType is the type of the value,
-- val is the printed representation of the value.
data ValData = VD {ValData -> Maybe Int
valPrec :: Maybe Int, ValData -> Maybe Integer
valInt :: Maybe Integer, ValData -> TypeData
valType :: TypeData, ValData -> Doc
val :: Doc}

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

updateValDoc :: (Doc -> Doc) -> ValData -> ValData
updateValDoc :: (Doc -> Doc) -> ValData -> ValData
updateValDoc Doc -> Doc
f ValData
v = Maybe Int -> Maybe Integer -> TypeData -> Doc -> ValData
vd (ValData -> Maybe Int
valPrec ValData
v) (ValData -> Maybe Integer
valInt ValData
v) (ValData -> TypeData
valType ValData
v) ((Doc -> Doc
f (Doc -> Doc) -> (ValData -> Doc) -> ValData -> Doc
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 = s ValData -> CommonThunk s
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 = (s ValData -> s ValData) -> CommonThunk s -> CommonThunk s
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 = (s ValData -> s ValData -> s ValData)
-> CommonThunk s -> CommonThunk s -> CommonThunk s
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 = CommonThunk s -> CommonThunk s
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 ((s ValData -> s ValData) -> CommonThunk s -> s ValData
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) = (s ValData -> s ValData) -> CommonThunk s -> s ValData
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` (s ValData -> s ValData) -> CommonThunk s -> s ValData
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
_) = String -> s ValData
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) = (s ValData -> s ValData) -> CommonThunk s -> s ValData
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
_) = (s ValData -> s ValData) -> CommonThunk s -> s ValData
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) = (s ValData -> s ValData) -> CommonThunk s -> s ValData
forall (s :: * -> *).
(s ValData -> s ValData) -> CommonThunk s -> s ValData
commonThunkDim s ValData -> s ValData
dim CommonThunk s
v