{-# LANGUAGE PostfixOperators #-}

-- | Implementations for C-like renderers are defined here.
module Drasil.GOOL.LanguageRenderer.CLike (charRender, float, double, char, 
  listType, setType, void, notOp, andOp, orOp, self, litTrue, litFalse, litFloat, 
  inlineIf, libFuncAppMixedArgs, libNewObjMixedArgs, listSize, increment1, 
  decrement1, varDec, varDecDef, setDecDef, listDec, extObjDecNew, switch, for, while, 
  intFunc, multiAssignError, multiReturnError, multiTypeError
) where

import Utils.Drasil (indent)

import Drasil.GOOL.CodeType (CodeType(..))
import Drasil.GOOL.InterfaceCommon (Label, Library, MSBody, VSType, SVariable, 
  SValue, MSStatement, MSParameter, SMethod, MixedCall, MixedCtorCall, 
  TypeElim(getType, getTypeString), ScopeSym(..),
  VariableElim(..), ValueSym(Value, valueType), VisibilitySym(..))
import qualified Drasil.GOOL.InterfaceCommon as IC (TypeSym(bool, float),
  ValueExpression(funcAppMixedArgs), DeclStatement(varDec, setDec, varDecDef))
import Drasil.GOOL.InterfaceGOOL (PermanenceSym(..), extNewObj, ($.))
import qualified Drasil.GOOL.InterfaceGOOL as IG (OOTypeSym(obj),
  OOValueExpression(newObjMixedArgs))
import Drasil.GOOL.RendererClassesCommon (MSMthdType, CommonRenderSym,
  RenderType(..), InternalVarElim(variableBind), RenderValue(valFromData), 
  ValueElim(valuePrec), ScopeElim(scopeData))
import qualified Drasil.GOOL.RendererClassesCommon as S (
  InternalListFunc(listSizeFunc), RenderStatement(stmt, loopStmt))
import qualified Drasil.GOOL.RendererClassesCommon as RC (BodyElim(..),
  InternalTypeElim(..), InternalVarElim(variable), ValueElim(value),
  StatementElim(statement))
import Drasil.GOOL.RendererClassesOO (OORenderSym,
  OORenderMethod(intMethod))
import qualified Drasil.GOOL.RendererClassesOO as RC (PermElim(..))
import Drasil.GOOL.AST (Binding(..), Terminator(..))
import Drasil.GOOL.Helpers (angles, toState, onStateValue)
import Drasil.GOOL.LanguageRenderer (forLabel, whileLabel, containing)
import qualified Drasil.GOOL.LanguageRenderer as R (switch, increment, 
  decrement, this', this)
import Drasil.GOOL.LanguageRenderer.Constructors (mkStmt, mkStmtNoEnd, 
  mkStateVal, mkStateVar, VSOp, unOpPrec, andPrec, orPrec)
import Drasil.GOOL.State (lensMStoVS, lensVStoMS, addLibImportVS, getClassName,
  useVarName, setVarScope)

import Prelude hiding (break,(<>))
import Control.Applicative ((<|>))
import Control.Monad.State (modify)
import Control.Lens.Zoom (zoom)
import Text.PrettyPrint.HughesPJ (Doc, text, (<>), (<+>), parens, vcat, semi, 
  equals, empty)
import qualified Text.PrettyPrint.HughesPJ as D (float)

-- Types --

floatRender, doubleRender, charRender, voidRender :: String
floatRender :: String
floatRender = String
"float"
doubleRender :: String
doubleRender = String
"double"
charRender :: String
charRender = String
"char"
voidRender :: String
voidRender = String
"void"

float :: (CommonRenderSym r) => VSType r
float :: forall (r :: * -> *). CommonRenderSym r => VSType r
float = CodeType
-> String -> Doc -> StateT ValueState Identity (r (Type r))
forall (r :: * -> *).
RenderType r =>
CodeType -> String -> Doc -> VSType r
typeFromData CodeType
Float String
floatRender (String -> Doc
text String
floatRender)

double :: (CommonRenderSym r) => VSType r
double :: forall (r :: * -> *). CommonRenderSym r => VSType r
double = CodeType
-> String -> Doc -> StateT ValueState Identity (r (Type r))
forall (r :: * -> *).
RenderType r =>
CodeType -> String -> Doc -> VSType r
typeFromData CodeType
Double String
doubleRender (String -> Doc
text String
doubleRender)

char :: (CommonRenderSym r) => VSType r
char :: forall (r :: * -> *). CommonRenderSym r => VSType r
char = CodeType
-> String -> Doc -> StateT ValueState Identity (r (Type r))
forall (r :: * -> *).
RenderType r =>
CodeType -> String -> Doc -> VSType r
typeFromData CodeType
Char String
charRender (String -> Doc
text String
charRender)

listType :: (CommonRenderSym r) => String -> VSType r -> VSType r
listType :: forall (r :: * -> *).
CommonRenderSym r =>
String -> VSType r -> VSType r
listType String
lst VSType r
t' = do 
  r (Type r)
t <- VSType r
t'
  CodeType -> String -> Doc -> VSType r
forall (r :: * -> *).
RenderType r =>
CodeType -> String -> Doc -> VSType r
typeFromData (CodeType -> CodeType
List (r (Type r) -> CodeType
forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType r (Type r)
t)) (String
lst 
    String -> String -> String
`containing` r (Type r) -> String
forall (r :: * -> *). TypeElim r => r (Type r) -> String
getTypeString r (Type r)
t) (Doc -> VSType r) -> Doc -> VSType r
forall a b. (a -> b) -> a -> b
$ String -> Doc
text String
lst Doc -> Doc -> Doc
<> Doc -> Doc
angles (r (Type r) -> Doc
forall (r :: * -> *). InternalTypeElim r => r (Type r) -> Doc
RC.type' r (Type r)
t) 

setType :: (OORenderSym r) => String -> VSType r -> VSType r
setType :: forall (r :: * -> *).
OORenderSym r =>
String -> VSType r -> VSType r
setType String
lst VSType r
t' = do 
  r (Type r)
t <- VSType r
t'
  CodeType -> String -> Doc -> VSType r
forall (r :: * -> *).
RenderType r =>
CodeType -> String -> Doc -> VSType r
typeFromData (CodeType -> CodeType
Set (r (Type r) -> CodeType
forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType r (Type r)
t)) (String
lst 
    String -> String -> String
`containing` r (Type r) -> String
forall (r :: * -> *). TypeElim r => r (Type r) -> String
getTypeString r (Type r)
t) (Doc -> VSType r) -> Doc -> VSType r
forall a b. (a -> b) -> a -> b
$ String -> Doc
text String
lst Doc -> Doc -> Doc
<> Doc -> Doc
angles (r (Type r) -> Doc
forall (r :: * -> *). InternalTypeElim r => r (Type r) -> Doc
RC.type' r (Type r)
t) 

void :: (CommonRenderSym r) => VSType r
void :: forall (r :: * -> *). CommonRenderSym r => VSType r
void = CodeType
-> String -> Doc -> StateT ValueState Identity (r (Type r))
forall (r :: * -> *).
RenderType r =>
CodeType -> String -> Doc -> VSType r
typeFromData CodeType
Void String
voidRender (String -> Doc
text String
voidRender)

-- Unary Operators --

notOp :: (Monad r) => VSOp r
notOp :: forall (r :: * -> *). Monad r => VSOp r
notOp = String -> VSOp r
forall (r :: * -> *). Monad r => String -> VSOp r
unOpPrec String
"!"

-- Binary Operators --

andOp :: (Monad r) => VSOp r
andOp :: forall (r :: * -> *). Monad r => VSOp r
andOp = String -> VSOp r
forall (r :: * -> *). Monad r => String -> VSOp r
andPrec String
"&&"

orOp :: (Monad r) => VSOp r
orOp :: forall (r :: * -> *). Monad r => VSOp r
orOp = String -> VSOp r
forall (r :: * -> *). Monad r => String -> VSOp r
orPrec String
"||"
-- Variables --

self :: (OORenderSym r) => SVariable r
self :: forall (r :: * -> *). OORenderSym r => SVariable r
self = do 
  String
l <- LensLike'
  (Zoomed (StateT MethodState Identity) String)
  ValueState
  MethodState
-> StateT MethodState Identity String
-> StateT ValueState Identity String
forall c.
LensLike'
  (Zoomed (StateT MethodState Identity) c) ValueState MethodState
-> StateT MethodState Identity c -> StateT ValueState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT MethodState Identity) String)
  ValueState
  MethodState
