@@ -8,6 +8,7 @@ package viper.silicon.supporters.functions
88
99import scala .annotation .unused
1010import com .typesafe .scalalogging .LazyLogging
11+ import viper .silicon .state .FunctionPreconditionTransformer
1112import viper .silver .ast
1213import viper .silver .ast .utility .Functions
1314import viper .silicon .common .collections .immutable .InsertionOrderedSet
@@ -51,6 +52,7 @@ class FunctionData(val programFunction: ast.Function,
5152 val function : HeapDepFun = symbolConverter.toFunction(programFunction)
5253 val limitedFunction = functionSupporter.limitedVersion(function)
5354 val statelessFunction = functionSupporter.statelessVersion(function)
55+ val preconditionFunction = functionSupporter.preconditionVersion(function)
5456
5557 val formalArgs : Map [ast.AbstractLocalVar , Var ] = toMap(
5658 for (arg <- programFunction.formalArgs;
@@ -67,6 +69,7 @@ class FunctionData(val programFunction: ast.Function,
6769 val functionApplication = App (function, `?s` +: formalArgs.values.toSeq)
6870 val limitedFunctionApplication = App (limitedFunction, `?s` +: formalArgs.values.toSeq)
6971 val triggerFunctionApplication = App (statelessFunction, formalArgs.values.toSeq)
72+ val preconditionFunctionApplication = App (preconditionFunction, `?s` +: formalArgs.values.toSeq)
7073
7174 val limitedAxiom =
7275 Forall (arguments,
@@ -175,15 +178,21 @@ class FunctionData(val programFunction: ast.Function,
175178 expressionTranslator.translatePrecondition(program, programFunction.pres, this )
176179 }
177180
181+ lazy val translatedPosts = {
182+ assert(phase == 1 , s " Postcondition axiom must be generated in phase 1, current phase is $phase" )
183+ if (programFunction.posts.nonEmpty) {
184+ expressionTranslator.translatePostcondition(program, programFunction.posts, this )
185+ }else {
186+ Seq ()
187+ }
188+ }
189+
178190 lazy val postAxiom : Option [Term ] = {
179191 assert(phase == 1 , s " Postcondition axiom must be generated in phase 1, current phase is $phase" )
180192
181193 if (programFunction.posts.nonEmpty) {
182- val posts =
183- expressionTranslator.translatePostcondition(program, programFunction.posts, this )
184-
185- val pre = And (translatedPres)
186- val innermostBody = And (generateNestedDefinitionalAxioms ++ List (Implies (pre, And (posts))))
194+ val pre = if (programFunction.pres.nonEmpty) preconditionFunctionApplication else True ()
195+ val innermostBody = And (generateNestedDefinitionalAxioms ++ List (Implies (pre, And (translatedPosts))))
187196 val bodyBindings : Map [Var , Term ] = Map (formalResult -> limitedFunctionApplication)
188197 val body = Let (toMap(bodyBindings), innermostBody)
189198
@@ -237,13 +246,17 @@ class FunctionData(val programFunction: ast.Function,
237246 }))
238247 }
239248
240- lazy val definitionalAxiom : Option [Term ] = {
249+ lazy val optBody : Option [Term ] = {
241250 assert(phase == 2 , s " Definitional axiom must be generated in phase 2, current phase is $phase" )
242251
243- val optBody = expressionTranslator.translate(program, programFunction, this )
252+ expressionTranslator.translate(program, programFunction, this )
253+ }
254+
255+ lazy val definitionalAxiom : Option [Term ] = {
256+ assert(phase == 2 , s " Definitional axiom must be generated in phase 2, current phase is $phase" )
244257
245258 optBody.map(translatedBody => {
246- val pre = And (translatedPres )
259+ val pre = if (programFunction.pres.nonEmpty) preconditionFunctionApplication else True ( )
247260 val nestedDefinitionalAxioms = generateNestedDefinitionalAxioms
248261 val body = And (nestedDefinitionalAxioms ++ List (Implies (pre, And (functionApplication === translatedBody))))
249262 val allTriggers = (
@@ -252,4 +265,18 @@ class FunctionData(val programFunction: ast.Function,
252265
253266 Forall (arguments, body, allTriggers)})
254267 }
268+
269+ lazy val preconditionPropagationAxiom : Seq [Term ] = {
270+ val pre = if (programFunction.pres.nonEmpty) preconditionFunctionApplication else True ()
271+ val bodyPreconditions = if (programFunction.body.isDefined) optBody.map(translatedBody => {
272+ val body = Implies (pre, FunctionPreconditionTransformer .transform(translatedBody, program))
273+ Forall (arguments, body, Seq (Trigger (functionApplication)))
274+ }) else None
275+ val postPreconditions = if (programFunction.posts.nonEmpty) {
276+ val bodyBindings : Map [Var , Term ] = Map (formalResult -> limitedFunctionApplication)
277+ val bodies = translatedPosts.map(tPost => Let (bodyBindings, Implies (pre, FunctionPreconditionTransformer .transform(tPost, program))))
278+ bodies.map(b => Forall (arguments, b, Seq (Trigger (limitedFunctionApplication))))
279+ } else Seq ()
280+ bodyPreconditions.toSeq ++ postPreconditions
281+ }
255282}
0 commit comments