module GT where
import Monad
import Monoid
import MonadState
import MonadWriter
import MonadRWS

-- Just a quick exercise in using monads.
-- Thought it'd be nice to share with the class.

data GOp
        = PushVal Integer
        | Push Integer
        | Pop Integer
        | Slide Integer
        | Update Integer
        | GAdd | GSub | GMul | GDiv | GMod | GPow
        | GNeg | GAbs
        deriving (Eq, Ord, Read, Show)

type Tmp = Integer

data ROp
        = LoadImm Tmp Integer
        | RAdd Tmp Tmp Tmp
        | RSub Tmp Tmp Tmp
        | RMul Tmp Tmp Tmp
        | RDiv Tmp Tmp Tmp
        | RMod Tmp Tmp Tmp
        | RPow Tmp Tmp Tmp
        | RNeg Tmp Tmp
        | RAbs Tmp Tmp
        deriving (Eq, Ord, Read, Show)

type CounterT m t = StateT Integer m t
type StackT t = State [Integer] t

type GST t = RWS () [ROp] (Integer, [Integer]) t

class Stack f where
        pushVal, push, pop, update, slide :: Integral t => t -> f ()
        popVal :: Integral t => f t

instance Integral t => Stack (RWS () [ROp] (t, [t])) where
        pushVal n = do
                                        (ctr, stk) <- get
                                        put (ctr, fromIntegral n : stk)
        popVal = do
                                        (ctr, top:stk) <- get
                                        put (ctr, stk)
                                        return (fromIntegral top)
        push n = do
                                (ctr, stk) <- get
                                put (ctr, stk!!fromIntegral n : stk)
        pop n = do
                                (ctr, stk) <- get
                                put (ctr, drop (fromIntegral n) stk)
        slide n = do
                                (ctr, top:stk) <- get
                                put (ctr, top : drop (fromIntegral n) stk)
        update n = do
                                (ctr, top:stk) <- get
                                let (front, _:back) = splitAt (fromIntegral n) stk
                                put (ctr, front ++ [top] ++ back)

class Counter f where
        gen :: Enum t => f t

instance Integral t => Counter (RWS () [ROp] (t, [t])) where
        gen = do
                                (ctr, stk) <- get
                                put (ctr + 1, stk)
                                return . toEnum . fromIntegral $ ctr + 1

instance (Enum t, Monad m) => Counter (StateT t m) where
        gen = do
                                ctr <- get
                                put $ succ ctr
                                ctr <- get
                                return . toEnum $ fromEnum ctr
                                
translate gOps = snd $ evalRWS (mapM trans gOps) () (0,[])

trans :: GOp -> GST ()
trans i = case i of
        PushVal n       ->
                do
                        reg <- gen
                        tell [LoadImm reg n]
                        pushVal reg
        Push n          -> push n
        Pop n           -> pop n
        Slide n         -> slide n
        Update n        -> update n
        GAdd            -> doBinOp RAdd
        GSub            -> doBinOp RSub
        GMul            -> doBinOp RMul
        GDiv            -> doBinOp RDiv
        GMod            -> doBinOp RMod
        GPow            -> doBinOp RPow
        GNeg            -> doUnOp RNeg
        GAbs            -> doUnOp RAbs
        where
                doUnOp op =
                        do
                                x <- popVal
                                y <- gen
                                tell [op y x]
                                pushVal y
                doBinOp op =
                        do
                                x <- popVal
                                y <- popVal
                                z <- gen
                                tell [op z x y]
                                pushVal z
_______________________________________________
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to