(MethodState -> Focusing Identity String MethodState)
-> ValueState -> Focusing Identity String ValueState
Lens' ValueState MethodState
lensVStoMS StateT MethodState Identity String
getClassName 
  String -> VSType r -> Doc -> SVariable r
forall (r :: * -> *).
CommonRenderSym r =>
String -> VSType r -> Doc -> SVariable r
mkStateVar String
R.this (String -> VSType r
forall (r :: * -> *). OOTypeSym r => String -> VSType r
IG.obj String
l) Doc
R.this'

-- Values --

litTrue :: (CommonRenderSym r) => SValue r
litTrue :: forall (r :: * -> *). CommonRenderSym r => SValue r
litTrue = VSType r -> Doc -> StateT ValueState Identity (r (Value r))
forall (r :: * -> *).
CommonRenderSym r =>
VSType r -> Doc -> SValue r
mkStateVal VSType r
forall (r :: * -> *). TypeSym r => VSType r
IC.bool (String -> Doc
text String
"true")

litFalse :: (CommonRenderSym r) => SValue r
litFalse :: forall (r :: * -> *). CommonRenderSym r => SValue r
litFalse = VSType r -> Doc -> StateT ValueState Identity (r (Value r))
forall (r :: * -> *).
CommonRenderSym r =>
VSType r -> Doc -> SValue r
mkStateVal VSType r
forall (r :: * -> *). TypeSym r => VSType r
IC.bool (String -> Doc
text String
"false")

