{-# LANGUAGE PostfixOperators #-}

-- | Implementations defined here are valid for any language renderer.
module GOOL.Drasil.LanguageRenderer.LanguagePolymorphic (fileFromData,
  multiBody, block, multiBlock, listInnerType, obj, negateOp, csc, sec, 
  cot, equalOp, notEqualOp, greaterOp, greaterEqualOp, lessOp, lessEqualOp, 
  plusOp, minusOp, multOp, divideOp, moduloOp, var, staticVar, objVar,
  classVarCheckStatic, arrayElem, litChar, litDouble, litInt, litString, 
  valueOf, arg, argsList, call, funcAppMixedArgs, selfFuncAppMixedArgs, 
  newObjMixedArgs, lambda, objAccess, objMethodCall, func, get, set, listAdd, 
  listAppend, listAccess, listSet, getFunc, setFunc, 
  listAppendFunc, stmt, loopStmt, emptyStmt, assign, subAssign, increment,
  objDecNew, print, closeFile, returnStmt, valStmt, comment, throw, ifCond,
  tryCatch, construct, param, method, getMethod, setMethod, initStmts,
  function, docFuncRepr, docFunc, buildClass, implementingClass, docClass,
  commentedClass, modFromData, fileDoc, docMod, OptionalSpace(..), defaultOptSpace
) where

import Utils.Drasil (indent)

import GOOL.Drasil.CodeType (CodeType(..), ClassName)
import GOOL.Drasil.ClassInterface (Label, Library, SFile, MSBody, MSBlock, 
  VSType, SVariable, SValue, VSFunction, MSStatement, MSParameter, SMethod,
  CSStateVar, SClass, FSModule, NamedArgs, Initializers, MixedCall,
  MixedCtorCall, FileSym(File), BodySym(Body), bodyStatements, oneLiner,
  BlockSym(Block), PermanenceSym(..), TypeSym(Type), TypeElim(getType,
  getTypeString), VariableSym(Variable), VariableElim(variableName,
  variableType), ValueSym(Value, valueType), NumericExpression((#-), (#/), sin,
  cos, tan), Comparison(..), funcApp, newObj, objMethodCallNoParams, ($.),
  StatementSym(multi), AssignStatement((&++)), (&=), IOStatement(printStr,
  printStrLn, printFile, printFileStr, printFileStrLn), ifNoElse, ScopeSym(..),
  ModuleSym(Module), convType)
import qualified GOOL.Drasil.ClassInterface as S (
  TypeSym(int, double, char, string, listType, arrayType, listInnerType,
  funcType, void), VariableSym(var, objVarSelf), Literal(litInt, litFloat,
  litDouble, litString), VariableValue(valueOf), FunctionSym(func),
  List(listSize, listAccess), StatementSym(valStmt), DeclStatement(varDecDef),
  IOStatement(print), ControlStatement(returnStmt, for), ParameterSym(param),
  MethodSym(method))
import GOOL.Drasil.RendererClasses (RenderSym, RenderFile(commentedMod),  
  RenderType(..), InternalVarElim(variableBind), RenderValue(valFromData),
  RenderFunction(funcFromData), FunctionElim(functionType), 
  RenderStatement(stmtFromData),  StatementElim(statementTerm), 
  MethodTypeSym(mType), RenderParam(paramFromData), 
  RenderMethod(intMethod, commentedFunc), RenderClass(inherit, implements), 
  RenderMod(updateModuleDoc), BlockCommentSym(..))
import qualified GOOL.Drasil.RendererClasses as S (RenderFile(fileFromData), 
  RenderValue(call), InternalGetSet(getFunc, setFunc),InternalListFunc
  (listAddFunc, listAppendFunc, listAccessFunc, listSetFunc),
  RenderStatement(stmt), InternalIOStmt(..), RenderMethod(intFunc), 
  RenderClass(intClass, commentedClass))
import qualified GOOL.Drasil.RendererClasses as RC (BodyElim(..), BlockElim(..),
  InternalVarElim(variable), ValueElim(value), FunctionElim(function), 
  StatementElim(statement), ClassElim(..), ModuleElim(..), BlockCommentElim(..))
import GOOL.Drasil.AST (Binding(..), Terminator(..), isSource)
import GOOL.Drasil.Helpers (doubleQuotedText, vibcat, emptyIfEmpty, toCode, 
  toState, onStateValue, on2StateValues, onStateList, getInnerType, getNestDegree,
  on2StateWrapped)
import GOOL.Drasil.LanguageRenderer (dot, ifLabel, elseLabel, access, addExt, 
  FuncDocRenderer, ClassDocRenderer, ModuleDocRenderer, getterName, setterName, 
  valueList, namedArgList)
import qualified GOOL.Drasil.LanguageRenderer as R (file, block, assign, 
  addAssign, subAssign, return', comment, getTerm, var, objVar, arg, func, 
  objAccess, commentedItem)
import GOOL.Drasil.LanguageRenderer.Constructors (mkStmt, mkStmtNoEnd, 
  mkStateVal, mkVal, mkStateVar, mkVar, mkStaticVar, VSOp, unOpPrec, 
  compEqualPrec, compPrec, addPrec, multPrec)
import GOOL.Drasil.State (FS, CS, MS, lensFStoGS, lensMStoVS, lensCStoFS, 
  currMain, currFileType, addFile, setMainMod, setModuleName, getModuleName,
  addParameter, getParameters, useVarName)

import Prelude hiding (print,sin,cos,tan,(<>))
import Data.Maybe (fromMaybe, maybeToList)
import Control.Monad.State (modify)
import Control.Lens ((^.), over)
import Control.Lens.Zoom (zoom)
import Text.PrettyPrint.HughesPJ (Doc, text, empty, render, (<>), (<+>), parens,
  brackets, integer, vcat, comma, isEmpty, space)
import qualified Text.PrettyPrint.HughesPJ as D (char, double)

-- Bodies --

multiBody :: (RenderSym r, Monad r) => [MSBody r] -> MS (r Doc)
multiBody :: forall (r :: * -> *).
(RenderSym r, Monad r) =>
[MSBody r] -> MS (r Doc)
multiBody [MSBody r]
bs = forall a b s. ([a] -> b) -> [State s a] -> State s b
onStateList (forall (r :: * -> *) a. Monad r => a -> r a
toCode forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
vibcat) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b s. (a -> b) -> State s a -> State s b
onStateValue forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body) [MSBody r]
bs

-- Blocks --

block :: (RenderSym r, Monad r) => [MSStatement r] -> MS (r Doc)
block :: forall (r :: * -> *).
(RenderSym r, Monad r) =>
[MSStatement r] -> MS (r Doc)
block [MSStatement r]
sts = forall a b s. ([a] -> b) -> [State s a] -> State s b
onStateList (forall (r :: * -> *) a. Monad r => a -> r a
toCode forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
R.block forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement) (forall a b. (a -> b) -> [a] -> [b]
map forall (r :: * -> *).
RenderStatement r =>
MSStatement r -> MSStatement r
S.stmt [MSStatement r]
sts)

multiBlock :: (RenderSym r, Monad r) => [MSBlock r] -> MS (r Doc)
multiBlock :: forall (r :: * -> *).
(RenderSym r, Monad r) =>
[MSBlock r] -> MS (r Doc)
multiBlock [MSBlock r]
bs = forall a b s. ([a] -> b) -> [State s a] -> State s b
onStateList (forall (r :: * -> *) a. Monad r => a -> r a
toCode forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
vibcat) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b s. (a -> b) -> State s a -> State s b
onStateValue forall (r :: * -> *). BlockElim r => r (Block r) -> Doc
RC.block) [MSBlock r]
bs

-- Types --

listInnerType :: (RenderSym r) => VSType r -> VSType r
listInnerType :: forall (r :: * -> *). RenderSym r => VSType r -> VSType r
listInnerType VSType r
t = VSType r
t forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (forall (r :: * -> *). TypeSym r => CodeType -> VSType r
convType forall b c a. (b -> c) -> (a -> b) -> a -> c
. CodeType -> CodeType
getInnerType forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType)

obj :: (RenderSym r) => ClassName -> VSType r
obj :: forall (r :: * -> *). RenderSym r => ClassName -> VSType r
obj ClassName
n = forall (r :: * -> *).
RenderType r =>
CodeType -> ClassName -> Doc -> VSType r
typeFromData (ClassName -> CodeType
Object ClassName
n) ClassName
n (ClassName -> Doc
text ClassName
n)

-- Unary Operators --

