Slide 1

Slide 1 text

Anthony M. Sloane Programming Languages Research Group Department of Computing Macquarie University Sydney, Australia http://www.comp.mq.edu.au/~asloane https://wiki.mq.edu.au/display/plrg Functional Pretty Printer Combinators in Scala

Slide 2

Slide 2 text

Linear, bounded, functional pretty printing S. Doaitse Swierstra and Olaf Chitil Journal of Functional Programming, 19 (1), 1-16, Jan. 2009 Also useful: Unparsing Expressions With Prefix and Postfix Operators Norman Ramsey Software—Practice and Experience, 28 (12), 1327-1356, Oct.1998

Slide 3

Slide 3 text

Basic Combinators trait Doc { def <> (e : Doc) : Doc } def text (t : String) : Doc def line : Doc def group (d : Doc) : Doc def empty : Doc def nest (d : Doc, j : Indent = defaultIndent) : Doc def pretty (d : Doc, w : Width = defaultWidth) : Layout

Slide 4

Slide 4 text

Some Derived Combinators def char (c : Char) : Doc = ... def space : Doc = char (' ') def semi : Doc = char (';') trait Doc { def <+> (e : Doc) : Doc = this <> space <> e } implicit def stringToDoc (s : String) : Doc = text (s) def value (v : Any) : Doc = string (v.toString) def enclose (l : Doc, d : Doc, r : Doc) : Doc = l <> d <> r def parens (d : Doc) : Doc = enclose (lparen, d, rparen) def ssep (ds : Seq[Doc], sep : Doc) : Doc = fold (ds, (_ <> sep <> _)) def product (p : Any) : Doc = ...

Slide 5

Slide 5 text

Simple Imperative Language trait ImperativeNode trait Exp extends ImperativeNode case class Num (d : Double) extends Exp case class Var (s : Idn) extends Exp case class Neg (e : Exp) extends Exp case class Add (l : Exp, r : Exp) extends Exp case class Sub (l : Exp, r : Exp) extends Exp case class Mul (l : Exp, r : Exp) extends Exp trait Stmt extends ImperativeNode case class Null () extends Stmt case class Seqn (ss : Seq[Stmt]) extends Stmt case class Asgn (v : Var, e : Exp) extends Stmt case class While (e : Exp, b : Stmt) extends Stmt

Slide 6

Slide 6 text

Pretty Printing Imperative Programs def show (t : ImperativeNode) : Doc = t match { case Num (d) => value (d) case Var (s) => s case Neg (e) => parens ("-" <> show (e)) case Add (l, r) => showbin (l, "+", r) case Sub (l, r) => showbin (l, "-", r) case Mul (l, r) => showbin (l, "*", r) case Div (l, r) => showbin (l, "/", r) case Null () => semi case Seqn (ss) => group (braces (nest (line <> ssep (ss map show, line)) <> line)) case Asgn (v, e) => show (v) <+> "=" <+> show (e) <> semi case While (e, b) => "while" <+> parens (show (e)) <> group (nest (line <> show (b))) } def showbin (l : ImperativeNode, op : String, r : ImperativeNode) : Doc = parens (show (l) <+> op <+> show (r))

Slide 7

Slide 7 text

Demo...

Slide 8

Slide 8 text

Doc Indent Width TreeCont TreeCont Tree Cont Pos Dq Out Remaining Layout Doc Tree Cont Out 0 w w 0 emptyDq Tree Cont Out "" Implementation (1) pretty

Slide 9

Slide 9 text

Implementation (2) empty nest (d, j) l <> r

Slide 10

Slide 10 text

Code...

Slide 11

Slide 11 text

Downloads This Scala implementation is included in the latest release of the Kiama language processing library: http://kiama.googlecode.com