litFloat :: (CommonRenderSym r) => Float -> SValue r
litFloat :: forall (r :: * -> *). CommonRenderSym r => Float -> SValue r
litFloat Float
f = VSType r -> Doc -> StateT ValueState Identity (r (Value r))
forall (r :: * -> *).
CommonRenderSym r =>
VSType r -> Doc -> SValue r
mkStateVal VSType r
forall (r :: * -> *). TypeSym r => VSType r
IC.float (Float -> Doc
D.float Float
f Doc -> Doc -> Doc
<> String -> Doc
text String
"f")

inlineIf :: (CommonRenderSym r) => SValue r -> SValue r -> SValue r -> SValue r
inlineIf :: forall (r :: * -> *).
CommonRenderSym r =>
SValue r -> SValue r -> SValue r -> SValue r
inlineIf SValue r
c' SValue r
v1' SValue r
v2' = do
  r (Value r)
c <- SValue r
c'
  r (Value r)
v1 <- SValue r
v1'
  r (Value r)
v2 <- SValue r
v2' 
  Maybe Int -> Maybe Integer -> VSType r -> Doc -> SValue r
forall (r :: * -> *).
RenderValue r =>
Maybe Int -> Maybe Integer -> VSType r -> Doc -> SValue r
valFromData (r (Value r) -> Maybe Int
forall {r :: * -> *}. ValueElim r => r (Value r) -> Maybe Int
prec r (Value r)
c) Maybe Integer
forall a. Maybe a
Nothing (r (Type r) -> VSType r
forall a s. a -> State s a
toState (r (Type r) -> VSType r) -> r (Type r) -> VSType r
forall a b. (a -> b) -> a -> b
$ r (Value r) -> r (Type r)
forall (r :: * -> *). ValueSym r => r (Value r) -> r (Type r)
valueType r (Value r)
v1) 
    (r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
c Doc -> Doc -> Doc
<+> String -> Doc
text String
"?" Doc -> Doc -> Doc
<+> r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
v1 Doc -> Doc -> Doc
<+> String -> Doc
text String
":" Doc -> Doc -> Doc
<+> r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
v2) 
  where prec :: r (Value r) -> Maybe Int