negateOp :: (Monad r) => VSOp r
negateOp :: forall (r :: * -> *). Monad r => VSOp r
negateOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
unOpPrec ClassName
"-"

csc :: (RenderSym r) => SValue r -> SValue r
csc :: forall (r :: * -> *). RenderSym r => SValue r -> SValue r
csc SValue r
v = forall (r :: * -> *). RenderSym r => VSType r -> SValue r
valOfOne (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType SValue r
v) forall (r :: * -> *).
NumericExpression r =>
SValue r -> SValue r -> SValue r
#/ forall (r :: * -> *). NumericExpression r => SValue r -> SValue r
sin SValue r
v

sec :: (RenderSym r) => SValue r -> SValue r
sec :: forall (r :: * -> *). RenderSym r => SValue r -> SValue r
sec SValue r
v = forall (r :: * -> *). RenderSym r => VSType r -> SValue r
valOfOne (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType SValue r
v) forall (r :: * -> *).
NumericExpression r =>
SValue r -> SValue r -> SValue r
#/ forall (r :: * -> *). NumericExpression r => SValue r -> SValue r
cos SValue r
v

cot :: (RenderSym r) => SValue r -> SValue r
cot :: forall (r :: * -> *). RenderSym r => SValue r -> SValue r
cot SValue r
v = forall (r :: * -> *). RenderSym r => VSType r -> SValue r
valOfOne (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType SValue r
v) forall (r :: * -> *).
NumericExpression r =>
SValue r -> SValue r -> SValue r
#/ forall (r :: * -> *). NumericExpression r => SValue r -> SValue r
tan SValue r
v

valOfOne :: (RenderSym r) => VSType r -> SValue r
valOfOne :: forall (r :: * -> *). RenderSym r => VSType r -> SValue r
valOfOne VSType r
t = VSType r
t forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (forall {r :: * -> *}. Literal r => CodeType -> VS (r (Value r))
getVal forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType)
  where getVal :: CodeType -> VS (r (Value r))
getVal CodeType
Float = forall (r :: * -> *). Literal r => Float -> SValue r
S.litFloat Float
1.0
        getVal CodeType
_ = forall (r :: * -> *). Literal r => Double -> SValue r
S.litDouble Double
1.0

-- Binary Operators --

equalOp :: (Monad r) => VSOp r
equalOp :: forall (r :: * -> *). Monad r => VSOp r
equalOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
compEqualPrec ClassName
"=="

notEqualOp :: (Monad r) => VSOp r
notEqualOp :: forall (r :: * -> *). Monad r => VSOp r
notEqualOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
compEqualPrec ClassName
"!="

greaterOp :: (Monad r) => VSOp r
greaterOp :: forall (r :: * -> *). Monad r => VSOp r
greaterOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
compPrec ClassName
">"

greaterEqualOp :: (Monad r) => VSOp r
greaterEqualOp :: forall (r :: * -> *). Monad r => VSOp r
greaterEqualOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
compPrec ClassName
">="

lessOp :: (Monad r) => VSOp r
lessOp :: forall (r :: * -> *). Monad r => VSOp r
lessOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
compPrec ClassName
"<"

lessEqualOp :: (Monad r) => VSOp r
lessEqualOp :: forall (r :: * -> *). Monad r => VSOp r
lessEqualOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
compPrec ClassName
"<="

plusOp :: (Monad r) => VSOp r
plusOp :: forall (r :: * -> *). Monad r => VSOp r
plusOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
addPrec ClassName
"+"

minusOp :: (Monad r) => VSOp r
minusOp :: forall (r :: * -> *). Monad r => VSOp r
minusOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
addPrec ClassName
"-"

multOp :: (Monad r) => VSOp r
multOp :: forall (r :: * -> *). Monad r => VSOp r
multOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
multPrec ClassName
"*"

divideOp :: (Monad r) => VSOp r
divideOp :: forall (r :: * -> *). Monad r => VSOp r
divideOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
multPrec ClassName
"/"

moduloOp :: (Monad r) => VSOp r
moduloOp :: forall (r :: * -> *). Monad r => VSOp r
moduloOp = forall (r :: * -> *). Monad r => ClassName -> VSOp r
multPrec ClassName
"%"

-- Variables --

var :: (RenderSym r) => Label -> VSType r -> SVariable r
var :: forall (r :: * -> *).
RenderSym r =>
ClassName -> VSType r -> SVariable r
var ClassName
n VSType r
t = forall (r :: * -> *).
RenderSym r =>
ClassName -> VSType r -> Doc -> SVariable r
mkStateVar ClassName
n VSType r
t (ClassName -> Doc
R.var ClassName
n)

staticVar :: (RenderSym r) => Label -> VSType r -> SVariable r
staticVar :: forall (r :: * -> *).
RenderSym r =>
ClassName -> VSType r -> SVariable r
staticVar ClassName
n VSType r
t = forall (r :: * -> *).
RenderSym r =>
ClassName -> VSType r -> Doc -> SVariable r
mkStaticVar ClassName
n VSType r
t (ClassName -> Doc
R.var ClassName
n)

-- | To be used in classVar implementations. Throws an error if the variable is 
-- not static since classVar is for accessing static variables from a class
classVarCheckStatic :: (RenderSym r) => r (Variable r) -> r (Variable r)
classVarCheckStatic :: forall (r :: * -> *).
RenderSym r =>
r (Variable r) -> r (Variable r)
classVarCheckStatic r (Variable r)
v = Binding -> r (Variable r)
classVarCS (forall (r :: * -> *).
InternalVarElim r =>
r (Variable r) -> Binding
variableBind r (Variable r)
v)
  where classVarCS :: Binding -> r (Variable r)
classVarCS Binding
Dynamic = forall a. HasCallStack => ClassName -> a
error
          ClassName
"classVar can only be used to access static variables"
        classVarCS Binding
Static = r (Variable r)
v

objVar :: (RenderSym r) => SVariable r -> SVariable r -> SVariable r
objVar :: forall (r :: * -> *).
RenderSym r =>
SVariable r -> SVariable r -> SVariable r
objVar SVariable r
o' SVariable r
v' = do
  r (Variable r)
o <- SVariable r
o'
  r (Variable r)
v <- SVariable r
v'
  let objVar' :: Binding -> SVariable r
objVar' Binding
Static = forall a. HasCallStack => ClassName -> a
error 
        ClassName
"Cannot access static variables through an object, use classVar instead"
      objVar' Binding
Dynamic = forall (r :: * -> *).
RenderSym r =>
ClassName -> r (Type r) -> Doc -> SVariable r
mkVar (forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName r (Variable r)
o ClassName -> ClassName -> ClassName
`access` forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName r (Variable r)
v) 
        (forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
v) (Doc -> Doc -> Doc
R.objVar (forall (r :: * -> *). InternalVarElim r => r (Variable r) -> Doc
RC.variable r (Variable r)
o) (forall (r :: * -> *). InternalVarElim r => r (Variable r) -> Doc
RC.variable r (Variable r)
v))
  Binding -> SVariable r
objVar' (forall (r :: * -> *).
InternalVarElim r =>
r (Variable r) -> Binding
variableBind r (Variable r)
v)

arrayElem :: (RenderSym r) => SValue r -> SVariable r -> SVariable r
arrayElem :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SVariable r -> SVariable r
arrayElem SValue r
i' SVariable r
v' = do
  r (Value r)
i <- SValue r
i'
  r (Variable r)
v <- SVariable r
v'
  let vName :: ClassName
vName = forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName r (Variable r)
v forall a. [a] -> [a] -> [a]
++ ClassName
"[" forall a. [a] -> [a] -> [a]
++ Doc -> ClassName
render (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
i) forall a. [a] -> [a] -> [a]
++ ClassName
"]"
      vType :: VSType r
vType = forall (r :: * -> *). RenderSym r => VSType r -> VSType r
listInnerType forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
v
      vRender :: Doc
vRender = forall (r :: * -> *). InternalVarElim r => r (Variable r) -> Doc
RC.variable r (Variable r)
v Doc -> Doc -> Doc
<> Doc -> Doc
brackets (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
i)
  forall (r :: * -> *).
RenderSym r =>
ClassName -> VSType r -> Doc -> SVariable r
mkStateVar ClassName
vName VSType r
vType Doc
vRender

-- Values --

