From fd0f1fb2da8469cfe519dffd9b7a3cfbf1a200d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9gis=20Blanc?= <regwblanc@gmail.com>
Date: Thu, 17 May 2012 15:30:46 +0200
Subject: [PATCH] a scala printer

---
 .../scala/leon/purescala/ScalaPrinter.scala   | 552 ++++++++++++++++++
 1 file changed, 552 insertions(+)
 create mode 100644 src/main/scala/leon/purescala/ScalaPrinter.scala

diff --git a/src/main/scala/leon/purescala/ScalaPrinter.scala b/src/main/scala/leon/purescala/ScalaPrinter.scala
new file mode 100644
index 000000000..31ede51a8
--- /dev/null
+++ b/src/main/scala/leon/purescala/ScalaPrinter.scala
@@ -0,0 +1,552 @@
+package leon.purescala
+
+/** This pretty-printer only print valid scala syntax */
+object ScalaPrinter {
+  import Common._
+  import Trees._
+  import TypeTrees._
+  import Definitions._
+
+  import java.lang.StringBuffer
+
+  def apply(tree: Expr): String = {
+    val retSB = pp(tree, new StringBuffer, 0)
+    retSB.toString
+  }
+
+  def apply(tpe: TypeTree): String = {
+    val retSB = pp(tpe, new StringBuffer, 0)
+    retSB.toString
+  }
+
+  def apply(defn: Definition): String = {
+    val retSB = pp(defn, new StringBuffer, 0)
+    retSB.toString
+  }
+
+  private def ind(sb: StringBuffer, lvl: Int) : StringBuffer = {
+      sb.append("  " * lvl)
+      sb
+  }
+
+  // EXPRESSIONS
+  // all expressions are printed in-line
+  private def ppUnary(sb: StringBuffer, expr: Expr, op1: String, op2: String, lvl: Int): StringBuffer = {
+    var nsb: StringBuffer = sb
+    nsb.append(op1)
+    nsb = pp(expr, nsb, lvl)
+    nsb.append(op2)
+    nsb
+  }
+
+  private def ppBinary(sb: StringBuffer, left: Expr, right: Expr, op: String, lvl: Int): StringBuffer = {
+    var nsb: StringBuffer = sb
+    nsb.append("(")
+    nsb = pp(left, nsb, lvl)
+    nsb.append(op)
+    nsb = pp(right, nsb, lvl)
+    nsb.append(")")
+    nsb
+  }
+
+  private def ppNary(sb: StringBuffer, exprs: Seq[Expr], pre: String, op: String, post: String, lvl: Int): StringBuffer = {
+    var nsb = sb
+    nsb.append(pre)
+    val sz = exprs.size
+    var c = 0
+
+    exprs.foreach(ex => {
+      nsb = pp(ex, nsb, lvl) ; c += 1 ; if(c < sz) nsb.append(op)
+    })
+
+    nsb.append(post)
+    nsb
+  }
+
+  private def pp(tree: Expr, sb: StringBuffer, lvl: Int): StringBuffer = tree match {
+    case Variable(id) => sb.append(id)
+    case DeBruijnIndex(idx) => sys.error("Not Valid Scala")
+    case Let(b,d,e) => {
+      sb.append("{\n")
+      ind(sb, lvl+1)
+      sb.append("val " + b + " = ")
+      pp(d, sb, lvl+1)
+      sb.append("\n")
+      ind(sb, lvl+1)
+      pp(e, sb, lvl+1)
+      sb.append("\n")
+      ind(sb, lvl)
+      sb.append("}\n")
+      ind(sb, lvl)
+      sb
+    }
+    case LetVar(b,d,e) => {
+      sb.append("{\n")
+      ind(sb, lvl+1)
+      sb.append("var " + b + " = ")
+      pp(d, sb, lvl+1)
+      sb.append("\n")
+      ind(sb, lvl+1)
+      pp(e, sb, lvl+1)
+      sb.append("\n")
+      ind(sb, lvl)
+      sb.append("}\n")
+      ind(sb, lvl)
+      sb
+    }
+    case LetDef(fd,e) => {
+      sb.append("\n")
+      pp(fd, sb, lvl+1)
+      sb.append("\n")
+      sb.append("\n")
+      ind(sb, lvl)
+      pp(e, sb, lvl)
+      sb
+    }
+    case And(exprs) => ppNary(sb, exprs, "(", " && ", ")", lvl)            // \land
+    case Or(exprs) => ppNary(sb, exprs, "(", " || ", ")", lvl)             // \lor
+    case Not(Equals(l, r)) => ppBinary(sb, l, r, " != ", lvl)    // \neq
+    case Iff(l,r) => sys.error("Not Scala Code")
+    case Implies(l,r) => sys.error("Not Scala Code")
+    case UMinus(expr) => ppUnary(sb, expr, "-(", ")", lvl)
+    case Equals(l,r) => ppBinary(sb, l, r, " == ", lvl)
+    case IntLiteral(v) => sb.append(v)
+    case BooleanLiteral(v) => sb.append(v)
+    case StringLiteral(s) => sb.append("\"" + s + "\"")
+    case UnitLiteral => sb.append("()")
+    case Block(exprs, last) => {
+      sb.append("{\n")
+      (exprs :+ last).foreach(e => {
+        ind(sb, lvl+1)
+        pp(e, sb, lvl+1)
+        sb.append("\n")
+      })
+      ind(sb, lvl)
+      sb.append("}\n")
+      sb
+    }
+    case Assignment(lhs, rhs) => ppBinary(sb, lhs.toVariable, rhs, " = ", lvl)
+    case wh@While(cond, body) => {
+      wh.invariant match {
+        case Some(inv) => {
+          sb.append("\n")
+          ind(sb, lvl)
+          sb.append("@invariant: ")
+          pp(inv, sb, lvl)
+          sb.append("\n")
+          ind(sb, lvl)
+        }
+        case None =>
+      }
+      sb.append("while(")
+      pp(cond, sb, lvl)
+      sb.append(")\n")
+      ind(sb, lvl+1)
+      pp(body, sb, lvl+1)
+      sb.append("\n")
+    }
+
+    case t@Tuple(exprs) => ppNary(sb, exprs, "(", ", ", ")", lvl)
+    case s@TupleSelect(t, i) => {
+      pp(t, sb, lvl)
+      sb.append("._" + i)
+      sb
+    }
+
+    case e@Epsilon(pred) => sys.error("Not Scala Code")
+    case Waypoint(i, expr) => pp(expr, sb, lvl)
+
+    case OptionSome(a) => {
+      var nsb = sb
+      nsb.append("Some(")
+      nsb = pp(a, nsb, lvl)
+      nsb.append(")")
+      nsb
+    }
+
+    case OptionNone(_) => sb.append("None")
+
+    case CaseClass(cd, args) => {
+      var nsb = sb
+      nsb.append(cd.id)
+      nsb = ppNary(nsb, args, "(", ", ", ")", lvl)
+      nsb
+    }
+    case CaseClassInstanceOf(cd, e) => {
+      var nsb = sb
+      nsb = pp(e, nsb, lvl)
+      nsb.append(".isInstanceOf[" + cd.id + "]")
+      nsb
+    }
+    case CaseClassSelector(_, cc, id) => pp(cc, sb, lvl).append("." + id)
+    case FunctionInvocation(fd, args) => {
+      var nsb = sb
+      nsb.append(fd.id)
+      nsb = ppNary(nsb, args, "(", ", ", ")", lvl)
+      nsb
+    }
+    case AnonymousFunction(es, ev) => {
+      var nsb = sb
+      nsb.append("{")
+      es.foreach {
+        case (as, res) => 
+          nsb = ppNary(nsb, as, "", " ", "", lvl)
+          nsb.append(" -> ")
+          nsb = pp(res, nsb, lvl)
+          nsb.append(", ")
+      }
+      nsb.append("else -> ")
+      nsb = pp(ev, nsb, lvl)
+      nsb.append("}")
+    }
+    case AnonymousFunctionInvocation(id, args) => {
+      var nsb = sb
+      nsb.append(id)
+      nsb = ppNary(nsb, args, "(", ", ", ")", lvl)
+      nsb
+    }
+    case Plus(l,r) => ppBinary(sb, l, r, " + ", lvl)
+    case Minus(l,r) => ppBinary(sb, l, r, " - ", lvl)
+    case Times(l,r) => ppBinary(sb, l, r, " * ", lvl)
+    case Division(l,r) => ppBinary(sb, l, r, " / ", lvl)
+    case Modulo(l,r) => ppBinary(sb, l, r, " % ", lvl)
+    case LessThan(l,r) => ppBinary(sb, l, r, " < ", lvl)
+    case GreaterThan(l,r) => ppBinary(sb, l, r, " > ", lvl)
+    case LessEquals(l,r) => ppBinary(sb, l, r, " <= ", lvl)      // \leq
+    case GreaterEquals(l,r) => ppBinary(sb, l, r, " >= ", lvl)   // \geq
+    case FiniteSet(rs) => ppNary(sb, rs, "{", ", ", "}", lvl)
+    case FiniteMultiset(rs) => ppNary(sb, rs, "{|", ", ", "|}", lvl)
+    case EmptySet(bt) => sb.append("Set()")                          // Ø
+    case EmptyMultiset(_) => sys.error("Not Valid Scala")
+    case Not(ElementOfSet(s,e)) => sys.error("TODO")
+    //case ElementOfSet(s,e) => ppBinary(sb, s, e, " \u2208 ", lvl)    // \in
+    //case SubsetOf(l,r) => ppBinary(sb, l, r, " \u2286 ", lvl)        // \subseteq
+    //case Not(SubsetOf(l,r)) => ppBinary(sb, l, r, " \u2288 ", lvl)        // \notsubseteq
+    case SetMin(s) => pp(s, sb, lvl).append(".min")
+    case SetMax(s) => pp(s, sb, lvl).append(".max")
+   // case SetUnion(l,r) => ppBinary(sb, l, r, " \u222A ", lvl)        // \cup
+   // case MultisetUnion(l,r) => ppBinary(sb, l, r, " \u222A ", lvl)   // \cup
+   // case MapUnion(l,r) => ppBinary(sb, l, r, " \u222A ", lvl)        // \cup
+   // case SetDifference(l,r) => ppBinary(sb, l, r, " \\ ", lvl)       
+   // case MultisetDifference(l,r) => ppBinary(sb, l, r, " \\ ", lvl)       
+   // case SetIntersection(l,r) => ppBinary(sb, l, r, " \u2229 ", lvl) // \cap
+   // case MultisetIntersection(l,r) => ppBinary(sb, l, r, " \u2229 ", lvl) // \cap
+   // case SetCardinality(t) => ppUnary(sb, t, "|", "|", lvl)
+   // case MultisetCardinality(t) => ppUnary(sb, t, "|", "|", lvl)
+   // case MultisetPlus(l,r) => ppBinary(sb, l, r, " \u228E ", lvl)    // U+
+   // case MultisetToSet(e) => pp(e, sb, lvl).append(".toSet")
+    case EmptyMap(_,_) => sb.append("Map()")
+    case SingletonMap(f,t) => ppBinary(sb, f, t, " -> ", lvl)
+    case FiniteMap(rs) => ppNary(sb, rs, "Map(", ", ", ")", lvl)
+    case MapGet(m,k) => {
+      var nsb = sb
+      pp(m, nsb, lvl)
+      nsb = ppNary(nsb, Seq(k), "(", ",", ")", lvl)
+      nsb
+    }
+    case MapIsDefinedAt(m,k) => {
+      var nsb = sb
+      pp(m, nsb, lvl)
+      nsb.append(".isDefinedAt")
+      nsb = ppNary(nsb, Seq(k), "(", ",", ")", lvl)
+      nsb
+    }
+    case ArrayLength(a) => {
+      pp(a, sb, lvl)
+      sb.append(".length")
+    }
+    case ArrayClone(a) => {
+      pp(a, sb, lvl)
+      sb.append(".clone")
+    }
+    case fill@ArrayFill(size, v) => {
+      sb.append("Array.fill(")
+      pp(size, sb, lvl)
+      sb.append(")(")
+      pp(v, sb, lvl)
+      sb.append(")")
+    }
+    case am@ArrayMake(v) => sys.error("Not Scala Code")
+    case sel@ArraySelect(ar, i) => {
+      pp(ar, sb, lvl)
+      sb.append("(")
+      pp(i, sb, lvl)
+      sb.append(")")
+    }
+    case up@ArrayUpdate(ar, i, v) => {
+      pp(ar, sb, lvl)
+      sb.append("(")
+      pp(i, sb, lvl)
+      sb.append(") = ")
+      pp(v, sb, lvl)
+    }
+    case up@ArrayUpdated(ar, i, v) => {
+      pp(ar, sb, lvl)
+      sb.append(".updated(")
+      pp(i, sb, lvl)
+      sb.append(", ")
+      pp(v, sb, lvl)
+      sb.append(")")
+    }
+    case FiniteArray(exprs) => {
+      ppNary(sb, exprs, "Array(", ", ", ")", lvl)
+    }
+
+    case Distinct(exprs) => {
+      var nsb = sb
+      nsb.append("distinct")
+      nsb = ppNary(nsb, exprs, "(", ", ", ")", lvl)
+      nsb
+    }
+    
+    case IfExpr(c, t, e) => {
+      var nsb = sb
+      nsb.append("(if (")
+      nsb = pp(c, nsb, lvl)
+      nsb.append(")\n")
+      ind(nsb, lvl+1)
+      nsb = pp(t, nsb, lvl+1)
+      nsb.append("\n")
+      ind(nsb, lvl)
+      nsb.append("else\n")
+      ind(nsb, lvl+1)
+      nsb = pp(e, nsb, lvl+1)
+      nsb.append(")")
+      nsb
+    }
+
+    case mex @ MatchExpr(s, csc) => {
+      def ppc(sb: StringBuffer, p: Pattern): StringBuffer = p match {
+        //case InstanceOfPattern(None,     ctd) =>
+        //case InstanceOfPattern(Some(id), ctd) =>
+        case CaseClassPattern(bndr,     ccd, subps) => {
+          var nsb = sb
+          bndr.foreach(b => nsb.append(b + " @ "))
+          nsb.append(ccd.id).append("(")
+          var c = 0
+          val sz = subps.size
+          subps.foreach(sp => {
+            nsb = ppc(nsb, sp)
+            if(c < sz - 1)
+              nsb.append(", ")
+            c = c + 1
+          })
+          nsb.append(")")
+        }
+        case WildcardPattern(None)     => sb.append("_")
+        case WildcardPattern(Some(id)) => sb.append(id)
+        case TuplePattern(bndr, subPatterns) => {
+          bndr.foreach(b => sb.append(b + " @ "))
+          sb.append("(")
+          subPatterns.init.foreach(p => {
+            ppc(sb, p)
+            sb.append(", ")
+          })
+          ppc(sb, subPatterns.last)
+          sb.append(")")
+        }
+        case _ => sb.append("Pattern?")
+      }
+
+      var nsb = sb
+      nsb == pp(s, nsb, lvl)
+      // if(mex.posInfo != "") {
+      //   nsb.append(" match@(" + mex.posInfo + ") {\n")
+      // } else {
+        nsb.append(" match {\n")
+      // }
+
+      csc.foreach(cs => {
+        ind(nsb, lvl+1)
+        nsb.append("case ")
+        nsb = ppc(nsb, cs.pattern)
+        cs.theGuard.foreach(g => {
+          nsb.append(" if ")
+          nsb = pp(g, nsb, lvl+1)
+        })
+        nsb.append(" => ")
+        nsb = pp(cs.rhs, nsb, lvl+1)
+        nsb.append("\n")
+      })
+      ind(nsb, lvl).append("}")
+      nsb
+    }
+
+    case ResultVariable() => sb.append("#res")
+    case EpsilonVariable((row, col)) => sb.append("x" + row + "_" + col)
+    case Not(expr) => ppUnary(sb, expr, "\u00AC(", ")", lvl)               // \neg
+
+    case e @ Error(desc) => {
+      var nsb = sb
+      nsb.append("error(\"" + desc + "\")[")
+      nsb = pp(e.getType, nsb, lvl)
+      nsb.append("]")
+      nsb
+    }
+
+    case _ => sb.append("Expr?")
+  }
+
+  // TYPE TREES
+  // all type trees are printed in-line
+  private def ppNaryType(sb: StringBuffer, tpes: Seq[TypeTree], pre: String, op: String, post: String, lvl: Int): StringBuffer = {
+    var nsb = sb
+    nsb.append(pre)
+    val sz = tpes.size
+    var c = 0
+
+    tpes.foreach(t => {
+      nsb = pp(t, nsb, lvl) ; c += 1 ; if(c < sz) nsb.append(op)
+    })
+
+    nsb.append(post)
+    nsb
+  }
+
+  private def pp(tpe: TypeTree, sb: StringBuffer, lvl: Int): StringBuffer = tpe match {
+    case Untyped => sb.append("???")
+    case UnitType => sb.append("Unit")
+    case Int32Type => sb.append("Int")
+    case BooleanType => sb.append("Boolean")
+    case ArrayType(bt) => pp(bt, sb.append("Array["), lvl).append("]")
+    case SetType(bt) => pp(bt, sb.append("Set["), lvl).append("]")
+    case MapType(ft,tt) => pp(tt, pp(ft, sb.append("Map["), lvl).append(","), lvl).append("]")
+    case MultisetType(bt) => pp(bt, sb.append("Multiset["), lvl).append("]")
+    case OptionType(bt) => pp(bt, sb.append("Option["), lvl).append("]")
+    case FunctionType(fts, tt) => {
+      var nsb = sb
+      if (fts.size > 1)
+        nsb = ppNaryType(nsb, fts, "(", ", ", ")", lvl)
+      else if (fts.size == 1)
+        nsb = pp(fts.head, nsb, lvl)
+      nsb.append(" => ")
+      pp(tt, nsb, lvl)
+    }
+    case TupleType(tpes) => ppNaryType(sb, tpes, "(", ", ", ")", lvl)
+    case c: ClassType => sb.append(c.classDef.id)
+    case _ => sb.append("Type?")
+  }
+
+  // DEFINITIONS
+  // all definitions are printed with an end-of-line
+  private def pp(defn: Definition, sb: StringBuffer, lvl: Int): StringBuffer = {
+
+    defn match {
+      case Program(id, mainObj) => {
+        assert(lvl == 0)
+        sb.append("package ")
+        sb.append(id)
+        sb.append(" {\n")
+        pp(mainObj, sb, lvl+1).append("}\n")
+      }
+
+      case ObjectDef(id, defs, invs) => {
+        var nsb = sb
+        ind(nsb, lvl)
+        nsb.append("object ")
+        nsb.append(id)
+        nsb.append(" {\n")
+
+        var c = 0
+        val sz = defs.size
+
+        defs.foreach(df => {
+          nsb = pp(df, nsb, lvl+1)
+          if(c < sz - 1) {
+            nsb.append("\n\n")
+          }
+          c = c + 1
+        })
+
+        nsb.append("\n")
+        ind(nsb, lvl).append("}\n")
+      }
+
+      case AbstractClassDef(id, parent) => {
+        var nsb = sb
+        ind(nsb, lvl)
+        nsb.append("sealed abstract class ")
+        nsb.append(id)
+        parent.foreach(p => nsb.append(" extends " + p.id))
+        nsb
+      }
+
+      case CaseClassDef(id, parent, varDecls) => {
+        var nsb = sb
+        ind(nsb, lvl)
+        nsb.append("case class ")
+        nsb.append(id)
+        nsb.append("(")
+        var c = 0
+        val sz = varDecls.size
+
+        varDecls.foreach(vd => {
+          nsb.append(vd.id)
+          nsb.append(": ")
+          nsb = pp(vd.tpe, nsb, lvl)
+          if(c < sz - 1) {
+            nsb.append(", ")
+          }
+          c = c + 1
+        })
+        nsb.append(")")
+        parent.foreach(p => nsb.append(" extends " + p.id))
+        nsb
+      }
+
+      case fd @ FunDef(id, rt, args, body, pre, post) => {
+        var nsb = sb
+
+        for(a <- fd.annotations) {
+          ind(nsb, lvl)
+          nsb.append("@" + a + "\n")
+        }
+
+        pre.foreach(prec => {
+          ind(nsb, lvl)
+          nsb.append("@pre : ")
+          nsb = pp(prec, nsb, lvl)
+          nsb.append("\n")
+        })
+
+        post.foreach(postc => {
+          ind(nsb, lvl)
+          nsb.append("@post: ")
+          nsb = pp(postc, nsb, lvl)
+          nsb.append("\n")
+        })
+
+        ind(nsb, lvl)
+        nsb.append("def ")
+        nsb.append(id)
+        nsb.append("(")
+
+        val sz = args.size
+        var c = 0
+        
+        args.foreach(arg => {
+          nsb.append(arg.id)
+          nsb.append(" : ")
+          nsb = pp(arg.tpe, nsb, lvl)
+
+          if(c < sz - 1) {
+            nsb.append(", ")
+          }
+          c = c + 1
+        })
+
+        nsb.append(") : ")
+        nsb = pp(rt, nsb, lvl)
+        nsb.append(" = ")
+        if(body.isDefined)
+          pp(body.get, nsb, lvl)
+        else
+          nsb.append("[unknown function implementation]")
+      }
+
+      case _ => sb.append("Defn?")
+    }
+  }
+}
+
+// vim: set ts=4 sw=4 et:
-- 
GitLab