{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Windll -- Copyright : (c) Tamar Christina 2009 - 2010 -- License : BSD3 -- -- Maintainer : tamar@zhox.com -- Stability : experimental -- Portability : portable -- -- Contains a pseudo implementation of an artificial stack. -- This is used to print a StackTrace out and manipulate the stack. -- ----------------------------------------------------------------------------- module WinDll.Debug.Stack ( Stack() , Stackable(..) , FunctionName , emptyStack , pushStack , topStack , popStack , newStack , sizeStack , shrinkStack , printStack ) where import System.FilePath import Data.Data import Data.Typeable type FunctionName = String -- | A simple stack implementation data Stack = Empty | Then FunctionName Stack | Combined Stack Stack | Recursed Stack Stack deriving (Typeable, Data, Eq, Show, Read, Ord) class Show a => Stackable a where toStack :: a -> Stack instance Stackable Stack where toStack = id instance Stackable String where toStack = newStack -- instance Show Stack where -- show = printStack -- | Pretty print a stack back out to a string printStack :: Stack -> String printStack Empty = [] printStack (Then fn s) = printStack s "\n\t\t" fn printStack (Combined s1 s2) = printStack s2 printStack s1 printStack (Recursed s1 s2) = printStack s2 printStack s1 "..." -- | Creating an empty stack emptyStack :: Stack emptyStack = Empty -- | Create a new stack from a template newStack :: FunctionName -> Stack newStack fn = pushStack Empty fn -- | Adding an element to the top of the stack pushStack :: Stackable st => st -> FunctionName -> Stack pushStack = flip Then . toStack -- | Remove an element from the top of the stack popStack :: Stack -> Stack popStack Empty = error "An empty stack cannot be popped" popStack (Then _ s) = s popStack (Combined s1 s2) = Combined (popStack s1) s2 popStack (Recursed s1 s2) = Recursed (popStack s1) s2 -- | Look at the item at the top of the stack, but does not remove it topStack :: Stack -> Maybe FunctionName topStack Empty = Nothing topStack (Then fn s) = Just fn topStack (Combined s1 s2) = topStack s1 topStack (Recursed s1 s2) = topStack s1 -- | The size of the stack e.g the amount of elements inside it sizeStack :: Stack -> Int sizeStack Empty = 0 sizeStack (Then _ s) = 1 + sizeStack s sizeStack (Combined s1 s2) = sizeStack s1 + sizeStack s2 sizeStack (Recursed s1 s2) = sizeStack s1 + sizeStack s2 -- | Shrinks and Compress the stack, reducing the stack to the bare minimum -- of steps/calls needed to represent the same stack shrinkStack :: Stack -> Stack shrinkStack = id