litChar :: (RenderSym r) => (Doc -> Doc) -> Char -> SValue r
litChar :: forall (r :: * -> *).
RenderSym r =>
(Doc -> Doc) -> Char -> SValue r
litChar Doc -> Doc
f Char
c = forall (r :: * -> *). RenderSym r => VSType r -> Doc -> SValue r
mkStateVal forall (r :: * -> *). TypeSym r => VSType r
S.char (Doc -> Doc
f forall a b. (a -> b) -> a -> b
$ if Char
c forall a. Eq a => a -> a -> Bool
== Char
'\n' then ClassName -> Doc
text ClassName
"\\n" else Char -> Doc
D.char Char
c)

litDouble :: (RenderSym r) => Double -> SValue r
litDouble :: forall (r :: * -> *). RenderSym r => Double -> SValue r
litDouble Double
d = forall (r :: * -> *). RenderSym r => VSType r -> Doc -> SValue r
mkStateVal forall (r :: * -> *). TypeSym r => VSType r
S.double (Double -> Doc
D.double Double
d)

litInt :: (RenderSym r) => Integer -> SValue r
litInt :: forall (r :: * -> *). RenderSym r => Integer -> SValue r
litInt Integer
i = forall (r :: * -> *). RenderSym r => VSType r -> Doc -> SValue r
mkStateVal forall (r :: * -> *). TypeSym r => VSType r
S.int (Integer -> Doc
integer Integer
i)

litString :: (RenderSym r) => String -> SValue r
litString :: forall (r :: * -> *). RenderSym r => ClassName -> SValue r
litString ClassName
s = forall (r :: * -> *). RenderSym r => VSType r -> Doc -> SValue r
mkStateVal forall (r :: * -> *). TypeSym r => VSType r
S.string (ClassName -> Doc
doubleQuotedText ClassName
s)

valueOf :: (RenderSym r) => SVariable r -> SValue r
valueOf :: forall (r :: * -> *). RenderSym r => SVariable r -> SValue r
valueOf SVariable r
v' = do 
  r (Variable r)
v <- SVariable r
v'
  forall (r :: * -> *). RenderSym r => r (Type r) -> Doc -> SValue r
mkVal (forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
v) (forall (r :: * -> *). InternalVarElim r => r (Variable r) -> Doc
RC.variable r (Variable r)
v)

arg :: (RenderSym r) => SValue r -> SValue r -> SValue r
arg :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SValue r -> SValue r
arg SValue r
n' SValue r
args' = do 
  r (Value r)
n <- SValue r
n'
  r (Value r)
args <- SValue r
args'
  r (Type r)
s <- forall (r :: * -> *). TypeSym r => VSType r
S.string
  forall (r :: * -> *). RenderSym r => r (Type r) -> Doc -> SValue r
mkVal r (Type r)
s (forall (r :: * -> *).
RenderSym r =>
r (Value r) -> r (Value r) -> Doc
R.arg r (Value r)
n r (Value r)
args)

argsList :: (RenderSym r) => String -> SValue r
argsList :: forall (r :: * -> *). RenderSym r => ClassName -> SValue r
argsList ClassName
l = forall (r :: * -> *). RenderSym r => VSType r -> Doc -> SValue r
mkStateVal (forall (r :: * -> *). TypeSym r => VSType r -> VSType r
S.arrayType forall (r :: * -> *). TypeSym r => VSType r
S.string) (ClassName -> Doc
text ClassName
l)

-- | First parameter is separator between name and value for named arguments, 
-- rest similar to call from ClassInterface
call :: (RenderSym r) => Doc -> Maybe Library -> Maybe Doc -> MixedCall r
call :: forall (r :: * -> *).
RenderSym r =>
Doc -> Maybe ClassName -> Maybe Doc -> MixedCall r
call Doc
sep Maybe ClassName
lib Maybe Doc
o ClassName
n VSType r
t [SValue r]
pas NamedArgs r
nas = do
  [r (Value r)]
pargs <- forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [SValue r]
pas
  [r (Variable r)]
nms <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall a b. (a, b) -> a
fst NamedArgs r
nas
  [r (Value r)]
nargs <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall a b. (a, b) -> b
snd NamedArgs r
nas
  let libDoc :: Doc
libDoc = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ClassName -> Doc
text ClassName
n) (ClassName -> Doc
text forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ClassName -> ClassName -> ClassName
`access` ClassName
n)) Maybe ClassName
lib
      obDoc :: Doc
obDoc = forall a. a -> Maybe a -> a
fromMaybe Doc
empty Maybe Doc
o
  forall (r :: * -> *). RenderSym r => VSType r -> Doc -> SValue r
mkStateVal VSType r
t forall a b. (a -> b) -> a -> b
$ Doc
obDoc Doc -> Doc -> Doc
<> Doc
libDoc Doc -> Doc -> Doc
<> Doc -> Doc
parens (forall (r :: * -> *). RenderSym r => [r (Value r)] -> Doc
valueList [r (Value r)]
pargs Doc -> Doc -> Doc
<> 
    (if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SValue r]
pas Bool -> Bool -> Bool
|| forall (t :: * -> *) a. Foldable t => t a -> Bool
null NamedArgs r
nas then Doc
empty else Doc
comma) Doc -> Doc -> Doc
<+> forall (r :: * -> *).
RenderSym r =>
Doc -> [(r (Variable r), r (Value r))] -> Doc
namedArgList Doc
sep 
    (forall a b. [a] -> [b] -> [(a, b)]
zip [r (Variable r)]
nms [r (Value r)]
nargs))

funcAppMixedArgs :: (RenderSym r) => MixedCall r
funcAppMixedArgs :: forall (r :: * -> *). RenderSym r => MixedCall r
funcAppMixedArgs = forall (r :: * -> *).
RenderValue r =>
Maybe ClassName -> Maybe Doc -> MixedCall r
S.call forall a. Maybe a
Nothing forall a. Maybe a
Nothing

selfFuncAppMixedArgs :: (RenderSym r) => Doc -> SVariable r -> MixedCall r
selfFuncAppMixedArgs :: forall (r :: * -> *).
RenderSym r =>
Doc -> SVariable r -> MixedCall r
selfFuncAppMixedArgs Doc
d SVariable r
slf ClassName
n VSType r
t [SValue r]
vs NamedArgs r
ns = do
  r (Variable r)
s <- SVariable r
slf 
  forall (r :: * -> *).
RenderValue r =>
Maybe ClassName -> Maybe Doc -> MixedCall r
S.call forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). InternalVarElim r => r (Variable r) -> Doc
RC.variable r (Variable r)
s Doc -> Doc -> Doc
<> Doc
d) ClassName
n VSType r
t [SValue r]
vs NamedArgs r
ns

newObjMixedArgs :: (RenderSym r) => String -> MixedCtorCall r
newObjMixedArgs :: forall (r :: * -> *). RenderSym r => MixedCall r
newObjMixedArgs ClassName
s VSType r
tp [SValue r]
vs NamedArgs r
ns = do
  r (Type r)
t <- VSType r
tp 
  forall (r :: * -> *).
RenderValue r =>
Maybe ClassName -> Maybe Doc -> MixedCall r
S.call forall a. Maybe a
Nothing forall a. Maybe a
Nothing (ClassName
s forall a. [a] -> [a] -> [a]
++ forall (r :: * -> *). TypeElim r => r (Type r) -> ClassName
getTypeString r (Type r)
t) (forall (m :: * -> *) a. Monad m => a -> m a
return r (Type r)
t) [SValue r]
vs NamedArgs r
ns

lambda :: (RenderSym r) => ([r (Variable r)] -> r (Value r) -> Doc) -> 
  [SVariable r] -> SValue r -> SValue r
lambda :: forall (r :: * -> *).
RenderSym r =>
([r (Variable r)] -> r (Value r) -> Doc)
-> [SVariable r] -> SValue r -> SValue r
lambda [r (Variable r)] -> r (Value r) -> Doc
f [SVariable r]
ps' SValue r
ex' = do
  [r (Variable r)]
ps <- forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [SVariable r]
ps'
  r (Value r)
ex <- SValue r
ex'
  let ft :: VSType r
ft = forall (r :: * -> *).
TypeSym r =>
[VSType r] -> VSType r -> VSType r
S.funcType (forall a b. (a -> b) -> [a] -> [b]
map (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType) [r (Variable r)]
ps) (forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType r (Value r)
ex)
  forall (r :: * -> *).
RenderValue r =>
Maybe Int -> VSType r -> Doc -> SValue r
valFromData (forall a. a -> Maybe a
Just Int
0) VSType r
ft ([r (Variable r)] -> r (Value r) -> Doc
f [r (Variable r)]
ps r (Value r)
ex)