prec r (Value r)
cd = r (Value r) -> Maybe Int
forall {r :: * -> *}. ValueElim r => r (Value r) -> Maybe Int
valuePrec r (Value r)
cd Maybe Int -> Maybe Int -> Maybe Int
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0

libFuncAppMixedArgs :: (CommonRenderSym r) => Library -> MixedCall r
libFuncAppMixedArgs :: forall (r :: * -> *). CommonRenderSym r => String -> MixedCall r
libFuncAppMixedArgs String
l String
n VSType r
t [SValue r]
vs NamedArgs r
ns = (ValueState -> ValueState) -> StateT ValueState Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (String -> ValueState -> ValueState
addLibImportVS String
l) StateT ValueState Identity () -> SValue r -> SValue r
forall a b.
StateT ValueState Identity a
-> StateT ValueState Identity b -> StateT ValueState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> 
  MixedCall r
forall (r :: * -> *). ValueExpression r => MixedCall r
IC.funcAppMixedArgs String
n VSType r
t [SValue r]
vs NamedArgs r
ns
  
libNewObjMixedArgs :: (OORenderSym r) => Library -> MixedCtorCall r
libNewObjMixedArgs :: forall (r :: * -> *). OORenderSym r => String -> MixedCtorCall r
libNewObjMixedArgs String
l VSType r
tp [SValue r]
vs NamedArgs r
ns = (ValueState -> ValueState) -> StateT ValueState Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (String -> ValueState -> ValueState
addLibImportVS String
l) StateT ValueState Identity () -> SValue r -> SValue r
forall a b.
StateT ValueState Identity a
-> StateT ValueState Identity b -> StateT ValueState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> 
  MixedCtorCall r
forall (r :: * -> *). OOValueExpression r => MixedCtorCall r
IG.newObjMixedArgs VSType r
tp [SValue r]
vs NamedArgs r
ns

-- Functions --

listSize :: (OORenderSym r) => SValue r -> SValue r
listSize :: forall (r :: * -> *). OORenderSym r => SValue r -> SValue r
listSize SValue r
v = SValue r
v SValue r -> VSFunction r -> SValue r
forall (r :: * -> *).
OOFunctionSym r =>
SValue r -> VSFunction r -> SValue r
$. SValue r -> VSFunction r
forall (r :: * -> *).
InternalListFunc r =>
SValue r -> VSFunction r
S.listSizeFunc SValue r
v

-- Statements --

increment1 :: (CommonRenderSym r) => SVariable r -> MSStatement r
increment1 :: forall (r :: * -> *).
CommonRenderSym r =>
SVariable r -> MSStatement r
increment1 SVariable r
vr' = do 
  r (Variable r)
vr <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Variable r)))
  MethodState
  ValueState
-> SVariable r -> StateT MethodState Identity (r (Variable r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Variable r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Variable r)) ValueState)
-> MethodState -> Focusing Identity (r (Variable r)) MethodState
Lens' MethodState ValueState
lensMStoVS SVariable r
vr'
  (Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt (Doc -> MSStatement r)
-> (r (Variable r) -> Doc) -> r (Variable r) -> MSStatement r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. r (Variable r) -> Doc
forall (r :: * -> *). CommonRenderSym r => r (Variable r) -> Doc
R.increment) r (Variable r)
vr

decrement1 :: (CommonRenderSym r) => SVariable r -> MSStatement r
decrement1 :: forall (r :: * -> *).
CommonRenderSym r =>
SVariable r -> MSStatement r
decrement1 SVariable r
vr' = do 
  r (Variable r)
vr <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Variable r)))
  MethodState
  ValueState
-> SVariable r -> StateT MethodState Identity (r (Variable r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Variable r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Variable r)) ValueState)
-> MethodState -> Focusing Identity (r (Variable r)) MethodState
Lens' MethodState ValueState
lensMStoVS SVariable r
vr'
  (Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt (Doc -> MSStatement r)
-> (r (Variable r) -> Doc) -> r (Variable r) -> MSStatement r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. r (Variable r) -> Doc
forall (r :: * -> *). CommonRenderSym r => r (Variable r) -> Doc
R.decrement) r (Variable r)
vr

