Created
December 10, 2015 18:44
-
-
Save mossprescott/e4205238e9dd3155fece to your computer and use it in GitHub Desktop.
A hack to capture source values in RenderTree and use them in diff()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/core/src/main/scala/quasar/RenderTree.scala b/core/src/main/scala/quasar/RenderTree.scala | |
| index 9114fe9..ca9db46 100644 | |
| --- a/core/src/main/scala/quasar/RenderTree.scala | |
| +++ b/core/src/main/scala/quasar/RenderTree.scala | |
| @@ -26,12 +26,18 @@ import argonaut._; import Argonaut._ | |
| import scalaz._; import Scalaz._ | |
| import simulacrum.typeclass | |
| -final case class RenderedTree(nodeType: List[String], label: Option[String], children: List[RenderedTree]) { | |
| - def simpleType: Option[String] = nodeType.headOption | |
| +final case class RenderedTree(nodeType: List[String], label: Option[String], children: List[RenderedTree], orig: Option[Any]) { | |
| + def simpleType: Option[String] = nodeType.headOption.map(_ + orig.cata(κ("."), "")) // HACK | |
| + // def simpleType: Option[String] = nodeType.headOption | |
| def relabel(f: String => String) = this.copy(label = label.map(f)) | |
| def retype(f: List[String] => List[String]) = this.copy(nodeType = f(nodeType)) | |
| + private def matches(that: RenderedTree) = | |
| + ((orig |@| that.orig))(_ == _).getOrElse(nodeType == that.nodeType && label == that.label) | |
| + // // ((orig |@| that.orig)) { (o1, o2) => val r = o1 == o2; println(r); r }.getOrElse(nodeType == that.nodeType && label == that.label) | |
| + // nodeType == that.nodeType && label == that.label | |
| + | |
| /** | |
| A tree that describes differences between two trees: | |
| - If the two trees are identical, the result is the same as (either) input. | |
| @@ -54,28 +60,25 @@ final case class RenderedTree(nodeType: List[String], label: Option[String], chi | |
| val deleted = ">>>" | |
| val added = "<<<" | |
| - (this, that) match { | |
| - case (RenderedTree(nodeType1, l1, children1), RenderedTree(nodeType2, l2, children2)) => { | |
| - if (nodeType1 != nodeType2 || l1 != l2) | |
| - RenderedTree(List("[Root differs]"), None, | |
| - prefixType(this, deleted) :: | |
| - prefixType(that, added) :: | |
| - Nil) | |
| - else { | |
| - def matchChildren(children1: List[RenderedTree], children2: List[RenderedTree]): List[RenderedTree] = (children1, children2) match { | |
| - case (Nil, Nil) => Nil | |
| - case (x :: xs, Nil) => prefixType(x, deleted) :: matchChildren(xs, Nil) | |
| - case (Nil, x :: xs) => prefixType(x, added) :: matchChildren(Nil, xs) | |
| - | |
| - case (a :: as, b :: bs) if a.typeAndLabel == b.typeAndLabel => a.diff(b) :: matchChildren(as, bs) | |
| - case (a1 :: a2 :: as, b :: bs) if a2.typeAndLabel == b.typeAndLabel => prefixType(a1, deleted) :: a2.diff(b) :: matchChildren(as, bs) | |
| - case (a :: as, b1 :: b2 :: bs) if a.typeAndLabel == b2.typeAndLabel => prefixType(b1, added) :: a.diff(b2) :: matchChildren(as, bs) | |
| - | |
| - case (a :: as, b :: bs) => prefixType(a, deleted) :: prefixType(b, added) :: matchChildren(as, bs) | |
| - } | |
| - RenderedTree(nodeType1, l1, matchChildren(children1, children2)) | |
| - } | |
| + if (!(this matches that)) | |
| + RenderedTree(List("[Root differs]"), None, | |
| + prefixType(this, deleted) :: | |
| + prefixType(that, added) :: | |
| + Nil, | |
| + None) | |
| + else { | |
| + def matchChildren(children1: List[RenderedTree], children2: List[RenderedTree]): List[RenderedTree] = (children1, children2) match { | |
| + case (Nil, Nil) => Nil | |
| + case (x :: xs, Nil) => prefixType(x, deleted) :: matchChildren(xs, Nil) | |
| + case (Nil, x :: xs) => prefixType(x, added) :: matchChildren(Nil, xs) | |
| + | |
| + case (a :: as, b :: bs) if a matches b => a.diff(b) :: matchChildren(as, bs) | |
| + case (a1 :: a2 :: as, b :: bs) if a2 matches b => prefixType(a1, deleted) :: a2.diff(b) :: matchChildren(as, bs) | |
| + case (a :: as, b1 :: b2 :: bs) if a matches b2 => prefixType(b1, added) :: a.diff(b2) :: matchChildren(as, bs) | |
| + | |
| + case (a :: as, b :: bs) => prefixType(a, deleted) :: prefixType(b, added) :: matchChildren(as, bs) | |
| } | |
| + RenderedTree(this.nodeType, this.label, matchChildren(this.children, that.children), this.orig) | |
| } | |
| } | |
| @@ -131,7 +134,7 @@ object RenderedTree { | |
| } | |
| implicit val RenderedTreeEncodeJson: EncodeJson[RenderedTree] = EncodeJson { | |
| - case RenderedTree(nodeType, label, children) => | |
| + case RenderedTree(nodeType, label, children, _) => | |
| Json.obj(( | |
| (nodeType match { | |
| case Nil => None | |
| @@ -146,10 +149,16 @@ object RenderedTree { | |
| } | |
| } | |
| object Terminal { | |
| - def apply(nodeType: List[String], label: Option[String]): RenderedTree = RenderedTree(nodeType, label, Nil) | |
| + @SuppressWarnings(Array("org.brianmckenna.wartremover.warts.DefaultArguments")) | |
| + def apply(nodeType: List[String], label: Option[String], orig: Option[Any] = None): | |
| + RenderedTree = | |
| + RenderedTree(nodeType, label, Nil, orig) | |
| } | |
| object NonTerminal { | |
| - def apply(nodeType: List[String], label: Option[String], children: List[RenderedTree]): RenderedTree = RenderedTree(nodeType, label, children) | |
| + @SuppressWarnings(Array("org.brianmckenna.wartremover.warts.DefaultArguments")) | |
| + def apply(nodeType: List[String], label: Option[String], children: List[RenderedTree], orig: Option[Any] = None): | |
| + RenderedTree = | |
| + RenderedTree(nodeType, label, children, orig) | |
| } | |
| @typeclass trait RenderTree[A] { | |
| @@ -188,8 +197,8 @@ object RenderTree extends RenderTreeInstances { | |
| for { | |
| n <- nodeName | |
| cc <- t match { | |
| - case RenderedTree(_, _, Nil) => state[Int, Cord](Cord("")) | |
| - case RenderedTree(_, _, children) => { | |
| + case RenderedTree(_, _, Nil, _) => state[Int, Cord](Cord("")) | |
| + case RenderedTree(_, _, children, _) => { | |
| for { | |
| nodes <- children.map(render(_)).sequenceU | |
| } yield nodes.map(cn => Cord(" ") ++ n ++ " -> " ++ cn.name ++ ";\n" ++ cn.dot).concatenate |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You also have to modify the
RenderTreeinstances for the types you suspect, which makes this a pain.