objAccess :: (RenderSym r) => SValue r -> VSFunction r -> SValue r
objAccess :: forall (r :: * -> *).
RenderSym r =>
SValue r -> VSFunction r -> SValue r
objAccess = forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
on2StateWrapped (\r (Value r)
v r (Function r)
f-> forall (r :: * -> *). RenderSym r => r (Type r) -> Doc -> SValue r
mkVal (forall (r :: * -> *).
FunctionElim r =>
r (Function r) -> r (Type r)
functionType r (Function r)
f) 
  (Doc -> Doc -> Doc
R.objAccess (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
v) (forall (r :: * -> *). FunctionElim r => r (Function r) -> Doc
RC.function r (Function r)
f)))

objMethodCall :: (RenderSym r) => Label -> VSType r -> SValue r -> [SValue r] 
  -> NamedArgs r -> SValue r
objMethodCall :: forall (r :: * -> *).
RenderSym r =>
ClassName
-> VSType r -> SValue r -> [SValue r] -> NamedArgs r -> SValue r
objMethodCall ClassName
f VSType r
t SValue r
ob [SValue r]
vs NamedArgs r
ns = SValue r
ob forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\r (Value r)
o -> forall (r :: * -> *).
RenderValue r =>
Maybe ClassName -> Maybe Doc -> MixedCall r
S.call forall a. Maybe a
Nothing 
  (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
o Doc -> Doc -> Doc
<> Doc
dot) ClassName
f VSType r
t [SValue r]
vs NamedArgs r
ns)

-- Functions --

func :: (RenderSym r) => Label -> VSType r -> [SValue r] -> VSFunction r
func :: forall (r :: * -> *).
RenderSym r =>
ClassName -> VSType r -> [SValue r] -> VSFunction r
func ClassName
l VSType r
t [SValue r]
vs = forall (r :: * -> *). ValueExpression r => PosCall r
funcApp ClassName
l VSType r
t [SValue r]
vs forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ((forall (r :: * -> *).
RenderFunction r =>
Doc -> VSType r -> VSFunction r
`funcFromData` VSType r
t) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> Doc
R.func forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value)

get :: (RenderSym r) => SValue r -> SVariable r -> SValue r
get :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SVariable r -> SValue r
get SValue r
v SVariable r
vToGet = SValue r
v forall (r :: * -> *).
FunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. forall (r :: * -> *).
InternalGetSet r =>
SVariable r -> VSFunction r
S.getFunc SVariable r
vToGet

set :: (RenderSym r) => SValue r -> SVariable r -> SValue r -> SValue r
set :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SVariable r -> SValue r -> SValue r
set SValue r
v SVariable r
vToSet SValue r
toVal = SValue r
v forall (r :: * -> *).
FunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. forall (r :: * -> *).
InternalGetSet r =>
VSType r -> SVariable r -> SValue r -> VSFunction r
S.setFunc (forall a b s. (a -> b) -> State s a -> State s b
onStateValue forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType SValue r
v) SVariable r
vToSet SValue r
toVal

listAdd :: (RenderSym r) => SValue r -> SValue r -> SValue r -> SValue r
listAdd :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SValue r -> SValue r -> SValue r
listAdd SValue r
v SValue r
i SValue r
vToAdd = SValue r
v forall (r :: * -> *).
FunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. forall (r :: * -> *).
InternalListFunc r =>
SValue r -> SValue r -> SValue r -> VSFunction r
S.listAddFunc SValue r
v SValue r
i SValue r
vToAdd

listAppend :: (RenderSym r) => SValue r -> SValue r -> SValue r
listAppend :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SValue r -> SValue r
listAppend SValue r
v SValue r
vToApp = SValue r
v forall (r :: * -> *).
FunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. forall (r :: * -> *).
InternalListFunc r =>
SValue r -> VSFunction r
S.listAppendFunc SValue r
vToApp

listAccess :: (RenderSym r) => SValue r -> SValue r -> SValue r
listAccess :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SValue r -> SValue r
listAccess SValue r
v SValue r
i = do
  r (Value r)
v' <- SValue r
v
  let checkType :: CodeType -> VSFunction r
