diff --git a/src/funcheck/CodeExtraction.scala b/src/funcheck/CodeExtraction.scala index 683db51ad63c590bdf1b46722cadfc5284f6befe..bd3ffe62d6a1c24e20f67b4441afca7a4944f5e7 100644 --- a/src/funcheck/CodeExtraction.scala +++ b/src/funcheck/CodeExtraction.scala @@ -109,9 +109,9 @@ trait CodeExtraction extends Extractors { scalaClassSyms.foreach(p => { if(p._1.isAbstractClass) { - classesToClasses += (p._1 -> new AbstractClassDef(p._2, None)) + classesToClasses += (p._1 -> new AbstractClassDef(p._2)) } else if(p._1.isCase) { - classesToClasses += (p._1 -> new CaseClassDef(p._2, None)) + classesToClasses += (p._1 -> new CaseClassDef(p._2)) } }) @@ -132,7 +132,7 @@ trait CodeExtraction extends Extractors { } if(superAC.length == 1) { - p._2.parent = Some(superAC.head) + p._2.setParent(superAC.head) } if(p._2.isInstanceOf[CaseClassDef]) { diff --git a/src/purescala/Definitions.scala b/src/purescala/Definitions.scala index 5d0d7d6ab48d710ad0106a536415945a7bab3e18..410903e8f76c582cc52166b0dc3c9d6e2d94f08f 100644 --- a/src/purescala/Definitions.scala +++ b/src/purescala/Definitions.scala @@ -38,14 +38,24 @@ object Definitions { /** Objects work as containers for class definitions, functions (def's) and * val's. */ case class ObjectDef(id: Identifier, defs : Seq[Definition], invariants: Seq[Expr]) extends Definition { - def getDefinedClasses : Seq[ClassTypeDef] = defs.filter(_.isInstanceOf[ClassTypeDef]).map(_.asInstanceOf[ClassTypeDef]) + // Watch out ! Use only when object is completely built ! + lazy val getDefinedClasses = computeDefinedClasses + // ...this one can be used safely at anytime. + def computeDefinedClasses : Seq[ClassTypeDef] = defs.filter(_.isInstanceOf[ClassTypeDef]).map(_.asInstanceOf[ClassTypeDef]) + + lazy val getClassHierarchyRoots = computeClassHierarchyRoots + def computeClassHierarchyRoots : Seq[ClassTypeDef] = defs.filter(_.isInstanceOf[ClassTypeDef]).map(_.asInstanceOf[ClassTypeDef]).filter(!_.hasParent) } /** Useful because case classes and classes are somewhat unified in some * patterns (of pattern-matching, that is) */ sealed trait ClassTypeDef extends Definition { + self => + val id: Identifier - var parent: Option[AbstractClassDef] + def parent: Option[AbstractClassDef] + def setParent(parent: AbstractClassDef) : self.type + def hasParent: Boolean = parent.isDefined val isAbstract: Boolean // val fields: VarDecls } @@ -60,9 +70,37 @@ object Definitions { if(acd == null) None else Some((acd.id, acd.parent)) } } - class AbstractClassDef(val id: Identifier, var parent: Option[AbstractClassDef]) extends ClassTypeDef { + class AbstractClassDef(val id: Identifier, prnt: Option[AbstractClassDef] = None) extends ClassTypeDef { + private var parent_ = prnt var fields: VarDecls = Nil val isAbstract = true + + private var children : List[ClassTypeDef] = Nil + + private[purescala] def registerChild(child: ClassTypeDef) : Unit = { + children = child :: children + } + + def knownChildren : Seq[ClassTypeDef] = { + children + } + + def knownDescendents : Seq[ClassTypeDef] = { + knownChildren ++ (knownChildren.map(c => c match { + case acd: AbstractClassDef => acd.knownDescendents + case _ => Nil + }).reduceLeft(_ ++ _)) + } + + def setParent(newParent: AbstractClassDef) = { + if(parent_.isDefined) { + scala.Predef.error("Resetting parent is forbidden.") + } + newParent.registerChild(this) + parent_ = Some(newParent) + this + } + def parent = parent_ } /** Case classes. */ @@ -71,9 +109,21 @@ object Definitions { if(ccd == null) None else Some((ccd.id, ccd.parent, ccd.fields)) } } - class CaseClassDef(val id: Identifier, var parent: Option[AbstractClassDef]) extends ClassTypeDef with ExtractorTypeDef { + + class CaseClassDef(val id: Identifier, prnt: Option[AbstractClassDef] = None) extends ClassTypeDef with ExtractorTypeDef { + private var parent_ = prnt var fields: VarDecls = Nil val isAbstract = false + + def setParent(newParent: AbstractClassDef) = { + if(parent_.isDefined) { + scala.Predef.error("Resetting parent is forbidden.") + } + newParent.registerChild(this) + parent_ = Some(newParent) + this + } + def parent = parent_ } /** "Regular" classes */ diff --git a/src/purescala/Z3Solver.scala b/src/purescala/Z3Solver.scala index 82a48a33c3b8f181beb915783e2ef985f238fdeb..43581f58e464e2645add144fd82317f44072d6b8 100644 --- a/src/purescala/Z3Solver.scala +++ b/src/purescala/Z3Solver.scala @@ -12,12 +12,12 @@ class Z3Solver(reporter: Reporter) extends Solver(reporter) { override val shortDescription = "Z3" // this is fixed - val z3cfg = new Z3Config() + private val z3cfg = new Z3Config() z3cfg.setParamValue("MODEL", "true") // we restart Z3 for each new program - var z3: Z3Context = null - var program: Program = null + private var z3: Z3Context = null + private var program: Program = null private var neverInitialized = true override def setProgram(prog: Program) : Unit = { @@ -32,14 +32,27 @@ class Z3Solver(reporter: Reporter) extends Solver(reporter) { prepareSorts } - var intSort : Z3Sort = null - var boolSort : Z3Sort = null + private var intSort : Z3Sort = null + private var boolSort : Z3Sort = null - def prepareSorts : Unit = { + private def prepareSorts : Unit = { + // NOTE THAT abstract classes that extend abstract classes are not + // currently supported in the translation intSort = z3.mkIntSort boolSort = z3.mkBoolSort - val classDefs = program.mainObject.getDefinedClasses + val roots = program.mainObject.getClassHierarchyRoots + val indexMap: Map[ClassTypeDef,Int] = Map(roots.zipWithIndex: _*) + println("indexMap: " + indexMap) + val childrenLists: Seq[List[CaseClassDef]] = roots.map(_ match { + case c: CaseClassDef => Nil + case a: AbstractClassDef => a.knownChildren.filter(_.isInstanceOf[CaseClassDef]).map(_.asInstanceOf[CaseClassDef]).toList + }) + println("children lists: " + childrenLists.toList.mkString("\n")) + + //val caseClassRoots = roots.filter(_.isInstanceOf[CaseClassDef]).map(_.asInstanceOf[CaseClassDef]) + //val absClassRoots = roots.filter(_.isInstanceOf[AbstractClassDef]).map(_.asInstanceOf[AbstractClassDef]) + // Abstract classes with no subclasses.. do we care? :) // - we can build an uninterpreted type for them. diff --git a/testcases/BinarySearchTree.scala b/testcases/BinarySearchTree.scala index e0f61f5146769332aa530d303eec8a311cfa1b20..246e9fe12c5cbcdf2b11474ef01a2244e8bd5d68 100644 --- a/testcases/BinarySearchTree.scala +++ b/testcases/BinarySearchTree.scala @@ -5,6 +5,8 @@ object BinarySearchTree { case class Node(left: Tree, value: Int, right: Tree) extends Tree case class Leaf() extends Tree + case class IntWrapper(value: Int) + def emptySet() : Tree = Leaf() def insert(tree: Tree, value: Int) : Node = (tree match {