Slide 1

Slide 1 text

Overview of the Kiama Language Processing Library Anthony M. Sloane [email protected] @inkytonik Programming Languages Research Group Department of Computing Macquarie University September 14, 2011

Slide 2

Slide 2 text

Kiama A collection of Scala-based internal domain-specific languages for solving problems in the domain of language processing. Problem Domain-specific language Structure representation Algebraic data types Text to structure Context-free grammars Output Pretty printing Transformation Term rewriting Decoration Attribute grammars Aim: to bring these high-level processing mechanisms closer to real programmers.

Slide 3

Slide 3 text

JSON (http://101companies.org) { "depts" : [ { "name" : "Research", "manager" : { "name" : "Craig", "address" : "Redmond", "salary" : 123456.0 }, "subunits" : [ { "type" : "employee", "name" : "Erik", "address" : "Utrecht", "salary" : 12345.0 }, ...

Slide 4

Slide 4 text

JSON Structure Representation abstract class JValue case class JObject (fields : List [(JName ,JValue)]) extends JValue case class JName (s : String) case class JArray (values: Vector[JValue ]) extends JValue case class JString (value : String) extends JValue case class JNumber (value : Double) extends JValue case class JTrue () extends JValue case class JFalse () extends JValue case class JNull () extends JValue

Slide 5

Slide 5 text

Pretty-printing Blah blah Transformations Bleak blah Bleek Blat Doc Pretty print Figure: Pretty-printing and the transformation pipeline

Slide 6

Slide 6 text

Pretty-printing: Default Format JObject ( List ( JName ("depts") -> JArray ( Vector ( JObject ( List ( JName ("type") -> JString ("department"), JName ("name") -> JString ("Research"), JName ("manager") -> JObject ( List ( JName ("name") -> JString ("Craig"), JName ("address") -> JString ("Redmond"), JName ("salary") -> JNumber (123456.0))), ...

Slide 7

Slide 7 text

Pretty-printing: Custom Format def show (t : JValue) : Doc = t match { case JNull () => "null" case JTrue () => "true" case JFalse () => "false" case JNumber (d) => value (d) case JString (s) => dquotes (value (s)) case JArray (vs) => brackets (group (nest (line <> ssep (vs map show , comma <> line)) <> line)) case JObject (ps) => braces (group (nest (line <> ssep (ps map showPair , comma <> line)) <> line)) } def showPair (p : (JName ,JValue)) : Doc = dquotes (p._1.s) <+> colon <+> show (p._2)

Slide 8

Slide 8 text

Transformation rule all (s) Figure: Transformation patterns

Slide 9

Slide 9 text

Transformation: Combinators def rule (f : Term ==> Term) : Strategy = ... def everywhere (s : => Strategy) : Strategy = topdown (attempt (s)) def attempt (s : => Strategy) : Strategy = s <+ id def topdown (s : => Strategy) : Strategy = s <* all (topdown (s))

Slide 10

Slide 10 text

Transformation: Cutting Salaries; Total Wage Bill def cut (c : JValue) : JValue = rewrite (everywhere ( rule { case (n @ JName ("salary"), JNumber (d)) => (n, JNumber (d / 2)) } )) (c) def total (c : JValue) : Double = everything (0.0) (_ + _) { case (JName ("salary"), JNumber (d)) => d } (c)

Slide 11

Slide 11 text

Typed Trees trait Node extends Attributable case class Company (depts : List[Dept ]) extends Node case class Dept (n : Name , m : Manager , su : List[SubUnit ]) extends Node type Manager = Employee case class Employee (n : Name , a : Address , s : Salary) extends Node abstract class SubUnit extends Node case class PU (e : Employee) extends SubUnit case class DU (d : Dept) extends SubUnit type Name = String type Address = String type Salary = Double

Slide 12

Slide 12 text

Decoration We want to avoid thinking about attribute dependencies, tree traversal patterns to satisfy those dependencies, and attribute storage. Figure: An attribute of a tree node depends on attributes of other nodes Solution: functional attribute definitions with memoisation.

Slide 13

Slide 13 text

Decoration: Employee Count and Salary Total val numemp : Node ==> Int = attr { case Company (ds) => (ds map numemp).sum case Dept (_, _, sus) => 1 + (sus map numemp).sum case DU (d) => d- >numemp case _ => 1 } val salary : Node ==> Double = attr { case Company (ds) => (ds map salary).sum case Dept (_, Employee (_, _, s), sus) => s + (sus map salary).sum case PU (e) => e- >salary case DU (d) => d- >salary case Employee (_, _, s) => s }

Slide 14

Slide 14 text

Decoration: Average Salary val averagesalary : Node ==> Double = attr { case n @ (_ : Company | _ : Dept) => (n- >salary) / (n- >numemp) case n => (n.parent[Node ])-> averagesalary } val aboveaverage : Employee ==> Boolean = attr { case e @ Employee (_, _, s) => s > (e- > averagesalary) }

Slide 15

Slide 15 text

Decoration: Salary of Boss val bosssalary : Node ==> Salary = attr { case n if n isRoot => Double.MaxValue case Dept (_, m, _) => m- >salary case e : Employee => e.parent[Node] match { case p @ Dept (_, m, _) if m eq e => // Avoid comparing manager ’s salary with itself p.parent[Node]->bosssalary case p => p- >bosssalary } }

Slide 16

Slide 16 text

Transformation and Decoration: Salary Precedence def precedence (c : Company) : Boolean = everything (true) (_ && _) { case e : Employee => e- >bosssalary >= e- >salary } (c)

Slide 17

Slide 17 text

More Information http://kiama.googlecode.com/ Related work: Stratego: http://strategoxt.org JastAdd: http://jastadd.org Swierstra, S., and Chitil, O. Linear, bounded, functional pretty-printing. Journal of Functional Programming 19, 1 (2008), 1–16

Slide 18

Slide 18 text

Ideas needed. . . Write a method to duplicate a case class instance with new children without using reflection. def dup[T <: Product] ( t : T, children : Array[AnyRef] ) : T For example, if Foo is a case class with two constructor parameters dup (Foo (a, b), Array (c, d)) should return Foo (c, d)