Skip to content

Commit 4833685

Browse files
authored
Fix pretty printer for termination measures (#831)
* fix pretty printer for termination measures * skip trailing space for empty tuples
1 parent 56e5d9a commit 4833685

3 files changed

Lines changed: 28 additions & 12 deletions

File tree

src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import scala.language.implicitConversions
1010
import scala.collection.immutable.Queue
1111
import scala.collection.immutable.Queue.{empty => emptyDq}
1212
import viper.silver.ast._
13+
import viper.silver.plugin.standard.termination.DecreasesClause
1314
import viper.silver.verifier.DummyNode
1415

1516
import scala.annotation.tailrec
@@ -528,13 +529,17 @@ object FastPrettyPrinter extends FastPrettyPrinterBase with BracketPrettyPrinter
528529
case Field(name, typ) =>
529530
text("field") <+> name <> ":" <+> show(typ)
530531
case Method(name, formalArgs, formalReturns, pres, posts, body) =>
532+
// for the time being, the termination plugin transforms decreases clauses into preconditions or postconditions
533+
val (terminationMeasuresInPres, actualPres) = pres.partition(exp => exp.isInstanceOf[DecreasesClause])
534+
val (terminationMeasuresInPosts, actualPosts) = posts.partition(exp => exp.isInstanceOf[DecreasesClause])
531535
group(text("method") <+> name <> nest(defaultIndent, parens(showVars(formalArgs))) <> {
532536
if (formalReturns.isEmpty) nil
533537
else nest(defaultIndent, line <> "returns" <+> parens(showVars(formalReturns)))
534538
}) <>
535539
nest(defaultIndent,
536-
showContracts("requires", pres) <>
537-
showContracts("ensures", posts)
540+
showContracts("requires", actualPres) <>
541+
showContracts("ensures", actualPosts) <>
542+
showDecreasesClauses(terminationMeasuresInPres ++ terminationMeasuresInPosts)
538543
) <>
539544
line <> (
540545
body match {
@@ -549,11 +554,15 @@ object FastPrettyPrinter extends FastPrettyPrinterBase with BracketPrettyPrinter
549554
case Some(exp) => braces(nest(defaultIndent, line <> show(exp)) <> line)
550555
})
551556
case Function(name, formalArgs, typ, pres, posts, optBody) =>
557+
// for the time being, the termination plugin transforms decreases clauses into preconditions or postconditions
558+
val (terminationMeasuresInPres, actualPres) = pres.partition(exp => exp.isInstanceOf[DecreasesClause])
559+
val (terminationMeasuresInPosts, actualPosts) = posts.partition(exp => exp.isInstanceOf[DecreasesClause])
552560
text("function") <+> name <> nest(defaultIndent, parens(showVars(formalArgs))) <>
553561
":" <+> show(typ) <>
554562
nest(defaultIndent,
555-
showContracts("requires", pres) <>
556-
showContracts("ensures", posts)
563+
showContracts("requires", actualPres) <>
564+
showContracts("ensures", actualPosts) <>
565+
showDecreasesClauses(terminationMeasuresInPres ++ terminationMeasuresInPosts)
557566
) <>
558567
line <>
559568
(optBody match {
@@ -576,6 +585,11 @@ object FastPrettyPrinter extends FastPrettyPrinterBase with BracketPrettyPrinter
576585
lineIfSomeNonEmpty(contracts) <> ssep(contracts.map(c => text(name) <+> nest(defaultIndent, show(c))), line)
577586
}
578587

588+
/** Shows a list of termination measures. */
589+
def showDecreasesClauses(measures: Seq[Exp]): Cont = {
590+
lineIfSomeNonEmpty(measures) <> ssep(measures.map(c => nest(defaultIndent, show(c))), line)
591+
}
592+
579593
/** Returns `n` lines if at least one element of `s` is non-empty, and an empty document otherwise. */
580594
def lineIfSomeNonEmpty[T](s: Seq[T]*)(implicit n: Int = 1) = {
581595
if (s.forall(e => e != null && e.isEmpty)) nil
@@ -692,11 +706,11 @@ object FastPrettyPrinter extends FastPrettyPrinterBase with BracketPrettyPrinter
692706
ssep((if (locals == null) Nil else locals map (text("var") <+> showVar(_))) ++ (stmtsToShow map show), line)
693707
}
694708
case While(cond, invs, body) =>
709+
val (terminationMeasures, actualInvs) = invs.partition(exp => exp.isInstanceOf[DecreasesClause])
695710
text("while") <+> parens(show(cond)) <>
696-
nest(defaultIndent,
697-
showContracts("invariant", invs)
698-
) <+> lineIfSomeNonEmpty(invs) <>
699-
showBlock(body)
711+
nest(defaultIndent, showContracts("invariant", actualInvs) <> showDecreasesClauses(terminationMeasures)) <+>
712+
lineIfSomeNonEmpty(invs) <>
713+
showBlock(body)
700714
case If(cond, thn, els) =>
701715
text("if") <+> parens(show(cond)) <+> showBlock(thn) <> showElse(els)
702716
case Label(name, invs) =>

src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstanceASTExtension.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ case class PredicateInstance(p: String, args: Seq[Exp])(override val pos: Positi
2323
override def verifyExtExp(): VerificationResult = ???
2424

2525
override def prettyPrint: PrettyPrintPrimitives#Cont =
26-
text("@") <> text(p) <> parens(ssep(args map show, char (',') <> space))
26+
text(p) <> parens(ssep(args map show, char (',') <> space))
2727

2828
override lazy val check: Seq[ConsistencyError] = {
2929
args.flatMap(Consistency.checkPure)

src/main/scala/viper/silver/plugin/standard/termination/TerminationASTExtension.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
package viper.silver.plugin.standard.termination
88

99
import viper.silver.ast._
10-
import viper.silver.ast.pretty.FastPrettyPrinter.{ContOps, char, space, ssep, text, toParenDoc}
10+
import viper.silver.ast.pretty.FastPrettyPrinter.{ContOps, char, nil, space, ssep, text, toParenDoc}
1111
import viper.silver.ast.pretty.PrettyPrintPrimitives
1212
import viper.silver.ast.utility.Consistency
1313
import viper.silver.verifier.{ConsistencyError, Failure, VerificationResult}
@@ -50,8 +50,10 @@ case class DecreasesTuple(tupleExpressions: Seq[Exp] = Nil, override val conditi
5050

5151
override val typ: Type = Bool
5252

53-
override lazy val prettyPrint: PrettyPrintPrimitives#Cont =
54-
text("decreases") <> space <> ssep(tupleExpressions map (toParenDoc(_)), char(',') <> space)
53+
override lazy val prettyPrint: PrettyPrintPrimitives#Cont = {
54+
text("decreases") <>
55+
(if (tupleExpressions.nonEmpty) space <> ssep(tupleExpressions map (toParenDoc(_)), char(',') <> space) else nil)
56+
}
5557

5658
override val extensionSubnodes: Seq[Node] = tupleExpressions ++ condition
5759

0 commit comments

Comments
 (0)