> module Haskore.General.LoopTreeTagged where

> import qualified Haskore.General.TagDictionary as Dict

> data T tag a =
>      Branch a [T tag a]
>    | Tag tag (T tag a) -- mark a point where we want return to later
>    | Loop tag          -- return to a marked point
>        deriving (Eq, Show)

The tag for \code{Tag} must be unique,
but multiple use in \code{Loop} is allowed.
Vice versa tags for \code{Loop} must be defined by a \code{Tag} constructor.

> example0 :: T Int Char
> example0 = Tag 0 (Branch 'a' [Tag 1 (Branch 'b' [Loop 1]), Loop 0])

\begin{comment}

Eq and Show

instance (Eq tag, Eq a) => Eq (T tag a) where
  Branch x xSub   == Branch y ySub    =  x == y && xSub == ySub
  Tag xTag xSub == Tag yTag ySub  =  xTag == yTag && xSub == ySub
  Loop xTag     == Loop yTag      =  xTag == yTag
  _             == _              =  False

instance (Show tag, Show a) => Show (T tag a) where
  show (Const x)   =  "(Const " ++ show x  ++ ")"
  show (Add e1 e2) =  "(Add "   ++ show e1 ++ " " ++ show e2 ++ ")"
  show (Tag i e)   =  "(Tag "   ++ show i  ++ " " ++ show e  ++ ")"
  show (Loop i)    =  "(Loop "  ++ show i  ++ ")"

\end{comment}

MapE:

> mapE :: (a -> b) -> T tag a -> T tag b
> mapE f =
>    let aux branch =
>           case branch of
>              Branch x sub  -> Branch (f x) (map aux sub)
>              Tag tag sub -> Tag tag (aux sub)
>              Loop tag    -> Loop tag
>    in  aux

> instance Functor (T tag) where
>    fmap = mapE

Replace all loops by the corresponding super-trees.
Internally the compiler should translate this into loops, again,
but this cannot be observed by the Haskell code anymore.

> unwind :: (Ord tag) => T tag a -> T tag a
> unwind =
>    let aux tags branch =
>           case branch of
>              Branch x sub  -> Branch x (map (aux tags) sub)
>              Tag tag sub -> let e' = aux (Dict.insert tag e' tags) sub
>                             in  e'
>              Loop tag    -> Dict.lookup tags tag
>    in  aux Dict.empty