@@ -19,10 +19,10 @@ import viper.silicon.state.terms._
1919// etc. as well.
2020trait FunctionRecorder extends Mergeable [FunctionRecorder ] {
2121 def data : Option [FunctionData ]
22- private [functions] def locToSnaps : Map [ast.LocationAccess , InsertionOrderedSet [(Stack [Term ], Term )]]
23- def locToSnap : Map [ast.LocationAccess , Term ]
24- private [functions] def fappToSnaps : Map [ast.FuncApp , InsertionOrderedSet [(Stack [Term ], Term )]]
25- def fappToSnap : Map [ast.FuncApp , Term ]
22+ private [functions] def locToSnaps : Map [( ast.LocationAccess , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]]
23+ def locToSnap : Map [( ast.LocationAccess , Seq [ ExpContext ]) , Term ]
24+ private [functions] def fappToSnaps : Map [( ast.FuncApp , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]]
25+ def fappToSnap : Map [( ast.FuncApp , Seq [ ExpContext ]) , Term ]
2626 def freshFvfsAndDomains : InsertionOrderedSet [SnapshotMapDefinition ]
2727 def freshFieldInvs : InsertionOrderedSet [InverseFunctions ]
2828 def freshConstrainedVars : InsertionOrderedSet [(Var , Term )]
@@ -41,19 +41,28 @@ trait FunctionRecorder extends Mergeable[FunctionRecorder] {
4141 def recordFreshMacro (decl : MacroDecl ): FunctionRecorder
4242 def depth : Int
4343 def changeDepthBy (delta : Int ): FunctionRecorder
44+ def enterLet (l : ast.Let ): FunctionRecorder
45+ def leaveLet (l : ast.Let ): FunctionRecorder
46+ def enterQuantifiedExp (q : ast.QuantifiedExp ): FunctionRecorder
47+ def leaveQuantifiedExp (q : ast.QuantifiedExp ): FunctionRecorder
4448}
4549
50+ trait ExpContext
51+ case class LetContext (l : ast.Let ) extends ExpContext
52+ case class QuantifierContext (q : ast.QuantifiedExp ) extends ExpContext
53+
4654case class ActualFunctionRecorder (private val _data : FunctionData ,
47- private [functions] val locToSnaps : Map [ast.LocationAccess , InsertionOrderedSet [(Stack [Term ], Term )]] = Map (),
48- private [functions] val fappToSnaps : Map [ast.FuncApp , InsertionOrderedSet [(Stack [Term ], Term )]] = Map (),
55+ private [functions] val locToSnaps : Map [( ast.LocationAccess , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]] = Map (),
56+ private [functions] val fappToSnaps : Map [( ast.FuncApp , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]] = Map (),
4957 freshFvfsAndDomains : InsertionOrderedSet [SnapshotMapDefinition ] = InsertionOrderedSet (),
5058 freshFieldInvs : InsertionOrderedSet [InverseFunctions ] = InsertionOrderedSet (),
5159 freshConstrainedVars : InsertionOrderedSet [(Var , Term )] = InsertionOrderedSet (),
5260 freshConstraints : InsertionOrderedSet [Term ] = InsertionOrderedSet (),
5361 freshSnapshots : InsertionOrderedSet [Function ] = InsertionOrderedSet (),
5462 freshPathSymbols : InsertionOrderedSet [Function ] = InsertionOrderedSet (),
5563 freshMacros : InsertionOrderedSet [MacroDecl ] = InsertionOrderedSet (),
56- depth : Int = 0 )
64+ depth : Int = 0 ,
65+ private val _context : Seq [ExpContext ] = Seq ())
5766 extends FunctionRecorder {
5867
5968 /* Depth is intended to reflect how often a nested function application or unfolding expression
@@ -93,8 +102,8 @@ case class ActualFunctionRecorder(private val _data: FunctionData,
93102 val data = Some (_data)
94103
95104 private def exprToSnap [E <: ast.Exp ]
96- (recordings : Map [E , InsertionOrderedSet [(Stack [Term ], Term )]])
97- : Map [E , Term ] = {
105+ (recordings : Map [( E , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]])
106+ : Map [( E , Seq [ ExpContext ]) , Term ] = {
98107
99108 recordings.map { case (expr, guardsToSnap) =>
100109 expr -> toTerm(guardsToSnap, None )
@@ -148,20 +157,20 @@ case class ActualFunctionRecorder(private val _data: FunctionData,
148157 }
149158 }
150159
151- def locToSnap : Map [ast.LocationAccess , Term ] = exprToSnap(locToSnaps)
152- def fappToSnap : Map [ast.FuncApp , Term ] = exprToSnap(fappToSnaps)
160+ def locToSnap : Map [( ast.LocationAccess , Seq [ ExpContext ]) , Term ] = exprToSnap(locToSnaps)
161+ def fappToSnap : Map [( ast.FuncApp , Seq [ ExpContext ]) , Term ] = exprToSnap(fappToSnaps)
153162
154163 private def recordExpressionSnapshot [E <: ast.Exp ]
155164 (loc : E ,
156165 guards : Stack [Term ],
157166 snap : Term ,
158- recordings : Map [E , InsertionOrderedSet [(Stack [Term ], Term )]])
159- : Option [Map [E , InsertionOrderedSet [(Stack [Term ], Term )]]] = {
167+ recordings : Map [( E , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]])
168+ : Option [Map [( E , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]]] = {
160169
161170 if (depth == 0 ) {
162- val guardsToSnaps = recordings.getOrElse(loc, InsertionOrderedSet ()) + (guards -> snap)
171+ val guardsToSnaps = recordings.getOrElse(( loc, _context) , InsertionOrderedSet ()) + (guards -> snap)
163172
164- Some (recordings + (loc -> guardsToSnaps))
173+ Some (recordings + (( loc, _context) -> guardsToSnaps))
165174 } else {
166175 None
167176 }
@@ -212,6 +221,30 @@ case class ActualFunctionRecorder(private val _data: FunctionData,
212221 def changeDepthBy (delta : Int ): ActualFunctionRecorder =
213222 copy(depth = depth + delta)
214223
224+ def enterLet (l : ast.Let ): FunctionRecorder = {
225+ copy(_context = _context :+ LetContext (l))
226+ }
227+
228+ def leaveLet (l : ast.Let ): FunctionRecorder = {
229+ assert(_context.nonEmpty && (_context.last match {
230+ case LetContext (`l`) => true
231+ case _ => false
232+ }))
233+ copy(_context = _context.init)
234+ }
235+
236+ def enterQuantifiedExp (q : ast.QuantifiedExp ): FunctionRecorder = {
237+ copy(_context = _context :+ QuantifierContext (q))
238+ }
239+
240+ def leaveQuantifiedExp (q : ast.QuantifiedExp ): FunctionRecorder = {
241+ assert(_context.nonEmpty && (_context.last match {
242+ case QuantifierContext (`q`) => true
243+ case _ => false
244+ }))
245+ copy(_context = _context.init)
246+ }
247+
215248 def merge (other : FunctionRecorder ): ActualFunctionRecorder = {
216249 if (depth > 1 ) return this
217250
@@ -271,10 +304,10 @@ case class ActualFunctionRecorder(private val _data: FunctionData,
271304
272305case object NoopFunctionRecorder extends FunctionRecorder {
273306 val data : Option [FunctionData ] = None
274- private [functions] val fappToSnaps : Map [ast.FuncApp , InsertionOrderedSet [(Stack [Term ], Term )]] = Map .empty
275- val fappToSnap : Map [ast.FuncApp , Term ] = Map .empty
276- private [functions] val locToSnaps : Map [ast.LocationAccess , InsertionOrderedSet [(Stack [Term ], Term )]] = Map .empty
277- val locToSnap : Map [ast.LocationAccess , Term ] = Map .empty
307+ private [functions] val fappToSnaps : Map [( ast.FuncApp , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]] = Map .empty
308+ val fappToSnap : Map [( ast.FuncApp , Seq [ ExpContext ]) , Term ] = Map .empty
309+ private [functions] val locToSnaps : Map [( ast.LocationAccess , Seq [ ExpContext ]) , InsertionOrderedSet [(Stack [Term ], Term )]] = Map .empty
310+ val locToSnap : Map [( ast.LocationAccess , Seq [ ExpContext ]) , Term ] = Map .empty
278311 val freshFvfsAndDomains : InsertionOrderedSet [SnapshotMapDefinition ] = InsertionOrderedSet .empty
279312 val freshFieldInvs : InsertionOrderedSet [InverseFunctions ] = InsertionOrderedSet .empty
280313 val freshConstrainedVars : InsertionOrderedSet [(Var , Term )] = InsertionOrderedSet .empty
@@ -300,4 +333,8 @@ case object NoopFunctionRecorder extends FunctionRecorder {
300333 def recordPathSymbol (symbol : Function ): NoopFunctionRecorder .type = this
301334 def recordFreshMacro (decl : MacroDecl ): NoopFunctionRecorder .type = this
302335 def changeDepthBy (delta : Int ): NoopFunctionRecorder .type = this
336+ def enterLet (l : ast.Let ): FunctionRecorder = this
337+ def leaveLet (l : ast.Let ): FunctionRecorder = this
338+ def enterQuantifiedExp (q : ast.QuantifiedExp ): FunctionRecorder = this
339+ def leaveQuantifiedExp (q : ast.QuantifiedExp ): FunctionRecorder = this
303340}
0 commit comments