{-# LANGUAGE DeriveFunctor, DeriveTraversable, DeriveFoldable, TemplateHaskell,
FlexibleContexts, ConstraintKinds #-}
module DataTypes.Mono where
import Data.Comp.Derive
import Data.Comp
type Var = String
data ArithLet a = Add a a | Mult a a | Sub a a | Val Int | Let Var a a | Var Var
deriving (Show, Functor, Foldable, Traversable)
data ArithExc a = Add' a a | Val' Int | Throw | Catch a a
deriving (Show, Functor, Foldable, Traversable)
data Code a = PUSH Int a
| ADD a
| THROW
| MARK a a
| UNMARK a
| NIL
deriving (Show, Functor, Foldable, Traversable)
$(derive
[makeShowF, makeEqF, makeNFDataF, makeArbitraryF, smartConstructors]
[''ArithLet, ''ArithExc, ''Code])
exprAL :: Int -> Term ArithLet
exprAL 0 = iVal 4
exprAL n = iLet "x" e1 e2
where e1 = (iVal 1 `iSub` iVal 2) `iAdd` iLet "y" e3 e4
e2 = iVar "x" `iMult` iVal 4 `iAdd` iLet "z" e5 e6 `iSub` exprAL (n-1)
e3 = iVal 2 `iAdd` iVal 3
e4 = iVar "y" `iAdd` iVar "y"
e5 = iVar "x" `iMult` iVar "x"
e6 = (iVar "x" `iSub` iVar "z") `iAdd` exprAL (n-1)
exprAE :: Int -> Term ArithExc
exprAE 0 = iVal' 3
exprAE n = iVal' 1 `iAdd'` iCatch (exprAE (n-1) `iAdd'` iThrow) (iVal' 2 `iAdd'` exprAE (n-1))