checkType (List CodeType
_) = forall (r :: * -> *).
InternalListFunc r =>
VSType r -> SValue r -> VSFunction r
S.listAccessFunc (forall (r :: * -> *). TypeSym r => VSType r -> VSType r
S.listInnerType forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ 
        forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType r (Value r)
v') SValue r
i
      checkType (Array CodeType
_) = SValue r
i forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\r (Value r)
ix -> forall (r :: * -> *).
RenderFunction r =>
Doc -> VSType r -> VSFunction r
funcFromData (Doc -> Doc
brackets (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
ix)) 
        (forall (r :: * -> *). TypeSym r => VSType r -> VSType r
S.listInnerType forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType r (Value r)
v'))
      checkType CodeType
_ = forall a. HasCallStack => ClassName -> a
error ClassName
"listAccess called on non-list-type value"
  SValue r
v forall (r :: * -> *).
FunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. CodeType -> VSFunction r
checkType (forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType (forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType r (Value r)
v'))

listSet :: (RenderSym r) => SValue r -> SValue r -> SValue r -> SValue r
listSet :: forall (r :: * -> *).
RenderSym r =>
SValue r -> SValue r -> SValue r -> SValue r
listSet SValue r
v SValue r
i SValue r
toVal = SValue r
v forall (r :: * -> *).
FunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. forall (r :: * -> *).
InternalListFunc r =>
SValue r -> SValue r -> SValue r -> VSFunction r
S.listSetFunc SValue r
v SValue r
i SValue r
toVal

getFunc :: (RenderSym r) => SVariable r -> VSFunction r
getFunc :: forall (r :: * -> *). RenderSym r => SVariable r -> VSFunction r
getFunc SVariable r
v = SVariable r
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\r (Variable r)
vr -> forall (r :: * -> *).
FunctionSym r =>
ClassName -> VSType r -> [SValue r] -> VSFunction r
S.func (ClassName -> ClassName
getterName forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName r (Variable r)
vr) 
  (forall a s. a -> State s a
toState forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
vr) [])

setFunc :: (RenderSym r) => VSType r -> SVariable r -> SValue r -> VSFunction r
setFunc :: forall (r :: * -> *).
RenderSym r =>
VSType r -> SVariable r -> SValue r -> VSFunction r
setFunc VSType r
t SVariable r
v SValue r
toVal = SVariable r
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\r (Variable r)
vr -> forall (r :: * -> *).
FunctionSym r =>
ClassName -> VSType r -> [SValue r] -> VSFunction r
S.func (ClassName -> ClassName
setterName forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName r (Variable r)
vr) VSType r
t 
  [SValue r
toVal])

listAppendFunc :: (RenderSym r) => Label -> SValue r -> VSFunction r
listAppendFunc :: forall (r :: * -> *).
RenderSym r =>
ClassName -> SValue r -> VSFunction r
listAppendFunc ClassName
f SValue r
v = forall (r :: * -> *).
FunctionSym r =>
ClassName -> VSType r -> [SValue r] -> VSFunction r
S.func ClassName
f (forall (r :: * -> *). TypeSym r => VSType r -> VSType r
S.listType forall a b. (a -> b) -> a -> b
$ forall a b s. (a -> b) -> State s a -> State s b
onStateValue forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType SValue r
v) [SValue r
v]

-- Statements --

stmt :: (RenderSym r) => MSStatement r -> MSStatement r
stmt :: forall (r :: * -> *). RenderSym r => MSStatement r -> MSStatement r
stmt MSStatement r
s' = do 
  r (Statement r)
s <- MSStatement r
s'
  forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmtNoEnd (forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement r (Statement r)
s Doc -> Doc -> Doc
<> Terminator -> Doc
R.getTerm (forall (r :: * -> *).
StatementElim r =>
r (Statement r) -> Terminator
statementTerm r (Statement r)
s))

loopStmt :: (RenderSym r) => MSStatement r -> MSStatement r
loopStmt :: forall (r :: * -> *). RenderSym r => MSStatement r -> MSStatement r
loopStmt = forall (r :: * -> *).
RenderStatement r =>
MSStatement r -> MSStatement r
S.stmt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). RenderSym r => MSStatement r -> MSStatement r
setEmpty

emptyStmt :: (RenderSym r) => MSStatement r
emptyStmt :: forall (r :: * -> *). RenderSym r => MSStatement r
emptyStmt = forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmtNoEnd Doc
empty

assign :: (RenderSym r) => Terminator -> SVariable r -> SValue r -> 
  MSStatement r
assign :: forall (r :: * -> *).
RenderSym r =>
Terminator -> SVariable r -> SValue r -> MSStatement r
assign Terminator
t SVariable r
vr' SValue r
v' = do 
  r (Variable r)
vr <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SVariable r
vr'
  r (Value r)
v <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SValue r
v'
  forall (r :: * -> *).
RenderStatement r =>
Doc -> Terminator -> MSStatement r
stmtFromData (forall (r :: * -> *).
RenderSym r =>
r (Variable r) -> r (Value r) -> Doc
R.assign r (Variable r)
vr r (Value r)
v) Terminator
t

subAssign :: (RenderSym r) => Terminator -> SVariable r -> SValue r -> 
  MSStatement r
subAssign :: forall (r :: * -> *).
RenderSym r =>
Terminator -> SVariable r -> SValue r -> MSStatement r
subAssign Terminator
t SVariable r
vr' SValue r
v' = do 
  r (Variable r)
vr <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SVariable r
vr'
  r (Value r)
v <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SValue r
v'
  forall (r :: * -> *).
RenderStatement r =>
Doc -> Terminator -> MSStatement r
stmtFromData (forall (r :: * -> *).
RenderSym r =>
r (Variable r) -> r (Value r) -> Doc
R.subAssign r (Variable r)
vr r (Value r)
v) Terminator
t

increment :: (RenderSym r) => SVariable r -> SValue r -> MSStatement r
increment :: forall (r :: * -> *).
RenderSym r =>
SVariable r -> SValue r -> MSStatement r
increment SVariable r
vr' SValue r
v'= do 
  r (Variable r)
vr <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SVariable r
vr'
  r (Value r)
v <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SValue r
v'
  forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmt forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
RenderSym r =>
r (Variable r) -> r (Value r) -> Doc
R.addAssign r (Variable r)
vr r (Value r)
v

objDecNew :: (RenderSym r) => SVariable r -> [SValue r] -> MSStatement r
objDecNew :: forall (r :: * -> *).
RenderSym r =>
SVariable r -> [SValue r] -> MSStatement r
objDecNew SVariable r
v [SValue r]
vs = forall (r :: * -> *).
DeclStatement r =>
SVariable r -> SValue r -> MSStatement r
S.varDecDef SVariable r
v (forall (r :: * -> *). ValueExpression r => PosCtorCall r
newObj (forall a b s. (a -> b) -> State s a -> State s b
onStateValue forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType SVariable r
v) [SValue r]
vs)

printList :: (RenderSym r) => Integer -> SValue r -> (SValue r -> MSStatement r)
  -> (String -> MSStatement r) -> (String -> MSStatement r) -> MSStatement r
printList :: forall (r :: * -> *).
RenderSym r =>
Integer
-> SValue r
-> (SValue r -> MSStatement r)
-> (ClassName -> MSStatement r)
-> (ClassName -> MSStatement r)
-> MSStatement r
printList Integer
n SValue r
v SValue r -> MSStatement r
prFn ClassName -> MSStatement r
prStrFn ClassName -> MSStatement r
prLnFn = forall (r :: * -> *).
StatementSym r =>
[MSStatement r] -> MSStatement r
multi [ClassName -> MSStatement r
prStrFn ClassName
"[", 
  forall (r :: * -> *).
ControlStatement r =>
MSStatement r
-> SValue r -> MSStatement r -> MSBody r -> MSStatement r
S.for (forall (r :: * -> *).
DeclStatement r =>
SVariable r -> SValue r -> MSStatement r
S.varDecDef VS (r (Variable r))
i (forall (r :: * -> *). Literal r => Integer -> SValue r
S.litInt Integer
0)) 
    (forall (r :: * -> *). VariableValue r => SVariable r -> SValue r
S.valueOf VS (r (Variable r))
i forall (r :: * -> *).
Comparison r =>
SValue r -> SValue r -> SValue r
?< (forall (r :: * -> *). List r => SValue r -> SValue r
S.listSize SValue r
v forall (r :: * -> *).
NumericExpression r =>
SValue r -> SValue r -> SValue r
#- forall (r :: * -> *). Literal r => Integer -> SValue r
S.litInt Integer
1)) (VS (r (Variable r))
i &++) 
    (forall (r :: * -> *). BodySym r => [MSStatement r] -> MSBody r
bodyStatements [SValue r -> MSStatement r
prFn (forall (r :: * -> *). List r => SValue r -> SValue r -> SValue r
S.listAccess SValue r
v (forall (r :: * -> *). VariableValue r => SVariable r -> SValue r
S.valueOf VS (r (Variable r))
i)), ClassName -> MSStatement r
prStrFn ClassName
", "]), 
  forall (r :: * -> *).
ControlStatement r =>
[(SValue r, MSBody r)] -> MSStatement r
ifNoElse [(forall (r :: * -> *). List r => SValue r -> SValue r
S.listSize SValue r
v forall (r :: * -> *).
Comparison r =>
SValue r -> SValue r -> SValue r
?> forall (r :: * -> *). Literal r => Integer -> SValue r
S.litInt Integer
0, forall (r :: * -> *). BodySym r => MSStatement r -> MSBody r
oneLiner forall a b. (a -> b) -> a -> b
$
    SValue r -> MSStatement r
prFn (forall (r :: * -> *). List r => SValue r -> SValue r -> SValue r
S.listAccess SValue r
v (forall (r :: * -> *). List r => SValue r -> SValue r
S.listSize SValue r
v forall (r :: * -> *).
NumericExpression r =>
SValue r -> SValue r -> SValue r
#- forall (r :: * -> *). Literal r => Integer -> SValue r
S.litInt Integer
1)))], 
  ClassName -> MSStatement r
prLnFn ClassName
"]"]
  where l_i :: ClassName
l_i = ClassName
"list_i" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> ClassName
show Integer
n
        i :: VS (r (Variable r))
i = forall (r :: * -> *).
VariableSym r =>
ClassName -> VSType r -> SVariable r
S.var ClassName
l_i forall (r :: * -> *). TypeSym r => VSType r
S.int

printObj :: ClassName -> (String -> MSStatement r) -> MSStatement r
printObj :: forall (r :: * -> *).
ClassName -> (ClassName -> MSStatement r) -> MSStatement r
printObj ClassName
n ClassName -> MSStatement r
prLnFn = ClassName -> MSStatement r
prLnFn forall a b. (a -> b) -> a -> b
$ ClassName
"Instance of " forall a. [a] -> [a] -> [a]
++ ClassName
n forall a. [a] -> [a] -> [a]
++ ClassName
" object"

print :: (RenderSym r) => Bool -> Maybe (SValue r) -> SValue r -> SValue r -> 
  MSStatement r
print :: forall (r :: * -> *).
RenderSym r =>
Bool -> Maybe (SValue r) -> SValue r -> SValue r -> MSStatement r
print Bool
newLn Maybe (SValue r)
f SValue r
printFn SValue r
v = forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SValue r
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CodeType -> StateT MethodState Identity (r (Statement r))
print' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType
  where print' :: CodeType -> StateT MethodState Identity (r (Statement r))
print' (List CodeType
t) = forall (r :: * -> *).
RenderSym r =>
Integer
-> SValue r
-> (SValue r -> MSStatement r)
-> (ClassName -> MSStatement r)
-> (ClassName -> MSStatement r)
-> MSStatement r
printList (Integer -> CodeType -> Integer
getNestDegree Integer
1 CodeType
t) SValue r
v SValue r -> StateT MethodState Identity (r (Statement r))
prFn ClassName -> StateT MethodState Identity (r (Statement r))
prStrFn 
          ClassName -> StateT MethodState Identity (r (Statement r))
prLnFn
        print' (Object ClassName
n) = forall (r :: * -> *).
ClassName -> (ClassName -> MSStatement r) -> MSStatement r
printObj ClassName
n ClassName -> StateT MethodState Identity (r (Statement r))
prLnFn
        print' CodeType
_ = forall (r :: * -> *).
InternalIOStmt r =>
Bool -> Maybe (SValue r) -> SValue r -> SValue r -> MSStatement r
S.printSt Bool
newLn Maybe (SValue r)
f SValue r
printFn SValue r
v
        prFn :: SValue r -> StateT MethodState Identity (r (Statement r))
