module Lang.LamIf.Syntax where

import FP

data PreAtom n e = 
    AInteger  
  | AVar n 
  | ALam n e
makePrisms ''PreAtom
makePrettySum ''PreAtom

mapAtomM  (Monad m)  (n  m n')  (n  m n')  (e  m e')  PreAtom n e  m (PreAtom n' e')
mapAtomM fVar fBdr fExp = \case
  AInteger i  return $ AInteger i
  AVar n  return AVar <> fVar n
  ALam n e  return ALam <> fBdr n <> fExp e

instance FunctorM (PreAtom n) where mapM f = mapAtomM return return f
instance Functor (PreAtom n) where map f = runID  mapM (ID  f)

data Op = Plus | Minus
  deriving (Eq,Ord)
makePrettySum ''Op

data PreExp n e =
    EAtom (PreAtom n e)
  | EIf e e e
  | ELet n e e
  | EOp Op e e
  | EApp e e
makePrettySum ''PreExp
instance (Pretty n)  Functorial Pretty (PreExp n) where functorial = W

mapExpM  (Monad m)  (n  m n')  (n  m n')  (e  m e')  PreExp n e  m (PreExp n' e')
mapExpM fVar fBdr fExp = \case
  EAtom a  return EAtom <> mapAtomM fVar fBdr fExp a
  EIf e₁ e₂ e₃  return EIf <> fExp e₁ <> fExp e₂ <> fExp e₃
  ELet x e₁ e₂  return ELet <> fBdr x <> fExp e₁ <> fExp e₂
  EOp o e₁ e₂  return (EOp o) <> fExp e₁ <> fExp e₂
  EApp e₁ e₂  return EApp <> fExp e₁ <> fExp e₂

mapExp  (n  n')  (n  n')  (e  e')  PreExp n e  PreExp n' e'
mapExp fVar fBdr fExp = runID  mapExpM (ID  fVar) (ID  fBdr) (ID  fExp)

instance FunctorM (PreExp n) where mapM f = mapExpM return return f
instance Functor (PreExp n) where map f = mapExp id id f