varDec :: (OORenderSym r) => r (Permanence r) -> r (Permanence r) -> Doc -> 
  SVariable r -> r (Scope r) -> MSStatement r
varDec :: forall (r :: * -> *).
OORenderSym r =>
r (Permanence r)
-> r (Permanence r)
-> Doc
-> SVariable r
-> r (Scope r)
-> MSStatement r
varDec r (Permanence r)
s r (Permanence r)
d Doc
pdoc SVariable r
v' r (Scope r)
scp = do 
  r (Variable r)
v <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Variable r)))
  MethodState
  ValueState
-> SVariable r -> StateT MethodState Identity (r (Variable r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Variable r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Variable r)) ValueState)
-> MethodState -> Focusing Identity (r (Variable r)) MethodState
Lens' MethodState ValueState
lensMStoVS SVariable r
v' 
  (MethodState -> MethodState) -> StateT MethodState Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((MethodState -> MethodState) -> StateT MethodState Identity ())
-> (MethodState -> MethodState) -> StateT MethodState Identity ()
forall a b. (a -> b) -> a -> b
$ String -> MethodState -> MethodState
useVarName (r (Variable r) -> String
forall (r :: * -> *). VariableElim r => r (Variable r) -> String
variableName r (Variable r)
v)
  (MethodState -> MethodState) -> StateT MethodState Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((MethodState -> MethodState) -> StateT MethodState Identity ())
-> (MethodState -> MethodState) -> StateT MethodState Identity ()
forall a b. (a -> b) -> a -> b
$ String -> ScopeData -> MethodState -> MethodState
setVarScope (r (Variable r) -> String
forall (r :: * -> *). VariableElim r => r (Variable r) -> String
variableName r (Variable r)
v) (r (Scope r) -> ScopeData
forall (r :: * -> *). ScopeElim r => r (Scope r) -> ScopeData
scopeData r (Scope r)
scp)
  Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt (r (Permanence r) -> Doc
forall (r :: * -> *). PermElim r => r (Permanence r) -> Doc
RC.perm (Binding -> r (Permanence r)
bind (Binding -> r (Permanence r)) -> Binding -> r (Permanence r)
forall a b. (a -> b) -> a -> b
$ r (Variable r) -> Binding
forall (r :: * -> *).
InternalVarElim r =>
r (Variable r) -> Binding
variableBind r (Variable r)
v)
    Doc -> Doc -> Doc
<+> r (Type r) -> Doc
forall (r :: * -> *). InternalTypeElim r => r (Type r) -> Doc
RC.type' (r (Variable r) -> r (Type r)
forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
v) Doc -> Doc -> Doc
<+> (CodeType -> Doc
ptrdoc (r (Type r) -> CodeType
forall (r :: * -> *). TypeElim r => r (Type r) -> CodeType
getType (r (Variable r) -> r (Type r)
forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType r (Variable r)
v)) Doc -> Doc -> Doc
<> 
    r (Variable r) -> Doc
forall (r :: * -> *). InternalVarElim r => r (Variable r) -> Doc
RC.variable r (Variable r)
v))
  where bind :: Binding -> r (Permanence r)
bind Binding
Static = r (Permanence r)
s
        bind Binding
Dynamic = r (Permanence r)
d
        ptrdoc :: CodeType -> Doc
ptrdoc (List CodeType
_) = Doc
pdoc
        ptrdoc (Set CodeType
_) = Doc
pdoc
        ptrdoc CodeType
_ = Doc
empty

varDecDef :: (CommonRenderSym r) => Terminator -> SVariable r -> r (Scope r) ->
  SValue r -> MSStatement r
varDecDef :: forall (r :: * -> *).
CommonRenderSym r =>
Terminator
-> SVariable r -> r (Scope r) -> SValue r -> MSStatement r
varDecDef Terminator
t SVariable r
vr r (Scope r)
scp SValue r
vl' = do 
  r (Statement r)
