Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Overview of the Kiama Language Processing Library

Overview of the Kiama Language Processing Library

Talk at ScalaSyd September 2011

Tony Sloane

August 21, 2014
Tweet

More Decks by Tony Sloane

Other Decks in Programming

Transcript

  1. 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
  2. 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.
  3. 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 }, ...
  4. 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
  5. Pretty-printing Blah blah Transformations Bleak blah Bleek Blat Doc Pretty

    print Figure: Pretty-printing and the transformation pipeline
  6. 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))), ...
  7. 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)
  8. 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))
  9. 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)
  10. 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
  11. 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.
  12. 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 }
  13. 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) }
  14. 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 } }
  15. Transformation and Decoration: Salary Precedence def precedence (c : Company)

    : Boolean = everything (true) (_ && _) { case e : Employee => e- >bosssalary >= e- >salary } (c)
  16. 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
  17. 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)