Skip to content

Instantly share code, notes, and snippets.

@mossprescott
Created December 10, 2015 18:44
Show Gist options
  • Select an option

  • Save mossprescott/e4205238e9dd3155fece to your computer and use it in GitHub Desktop.

Select an option

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()
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
@mossprescott

Copy link
Copy Markdown
Author

You also have to modify the RenderTree instances for the types you suspect, which makes this a pain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment