Skip to content
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

Include definedness checks during exhale #457

Merged
merged 33 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a091467
add definedness state option to DefinednessComponent trait
gauravpartha Mar 21, 2023
43a3a33
Take definedness state into account for definedness of unfolding and …
gauravpartha Mar 23, 2023
b5b101b
wip
gauravpartha Mar 23, 2023
b58a406
unfolding in exhale only as way to gain more information (or for defi…
gauravpartha Mar 24, 2023
2903488
avoid definedness checks in exhale invocations of translateStmt when …
gauravpartha Mar 24, 2023
d7e0968
move DefinednessCheckData from the trait to its implementation
gauravpartha Mar 24, 2023
3b97011
Unfolding in exhale to gain more information is done in the well-defi…
gauravpartha Mar 27, 2023
7fda6d1
remove redundant import
gauravpartha Mar 27, 2023
65fd2f4
exhale: don't handle unfolding in a separate case inside package stat…
gauravpartha Mar 27, 2023
2dcdc5d
clearer definedness data interface
gauravpartha Mar 27, 2023
60370f0
better documentation
gauravpartha Mar 27, 2023
a8329ab
minor
gauravpartha Mar 27, 2023
a84a96e
update Silver to pr branch
gauravpartha Mar 27, 2023
8f59ef5
minor fix
gauravpartha Mar 28, 2023
a768d86
better documentation
gauravpartha Mar 28, 2023
d2d886a
fix
gauravpartha Mar 28, 2023
0184907
minor
gauravpartha Mar 28, 2023
62edf8f
remove checkDefinednessOfSpecAndExhale (subsumed by exhale)
gauravpartha Mar 28, 2023
43197c1
fix exhale and definedness error order in call
gauravpartha Mar 28, 2023
2586461
better documentation
gauravpartha Mar 28, 2023
b97f738
fix
gauravpartha Mar 28, 2023
3da8ac5
use sequence of expressions directly in exhale
gauravpartha Mar 28, 2023
a35d9fe
update silver commit
gauravpartha Apr 15, 2023
2a87229
check whether predicate exists when unfolding for more information in…
gauravpartha Apr 15, 2023
f2865f1
reuse temporary variable also for nonnegative permission check in exhale
gauravpartha Apr 16, 2023
8603c09
for the exhale: only emit the initialization of the well-definedness …
gauravpartha Apr 20, 2023
a454c01
update Silver commit
gauravpartha Apr 20, 2023
3d20bc4
update silver commit
gauravpartha Apr 23, 2023
2b4faac
update silver commit
gauravpartha Apr 23, 2023
85b7070
minor fixes
gauravpartha Apr 25, 2023
26908ab
update Silver commit
gauravpartha Apr 25, 2023
b22d4ac
Merge branch 'master' into exhale_with_definedness
gauravpartha Apr 25, 2023
5a221ce
evaluate receiver in original state (hasDirectPerm QuantifiedPermModule)
gauravpartha Apr 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src/main/scala/viper/carbon/modules/ExhaleModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

package viper.carbon.modules

import components.{ComponentRegistry, ExhaleComponent}
import components.{ComponentRegistry, DefinednessState, ExhaleComponent}
import viper.silver.{ast => sil}
import viper.carbon.boogie.Stmt
import viper.silver.verifier.PartialVerificationError
Expand All @@ -25,7 +25,10 @@ import viper.silver.verifier.PartialVerificationError
trait ExhaleModule extends Module with ExhaleComponent with ComponentRegistry[ExhaleComponent] {

/**
* @param exp the expression to be exhaled and the error to be raised if the exhale fails.
* @param exp A sequence of triples where the conjunction of the corresponding expressions (projection on the
* the first element) is to be exhaled. The triple includes the error to be raised if the exhale fails and
* the error to be raised if a well-definedness check fails during the exhale (if the latter is set
* to [[None]], then no well-definedness checks are performed).
* @param havocHeap A boolean used to allow or prevent havocing the heap after the exhale.
* For example, the heap is not havoced after the exhale when translating a fold statement.
* @param isAssert A boolean that tells whether the exhale method is being called during an exhale statement or an assert statement
Expand All @@ -38,6 +41,25 @@ trait ExhaleModule extends Module with ExhaleComponent with ComponentRegistry[Ex
* The 'statesStackForPackageStmt' and 'insidePackageStmt' are used when translating statements during packaging a wand.
* For more details refer to the note in the wand module.
*/
def exhale(exp: Seq[(sil.Exp, PartialVerificationError)], havocHeap: Boolean = true, isAssert: Boolean = false
, statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false): Stmt
}
def exhale(exp: Seq[(sil.Exp, PartialVerificationError, Option[PartialVerificationError])], havocHeap: Boolean = true,
isAssert: Boolean = false, statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false): Stmt

/** convenience methods */

def exhaleWithoutDefinedness(exp: Seq[(sil.Exp, PartialVerificationError)], havocHeap: Boolean = true,
isAssert: Boolean = false, statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false): Stmt = {
exhale(exp.map(eError => (eError._1, eError._2, None)), havocHeap = havocHeap, isAssert = isAssert, statesStackForPackageStmt, insidePackageStmt = insidePackageStmt)
}

def exhaleSingleWithoutDefinedness(exp: sil.Exp, exhaleError: PartialVerificationError, havocHeap: Boolean = true,
isAssert: Boolean = false, statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false): Stmt = {
exhale(Seq((exp, exhaleError, None)), havocHeap = havocHeap, isAssert = isAssert, statesStackForPackageStmt, insidePackageStmt = insidePackageStmt)
}

def exhaleSingleWithDefinedness(exp: sil.Exp, exhaleError: PartialVerificationError, definednessError: PartialVerificationError,
havocHeap: Boolean = true, isAssert: Boolean = false, statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false) = {
exhale(Seq((exp, exhaleError, Some(definednessError))), havocHeap = havocHeap, isAssert = isAssert,
statesStackForPackageStmt, insidePackageStmt = insidePackageStmt)
}

}
45 changes: 21 additions & 24 deletions src/main/scala/viper/carbon/modules/ExpModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ package viper.carbon.modules

import viper.silver.{ast => sil}
import viper.carbon.boogie.{Exp, LocalVar, Stmt}
import viper.carbon.modules.components.{ComponentRegistry, DefinednessComponent}
import viper.carbon.modules.components.{ComponentRegistry, DefinednessComponent, DefinednessState}
import viper.silver.verifier.PartialVerificationError

/**
Expand All @@ -30,30 +30,27 @@ trait ExpModule extends Module with ComponentRegistry[DefinednessComponent] {
*/
def allFreeAssumptions(e: sil.Exp): Stmt

/**
* Check definedness of Viper expressions as they occur in the program.
*
* makeChecks provides the possibility of switching off most checks, to get
* only the side-effects (unfoldings) of unravelling the expression. Note that
* the parameter should be passed down through recursive calls (default true)
*
* ignoreIfInWand gives the option to ignore the definedness check if it is called during a package statement
*
* inWand distinguish when check definedness is called during a package statement.
*/
/***
* Check well-definedness of Viper expressions. This method should only be invoked on pure Viper expressions or
* impure *atomic* Viper assertions (e.g., accessibility predicates, quantified permissions).
* For other kinds of impure assertions such as separating conjunctions where one conjunct is impure, well-definedness
* is always tied to an inhale or exhale (or assert) operation. In those cases, the corresponding inhale and exhale
* methods should be invoked, which permit switching on well-definedness checks.
*
* @param e
* @param error
* @param makeChecks provides the possibility of switching off most checks, to get only the side-effects (unfoldings)
* of unravelling the expression. Note that the parameter should be passed down through recursive
* calls (default true)
* @param definednessStateOpt If defined, then represents the state in which permission checks that are part of the definedness
* check should be made, otherwise these checks should be made in the currently active state.
* Expressions should be evaluated in the currently active state.
* @param insidePackageStmt true if call is made during a package statement
* @param ignoreIfInWand gives the option to ignore the definedness check if it is called during a package statement
* @return
*/
def checkDefinedness(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean = true,
definednessStateOpt: Option[DefinednessState] = None,
insidePackageStmt: Boolean = false, ignoreIfInWand: Boolean = false): Stmt

/**
* Check definedness of Viper assertions such as pre-/postconditions or invariants.
* The implementation works by exhaling 'e' and checking the necessary properties
* along the way.
*
* statesStackForPackageStmt stack of states used in translating statements during packaging a wand (carries currentState and LHS of wands)
* insidePackageStmt Boolean that represents whether this method is being called during packaging a wand or not.
* The 'statesStackForPackageStmt' and 'insidePackageStmt' are used when translating statements during packaging a wand.
* For more details refer to the general note in 'wandModule'.
*/
def checkDefinednessOfSpecAndExhale(e: sil.Exp, definednessError: PartialVerificationError, exhaleError: PartialVerificationError,
statesStackForPackageStmt: List[Any] = null, insidePackageStmt: Boolean = false): Stmt
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@ trait DefinednessComponent extends Component {
* the well-definedness checks for `e`'s subnodes.
* If `makeChecks` is set to false, then no definedness checks should be emitted. See [[partialCheckDefinedness]]
* for the purpose of `makeChecks`.
* If `definednessStateOpt` is defined, then it represents the state in which permission checks that are part of the
* definedness check should be made, otherwise these checks should be done in the currently active state.
* Expressions should be evaluated in the currently active state.
*/
def simplePartialCheckDefinednessBefore(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean): Stmt = Statements.EmptyStmt
def simplePartialCheckDefinednessBefore(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean,
definednessStateOpt: Option[DefinednessState]): Stmt = Statements.EmptyStmt

/**
* Same as [[simplePartialCheckDefinednessBefore]], except that this well-definedness check is invoked and emitted
* *after* the well-definedness checks of `e`'s subnodes are invoked and emitted.
*/
def simplePartialCheckDefinednessAfter(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean): Stmt = Statements.EmptyStmt
def simplePartialCheckDefinednessAfter(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean,
definednessStateOpt: Option[DefinednessState]): Stmt = Statements.EmptyStmt

/**
* Proof obligations for a given expression. The first part of the result is used before
Expand All @@ -43,7 +48,21 @@ trait DefinednessComponent extends Component {
* The makeChecks argument can be set to false to cause the expression to be explored (and
* corresponding unfoldings to be executed), but no other checks to actually be made. Note that this method
* must be overridden for this parameter to be used.
* If `definednessStateOpt` is defined, then it represents the state in which permission checks that are part of the
* definedness check should be made, otherwise these checks should be done in the currently active state.
* Expressions should be evaluated in the currently active state.
*/
def partialCheckDefinedness(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean): (() => Stmt, () => Stmt) =
(() => simplePartialCheckDefinednessBefore(e, error, makeChecks), () => simplePartialCheckDefinednessAfter(e, error, makeChecks))
def partialCheckDefinedness(e: sil.Exp, error: PartialVerificationError, makeChecks: Boolean,
definednessStateOpt: Option[DefinednessState]): (() => Stmt, () => Stmt) =
(
() => simplePartialCheckDefinednessBefore(e, error, makeChecks, definednessStateOpt),
() => simplePartialCheckDefinednessAfter(e, error, makeChecks, definednessStateOpt)
)

}

/**
* Wrapper for representing the definedness state.
* @param setDefState Running this should set the currently active state to the definedness state.
*/
case class DefinednessState(var setDefState: () => Unit)
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,24 @@ trait ExhaleComponent extends Component {
/**
* Exhale a single expression.
*/
def exhaleExp(e: sil.Exp, error: PartialVerificationError): Stmt = Statements.EmptyStmt
def exhaleExp(e: sil.Exp, error: PartialVerificationError, definednessStateOpt: Option[DefinednessState]): Stmt = Statements.EmptyStmt

/**
*/

/***
* Method that allows components to contribute to exhaling an expression.
* The first part of the result is used before exhaling the expression, and finally after exhaling the expression
* the second part of the result is used.
* @param e expression to be exhaled.
* @param error exhale error
* @param definednessStateOpt If defined, then this expresses the current state in which definedness checks are performed
* ("definedness state"). If defined and if the implementing component is responsible for the
* top-level operator in @{code e}, then the component must ensure that that the definedness
* state is updated (and restored) correctly.
* @return
*/
def exhaleExpBeforeAfter(e: sil.Exp, error: PartialVerificationError): (() => Stmt, () => Stmt) =
(() => exhaleExp(e, error), () => Statements.EmptyStmt)
def exhaleExpBeforeAfter(e: sil.Exp, error: PartialVerificationError, definednessStateOpt: Option[DefinednessState]): (() => Stmt, () => Stmt) =
(() => exhaleExp(e, error, definednessStateOpt), () => Statements.EmptyStmt)

}
Loading