prFn = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (r :: * -> *). IOStatement r => SValue r -> MSStatement r
S.print forall (r :: * -> *).
IOStatement r =>
SValue r -> SValue r -> MSStatement r
printFile Maybe (SValue r)
f
        prStrFn :: ClassName -> StateT MethodState Identity (r (Statement r))
prStrFn = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (r :: * -> *). IOStatement r => ClassName -> MSStatement r
printStr forall (r :: * -> *).
IOStatement r =>
SValue r -> ClassName -> MSStatement r
printFileStr Maybe (SValue r)
f
        prLnFn :: ClassName -> StateT MethodState Identity (r (Statement r))
prLnFn = if Bool
newLn then forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (r :: * -> *). IOStatement r => ClassName -> MSStatement r
printStrLn forall (r :: * -> *).
IOStatement r =>
SValue r -> ClassName -> MSStatement r
printFileStrLn Maybe (SValue r)
f else forall b a. b -> (a -> b) -> Maybe a -> b
maybe 
          forall (r :: * -> *). IOStatement r => ClassName -> MSStatement r
printStr forall (r :: * -> *).
IOStatement r =>
SValue r -> ClassName -> MSStatement r
printFileStr Maybe (SValue r)
f 

closeFile :: (RenderSym r) => Label -> SValue r -> MSStatement r
closeFile :: forall (r :: * -> *).
RenderSym r =>
ClassName -> SValue r -> MSStatement r
closeFile ClassName
n SValue r
f = forall (r :: * -> *). StatementSym r => SValue r -> MSStatement r
S.valStmt forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
InternalValueExp r =>
VSType r -> SValue r -> ClassName -> SValue r
objMethodCallNoParams forall (r :: * -> *). TypeSym r => VSType r
S.void SValue r
f ClassName
n

returnStmt :: (RenderSym r) => Terminator -> SValue r -> MSStatement r
returnStmt :: forall (r :: * -> *).
RenderSym r =>
Terminator -> SValue r -> MSStatement r
returnStmt Terminator
t SValue r
v' = do 
  r (Value r)
v <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SValue r
v'
  forall (r :: * -> *).
RenderStatement r =>
Doc -> Terminator -> MSStatement r
stmtFromData (forall (r :: * -> *). RenderSym r => [r (Value r)] -> Doc
R.return' [r (Value r)
v]) Terminator
t

valStmt :: (RenderSym r) => Terminator -> SValue r -> MSStatement r
valStmt :: forall (r :: * -> *).
RenderSym r =>
Terminator -> SValue r -> MSStatement r
valStmt Terminator
t SValue r
v' = do 
  r (Value r)
v <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SValue r
v'
  forall (r :: * -> *).
RenderStatement r =>
Doc -> Terminator -> MSStatement r
stmtFromData (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
v) Terminator
t

comment :: (RenderSym r) => Doc -> Label -> MSStatement r
comment :: forall (r :: * -> *).
RenderSym r =>
Doc -> ClassName -> MSStatement r
comment Doc
cs ClassName
c = forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmtNoEnd (ClassName -> Doc -> Doc
R.comment ClassName
c Doc
cs)

throw :: (RenderSym r) => (r (Value r) -> Doc) -> Terminator -> Label -> 
  MSStatement r
throw :: forall (r :: * -> *).
RenderSym r =>
(r (Value r) -> Doc) -> Terminator -> ClassName -> MSStatement r
throw r (Value r) -> Doc
f Terminator
t ClassName
l = do 
  r (Value r)
msg <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS (forall (r :: * -> *). Literal r => ClassName -> SValue r
S.litString ClassName
l)
  forall (r :: * -> *).
RenderStatement r =>
Doc -> Terminator -> MSStatement r
stmtFromData (r (Value r) -> Doc
f r (Value r)
msg) Terminator
t

newtype OptionalSpace = OSpace {OptionalSpace -> Doc
oSpace :: Doc}

defaultOptSpace :: OptionalSpace
defaultOptSpace :: OptionalSpace
defaultOptSpace = OSpace {oSpace :: Doc
oSpace = Doc
space}

optSpaceDoc :: OptionalSpace -> Doc
optSpaceDoc :: OptionalSpace -> Doc
optSpaceDoc OSpace {oSpace :: OptionalSpace -> Doc
oSpace = Doc
sp} = Doc
sp

-- ControlStatements --

-- 1st parameter is a Doc function to use on the render of each condition (i.e. parens)
-- 2nd parameter is the syntax for starting a block in an if-condition
-- 3rd parameter is the keyword for an else-if statement
-- 4th parameter is the syntax for ending a block in an if-condition
ifCond :: (RenderSym r) => (Doc -> Doc) -> Doc -> OptionalSpace -> Doc -> Doc ->
  [(SValue r, MSBody r)] -> MSBody r -> MSStatement r
ifCond :: forall (r :: * -> *).
RenderSym r =>
(Doc -> Doc)
-> Doc
-> OptionalSpace
-> Doc
-> Doc
-> [(SValue r, MSBody r)]
-> MSBody r
-> MSStatement r
ifCond Doc -> Doc
_ Doc
_ OptionalSpace
_ Doc
_ Doc
_ [] MSBody r
_ = forall a. HasCallStack => ClassName -> a
error ClassName
"if condition created with no cases"
ifCond Doc -> Doc
f Doc
ifStart OptionalSpace
os Doc
elif Doc
bEnd ((SValue r, MSBody r)
c:[(SValue r, MSBody r)]
cs) MSBody r
eBody =
    let ifSect :: (StateT ValueState Identity (r (Value r)),
 State MethodState (r (Body r)))
-> State MethodState Doc
ifSect (StateT ValueState Identity (r (Value r))
v, State MethodState (r (Body r))
b) = forall a b c s.
(a -> b -> c) -> State s a -> State s b -> State s c
on2StateValues (\r (Value r)
val r (Body r)
bd -> [Doc] -> Doc
vcat [
          Doc
ifLabel Doc -> Doc -> Doc
<+> Doc -> Doc
f (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
val) Doc -> Doc -> Doc
<> OptionalSpace -> Doc
optSpaceDoc OptionalSpace
os Doc -> Doc -> Doc
<> Doc
ifStart,
          Doc -> Doc
indent forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body r (Body r)
bd,
          Doc
bEnd]) (forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS StateT ValueState Identity (r (Value r))
v) State MethodState (r (Body r))
b
        elseIfSect :: (StateT ValueState Identity (r (Value r)),
 State MethodState (r (Body r)))
-> State MethodState Doc
elseIfSect (StateT ValueState Identity (r (Value r))
v, State MethodState (r (Body r))
b) = forall a b c s.
(a -> b -> c) -> State s a -> State s b -> State s c
on2StateValues (\r (Value r)
val r (Body r)
bd -> [Doc] -> Doc
vcat [
          Doc
elif Doc -> Doc -> Doc
<+> Doc -> Doc
f (forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
val) Doc -> Doc -> Doc
<> OptionalSpace -> Doc
optSpaceDoc OptionalSpace
os Doc -> Doc -> Doc
<> Doc
ifStart,
          Doc -> Doc
indent forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body r (Body r)
bd,
          Doc
bEnd]) (forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS StateT ValueState Identity (r (Value r))
v) State MethodState (r (Body r))
b
        elseSect :: State MethodState Doc
elseSect = forall a b s. (a -> b) -> State s a -> State s b
onStateValue (\r (Body r)
bd -> Doc -> Doc -> Doc
emptyIfEmpty (forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body r (Body r)
bd) forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [
          Doc
elseLabel Doc -> Doc -> Doc
<> OptionalSpace -> Doc
optSpaceDoc OptionalSpace
os Doc -> Doc -> Doc
<> Doc
ifStart,
          Doc -> Doc
indent forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body r (Body r)
bd,
          Doc
bEnd]) MSBody r
eBody
    in forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence (forall {r :: * -> *} {r :: * -> *}.
(ValueElim r, BodyElim r) =>
(StateT ValueState Identity (r (Value r)),
 State MethodState (r (Body r)))
-> State MethodState Doc
ifSect (SValue r, MSBody r)
c forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map forall {r :: * -> *} {r :: * -> *}.
(ValueElim r, BodyElim r) =>
(StateT ValueState Identity (r (Value r)),
 State MethodState (r (Body r)))
-> State MethodState Doc
elseIfSect [(SValue r, MSBody r)]
cs forall a. [a] -> [a] -> [a]
++ [State MethodState Doc
elseSect]) 
      forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmtNoEnd forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc] -> Doc
vcat)

tryCatch :: (RenderSym r) => (r (Body r) -> r (Body r) -> Doc) -> MSBody r -> 
  MSBody r -> MSStatement r
