Skip to content

Instantly share code, notes, and snippets.

@b-studios
Created June 20, 2013 17:50
Show Gist options
  • Save b-studios/5824962 to your computer and use it in GitHub Desktop.
Save b-studios/5824962 to your computer and use it in GitHub Desktop.
An attempt to visualize kiama's rewriting process, the html output can be seen at http://b-studios.de/demos/kiama_debug/.
trait DebugRewriter extends org.kiama.rewriting.CallbackRewriter {
import org.bitbucket.inkytonik.dsprofile.Events.{Event, Start}
import org.bitbucket.inkytonik.dsprofile.Events
Events.profiling = true
// ... some outputbuffering and pretty printing here
override def rewriting[T] (oldTerm : T, newTerm : T) : T = {
// in order to get the name of the strategy responsible for this rewrite action we do some hacky analysis of the
// event history
val lastStartEvent = Events.events.filter { (e: Event) =>
e.kind == Start && e.dimensions.get("subject") == Some(oldTerm)
}.last
outputBuffer.append(<div class="rule success"><span class="name">{lastStartEvent.dimensions.get("strategy").getOrElse("unknown")}</span>
<code class="before">{XMLPrettyPrinter.pretty(oldTerm)}</code>
<code class="after">{XMLPrettyPrinter.pretty(newTerm)}</code>
</div>.toString)
super.rewriting(oldTerm, newTerm)
}
}
/**
* The example rewriter: Converting a formula of classical propositional logic into disjunctive normal form
*/
lazy val normalize = doubleNeg <+ deMorgan <+ distr
lazy val doubleNeg = rule("doubleNeg", {
case Neg(Neg(x)) => x
})
lazy val deMorgan = rule("deMorgan", {
case Neg(Disj(x, y)) => Conj(Neg(x), Neg(y))
case Neg(Conj(x, y)) => Disj(Neg(x), Neg(y))
})
lazy val distr = rule("distr", {
case Conj(x, Disj(y, z)) => Disj(Conj(x, y), Conj(x, z))
case Conj(Disj(y, z), x) => Disj(Conj(y, x), Conj(z, x))
})
val input = Conj(Disj('x, 'y), Neg(Disj(Neg('a), Neg(Neg('b)))))
reduce(normalize) (input)
/**
* Turns any object into a printable xml document
*/
object XMLPrettyPrinter {
/// ...
def token(name: String, content: String) =
<span class={ "token " + name }>{content}</span>
def pretty(e: Any): scala.xml.Node = e match {
case s:Seq[_] =>
<span class="list ref" data-id={System.identityHashCode(s).toString}>{lbracket}{list(s.toList, comma)}{rbracket}</span>
case t:Product if t.productPrefix.startsWith("Tuple") =>
<span class="tuple ref" data-id={System.identityHashCode(t).toString}>{lparen}{list(t.productIterator.toList, comma)}{rparen}</span>
case p:Product =>
<span class={"product size%s ref".format(p.productArity)} data-id={System.identityHashCode(p).toString}>{token("name", p.productPrefix)}{lparen}<span class="contents">{list(p.productIterator.toList, comma)}</span>{rparen}</span>
case sym:Symbol =>
token("symbol", sym.name)
case s:String =>
token("string", s)
case _ =>
<span class={"%s ref".format(e.getClass().toString) } data-id={System.identityHashCode(e).toString}>{e.toString}</span>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment