compdata-0.8: examples/Examples/Automata/SimpComp2.hs
{-# LANGUAGE TemplateHaskell, FlexibleContexts, MultiParamTypeClasses,
TypeOperators, FlexibleInstances, UndecidableInstances,
ScopedTypeVariables, TypeSynonymInstances, RankNTypes, ImplicitParams, DeriveDataTypeable #-}
module Examples.Automata.Compiler where
import Data.Comp.Automata
import Data.Comp.Zippable
import Data.Comp.Derive
import Data.Comp.Ops
import Data.Comp hiding (height)
import Data.Foldable
import Prelude hiding (foldl)
import Data.Set (Set, union, singleton, delete, member)
import qualified Data.Set as Set
import Data.Map (Map)
import qualified Data.Map as Map
type Var = String
data Sig e = Const Int | Plus e e | LetIn Var e e | Var Var
$(derive [makeFunctor, makeFoldable, smartConstructors, makeShowF] [''Sig])
instance Zippable Sig where
fzip _ (Const i) = Const i
fzip (Cons a (Cons b _)) (Plus x y) = Plus (a,x) (b,y)
fzip (Cons a (Cons b _)) (LetIn v x y) = LetIn v (a,x) (b,y)
fzip _ (Var v) = Var v
instance (Zippable f, Zippable g) => Zippable (f :+: g) where
fzip x (Inl v) = Inl $ fzip x v
fzip x (Inr v) = Inr $ fzip x v
-- evalSt :: UpState Sig Int
-- evalSt (Const i) = i
-- evalSt (Plus x y) = x + y
type Addr = Int
data Instr = Acc Int
| Load Addr
| Store Addr
| Add Addr
deriving (Show)
type Code = [Instr]
-- heightSt :: UpState Sig Int
-- heightSt (Const _) = 0
-- heightSt (Plus x y) = 1 + max x y
-- heightSt (LetIn _ e b) = 1 + max e b
-- heightSt (Var _) = 0
-- codeSt :: (Int :< q) => DUpState Sig q Code
-- codeSt (Const x) = [Acc x]
-- codeSt (Plus x y) = below x ++ [Store a] ++ below y ++ [Add a] where a = below y
-- code :: Term Sig -> Code
-- code = fst . runDUpState (codeSt <*> dUpState heightSt)
type Vars = Set Var
fvSt :: UpState Sig Vars
fvSt (Var v) = singleton v
fvSt (LetIn v e b) | v `member` b = e `union` delete v b
| otherwise = delete v b
fvSt t = foldl union Set.empty t
-- | Stateful homomorphism that removes unnecessary let bindings.
remLetHom :: (Vars :< q) => QHom Sig q Sig
remLetHom (LetIn v _ y) | not (v `Set.member` below y) = Hole y
remLetHom t = simpCxt t
remLet :: Term Sig -> Term Sig
remLet = runUpHom fvSt remLetHom
ldepthSt :: DownState Sig Int
ldepthSt (d,LetIn _ _ b) = b |-> d + 1
ldepthSt _ = o
type Ren = Map Var Var
newVar :: (?above :: q, Int :< q) => Var
newVar = show (above :: Int)
renSt :: (Int :< q) => DDownState Sig q Ren
renSt (LetIn v _ b) = b |-> (v |-> newVar & above)
renSt _ = o
renameHom :: (Ren :< q, Int :< q) => QHom Sig q Sig
renameHom (LetIn _ a b) = iLetIn newVar (Hole a) (Hole b)
renameHom (Var v) = case Map.lookup v above of
Nothing -> iVar v
Just v' -> iVar v'
renameHom t = simpCxt t
renameInit :: (Ren, Int)
renameInit = (o, 0)
rename :: Term Sig -> Term Sig
rename = runDownHom (downState (renSt >*< dDownState ldepthSt))
renameHom renameInit
heightSt :: Foldable f => UpState f Int
heightSt t = foldl max 0 t + 1
newtype Height = Height {height :: Int}
heightSt' :: (Functor f,Foldable f) => UpState f Height
heightSt' = tagUpState Height height heightSt
newtype Depth = Depth {depth :: Int}
ldepthSt' :: DownState Sig Depth
ldepthSt' = tagDownState Depth depth ldepthSt
type Bind = Map Var Int
bindSt :: (Depth :< q) => DDownState Sig q Bind
bindSt (LetIn v _ e) = e |-> (v |-> 2 * depth above & above)
bindSt _ = o
codeSt :: (Height :< q, Depth :< q, Bind :< q) => DUpState Sig q Code
codeSt (Const x) = [Acc x]
codeSt (Plus x y) = below x ++ [Store a] ++ below y ++ [Add a]
where a = 2 * height (below y) + 1
codeSt (LetIn _ b e) = below b ++ [Store a] ++ below e
where a = 2 * depth above
codeSt (Var v) = case Map.lookup v above of
Nothing -> error $ "unbound variable " ++ v
Just i -> [Load i]
code :: Term Sig -> (Code, Height)
code = runDState
(codeSt <*> dUpState heightSt')
(bindSt >*< dDownState ldepthSt')
(o :: Bind, Depth 0)