vd <- SVariable r -> r (Scope r) -> MSStatement r
forall (r :: * -> *).
DeclStatement r =>
SVariable r -> r (Scope r) -> MSStatement r
IC.varDec SVariable r
vr r (Scope r)
scp
  r (Value r)
vl <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS SValue r
vl'
  let stmtCtor :: Terminator -> Doc -> MSStatement r
stmtCtor Terminator
Empty = Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmtNoEnd
      stmtCtor Terminator
Semi = Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt
  Terminator -> Doc -> MSStatement r
forall {r :: * -> *}.
CommonRenderSym r =>
Terminator -> Doc -> MSStatement r
stmtCtor Terminator
t (r (Statement r) -> Doc
forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement r (Statement r)
vd Doc -> Doc -> Doc
<+> Doc
equals Doc -> Doc -> Doc
<+> r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
vl)

setDecDef :: (CommonRenderSym r) => Terminator -> SVariable r -> r (Scope r) -> SValue r -> 
  MSStatement r
setDecDef :: forall (r :: * -> *).
CommonRenderSym r =>
Terminator
-> SVariable r -> r (Scope r) -> SValue r -> MSStatement r
setDecDef Terminator
t SVariable r
vr r (Scope r)
scp SValue r
vl' = do 
  r (Statement r)
vd <- SVariable r -> r (Scope r) -> MSStatement r
forall (r :: * -> *).
DeclStatement r =>
SVariable r -> r (Scope r) -> MSStatement r
IC.setDec SVariable r
vr r (Scope r)
scp
  r (Value r)
vl <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS SValue r
vl'
  let stmtCtor :: Terminator -> Doc -> MSStatement r
stmtCtor Terminator
Empty = Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmtNoEnd
      stmtCtor Terminator
Semi = Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt
  Terminator -> Doc -> MSStatement r
forall {r :: * -> *}.
CommonRenderSym r =>
Terminator -> Doc -> MSStatement r
stmtCtor Terminator
t (r (Statement r) -> Doc
forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement r (Statement r)
vd Doc -> Doc -> Doc
<+> Doc
equals Doc -> Doc -> Doc
<+> r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
vl)

listDec :: (CommonRenderSym r) => (r (Value r) -> Doc) -> SValue r ->
  SVariable r -> r (Scope r) -> MSStatement r
listDec :: forall (r :: * -> *).
CommonRenderSym r =>
(r (Value r) -> Doc)
-> SValue r -> SVariable r -> r (Scope r) -> MSStatement r
listDec r (Value r) -> Doc
f SValue r
vl SVariable r
v r (Scope r)
scp = do 
  r (Value r)
sz <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS SValue r
vl
  r (Statement r)
vd <- SVariable r -> r (Scope r) -> MSStatement r
forall (r :: * -> *).
DeclStatement r =>
SVariable r -> r (Scope r) -> MSStatement r
IC.varDec SVariable r
v r (Scope r)
scp
  Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt (r (Statement r) -> Doc
forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement r (Statement r)
vd Doc -> Doc -> Doc
<> r (Value r) -> Doc
f r (Value r)
sz)
  
extObjDecNew :: (OORenderSym r) => Library -> SVariable r -> r (Scope r) ->
  [SValue r] -> MSStatement r
extObjDecNew :: forall (r :: * -> *).
OORenderSym r =>
String -> SVariable r -> r (Scope r) -> [SValue r] -> MSStatement r
extObjDecNew String
l SVariable r
v r (Scope r)
scp [SValue r]
vs = SVariable r
-> r (Scope r)
-> SValue r
-> StateT MethodState Identity (r (Statement r))
forall (r :: * -> *).
DeclStatement r =>
SVariable r -> r (Scope r) -> SValue r -> MSStatement r
IC.varDecDef SVariable r
v r (Scope r)
scp
  (String -> PosCtorCall r
forall (r :: * -> *).
OOValueExpression r =>
String -> PosCtorCall r
extNewObj String
l ((r (Variable r) -> r (Type r))
-> SVariable r -> StateT ValueState Identity (r (Type r))
forall a b s. (a -> b) -> State s a -> State s b
onStateValue r (Variable r) -> r (Type r)
forall (r :: * -> *).
VariableElim r =>
r (Variable r) -> r (Type r)
variableType SVariable r
v) [SValue r]
vs)

