Skip to content

Commit

Permalink
add desired functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
jcp19 committed Jan 11, 2024
1 parent a62aac3 commit 9d4463a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
13 changes: 13 additions & 0 deletions src/main/scala/viper/gobra/frontend/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ object ConfigDefaults {
lazy val DefaultParseAndTypeCheckMode: TaskManagerMode = TaskManagerMode.Parallel
lazy val DefaultRequireTriggers: Boolean = false
lazy val DefaultDisableSetAxiomatization: Boolean = false
lazy val DefaultDisableCheckTerminationPureFns: Boolean = false
}

// More-complete exhale modes
Expand Down Expand Up @@ -141,6 +142,7 @@ case class Config(
// when enabled, all quantifiers without triggers are rejected
requireTriggers: Boolean = ConfigDefaults.DefaultRequireTriggers,
disableSetAxiomatization: Boolean = ConfigDefaults.DefaultDisableSetAxiomatization,
disableCheckTerminationPureFns: Boolean = ConfigDefaults.DefaultDisableCheckTerminationPureFns,
) {

def merge(other: Config): Config = {
Expand Down Expand Up @@ -192,6 +194,7 @@ case class Config(
parseAndTypeCheckMode = parseAndTypeCheckMode,
requireTriggers = requireTriggers || other.requireTriggers,
disableSetAxiomatization = disableSetAxiomatization || other.disableSetAxiomatization,
disableCheckTerminationPureFns = disableCheckTerminationPureFns || other.disableCheckTerminationPureFns,
)
}

Expand Down Expand Up @@ -247,6 +250,7 @@ case class BaseConfig(gobraDirectory: Path = ConfigDefaults.DefaultGobraDirector
parseAndTypeCheckMode: TaskManagerMode = ConfigDefaults.DefaultParseAndTypeCheckMode,
requireTriggers: Boolean = ConfigDefaults.DefaultRequireTriggers,
disableSetAxiomatization: Boolean = ConfigDefaults.DefaultDisableSetAxiomatization,
disableCheckTerminationPureFns: Boolean = ConfigDefaults.DefaultDisableCheckTerminationPureFns,
) {
def shouldParse: Boolean = true
def shouldTypeCheck: Boolean = !shouldParseOnly
Expand Down Expand Up @@ -306,6 +310,7 @@ trait RawConfig {
parseAndTypeCheckMode = baseConfig.parseAndTypeCheckMode,
requireTriggers = baseConfig.requireTriggers,
disableSetAxiomatization = baseConfig.disableSetAxiomatization,
disableCheckTerminationPureFns = baseConfig.disableCheckTerminationPureFns,
)
}

Expand Down Expand Up @@ -710,6 +715,13 @@ class ScallopGobraConfig(arguments: Seq[String], isInputOptional: Boolean = fals
noshort = true,
)

val disableCheckTerminationPureFns: ScallopOption[Boolean] = opt[Boolean](
name = "disableTermCheckPureFns",
descr = "Do not check that all pure functions are marked with termination measures,",
default = Some(ConfigDefaults.DefaultDisableCheckTerminationPureFns),
noshort = true,
)

val parseAndTypeCheckMode: ScallopOption[TaskManagerMode] = choice(
name = "parseAndTypeCheckMode",
choices = Seq("LAZY", "SEQUENTIAL", "PARALLEL"),
Expand Down Expand Up @@ -909,5 +921,6 @@ class ScallopGobraConfig(arguments: Seq[String], isInputOptional: Boolean = fals
parseAndTypeCheckMode = parseAndTypeCheckMode(),
requireTriggers = requireTriggers(),
disableSetAxiomatization = disableSetAxiomatization(),
disableCheckTerminationPureFns = disableCheckTerminationPureFns(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
package viper.gobra.frontend.info.implementation.typing.ghost

import org.bitbucket.inkytonik.kiama.util.Messaging.{Messages, error, noMessages}
import viper.gobra.ast.frontend.{PBlock, PCodeRootWithResult, PExplicitGhostMember, PFPredicateDecl, PFunctionDecl, PFunctionSpec, PGhostMember, PIdnUse, PImplementationProof, PMPredicateDecl, PMethodDecl, PMethodImplementationProof, PParameter, PReturn, PVariadicType, PWithBody}
import viper.gobra.ast.frontend.{PBlock, PCodeRootWithResult, PExplicitGhostMember, PFPredicateDecl, PFunctionDecl, PFunctionSpec, PGhostMember, PIdnUse, PImplementationProof, PMember, PMPredicateDecl, PMethodDecl, PMethodImplementationProof, PParameter, PReturn, PVariadicType, PWithBody}
import viper.gobra.frontend.info.base.SymbolTable.{MPredicateSpec, MethodImpl, MethodSpec}
import viper.gobra.frontend.info.base.Type.{InterfaceT, Type, UnknownType}
import viper.gobra.frontend.info.implementation.TypeInfoImpl
import viper.gobra.frontend.info.implementation.typing.BaseTyping
import viper.gobra.util.Violation

trait GhostMemberTyping extends BaseTyping { this: TypeInfoImpl =>

Expand Down Expand Up @@ -58,13 +59,26 @@ trait GhostMemberTyping extends BaseTyping { this: TypeInfoImpl =>
}
}

private[typing] def wellFoundedIfNeededPureSpec(member: PMember): Messages = {
val spec = member match {
case m: PMethodDecl => m.spec
case f: PFunctionDecl => f.spec
case _ => Violation.violation("The function wellFoundedIfNeededPureSpec was called with an unexpected member type.")
}
val hasMeasureIfNeeded = config.disableCheckTerminationPureFns || spec.terminationMeasures.nonEmpty
val needsMeasureError =
error(member, "All pure functions must have termination measures, but none was found for this member.", !hasMeasureIfNeeded)
needsMeasureError
}

private[typing] def wellDefIfPureMethod(member: PMethodDecl): Messages = {

if (member.spec.isPure) {
isSingleResultArg(member) ++
isSinglePureReturnExpr(member) ++
isPurePostcondition(member.spec) ++
nonVariadicArguments(member.args)
nonVariadicArguments(member.args) ++
wellFoundedIfNeededPureSpec(member)
} else noMessages
}

Expand All @@ -79,7 +93,8 @@ trait GhostMemberTyping extends BaseTyping { this: TypeInfoImpl =>
isSingleResultArg(member) ++
isSinglePureReturnExpr(member) ++
isPurePostcondition(member.spec) ++
nonVariadicArguments(member.args)
nonVariadicArguments(member.args) ++
wellFoundedIfNeededPureSpec(member)
} else noMessages
}

Expand Down

0 comments on commit 9d4463a

Please sign in to comment.