Skip to content

Commit c908e75

Browse files
authored
Merge pull request #151 from jad-hamza/simplestValue
Make simplestValue top-level for overrides + hasInstance fix on ADTType
2 parents ec3b77f + 108cfef commit c908e75

File tree

1 file changed

+67
-49
lines changed

1 file changed

+67
-49
lines changed

src/main/scala/inox/ast/SymbolOps.scala

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -903,74 +903,92 @@ trait SymbolOps { self: TypeOps =>
903903
defs.foldRight(bd){ case ((vd, e), body) => Let(vd, e, body) }
904904
}
905905

906-
def hasInstance(tpe: Type): Option[Boolean] = tpe match {
906+
protected def hasInstance(tpe: Type, seen: Set[Type]): Option[Boolean] = tpe match {
907907
case _: TypeParameter => None
908-
case MapType(_, to) => hasInstance(to)
909-
case TupleType(tpes) => if (tpes.forall(tp => hasInstance(tp) contains true)) Some(true) else None
908+
case MapType(_, to) => hasInstance(to, seen)
909+
case TupleType(tpes) => if (tpes.forall(tp => hasInstance(tp, seen) contains true)) Some(true) else None
910910
case SigmaType(params, to) =>
911-
if ((params.map(_.tpe) :+ to).forall(tp => hasInstance(tp) contains true)) Some(true) else None
911+
if ((params.map(_.tpe) :+ to).forall(tp => hasInstance(tp, seen) contains true)) Some(true) else None
912912
case adt: ADTType =>
913913
val sort = adt.getSort
914-
if (sort.hasInvariant) None
914+
if (seen(adt)) None
915+
else if (sort.hasInvariant) None
915916
else if (!sort.definition.isWellFormed) Some(false)
916-
else Some(true)
917+
else if (sort.constructors.sortBy(_.fields.size).exists(cons =>
918+
cons.fields.forall(vd => hasInstance(vd.tpe, seen + adt) contains true)))
919+
Some(true)
920+
else None
917921
case _: RefinementType => None
918922
case _ => Some(true)
919923
}
920924

925+
final def hasInstance(tpe: Type): Option[Boolean] = hasInstance(tpe, Set())
926+
921927
case class NoSimpleValue(tpe: Type) extends Exception(s"No simple value found for type $tpe")
922928

923929
/** Returns simplest value of a given type */
924-
def simplestValue(tpe: Type, allowSolver: Boolean = true)(implicit sem: symbols.Semantics, ctx: Context): Expr = {
925-
def rec(tpe: Type, seen: Set[Type]): Expr = tpe match {
926-
case StringType() => StringLiteral("")
927-
case BVType(signed, size) => BVLiteral(signed, 0, size)
928-
case RealType() => FractionLiteral(0, 1)
929-
case IntegerType() => IntegerLiteral(0)
930-
case CharType() => CharLiteral('a')
931-
case BooleanType() => BooleanLiteral(false)
932-
case UnitType() => UnitLiteral()
933-
case SetType(baseType) => FiniteSet(Seq(), baseType)
934-
case BagType(baseType) => FiniteBag(Seq(), baseType)
935-
case MapType(fromType, toType) => FiniteMap(Seq(), rec(toType, seen), fromType, toType)
936-
case TupleType(tpes) => Tuple(tpes.map(rec(_, seen)))
937-
938-
case adt @ ADTType(id, tps) =>
939-
val sort = adt.getSort
940-
if (!sort.definition.isWellFormed) throw NoSimpleValue(adt)
941-
942-
if (seen(adt)) {
943-
Choose(ValDef.fresh("res", adt), BooleanLiteral(true))
944-
} else if (sort.hasInvariant) {
945-
if (!allowSolver) throw NoSimpleValue(adt)
946-
947-
val p = Variable.fresh("p", FunctionType(Seq(adt), BooleanType()))
948-
val res = Variable.fresh("v", adt)
949-
950-
import solvers._
951-
import SolverResponses._
952-
953-
SimpleSolverAPI(sem.getSolver).solveSAT(Application(p, Seq(res))) match {
954-
case SatWithModel(model) => model.vars.get(res.toVal).getOrElse(throw NoSimpleValue(adt))
955-
case _ => throw NoSimpleValue(adt)
930+
protected def simplestValue(tpe: Type, seen: Set[Type], allowSolver: Boolean, inLambda: Boolean)
931+
(implicit sem: symbols.Semantics, ctx: Context): Expr = tpe match {
932+
case StringType() => StringLiteral("")
933+
case BVType(signed, size) => BVLiteral(signed, 0, size)
934+
case RealType() => FractionLiteral(0, 1)
935+
case IntegerType() => IntegerLiteral(0)
936+
case CharType() => CharLiteral('a')
937+
case BooleanType() => BooleanLiteral(false)
938+
case UnitType() => UnitLiteral()
939+
case SetType(baseType) => FiniteSet(Seq(), baseType)
940+
case BagType(baseType) => FiniteBag(Seq(), baseType)
941+
case MapType(fromType, toType) => FiniteMap(Seq(), simplestValue(toType, seen, allowSolver, inLambda), fromType, toType)
942+
case TupleType(tpes) => Tuple(tpes.map(simplestValue(_, seen, allowSolver, inLambda)))
943+
944+
case adt @ ADTType(id, tps) =>
945+
val sort = adt.getSort
946+
if (!sort.definition.isWellFormed) throw NoSimpleValue(adt)
947+
948+
if (seen(adt)) {
949+
if (inLambda) Choose(ValDef.fresh("res", adt), BooleanLiteral(true))
950+
else throw NoSimpleValue(adt)
951+
} else if (sort.hasInvariant) {
952+
if (!allowSolver) throw NoSimpleValue(adt)
953+
954+
val p = Variable.fresh("p", FunctionType(Seq(adt), BooleanType()))
955+
val res = Variable.fresh("v", adt)
956+
957+
import solvers._
958+
import SolverResponses._
959+
960+
SimpleSolverAPI(sem.getSolver).solveSAT(Application(p, Seq(res))) match {
961+
case SatWithModel(model) => model.vars.get(res.toVal).getOrElse(throw NoSimpleValue(adt))
962+
case _ => throw NoSimpleValue(adt)
963+
}
964+
} else {
965+
for (cons <- sort.constructors.sortBy(_.fields.size)) {
966+
try {
967+
return ADT(
968+
cons.id,
969+
cons.tps,
970+
cons.fields.map(vd => simplestValue(vd.getType, seen + adt, allowSolver, inLambda))
971+
)
972+
} catch {
973+
case NoSimpleValue(_) => ()
956974
}
957-
} else {
958-
val cons = sort.constructors.sortBy(_.fields.size).head
959-
ADT(cons.id, cons.tps, cons.fields.map(vd => rec(vd.getType, seen + adt)))
960975
}
976+
throw NoSimpleValue(adt)
977+
}
961978

962-
case tp: TypeParameter =>
963-
GenericValue(tp, 0)
964-
965-
case ft @ FunctionType(from, to) =>
966-
Lambda(from.map(tpe => ValDef.fresh("x", tpe, true)), rec(to, seen))
979+
case tp: TypeParameter =>
980+
GenericValue(tp, 0)
967981

968-
case _ => throw NoSimpleValue(tpe)
969-
}
982+
case ft @ FunctionType(from, to) =>
983+
Lambda(from.map(tpe => ValDef.fresh("x", tpe, true)), simplestValue(to, seen, allowSolver, true))
970984

971-
rec(tpe, Set.empty)
985+
case _ => throw NoSimpleValue(tpe)
972986
}
973987

988+
final def simplestValue(tpe: Type, allowSolver: Boolean = true)
989+
(implicit sem: symbols.Semantics, ctx: Context): Expr = {
990+
simplestValue(tpe, Set.empty, allowSolver, false)
991+
}
974992

975993
/** Hoists all IfExpr at top level.
976994
*

0 commit comments

Comments
 (0)