Skip to content

Commit

Permalink
Fix typing for quint empty sets (#2466)
Browse files Browse the repository at this point in the history
The converter for quint empty types was constructing types wrapped in a
Set. This fixes that error, and expands the test to check for this.

Going forward, I write the quint integration while I expand the
converter to catch this earlier.
  • Loading branch information
Shon Feder authored Mar 8, 2023
1 parent 2739ebc commit 284268d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 8 deletions.
1 change: 1 addition & 0 deletions .unreleased/bug-fixes/quint-empty-sets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix the typing of quint empty sets during conversion (see #2466)
23 changes: 16 additions & 7 deletions tla-io/src/main/scala/at/forsyte/apalache/io/quint/Quint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,21 @@ class Quint(moduleData: QuintOutput) {
case tooManyArgs => throwOperatorArityError(op, "binary", tooManyArgs)
}

private def setEnumeration(id: Int): Seq[QuintEx] => TBuilderInstruction = {
variadicApp {
// Empty sets must be handled specially since we cannot infer their type
// from the given arguments
case Seq() =>
val elementType = types(id).typ match {
case QuintSetT(t) => Quint.typeToTlaType(t)
case invalidType =>
throw new QuintIRParseError(s"Set with id ${id} has invalid type ${invalidType}")
}
tla.emptySet(elementType)
case args => tla.enumSet(args: _*)
}
}

private val tlaApplication: QuintApp => TBuilderInstruction = { case QuintApp(id, opName, quintArgs) =>
val applicationBuilder: Seq[QuintEx] => TBuilderInstruction = opName match {
// First we check for application of builtin operators
Expand Down Expand Up @@ -228,13 +243,7 @@ class Quint(moduleData: QuintOutput) {
case "iuminus" => unaryApp(opName, tla.uminus)

// Sets
case "Set" =>
variadicApp {
// Empty sets must be handled specially since we cannot infer their type
// from the given arguments
case Seq() => tla.emptySet(Quint.typeToTlaType(types(id).typ))
case args => tla.enumSet(args: _*)
}
case "Set" => setEnumeration(id)
case "exists" => binaryBindingApp(opName, tla.exists)
case "forall" => binaryBindingApp(opName, tla.forall)
case "in" => binaryApp(opName, tla.in)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import org.scalatestplus.junit.JUnitRunner

import QuintType._
import QuintEx._
import at.forsyte.apalache.tla.lir.Typed
import at.forsyte.apalache.tla.lir.SetT1
import at.forsyte.apalache.tla.lir.IntT1

/**
* Tests the conversion of quint expressions and declarations into TLA expressions
Expand Down Expand Up @@ -206,7 +209,13 @@ class TestQuintEx extends AnyFunSuite {
}

test("can convert builtin Set operator application for empty sets") {
assert(convert(Q.emptyIntSet) == """{}""")
val tlaEx = quint.exToTla(Q.emptyIntSet).get
// Ensure the constructed empty set has the required type
assert(tlaEx.typeTag match {
case Typed(SetT1(IntT1)) => true
case _ => false
})
assert(tlaEx.toString() == """{}""")
}
test("can convert builtin exists operator application") {
assert(convert(Q.app("exists", Q.intSet, Q.intIsGreaterThanZero)) == "∃n ∈ {1, 2, 3}: (n > 0)")
Expand Down

0 comments on commit 284268d

Please sign in to comment.