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, 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
) 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
(ScopeTag -> ScopeTag -> Bool)
-> (ScopeTag -> ScopeTag -> Bool) -> Eq ScopeTag
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
(QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool) -> Eq QualifiedName
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
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
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
$cp1Ord :: Eq 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 Header = Bool
False
isSource _ = 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 :: Binding -> a -> a -> a
onBinding Static s :: a
s _ = a
s
onBinding Dynamic _ d :: 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 m :: ModData
m f :: 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 f :: Doc -> Doc
f m :: 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 m :: MethodData
m f :: 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 f :: Doc -> Doc
f v :: 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 -> [FileData]
progMods :: [FileData]}

progD :: String -> [FileData] -> ProgData
progD :: String -> [FileData] -> ProgData
progD n :: String
n fs :: [FileData]
fs = String -> [FileData] -> ProgData
ProgD String
n ((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 -> [FileData] -> ProgData
progD "" []

-- 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 f :: Doc -> Doc
f v :: ValData
v = Maybe Int -> TypeData -> Doc -> ValData
vd (ValData -> Maybe Int
valPrec 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