From ecbb6a78eb9fdad34a0e34de166c56482dda7c15 Mon Sep 17 00:00:00 2001
From: Philippe Suter <philippe.suter@gmail.com>
Date: Tue, 9 Jun 2009 16:42:57 +0000
Subject: [PATCH] stub for purescala pretty printer, some (really) basic
 extraction is in place... looking good

---
 src/funcheck/AnalysisComponent.scala |  3 +-
 src/funcheck/CodeExtraction.scala    | 47 ++++++++++++++++++++++++++--
 src/funcheck/Extractors.scala        | 10 ++++--
 src/funcheck/purescala/Trees.scala   |  9 +++++-
 4 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/src/funcheck/AnalysisComponent.scala b/src/funcheck/AnalysisComponent.scala
index 496fcdb3f..19acd5c7d 100644
--- a/src/funcheck/AnalysisComponent.scala
+++ b/src/funcheck/AnalysisComponent.scala
@@ -27,8 +27,7 @@ class AnalysisComponent(val global: Global, val pluginInstance: FunCheckPlugin)
       // stopIfErrors
       // (new ForeachTreeTraverser(findContracts)).traverse(unit.body)
       // stopIfErrors
-      (new ForeachTreeTraverser(showObjects)).traverse(unit.body)
-      // (new ForeachTreeTraverser(mircoTraverser(unit))).traverse(unit.body)
+      (new ForeachTreeTraverser(extractCode(unit))).traverse(unit.body)
 
       if(pluginInstance.stopAfterAnalysis) {
         println("Analysis complete. Now terminating the compiler process.")
diff --git a/src/funcheck/CodeExtraction.scala b/src/funcheck/CodeExtraction.scala
index 65e2219ba..e2de5a969 100644
--- a/src/funcheck/CodeExtraction.scala
+++ b/src/funcheck/CodeExtraction.scala
@@ -2,12 +2,14 @@ package funcheck
 
 import scala.tools.nsc._
 import scala.tools.nsc.plugins._
+import purescala.Trees._
 
 trait CodeExtraction {
   self: AnalysisComponent =>
 
   import global._
   import StructuralExtractors._
+  import ExpressionExtractors._
 
   def findContracts(tree: Tree): Unit = tree match {
     case DefDef(/*mods*/ _, name, /*tparams*/ _, /*vparamss*/ _, /*tpt*/ _, body) => {
@@ -34,8 +36,49 @@ trait CodeExtraction {
     case _ => ;
   }
 
-  def showObjects(tree: Tree): Unit = tree match {
-    case ObjectDefn(name) => println(name + " appears to be an object.")
+  def extractCode(unit: CompilationUnit)(tree: Tree): Unit = tree match {
+    case d @ DefDef(mods, name, tparams, vparamss, tpt, body) => {
+      println("In: " + name)
+      println(d.symbol)
+      println(d.mods)
+      
+      
+      toPureScala(unit)(body) match {
+        case Some(t) => println("  the body was extracted as: " + t)
+        case None => println("  the body could not be extracted. Is it pure Scala?")
+      }
+    }
+
     case _ => ;
   }
+
+  /** An exception thrown when non-purescala compatible code is encountered. */
+  sealed case class ImpureCodeEncounteredException(tree: Tree) extends Exception
+
+  /** Attempts to convert a scalac AST to a pure scala AST. */
+  def toPureScala(unit: CompilationUnit)(tree: Tree): Option[Expr] = {
+    try {
+      Some(scala2PureScala(unit, false)(tree))
+    } catch {
+      case ImpureCodeEncounteredException(_) => None
+    }
+  }
+
+  /** Forces conversion from scalac AST to purescala AST, throws an Exception
+   * if impossible. If not in 'silent mode', non-pure AST nodes are reported as
+   * errors. */
+  private def scala2PureScala(unit: CompilationUnit, silent: Boolean)(tree: Tree): Expr = {
+    tree match {
+      case ExInt32Literal(v) => IntLiteral(v)
+      case ExBooleanLiteral(v) => BooleanLiteral(v)
+
+      // default behaviour is to complain :)
+      case _ => {
+        if(!silent) {
+          unit.error(tree.pos, "Could not extract as PureScala.")
+        }
+        throw ImpureCodeEncounteredException(tree)
+      }
+    }
+  }
 }
diff --git a/src/funcheck/Extractors.scala b/src/funcheck/Extractors.scala
index 697a44716..609b4475b 100644
--- a/src/funcheck/Extractors.scala
+++ b/src/funcheck/Extractors.scala
@@ -54,7 +54,7 @@ trait Extractors {
         case c @ ClassDef(_, name, tparams, impl) => {
           println(name.toString + " is being traversed.")
           println(c.symbol)
-          if(c.symbol.hasFlag(symtab.Flags.MODULE)) {
+          if(c.symbol.isModuleClass) {
             Some(name.toString)
           } else {
             None
@@ -67,13 +67,19 @@ trait Extractors {
 
   object ExpressionExtractors {
     object ExBooleanLiteral {
-      /** Extracts the 'true' of 'false' constants. */
       def unapply(tree: Tree): Option[Boolean] = tree match {
         case Literal(Constant(true)) => Some(true)
         case Literal(Constant(false)) => Some(false)
         case _ => None
       }
     }
+
+    object ExInt32Literal {
+      def unapply(tree: Tree): Option[Int] = tree match {
+        case Literal(c @ Constant(i)) if c.tpe == IntClass.tpe => Some(c.intValue)
+        case _ => None
+      }
+    }
   }
 
   object TypeExtractors {
diff --git a/src/funcheck/purescala/Trees.scala b/src/funcheck/purescala/Trees.scala
index 667cbac68..af637214a 100644
--- a/src/funcheck/purescala/Trees.scala
+++ b/src/funcheck/purescala/Trees.scala
@@ -11,7 +11,9 @@ object Trees {
    * correctly typed at construction time. Each AST node checks that the
    * children provided satisfy whatever typing constraints are required by the
    * node, and each node is then responsible for communicating its type. */
-  sealed abstract class Expr extends Typed
+  sealed abstract class Expr extends Typed {
+    override def toString: String = PrettyPrinter(this)
+  }
 
   /** 
    Go through each type, add the operations.
@@ -132,6 +134,11 @@ see examples in:
     val getType = Int32Type
   }
 
+  case class UMinus(expr: Expr) extends Expr {
+    assert(expr.getType == Int32Type)
+    val getType = Int32Type
+  }
+
   case class Times(lhs: Expr, rhs: Expr) extends Expr {
     assert(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
-- 
GitLab