module PathTree
(
PathTree(..),DynTree(..),
-- PathTree should be abstract...
emptyPathTree,updateNode,mapPathTree,node,subTree,listNodes,
attrMapPathTree,
pruneTree,
pos,unpos,spineVals
) where
import Direction
--import Path
import HbcUtils(apSnd)
import Maptrace(ctrace)
data PathTree n
= Node n (PathTree n) (PathTree n)
| Dynamic (DynTree (PathTree n))
| Tip
deriving (Eq, Ord, Show)
data DynTree n
= DynNode n (DynTree n) (DynTree n)
| DynTip
deriving (Eq, Ord, Show)
emptyPathTree = Tip
lookupPath f z = subTree (\(Node w _ _) -> f w) z
subNodes x = subTree (listNodes []) [] x
listNodes ns t =
case t of
Tip -> ns
Node n l r -> listNodes (listNodes (n : ns) l) r
Dynamic dt -> listDynNodes ns dt
listDynNodes ns dt =
case dt of
DynTip -> ns
DynNode t l r -> listNodes (listDynNodes (listDynNodes ns r) l) t
subTree f z Tip _ = z
subTree f z (Dynamic dt) p = dynSelect (subTree f z) z dt p
subTree f z n [] = f n
subTree f z (Node _ l _) (L : path') = subTree f z l path'
subTree f z (Node _ _ r) (R : path') = subTree f z r path'
--subTree _ _ t p = error ("subTree _ _ "++show t++" "++show p)
-- Other cases of ill matching trees/paths return z, so why shouldn't this one?
subTree _ z t p = ctrace "subTree" ("subTree _ _ "++show t++" "++show p) z
{-
dynSubTree f z DynTip _ _ = z
dynSubTree f z (DynNode t _ _) 0 path' = subTree f z t path'
dynSubTree f z (DynNode _ l r) n path' =
dynSubTree f z (if n `rem` 2 == 0 then l else r) (n `quot` 2) path'
-}
dynSelect f z dn (Dno n:p) = dynSelect' dn (pos n) where
dynSelect' DynTip _ = z
dynSelect' (DynNode t l r) n = if n == 0 then f t p else
dynSelect' (if n `rem` 2 == 0 then l else r) (n `quot` 2)
dynSelect f z dn _ = z
pruneNode e = insertTree e Tip
insertTree n = updTree id n . const
pruneTree i e t path = updTree i e (const Tip) t path
updateNode i e t path f = updTree i e g t path
where g Tip = Node (f e) Tip Tip
g (Node n l r) = Node (f n) l r
updTree i e f t path' =
case path' of
[] -> f t
L : path'' -> updLeft i e f t path''
R : path'' -> updRight i e f t path''
Dno n : path'' -> updateDyn i e f t (pos n) path''
updLeft i e f t path' =
case t of
Tip -> Node e (updTree i e f Tip path') Tip
Node n l r -> Node (i n) (updTree i e f l path') r
-- !!! space leak danger if i n is never used
-- need stingy evaluation!!
Dynamic _ -> error "PathTree.hs: updLeft (Dynamic _)"
updRight i e f t path' =
case t of
Tip -> Node e Tip (updTree i e f Tip path')
Node n l r -> Node (i n) l (updTree i e f r path')
-- !!! space leak danger if i n is never used
-- need stingy evaluation!!
Dynamic _ -> error "PathTree.hs: updRight (Dynamic _)"
updateDyn i e f t n path' =
case t of
Tip -> Dynamic (updateDyn' i e f DynTip n path')
Node _ _ _ -> Dynamic (updateDyn' i e f DynTip n path') -- throwing away part of the tree !!!
Dynamic t' -> Dynamic (updateDyn' i e f t' n path')
updateDyn' i e f DynTip 0 path' =
DynNode (updTree i e f Tip path') DynTip DynTip
updateDyn' i e f (DynNode t l r) 0 path' = DynNode (updTree i e f t path') l r
updateDyn' i e f t n path' =
(if n `rem` 2 == 0 then updDynLeft else updDynRight) i e f
t
(n `quot` 2)
path'
updDynLeft i e f t n path' =
case t of
DynTip -> DynNode Tip (updateDyn' i e f DynTip n path') DynTip
DynNode t' l r -> DynNode t' (updateDyn' i e f l n path') r
updDynRight i e f t n path' =
case t of
DynTip -> DynNode Tip DynTip (updateDyn' i e f DynTip n path')
DynNode t' l r -> DynNode t' l (updateDyn' i e f r n path')
pos :: Int->Int
pos 0 = 0
pos n = if n < 0 then (-2) * n else 2 * n + 1
unpos :: Int->Int
unpos n =
if even n
then -(n `quot` 2)
else n `quot` 2
mapPathTree f t =
case t of
Node n lt rt -> Node (f n) (mapPathTree f lt) (mapPathTree f rt)
Dynamic dt -> Dynamic (mapDyn (mapPathTree f) dt)
Tip -> Tip
mapDyn f dt =
case dt of
DynNode n lt rt -> DynNode (f n) (mapDyn f lt) (mapDyn f rt)
DynTip -> DynTip
attrMapPathTree :: (i -> [s] -> a -> (i,s,b)) -> i -> PathTree a ->
([s],PathTree b)
attrMapPathTree f i t = case t of
Node n lt rt -> ([s],Node n' lt' rt') where
(sl,lt') = attrMapPathTree f i' lt
(sr,rt') = attrMapPathTree f i' rt
(i',s,n') = f i (sl++sr) n
-- should perhaps extract ++ and []
Tip -> ([],Tip)
Dynamic dt -> apSnd Dynamic (attrMapDyn f i dt)
attrMapDyn f i dt = case dt of
DynTip -> ([],DynTip)
DynNode t lt rt -> (s++sl++sr,DynNode t' lt' rt') where
-- order?
(sl,lt') = attrMapDyn f i lt
(sr,rt') = attrMapDyn f i rt
(s,t') = attrMapPathTree f i t
spineVals t p = case t of
Tip -> []
Node v l r -> v : case p of
L:p' -> spineVals l p'
R:p' -> spineVals r p'
_ -> []
Dynamic dt -> dynSelect spineVals [] dt p
node t =
case t of
Node i lt rt -> (Just i,children lt (children rt []))
Tip -> (Nothing,[])
Dynamic dt -> (Nothing,dynChildren dt [])
children t ts =
case t of
Tip -> ts
Node _ _ _ -> t:ts
Dynamic dt -> dynChildren dt ts
dynChildren dt ts =
case dt of
DynTip -> ts
DynNode t lt rt -> (children t . dynChildren lt . dynChildren rt) ts
-- !! order??