tryCatch :: forall (r :: * -> *).
RenderSym r =>
(r (Body r) -> r (Body r) -> Doc)
-> MSBody r -> MSBody r -> MSStatement r
tryCatch r (Body r) -> r (Body r) -> Doc
f = forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> m a -> m b -> m c
on2StateWrapped (\r (Body r)
tb1 r (Body r)
tb2 -> forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmtNoEnd (r (Body r) -> r (Body r) -> Doc
f r (Body r)
tb1 r (Body r)
tb2))

-- Methods --

construct :: (RenderSym r) => Label -> MS (r (Type r))
construct :: forall (r :: * -> *). RenderSym r => ClassName -> MS (r (Type r))
construct ClassName
n = forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
RenderType r =>
CodeType -> ClassName -> Doc -> VSType r
typeFromData (ClassName -> CodeType
Object ClassName
n) ClassName
n Doc
empty

param :: (RenderSym r) => (r (Variable r) -> Doc) -> SVariable r -> 
  MSParameter r
param :: forall (r :: * -> *).
RenderSym r =>
(r (Variable r) -> Doc) -> SVariable r -> MSParameter r
param r (Variable r) -> Doc
f SVariable r
v' = do
  r (Variable r)
v <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SVariable r
v'
  let n :: ClassName
n = forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName r (Variable r)
v
  forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify forall a b. (a -> b) -> a -> b
$ ClassName -> MethodState -> MethodState
addParameter ClassName
n
  forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify forall a b. (a -> b) -> a -> b
$ ClassName -> MethodState -> MethodState
useVarName ClassName
n
  forall (r :: * -> *).
RenderParam r =>
SVariable r -> Doc -> MSParameter r
paramFromData SVariable r
v' forall a b. (a -> b) -> a -> b
$ r (Variable r) -> Doc
f r (Variable r)
v

method :: (RenderSym r) => Label -> r (Scope r) -> r (Permanence r) -> VSType r 
  -> [MSParameter r] -> MSBody r -> SMethod r
method :: forall (r :: * -> *).
RenderSym r =>
ClassName
-> r (Scope r)
-> r (Permanence r)
-> VSType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
method ClassName
n r (Scope r)
s r (Permanence r)
p VSType r
t = forall (r :: * -> *).
RenderMethod r =>
Bool
-> ClassName
-> r (Scope r)
-> r (Permanence r)
-> MSMthdType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
intMethod Bool
False ClassName
n r (Scope r)
s r (Permanence r)
p (forall (r :: * -> *). MethodTypeSym r => VSType r -> MSMthdType r
mType VSType r
t)

getMethod :: (RenderSym r) => SVariable r -> SMethod r
getMethod :: forall (r :: * -> *). RenderSym r => SVariable r -> SMethod r
getMethod SVariable r
v = forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SVariable r
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\r (Variable r)
vr -> forall (r :: * -> *).
MethodSym r =>
ClassName
-> r (Scope r)
-> r (Permanence r)
-> VSType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
S.method (ClassName -> ClassName
getterName forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName 
  r (Variable r)
vr) forall (r :: * -> *). ScopeSym r => r (Scope r)
public forall (r :: * -> *). PermanenceSym r => r (Permanence r)
dynamic (forall a s. a -> State s a
toState forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
vr) [] MS (r (Body r))
getBody)
  where getBody :: MS (r (Body r))
getBody = forall (r :: * -> *). BodySym r => MSStatement r -> MSBody r
oneLiner forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *).
ControlStatement r =>
SValue r -> MSStatement r
S.returnStmt (forall (r :: * -> *). VariableValue r => SVariable r -> SValue r
S.valueOf forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). VariableSym r => SVariable r -> SVariable r
S.objVarSelf SVariable r
v)

setMethod :: (RenderSym r) => SVariable r -> SMethod r
setMethod :: forall (r :: * -> *). RenderSym r => SVariable r -> SMethod r
setMethod SVariable r
v = forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' MethodState ValueState
lensMStoVS SVariable r
v forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\r (Variable r)
vr -> forall (r :: * -> *).
MethodSym r =>
ClassName
-> r (Scope r)
-> r (Permanence r)
-> VSType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
S.method (ClassName -> ClassName
setterName forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). VariableElim r => r (Variable r) -> ClassName
variableName 
  r (Variable r)
vr) forall (r :: * -> *). ScopeSym r => r (Scope r)
public forall (r :: * -> *). PermanenceSym r => r (Permanence r)
dynamic forall (r :: * -> *). TypeSym r => VSType r
S.void [forall (r :: * -> *).
ParameterSym r =>
SVariable r -> MSParameter r
S.param SVariable r
v] MS (r (Body r))
setBody)
  where setBody :: MS (r (Body r))
setBody = forall (r :: * -> *). BodySym r => MSStatement r -> MSBody r
oneLiner forall a b. (a -> b) -> a -> b
$ forall (r :: * -> *). VariableSym r => SVariable r -> SVariable r
S.objVarSelf SVariable r
v forall (r :: * -> *).
AssignStatement r =>
SVariable r -> SValue r -> MSStatement r
&= forall (r :: * -> *). VariableValue r => SVariable r -> SValue r
S.valueOf SVariable r
v

initStmts :: (RenderSym r) => Initializers r -> MSBody r
initStmts :: forall (r :: * -> *). RenderSym r => Initializers r -> MSBody r
initStmts = forall (r :: * -> *). BodySym r => [MSStatement r] -> MSBody r
bodyStatements forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (\(VS (r (Variable r))
vr, VS (r (Value r))
vl) -> forall (r :: * -> *). VariableSym r => SVariable r -> SVariable r
S.objVarSelf VS (r (Variable r))
vr forall (r :: * -> *).
AssignStatement r =>
SVariable r -> SValue r -> MSStatement r
&= VS (r (Value r))
vl)

function :: (RenderSym r) => Label -> r (Scope r) -> VSType r -> 
  [MSParameter r] -> MSBody r -> SMethod r
function :: forall (r :: * -> *).
RenderSym r =>
ClassName
-> r (Scope r)
-> VSType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
function ClassName
n r (Scope r)
s VSType r
t = forall (r :: * -> *).
RenderMethod r =>
Bool
-> ClassName
-> r (Scope r)
-> r (Permanence r)
-> MSMthdType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
S.intFunc Bool
False ClassName
n r (Scope r)
s forall (r :: * -> *). PermanenceSym r => r (Permanence r)
static (forall (r :: * -> *). MethodTypeSym r => VSType r -> MSMthdType r
mType VSType r
t)
  
docFuncRepr :: (RenderSym r) => FuncDocRenderer -> String -> [String] -> 
  [String] -> SMethod r -> SMethod r
docFuncRepr :: forall (r :: * -> *).
RenderSym r =>
FuncDocRenderer
-> ClassName
-> [ClassName]
-> [ClassName]
-> SMethod r
-> SMethod r
docFuncRepr FuncDocRenderer
f ClassName
desc [ClassName]
pComms [ClassName]
rComms = forall (r :: * -> *).
RenderMethod r =>
MS (r (BlockComment r)) -> SMethod r -> SMethod r
commentedFunc (forall (r :: * -> *) a.
BlockCommentSym r =>
State a [ClassName] -> State a (r (BlockComment r))
docComment forall a b. (a -> b) -> a -> b
$ forall a b s. (a -> b) -> State s a -> State s b
onStateValue 
  (\[ClassName]
ps -> FuncDocRenderer
f ClassName
desc (forall a b. [a] -> [b] -> [(a, b)]
zip [ClassName]
ps [ClassName]
pComms) [ClassName]
rComms) MS [ClassName]
getParameters)

docFunc :: (RenderSym r) => FuncDocRenderer -> String -> [String] -> 
  Maybe String -> SMethod r -> SMethod r
docFunc :: forall (r :: * -> *).
RenderSym r =>
FuncDocRenderer
-> ClassName
-> [ClassName]
-> Maybe ClassName
-> SMethod r
-> SMethod r
docFunc FuncDocRenderer
f ClassName
desc [ClassName]
pComms Maybe ClassName
rComm = forall (r :: * -> *).
RenderSym r =>
FuncDocRenderer
-> ClassName
-> [ClassName]
-> [ClassName]
-> SMethod r
-> SMethod r
docFuncRepr FuncDocRenderer
f ClassName
desc [ClassName]
pComms (forall a. Maybe a -> [a]
maybeToList Maybe ClassName
rComm)