-- 1st parameter is a Doc function to apply to the render of the control value (i.e. parens)
-- 2nd parameter is a statement to end every case with
switch :: (CommonRenderSym r) => (Doc -> Doc) -> MSStatement r -> SValue r -> 
  [(SValue r, MSBody r)] -> MSBody r -> MSStatement r
switch :: forall (r :: * -> *).
CommonRenderSym r =>
(Doc -> Doc)
-> MSStatement r
-> SValue r
-> [(SValue r, MSBody r)]
-> MSBody r
-> MSStatement r
switch Doc -> Doc
f MSStatement r
st SValue r
v [(SValue r, MSBody r)]
cs MSBody r
bod = do
  r (Statement r)
s <- MSStatement r -> MSStatement r
forall (r :: * -> *).
RenderStatement r =>
MSStatement r -> MSStatement r
S.stmt MSStatement r
st
  r (Value r)
val <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS SValue r
v
  [r (Value r)]
vals <- ((SValue r, MSBody r) -> StateT MethodState Identity (r (Value r)))
-> [(SValue r, MSBody r)]
-> StateT MethodState Identity [r (Value r)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS (SValue r -> StateT MethodState Identity (r (Value r)))
-> ((SValue r, MSBody r) -> SValue r)
-> (SValue r, MSBody r)
-> StateT MethodState Identity (r (Value r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SValue r, MSBody r) -> SValue r
forall a b. (a, b) -> a
fst) [(SValue r, MSBody r)]
cs
  [r (Body r)]
bods <- ((SValue r, MSBody r) -> MSBody r)
-> [(SValue r, MSBody r)]
-> StateT MethodState Identity [r (Body r)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (SValue r, MSBody r) -> MSBody r
forall a b. (a, b) -> b
snd [(SValue r, MSBody r)]
cs
  r (Body r)
dflt <- MSBody r
bod
  Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmt (Doc -> MSStatement r) -> Doc -> MSStatement r
forall a b. (a -> b) -> a -> b
$ (Doc -> Doc)
-> r (Statement r)
-> r (Value r)
-> r (Body r)
-> [(r (Value r), r (Body r))]
-> Doc
forall (r :: * -> *).
CommonRenderSym r =>
(Doc -> Doc)
-> r (Statement r)
-> r (Value r)
-> r (Body r)
-> [(r (Value r), r (Body r))]
-> Doc
R.switch Doc -> Doc
f r (Statement r)
s r (Value r)
val r (Body r)
dflt ([r (Value r)] -> [r (Body r)] -> [(r (Value r), r (Body r))]
forall a b. [a] -> [b] -> [(a, b)]
zip [r (Value r)]
vals [r (Body r)]
bods)

for :: (CommonRenderSym r) => Doc -> Doc -> MSStatement r -> SValue r -> 
  MSStatement r -> MSBody r -> MSStatement r
for :: forall (r :: * -> *).
CommonRenderSym r =>
Doc
-> Doc
-> MSStatement r
-> SValue r
-> MSStatement r
-> MSBody r
-> MSStatement r
for Doc
bStart Doc
bEnd MSStatement r
sInit SValue r
vGuard MSStatement r
sUpdate MSBody r
b = do
  r (Statement r)
initl <- MSStatement r -> MSStatement r
forall (r :: * -> *).
RenderStatement r =>
MSStatement r -> MSStatement r
S.loopStmt MSStatement r
sInit
  r (Value r)
guard <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS SValue r
vGuard
  r (Statement r)
upd <- MSStatement r -> MSStatement r
forall (r :: * -> *).
RenderStatement r =>
MSStatement r -> MSStatement r
S.loopStmt MSStatement r
sUpdate
  r (Body r)
bod <- MSBody r
b
  Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmtNoEnd (Doc -> MSStatement r) -> Doc -> MSStatement r
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [
    Doc
forLabel Doc -> Doc -> Doc
<+> Doc -> Doc
parens (r (Statement r) -> Doc
forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement r (Statement r)
initl Doc -> Doc -> Doc
<> Doc
semi Doc -> Doc -> Doc
<+> r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
guard Doc -> Doc -> Doc
<> 
      Doc
semi Doc -> Doc -> Doc
<+> r (Statement r) -> Doc
forall (r :: * -> *). StatementElim r => r (Statement r) -> Doc
RC.statement r (Statement r)
upd) Doc -> Doc -> Doc
<+> Doc
bStart,
    Doc -> Doc
indent (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ r (Body r) -> Doc
forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body r (Body r)
bod,
    Doc
bEnd]
  
-- Doc function parameter is applied to the render of the while-condition
while :: (CommonRenderSym r) => (Doc -> Doc) -> Doc -> Doc -> SValue r -> MSBody r -> 
  MSStatement r
while :: forall (r :: * -> *).
CommonRenderSym r =>
(Doc -> Doc) -> Doc -> Doc -> SValue r -> MSBody r -> MSStatement r
while Doc -> Doc
f Doc
bStart Doc
bEnd SValue r
v' MSBody r
b'= do 
  r (Value r)
v <- LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
-> SValue r -> StateT MethodState Identity (r (Value r))
forall c.
LensLike'
  (Zoomed (StateT ValueState Identity) c) MethodState ValueState
-> StateT ValueState Identity c -> StateT MethodState Identity c
forall (m :: * -> *) (n :: * -> *) s t c.
Zoom m n s t =>
LensLike' (Zoomed m c) t s -> m c -> n c
zoom LensLike'
  (Zoomed (StateT ValueState Identity) (r (Value r)))
  MethodState
  ValueState
(ValueState -> Focusing Identity (r (Value r)) ValueState)
-> MethodState -> Focusing Identity (r (Value r)) MethodState
Lens' MethodState ValueState
lensMStoVS SValue r
v'
  r (Body r)
b <- MSBody r
b'
  Doc -> MSStatement r
forall (r :: * -> *). CommonRenderSym r => Doc -> MSStatement r
mkStmtNoEnd ([Doc] -> Doc
vcat [Doc
whileLabel Doc -> Doc -> Doc
<+> Doc -> Doc
f (r (Value r) -> Doc
forall (r :: * -> *). ValueElim r => r (Value r) -> Doc
RC.value r (Value r)
v) Doc -> Doc -> Doc
<+> Doc
bStart, 
    Doc -> Doc
indent (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ r (Body r) -> Doc
forall (r :: * -> *). BodyElim r => r (Body r) -> Doc
RC.body r (Body r)
b, 
    Doc
bEnd]) 

-- Methods --

intFunc :: (OORenderSym r) => Bool -> Label -> r (Visibility  r) ->
  r (Permanence r) -> MSMthdType r -> [MSParameter r] -> MSBody r -> SMethod r
intFunc :: forall (r :: * -> *).
OORenderSym r =>
Bool
-> String
-> r (Visibility r)
-> r (Permanence r)
-> MSMthdType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
intFunc = Bool
-> String
-> r (Visibility r)
-> r (Permanence r)
-> MSMthdType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
forall (r :: * -> *).
OORenderMethod r =>
Bool
-> String
-> r (Visibility r)
-> r (Permanence r)
-> MSMthdType r
-> [MSParameter r]
-> MSBody r
-> SMethod r
intMethod

-- Error Messages --

multiAssignError :: String -> String
multiAssignError :: String -> String
multiAssignError String
l = String
"No multiple assignment statements in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
l

multiReturnError :: String -> String
multiReturnError :: String -> String
multiReturnError String
l = String
"Cannot return multiple values in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
l

multiTypeError :: String -> String
multiTypeError :: String -> String
multiTypeError String
l = String
"Multi-types not supported in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
l