Skip to content

Commit

Permalink
added RTree with separate frozen and unfrozend transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffreyrosenbluth committed Sep 25, 2013
1 parent 1e2b9f1 commit 4f30b95
Showing 1 changed file with 42 additions and 23 deletions.
65 changes: 42 additions & 23 deletions src/Diagrams/Core/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
module Diagrams.Core.Compile
( DTree(..)
, DNode(..)
, RTree(..)
, RNode(..)
, fromDTree
, toTree
, getPrims
) where


Expand All @@ -37,7 +39,18 @@ data DNode b v a = DStyle (Style v)
| DPrim (Prim b v)
| DEmpty

{- for some quick and dirty testing
type DTree b v a = Tree (DNode b v a)

data RNode b v a = RStyle (Style v)
| RFrozenTr (Transformation v)
| RUnFrozenTr

This comment has been minimized.

Copy link
@byorgey

byorgey Sep 26, 2013

Member

Ah, this confused me for a moment but I understand --- we push all unfrozen transformations all the way down to primitives. So what's the benefit of keeping an RUnfrozenTr node around?

This comment has been minimized.

Copy link
@jeffreyrosenbluth

jeffreyrosenbluth Sep 26, 2013

Author Member

I guess there is none, so we should just push the transformations down using REmpty?

Yes, that works.

This comment has been minimized.

Copy link
@jeffreyrosenbluth

jeffreyrosenbluth Sep 26, 2013

Author Member

By the way unfrozen transformations may become frozen along the way to the primitives in which case they are not pushed all the way down.

This comment has been minimized.

Copy link
@byorgey

byorgey Sep 26, 2013

Member

Right, almost as a byproduct this correctly handles splitting a transformation into frozen and unfrozen parts in different subtrees.

| RAnnot a
| RPrim (Transformation v) (Prim b v)
| REmpty

type RTree b v a = Tree (RNode b v a )

{--for some quick and dirty testing
deriving Show
instance Show (Prim b v) where
Expand All @@ -47,10 +60,7 @@ instance Show (Transformation v) where
show _ = "transform"
instance Show (Style v) where
show _ = "style"
-}

type DTree b v a = Tree (DNode b v a)
show _ = "style" -}

toTree :: HasLinearMap v => QDiagram b v m -> Maybe (DTree b v ())
toTree (QD qd)
Expand Down Expand Up @@ -87,20 +97,29 @@ toTree (QD qd)
(\a t -> Node (DAnnot a) [t])
qd

primList :: HasLinearMap v
=> DTree b v () -> [(Prim b v, (Split (Transformation v), Style v))]
primList = primList' (mempty, mempty)
where
primList' dacc (Node (DPrim p) ts) =
(p, dacc) : concatMap (primList' dacc) ts
primList' (t, s) (Node (DStyle sty) ts) =
concatMap (primList' (t, s <> act t sty)) ts
primList' (t, s) (Node (DTransform tr) ts) =
concatMap (primList' (t <> tr, s)) ts
primList' dacc (Node (DAnnot ()) ts) = concatMap (primList' dacc) ts
primList' dacc (Node DEmpty ts) = concatMap (primList' dacc) ts


getPrims :: HasLinearMap v
=> QDiagram b v m -> [(Prim b v, (Split (Transformation v), Style v))]
getPrims d = primList $ fromMaybe (Node DEmpty []) (toTree d)
-- | Convert a DTree to an RTree which has separate nodes for frozen and
-- unforzen transormations. The unforzen transformations are accumulated.
-- When a frozen transformation is reached the transform is put in the node
-- for processsing by the backend and the accumulator is reset.
fromDTree :: HasLinearMap v => Transformation v -> DTree b v () -> RTree b v ()

-- Prims are left as is.
fromDTree accTr (Node (DPrim p) _)
= Node (RPrim accTr p) []

-- Styles are stored in the node
fromDTree accTr (Node (DStyle s) ts)
= Node (RStyle s) (fmap (fromDTree accTr) ts)

-- Unfrozen transformations are accumulated
fromDTree accTr (Node (DTransform (M tr)) ts)
= Node RUnFrozenTr (fmap (fromDTree (accTr <> tr)) ts)

-- Frozen transformations are stored in the node and the accumulator is reset.
fromDTree accTr (Node (DTransform (tr1 :| tr2)) ts)
= Node (RFrozenTr (accTr <> tr1)) (fmap (fromDTree tr2) ts)

-- DAnnot and DEmpty nodes become REmpties, in the future my want to
-- handle DAnnots differently if they are used.
fromDTree accTr (Node _ ts)
= Node REmpty (fmap (fromDTree accTr) ts)

9 comments on commit 4f30b95

@jeffreyrosenbluth
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously not the most efficient implementation since we need to traverse the tree twice to get the resulting RTree.
Eventually toTree and fromDTree should be merged. This may warrant an alternative implementation of foldDUAL.

@byorgey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not worried about multiple traversals. I don't think it really makes much practical difference. Two linear-time traversals in sequence are still just linear time. I would rather have the code be modular and understandable than smoosh all the processing together into a single function. In fact, I was originally thinking of putting this directly in toTree but I actually like this separation better! Note also that we are probably going to want to do yet more optimization passes over RTrees anyway.

@jeffreyrosenbluth
Copy link
Member Author

@jeffreyrosenbluth jeffreyrosenbluth commented on 4f30b95 Sep 26, 2013 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@byorgey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the next steps should be (1) continuing to clean this up, adding more documentation, etc., and (2) figuring out what changes we want to make to the Backend class. Did you already have ideas about that? Once we get that set, I think we can then merge this back in and then work on adding additional optimizations and so on.

@jeffreyrosenbluth
Copy link
Member Author

@jeffreyrosenbluth jeffreyrosenbluth commented on 4f30b95 Sep 26, 2013 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@byorgey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for now it makes sense to leave withStyle in place---ideally, existing backends will just continue to work, with the option of upgrading to the new interface. But we could add two new methods taking just a transformation or just a style (with default implementations in terms of withStyle).

I am quite confident that RTree will work with other backends (though I have been wrong before =).

I don't think I'll be able to help look at clipping this week but I hope to be able to help next week. But also, I have no idea how clipping works anymore---maybe someone like @cmears or @jbracker could help (if they have time).

@jeffreyrosenbluth
Copy link
Member Author

@jeffreyrosenbluth jeffreyrosenbluth commented on 4f30b95 Sep 26, 2013 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@byorgey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, great. And by the way, I'm quite pleased with the way all of this is turning out!

@jeffreyrosenbluth
Copy link
Member Author

@jeffreyrosenbluth jeffreyrosenbluth commented on 4f30b95 Sep 27, 2013 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.