diff --git a/src/funcheck/AnalysisComponent.scala b/src/funcheck/AnalysisComponent.scala index 496fcdb3f1930fe6727baad64fa2be7a6bb7383e..19acd5c7d96e7a81e922e02dec3e57a26e6a3bd8 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 65e2219ba0b7c9b9d676e84683d2a64e7924f69c..e2de5a9698fc519d5160e3a6a50dca1c48f8e9cd 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 697a44716d1cdfa6f4053abd856fc068b0c585bf..609b4475b3f7dfc6a58c3fb3da183a3de6200240 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 667cbac68af768ef64a2dede5fa6511c787c3c10..af637214a053aaf6a8a96f678a40c424431bc34b 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