-- Classes --

buildClass :: (RenderSym r) =>  Maybe Label -> [CSStateVar r] -> 
  [SMethod r] -> SClass r
buildClass :: forall (r :: * -> *).
RenderSym r =>
Maybe ClassName -> [CSStateVar r] -> [SMethod r] -> SClass r
buildClass Maybe ClassName
p [CSStateVar r]
stVars [SMethod r]
methods = do 
  ClassName
n <- forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom Lens' ClassState FileState
lensCStoFS FS ClassName
getModuleName
  forall (r :: * -> *).
RenderClass r =>
ClassName
-> r (Scope r)
-> r Doc
-> [CSStateVar r]
-> [SMethod r]
-> SClass r
S.intClass ClassName
n forall (r :: * -> *). ScopeSym r => r (Scope r)
public (forall (r :: * -> *). RenderClass r => Maybe ClassName -> r Doc
inherit Maybe ClassName
p) [CSStateVar r]
stVars [SMethod r]
methods

implementingClass :: (RenderSym r) => Label -> [Label] -> [CSStateVar r] -> 
  [SMethod r] -> SClass r
implementingClass :: forall (r :: * -> *).
RenderSym r =>
ClassName
-> [ClassName] -> [CSStateVar r] -> [SMethod r] -> SClass r
implementingClass ClassName
n [ClassName]
is = forall (r :: * -> *).
RenderClass r =>
ClassName
-> r (Scope r)
-> r Doc
-> [CSStateVar r]
-> [SMethod r]
-> SClass r
S.intClass ClassName
n forall (r :: * -> *). ScopeSym r => r (Scope r)
public (forall (r :: * -> *). RenderClass r => [ClassName] -> r Doc
implements [ClassName]
is)

docClass :: (RenderSym r) => ClassDocRenderer -> String -> SClass r -> SClass r
docClass :: forall (r :: * -> *).
RenderSym r =>
ClassDocRenderer -> ClassName -> SClass r -> SClass r
docClass ClassDocRenderer
cdr ClassName
d = forall (r :: * -> *).
RenderClass r =>
CS (r (BlockComment r)) -> SClass r -> SClass r
S.commentedClass (forall (r :: * -> *) a.
BlockCommentSym r =>
State a [ClassName] -> State a (r (BlockComment r))
docComment forall a b. (a -> b) -> a -> b
$ forall a s. a -> State s a
toState forall a b. (a -> b) -> a -> b
$ ClassDocRenderer
cdr ClassName
d)

commentedClass :: (RenderSym r, Monad r) => CS (r (BlockComment r)) -> SClass r 
  -> CS (r Doc)
commentedClass :: forall (r :: * -> *).
(RenderSym r, Monad r) =>
CS (r (BlockComment r)) -> SClass r -> CS (r Doc)
commentedClass = forall a b c s.
(a -> b -> c) -> State s a -> State s b -> State s c
on2StateValues (\r (BlockComment r)
cmt r (Class r)
cs -> forall (r :: * -> *) a. Monad r => a -> r a
toCode forall a b. (a -> b) -> a -> b
$ Doc -> Doc -> Doc
R.commentedItem 
  (forall (r :: * -> *).
BlockCommentElim r =>
r (BlockComment r) -> Doc
RC.blockComment' r (BlockComment r)
cmt) (forall (r :: * -> *). ClassElim r => r (Class r) -> Doc
RC.class' r (Class r)
cs))

-- Modules --

modFromData :: Label -> (Doc -> r (Module r)) -> FS Doc -> FSModule r
modFromData :: forall (r :: * -> *).
ClassName -> (Doc -> r (Module r)) -> FS Doc -> FSModule r
modFromData ClassName
n Doc -> r (Module r)
f FS Doc
d = forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (ClassName -> FileState -> FileState
setModuleName ClassName
n) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall a b s. (a -> b) -> State s a -> State s b
onStateValue Doc -> r (Module r)
f FS Doc
d

-- Files --

fileDoc :: (RenderSym r) => String -> (r (Module r) -> r (Block r)) -> 
  r (Block r) -> FSModule r -> SFile r
fileDoc :: forall (r :: * -> *).
RenderSym r =>
ClassName
-> (r (Module r) -> r (Block r))
-> r (Block r)
-> FSModule r
-> SFile r
fileDoc ClassName
ext r (Module r) -> r (Block r)
topb r (Block r)
botb FSModule r
mdl = do
  r (Module r)
m <- FSModule r
mdl
  ClassName
nm <- FS ClassName
getModuleName
  let fp :: ClassName
fp = ClassName -> ClassName -> ClassName
addExt ClassName
ext ClassName
nm
      updm :: r (Module r)
updm = forall (r :: * -> *).
RenderMod r =>
(Doc -> Doc) -> r (Module r) -> r (Module r)
updateModuleDoc (\Doc
d -> Doc -> Doc -> Doc
emptyIfEmpty Doc
d 
        (Doc -> Doc -> Doc -> Doc
R.file (forall (r :: * -> *). BlockElim r => r (Block r) -> Doc
RC.block forall a b. (a -> b) -> a -> b
$ r (Module r) -> r (Block r)
topb r (Module r)
m) Doc
d (forall (r :: * -> *). BlockElim r => r (Block r) -> Doc
RC.block r (Block r)
botb))) r (Module r)
m
  forall (r :: * -> *).
RenderFile r =>
ClassName -> FSModule r -> SFile r
S.fileFromData ClassName
fp (forall a s. a -> State s a
toState r (Module r)
updm)

docMod :: (RenderSym r) => ModuleDocRenderer -> String -> String -> 
  [String] -> String -> SFile r -> SFile r
docMod :: forall (r :: * -> *).
RenderSym r =>
ModuleDocRenderer
-> ClassName
-> ClassName
-> [ClassName]
-> ClassName
-> SFile r
-> SFile r
docMod ModuleDocRenderer
mdr ClassName
e ClassName
d [ClassName]
a ClassName
dt SFile r
fl = forall (r :: * -> *).
RenderFile r =>
SFile r -> FS (r (BlockComment r)) -> SFile r
commentedMod SFile r
fl (forall (r :: * -> *) a.
BlockCommentSym r =>
State a [ClassName] -> State a (r (BlockComment r))
docComment forall a b. (a -> b) -> a -> b
$ ModuleDocRenderer
mdr ClassName
d [ClassName]
a ClassName
dt forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClassName -> ClassName -> ClassName
addExt ClassName
e 
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FS ClassName
getModuleName)

fileFromData :: (RenderSym r) => (FilePath -> r (Module r) -> r (File r)) 
  -> FilePath -> FSModule r -> SFile r
fileFromData :: forall (r :: * -> *).
RenderSym r =>
(ClassName -> r (Module r) -> r (File r))
-> ClassName -> FSModule r -> SFile r
fileFromData ClassName -> r (Module r) -> r (File r)
f ClassName
fpath FSModule r
mdl' = do
  -- Add this file to list of files as long as it is not empty
  r (Module r)
mdl <- FSModule r
mdl'
  forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (\FileState
s -> if Doc -> Bool
isEmpty (forall (r :: * -> *). ModuleElim r => r (Module r) -> Doc
RC.module' r (Module r)
mdl) 
    then FileState
s
    else forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over Lens' FileState GOOLState
lensFStoGS (FileType -> ClassName -> GOOLState -> GOOLState
addFile (FileState
s forall s a. s -> Getting a s a -> a
^. Lens' FileState FileType
currFileType) ClassName
fpath) forall a b. (a -> b) -> a -> b
$ 
      -- If this is the main source file, set it as the main module in the state
      if FileState
s forall s a. s -> Getting a s a -> a
^. Lens' FileState Bool
currMain Bool -> Bool -> Bool
&& FileType -> Bool
isSource (FileState
s forall s a. s -> Getting a s a -> a
^. Lens' FileState FileType
currFileType) 
        then forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over Lens' FileState GOOLState
lensFStoGS (ClassName -> GOOLState -> GOOLState
setMainMod ClassName
fpath) FileState
s
        else FileState
s)
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ClassName -> r (Module r) -> r (File r)
f ClassName
fpath r (Module r)
mdl

-- Helper functions

setEmpty :: (RenderSym r) => MSStatement r -> MSStatement r
setEmpty :: forall (r :: * -> *). RenderSym r => MSStatement r -> MSStatement r
setEmpty MSStatement r
s' = MSStatement r
s' forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (r :: * -> *). RenderSym r => Doc -> MSStatement r
mkStmtNoEnd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement