-
Notifications
You must be signed in to change notification settings - Fork 48
Advanced logical proofs #785
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jogasser
wants to merge
54
commits into
viperproject:master
Choose a base branch
from
jogasser:advanced-logical-proofs
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 34 commits
Commits
Show all changes
54 commits
Select commit
Hold shift + click to select a range
9c034cc
Existential Elimination v1
dinanoe c229ac5
Merge branch 'master' of https://github.com/dinanoe/silver
dinanoe a2c5c6d
Existential Elimination added Trigger typecheck
dinanoe 1b56187
Existential Elimination comments
dinanoe 8704df5
Merge branch 'viperproject:master' into master
dinanoe 2eba4da
Universal Introduction v1
dinanoe 2b2211f
Added Flow Analysis with Graph
dinanoe 76ed0cd
oldCall added, restructured Code
dinanoe 37429f9
merge1
dinanoe 2118cef
Complete Bachelor Thesis
dinanoe ab682a9
Merge branch 'viperproject:master' into master
dinanoe 437b56c
Merge branch 'master' into master
ArquintL 7dc7952
Merges tag 'v.24.01-release' into 'advanced-logical-proofs'
ArquintL 663797f
fixes parser to correctly parse syntax of reasoning plugin
ArquintL abe8a9c
reduces diff
ArquintL 3195a8d
adds license headers
ArquintL 0c0efd7
fixes a compiler error
ArquintL 3da1caf
changes testcases that use 'heap', which is now a keyword
ArquintL c217565
cleans up reasoning plugin further
ArquintL 383a4df
Merges branch 'master' into 'advanced-logical-proofs'
ArquintL 4847f56
changes yet another testcase that uses 'heap', which is now a keyword
ArquintL 7d05083
first version of graph map taint analysis
jgaAdibilis 4153019
added assume analysis & modular method analysis
jgaAdibilis 2e6d4e5
fix a bug in method handling & rename variables
jgaAdibilis 9a5b903
ordered tests
jgaAdibilis e558efa
add more tests & cleanup
jgaAdibilis 8e1efab
remove logs
jgaAdibilis 290bfa3
Merge remote-tracking branch 'origin/master' into advanced-logical-pr…
jgaAdibilis 191a812
remove todo
jgaAdibilis 04de8bc
add missing position information to ImpureAssumeRewriter
jgaAdibilis f79936a
fix method analysis modularity
jgaAdibilis 6d6179c
add assumesNothing spec to specify that a method contains no assume/i…
jgaAdibilis b4a1086
update recursive methods & add noAssumes check
jgaAdibilis 81f9b62
Merge branch 'master' into advanced-logical-proofs
ArquintL 90a763b
treat non-terminating loop as assume statement & some cleanup
jgaAdibilis a25d1ae
Merge remote-tracking branch 'origin/advanced-logical-proofs' into ad…
jgaAdibilis 23a3a4b
Merge remote-tracking branch 'origin/master' into advanced-logical-pr…
jgaAdibilis a814df4
change position of reported error
jgaAdibilis cf0fea1
Update src/main/scala/viper/silver/plugin/standard/reasoning/Reasonin…
jogasser 78960ff
Update src/main/scala/viper/silver/plugin/standard/reasoning/BeforeVe…
jogasser e93fd6b
Update src/main/scala/viper/silver/plugin/standard/reasoning/BeforeVe…
jogasser 695c91b
Apply suggestions from code review
jogasser 9bb7f88
Apply suggestions from code review
jogasser a0617ce
address mr comments
jgaAdibilis a452e1d
split AssumeNode into multiple AssumeNodes for better error reporting
jgaAdibilis ab3e166
split veforeVerify method
jgaAdibilis 20cf3e9
add assume to pretty print
jgaAdibilis f0476da
improves type guarantees of modular taint analysis and fixes terminat…
ArquintL 33e0b33
fix a bug where local variables in methods were not correctly cleaned…
jgaAdibilis 1d36454
remove local variables from calculated influences before they are che…
jgaAdibilis 62b2649
Merge branch 'advanced-logical-proofs' into arquintl-advanced-logical…
ArquintL 3362648
Merge pull request #1 from viperproject/arquintl-advanced-logical-proofs
jogasser 1e41b5e
remove TODO
jgaAdibilis 8f2fa05
add test, fix positioning & block placement
jgaAdibilis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
151 changes: 151 additions & 0 deletions
151
src/main/scala/viper/silver/plugin/standard/reasoning/BeforeVerifyHelper.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| // | ||
| // Copyright (c) 2011-2024 ETH Zurich. | ||
|
|
||
| package viper.silver.plugin.standard.reasoning | ||
|
|
||
|
|
||
| import viper.silver.ast.utility.Expressions | ||
| import viper.silver.ast.{Apply, Declaration, Exhale, Exp, FieldAssign, Fold, Inhale, LocalVarDecl, Method, MethodCall, Package, Program, Seqn, Stmt, Unfold} | ||
| import viper.silver.verifier.{AbstractError, ConsistencyError} | ||
| import viper.silver.plugin.standard.reasoning.analysis.AnalysisUtils | ||
|
|
||
| import scala.collection.mutable | ||
|
|
||
| trait BeforeVerifyHelper { | ||
| /** methods to rename variables for the encoding of the new syntax */ | ||
| def uniqueName(name: String, usedNames: mutable.Set[String]): String = { | ||
| var i = 1 | ||
| var newName = name | ||
| while (usedNames.contains(newName)) { | ||
| newName = name + i | ||
| i += 1 | ||
| } | ||
| usedNames.add(newName) | ||
| newName | ||
| } | ||
|
|
||
| def substituteWithFreshVars[E <: Exp](vars: Seq[LocalVarDecl], exp: E, usedNames: mutable.Set[String]): (Seq[(LocalVarDecl, LocalVarDecl)], E) = { | ||
| val declMapping = vars.map(oldDecl => | ||
| oldDecl -> LocalVarDecl(uniqueName(oldDecl.name, usedNames), oldDecl.typ)(oldDecl.pos, oldDecl.info, oldDecl.errT)) | ||
| val transformedExp = applySubstitution(declMapping, exp) | ||
| (declMapping, transformedExp) | ||
| } | ||
|
|
||
| def applySubstitution[E <: Exp](mapping: Seq[(LocalVarDecl, LocalVarDecl)], exp: E): E = { | ||
| Expressions.instantiateVariables(exp, mapping.map(_._1.localVar), mapping.map(_._2.localVar)) | ||
| } | ||
|
|
||
| def applySubstitutionWithExp[E <: Exp](mapping: Seq[(LocalVarDecl, Exp)], exp: E): E = { | ||
| Expressions.instantiateVariables(exp, mapping.map(_._1.localVar), mapping.map(_._2)) | ||
| } | ||
|
|
||
| /** | ||
| * get all variables that are assigned to inside the block and take intersection with universal introduction | ||
| * variables. If they are contained throw error since these variables should be immutable | ||
| * | ||
| * @param modified_vars: set of variables that were modified in a given statement | ||
| * @param quantified_vars: set of quantified variables in the universal introduction statement. | ||
| * @param reportError: Method to report the error when a qunatified variable was modified | ||
| * @param u: universal introduction statement, used for details in error message | ||
| */ | ||
| def checkReassigned(modified_vars: Set[LocalVarDecl], quantified_vars: Seq[LocalVarDecl], reportError: AbstractError => Unit, u: UniversalIntro): Unit = { | ||
| val reassigned_vars: Set[LocalVarDecl] = modified_vars.intersect(quantified_vars.toSet) | ||
| if (reassigned_vars.nonEmpty) { | ||
| val reassigned_names: String = reassigned_vars.mkString(", ") | ||
| val reassigned_pos: String = reassigned_vars.map(_.pos).mkString(", ") | ||
| reportError(ConsistencyError("Universal Introduction variable(s) (" + reassigned_names + ") might have been reassigned at position(s) (" + reassigned_pos + ")", u.pos)) | ||
| } | ||
| } | ||
|
|
||
jogasser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| private def specifiesLemma(m: Method): Boolean = (m.pres ++ m.posts).exists { | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| case _: Lemma => true | ||
| case _ => false | ||
| } | ||
|
|
||
| /** check if isLemma precondition is correct */ | ||
| def checkLemma(input: Program, reportError: AbstractError => Unit): Unit = { | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| input.methods.foreach(method => { | ||
| val containsLemma = specifiesLemma(method) | ||
| val (containsDecreases, containsDecreasesStar) = AnalysisUtils.containsDecreasesAnnotations(method) | ||
|
|
||
| if (containsLemma) { | ||
| /** report error if there is no decreases clause or specification */ | ||
| if(!containsDecreases) { | ||
| reportError(ConsistencyError(s"method ${method.name} marked lemma might not contain decreases clause", method.pos)) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** report error if the decreases statement might not prove termination */ | ||
| if (containsDecreasesStar) { | ||
| reportError(ConsistencyError("decreases statement might not prove termination", method.pos)) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** check method body for impure statements */ | ||
| checkBodyPure(method.body.getOrElse(Seqn(Seq(), Seq())()), method, input, reportError) | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| /** checks whether the body is pure, reports error if impure operation found */ | ||
| def checkBodyPure(stmt: Stmt, method: Method, prog: Program, reportError: AbstractError => Unit): Boolean = { | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| var pure: Boolean = true | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| stmt match { | ||
| case Seqn(ss, _) => | ||
| ss.foreach(s => { | ||
| pure = pure && checkBodyPure(s, method, prog, reportError) | ||
| }) | ||
| pure | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /** case for statements considered impure */ | ||
| case ie@(Inhale(_) | Exhale(_) | FieldAssign(_, _) | Fold(_) | Unfold(_) | Apply(_) | Package(_, _)) => | ||
| reportError(ConsistencyError(s"method ${method.name} marked lemma might contain impure statement ${ie}", ie.pos)) | ||
| false | ||
| case m@MethodCall(methodName, _, _) => | ||
| val mc = prog.findMethod(methodName) | ||
| val containsLemma = specifiesLemma(mc) | ||
|
|
||
| /** if called method is not a lemma report error */ | ||
| if (!containsLemma) { | ||
| reportError(ConsistencyError(s"method ${method.name} marked lemma might contain call to method ${m}", m.pos)) | ||
| false | ||
| } else { | ||
| pure | ||
| } | ||
jogasser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| case _ => | ||
| pure | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| /** checks that influences by annotations are used correctly. */ | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| def checkInfluencedBy(input: Program, reportError: AbstractError => Unit): Unit = { | ||
| input.methods.foreach(method => { | ||
| val argVars = method.formalArgs.toSet + AnalysisUtils.heapVertex | ||
| val retVars = method.formalReturns.toSet.asInstanceOf[Set[Declaration]] + AnalysisUtils.heapVertex + AnalysisUtils.AssumeNode(method.pos) | ||
|
|
||
| val seenVars: mutable.Set[Declaration] = mutable.Set() | ||
| /** iterate through method postconditions to find flow annotations */ | ||
| method.posts.foreach { | ||
| case v@FlowAnnotation(target, args) => | ||
| val targetVarDecl = AnalysisUtils.getDeclarationFromFlowVar(target, method) | ||
|
|
||
| if (!retVars.contains(targetVarDecl)) { | ||
| reportError(ConsistencyError(s"Only return variables can be influenced. ${targetVarDecl.name} is not be a return variable.", v.pos)) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| if (seenVars.contains(targetVarDecl)) { | ||
| reportError(ConsistencyError(s"Only one influenced by expression per return variable can exist. ${targetVarDecl.name} is used several times.", v.pos)) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| seenVars.add(targetVarDecl) | ||
|
|
||
| args.foreach(arg => { | ||
| val argVarDecl = AnalysisUtils.getLocalVarDeclFromFlowVar(arg) | ||
| if (!argVars.contains(argVarDecl)) { | ||
| reportError(ConsistencyError(s"Only method arguments can influence a return variable. ${argVarDecl.name} is not be a method argument.", v.pos)) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| }) | ||
| case _ => () | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| }) | ||
| } | ||
| } | ||
173 changes: 173 additions & 0 deletions
173
src/main/scala/viper/silver/plugin/standard/reasoning/ReasoningASTExtension.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| // | ||
| // Copyright (c) 2011-2024 ETH Zurich. | ||
|
|
||
| package viper.silver.plugin.standard.reasoning | ||
|
|
||
| import viper.silver.ast._ | ||
| import viper.silver.ast.pretty.FastPrettyPrinter.{ContOps, brackets, char, defaultIndent, group, line, nest, nil, parens, show, showBlock, showVars, space, ssep, text, toParenDoc} | ||
| import viper.silver.ast.pretty.PrettyPrintPrimitives | ||
| import viper.silver.ast.utility.Consistency | ||
| import viper.silver.verifier.{ConsistencyError, Failure, VerificationResult} | ||
|
|
||
|
|
||
| case object ReasoningInfo extends FailureExpectedInfo | ||
|
|
||
| case class ExistentialElim(varList: Seq[LocalVarDecl], trigs: Seq[Trigger], exp: Exp)(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends ExtensionStmt { | ||
| override lazy val check: Seq[ConsistencyError] = Consistency.checkPure(exp) ++ | ||
| (if (!(exp isSubtype Bool)) Seq(ConsistencyError(s"Body of existential quantifier must be of Bool type, but found ${exp.typ}", exp.pos)) else Seq()) ++ | ||
| (if (varList.isEmpty) Seq(ConsistencyError("Quantifier must have at least one quantified variable.", pos)) else Seq()) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| override lazy val prettyPrint: PrettyPrintPrimitives#Cont = { | ||
| text("obtain") <+> showVars(varList) <+> | ||
| text("where") <+> (if (trigs.isEmpty) nil else space <> ssep(trigs map show, space)) <+> | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| toParenDoc(exp) | ||
| } | ||
|
|
||
| override val extensionSubnodes: Seq[Node] = varList ++ trigs ++ Seq(exp) | ||
|
|
||
| /** declarations contributed by this statement that should be added to the parent scope */ | ||
| override def declarationsInParentScope: Seq[Declaration] = varList | ||
| } | ||
|
|
||
| case class UniversalIntro(varList: Seq[LocalVarDecl], triggers: Seq[Trigger], exp1: Exp, exp2: Exp, block: Seqn)(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends ExtensionStmt with Scope { | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // See also Expression Line 566 | ||
| override lazy val check: Seq[ConsistencyError] = | ||
| (if (!(exp1 isSubtype Bool)) Seq(ConsistencyError(s"Body of universal quantifier must be of Bool type, but found ${exp1.typ}", exp1.pos)) else Seq()) ++ | ||
| (if (varList.isEmpty) Seq(ConsistencyError("Quantifier must have at least one quantified variable.", pos)) else Seq()) ++ | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Consistency.checkAllVarsMentionedInTriggers(varList, triggers) | ||
|
|
||
| override val scopedDecls: Seq[Declaration] = varList | ||
|
|
||
| override lazy val prettyPrint: PrettyPrintPrimitives#Cont = { | ||
| text("prove forall") <+> showVars(varList) <+> | ||
| text("assuming") <+> | ||
| toParenDoc(exp1) <+> | ||
| text("implies") <+> toParenDoc(exp2) <+> | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| showBlock(block) | ||
| } | ||
|
|
||
| override val extensionSubnodes: Seq[Node] = varList ++ triggers ++ Seq(exp1, exp2, block) | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| sealed trait FlowVar extends ExtensionExp { | ||
| override def extensionIsPure: Boolean = true | ||
|
|
||
| override def verifyExtExp(): VerificationResult = { | ||
| assert(assertion = false, "FlowAnalysis: verifyExtExp has not been implemented.") | ||
| Failure(Seq(ConsistencyError("FlowAnalysis: verifyExtExp has not been implemented.", pos))) | ||
| } | ||
| } | ||
|
|
||
| case class Assumes()(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends FlowVar { | ||
| override val extensionSubnodes: Seq[Node] = Seq.empty | ||
| override def typ: Type = InternalType | ||
| override def prettyPrint: PrettyPrintPrimitives#Cont = PAssumesKeyword.keyword | ||
| } | ||
|
|
||
| case class Heap()(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends FlowVar { | ||
| override val extensionSubnodes: Seq[Node] = Seq.empty | ||
| override def typ: Type = InternalType | ||
| override def prettyPrint: PrettyPrintPrimitives#Cont = PHeapKeyword.keyword | ||
| } | ||
|
|
||
| case class Var(decl: LocalVar)(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends FlowVar { | ||
| override val extensionSubnodes: Seq[Node] = Seq(decl) | ||
| override def typ: Type = decl.typ | ||
| override def prettyPrint: PrettyPrintPrimitives#Cont = show(decl) | ||
| } | ||
|
|
||
| case class NoAssumeAnnotation()(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends ExtensionExp with Node { | ||
| override def extensionIsPure: Boolean = true | ||
|
|
||
| override def extensionSubnodes: Seq[Node] = Seq() | ||
|
|
||
| override def typ: Type = Bool | ||
|
|
||
| override def verifyExtExp(): VerificationResult = { | ||
| assert(assertion = false, "FlowAnalysis: verifyExtExp has not been implemented.") | ||
| Failure(Seq(ConsistencyError("FlowAnalysis: verifyExtExp has not been implemented.", pos))) | ||
| } | ||
|
|
||
| /** Pretty printing functionality as defined for other nodes in class FastPrettyPrinter. | ||
| * Sample implementation would be text("old") <> parens(show(e)) for pretty-printing an old-expression. */ | ||
| override def prettyPrint: PrettyPrintPrimitives#Cont = { | ||
| text("assumes nothing") | ||
| } | ||
| } | ||
|
|
||
| case class FlowAnnotation(v: FlowVar, varList: Seq[FlowVar])(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends ExtensionExp with Node with Scope { | ||
| override def extensionIsPure: Boolean = true | ||
|
|
||
| override val scopedDecls: Seq[Declaration] = Seq() | ||
|
|
||
| override def typ: Type = Bool | ||
|
|
||
| override def verifyExtExp(): VerificationResult = { | ||
| assert(assertion = false, "FlowAnalysis: verifyExtExp has not been implemented.") | ||
| Failure(Seq(ConsistencyError("FlowAnalysis: verifyExtExp has not been implemented.", pos))) | ||
| } | ||
|
|
||
| override def extensionSubnodes: Seq[Node] = Seq(v) ++ varList | ||
|
|
||
| /** Pretty printing functionality as defined for other nodes in class FastPrettyPrinter. | ||
| * Sample implementation would be text("old") <> parens(show(e)) for pretty-printing an old-expression. */ | ||
| override def prettyPrint: PrettyPrintPrimitives#Cont = { | ||
| text("influenced") <+> (v match { | ||
| case value: Var => (show(value.decl)) | ||
| case _ => text("heap") | ||
| }) <+> | ||
| text("by") <+> | ||
| ssep(varList.map { | ||
| case value: Var => show(value.decl) | ||
| case _ => text("heap") | ||
| }, group(char(',') <> line(" "))) | ||
jogasser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| case class Lemma()(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends ExtensionExp with Node with Scope { | ||
| override def extensionIsPure: Boolean = true | ||
|
|
||
| override val scopedDecls: Seq[Declaration] = Seq() | ||
|
|
||
| override def typ: Type = Bool | ||
|
|
||
| override def verifyExtExp(): VerificationResult = { | ||
| assert(assertion = false, "Lemma: verifyExtExp has not been implemented.") | ||
| Failure(Seq(ConsistencyError("Lemma: verifyExtExp has not been implemented.", pos))) | ||
| } | ||
|
|
||
| override def extensionSubnodes: Seq[Node] = Seq() | ||
|
|
||
| /** Pretty printing functionality as defined for other nodes in class FastPrettyPrinter. | ||
| * Sample implementation would be text("old") <> parens(show(e)) for pretty-printing an old-expression. */ | ||
| override def prettyPrint: PrettyPrintPrimitives#Cont = { | ||
| text("isLemma") | ||
| } | ||
| } | ||
|
|
||
| case class OldCall(methodName: String, args: Seq[Exp], rets: Seq[LocalVar], oldLabel: String)(val pos: Position = NoPosition, val info: Info = NoInfo, val errT: ErrorTrafo = NoTrafos) extends ExtensionStmt with Scope { | ||
| override val scopedDecls: Seq[Declaration] = Seq() | ||
|
|
||
| override lazy val check: Seq[ConsistencyError] = { | ||
| var s = Seq.empty[ConsistencyError] | ||
| if (!Consistency.noResult(this)) | ||
| s :+= ConsistencyError("Result variables are only allowed in postconditions of functions.", pos) | ||
| if (!Consistency.noDuplicates(rets)) | ||
| s :+= ConsistencyError("Targets are not allowed to have duplicates", rets.head.pos) | ||
| s ++= args.flatMap(Consistency.checkPure) | ||
| s | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| override lazy val prettyPrint: PrettyPrintPrimitives#Cont = { | ||
| val call = text("oldCall") <> brackets(text(oldLabel)) <> text(methodName) <> nest(defaultIndent, parens(ssep(args map show, group(char(',') <> line)))) | ||
| rets match { | ||
| case Nil => call | ||
| case _ => ssep(rets map show, char(',') <> space) <+> ":=" <+> call | ||
| } | ||
| } | ||
|
|
||
| override val extensionSubnodes: Seq[Node] = args ++ rets | ||
| } | ||
40 changes: 40 additions & 0 deletions
40
src/main/scala/viper/silver/plugin/standard/reasoning/ReasoningErrors.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| // | ||
| // Copyright (c) 2011-2024 ETH Zurich. | ||
|
|
||
| package viper.silver.plugin.standard.reasoning | ||
|
|
||
| import viper.silver.verifier._ | ||
| import viper.silver.verifier.reasons.ErrorNode | ||
|
|
||
| case class ExistentialElimFailed(override val offendingNode: ErrorNode, override val reason: ErrorReason, override val cached: Boolean = false) extends ExtensionAbstractVerificationError { | ||
| override val id = "existential elimination.failed" | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| override val text = " no witness could be found." | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| override def withNode(offendingNode: errors.ErrorNode = this.offendingNode): ExistentialElimFailed = | ||
| ExistentialElimFailed(this.offendingNode, this.reason, this.cached) | ||
|
|
||
| override def withReason(r: ErrorReason): ExistentialElimFailed = ExistentialElimFailed(offendingNode, r, cached) | ||
| } | ||
|
|
||
| case class UniversalIntroFailed(override val offendingNode: ErrorNode, override val reason: ErrorReason, override val cached: Boolean = false) extends ExtensionAbstractVerificationError { | ||
| override val id = "universal introduction.failed" | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| override val text = " not true for all vars." | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| override def withNode(offendingNode: errors.ErrorNode = this.offendingNode): UniversalIntroFailed = | ||
| UniversalIntroFailed(this.offendingNode, this.reason, this.cached) | ||
|
|
||
| override def withReason(r: ErrorReason): UniversalIntroFailed = UniversalIntroFailed(offendingNode, r, cached) | ||
| } | ||
|
|
||
jogasser marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| case class FlowAnalysisFailed(override val offendingNode: ErrorNode, override val reason: ErrorReason, override val cached: Boolean = false) extends ExtensionAbstractVerificationError { | ||
| override val id = "flow analysis.failed" | ||
| override val text = " ." | ||
|
|
||
| override def withNode(offendingNode: errors.ErrorNode = this.offendingNode): FlowAnalysisFailed = | ||
| FlowAnalysisFailed(this.offendingNode, this.reason, this.cached) | ||
|
|
||
| override def withReason(r: ErrorReason): FlowAnalysisFailed = FlowAnalysisFailed(offendingNode, r, cached) | ||
| } | ||
jogasser marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.