77package viper .silicon .interfaces
88
99import viper .silicon .interfaces .state .Chunk
10- import viper .silicon .reporting .Converter
10+ import viper .silicon .reporting .{Converter , ExtractedModel , ExtractedModelEntry , GenericDomainInterpreter ,
11+ ModelInterpreter , ExtractedFunction , DomainEntry , VarEntry , RefEntry , NullRefEntry , UnprocessedModelEntry }
1112import viper .silicon .state .{State , Store }
12- import viper .silver .verifier .{Counterexample , FailureContext , Model , VerificationError }
13+ import viper .silver .verifier .{Counterexample , FailureContext , Model , VerificationError , ValueEntry , ApplicationEntry , ConstantEntry }
1314import viper .silicon .state .terms .Term
15+ import viper .silicon .verifier .Verifier
1416import viper .silver .ast
1517
1618/*
@@ -146,19 +148,84 @@ case class SiliconMappedCounterexample(internalStore: Store,
146148 extends SiliconCounterexample {
147149
148150 val converter : Converter =
149- Converter (nativeModel, internalStore, heap, oldHeaps)
151+ Converter (nativeModel, internalStore, heap, oldHeaps, Verifier .program )
150152
151153 val model : Model = nativeModel
154+ val interpreter : ModelInterpreter [ExtractedModelEntry , Seq [ExtractedModelEntry ]] = GenericDomainInterpreter (converter)
155+ private var heapNames : Map [ValueEntry , String ] = Map ()
152156
153157 override lazy val toString : String = {
154- val buf = converter.modelAtLabel
155- .map(x => s " model at label: ${x._1}\n ${x._2.toString}\n " )
158+ val extractedModel = converter.extractedModel
159+ val bufModels = converter.modelAtLabel
160+ .map { case (label, model) => s " model at label $label: \n ${interpret(model).toString}" }
156161 .mkString(" \n " )
162+ val (bufDomains, bufNonDomainFunctions) = functionsToString()
163+ s " $bufModels\n on return: \n ${interpret(extractedModel).toString} $bufDomains $bufNonDomainFunctions"
164+ }
165+ private def interpret (t : ExtractedModel ): ExtractedModel =
166+ ExtractedModel (t.entries.map{ case (name, entry) => (name, interpret(entry)) })
167+ private def interpret (t : ExtractedModelEntry ): ExtractedModelEntry = interpreter.interpret(t, Seq ())
168+
169+ private def functionsToString () : (String , String ) = {
170+ // extractedModel.entries should be a bijection so we can invert the map
171+ // Since we only care about ref entries we can remove everything else
172+ val invEntries = converter.extractedModel.entries.flatMap{ case (name, entry) =>
173+ entry match {
174+ case RefEntry (symName, _) => Some (symName -> name)
175+ case NullRefEntry (symName)=> Some (symName -> name)
176+ case _ => None
177+ }}
178+
179+ val replaceDomainFunction = converter.domains.map{
180+ case DomainEntry (names, types, functions) =>
181+ DomainEntry (names, types, renameFunctions(functions, invEntries))
182+ }
183+ val bufDomains = replaceDomainFunction.nonEmpty match {
184+ case true => " \n Domain: \n " + replaceDomainFunction.map(domain => domain.toString()).mkString(" \n " )
185+ case false => " "
186+ }
187+
188+ val replaceNonDomainFunctions = renameFunctions(converter.nonDomainFunctions, invEntries)
189+ val bufNonDomainFunctions = replaceNonDomainFunctions.nonEmpty match {
190+ case true => " \n Functions: \n " + replaceNonDomainFunctions.map(fn => fn.toString()).mkString(" \n " )
191+ case false => " "
192+ }
193+ (bufDomains, bufNonDomainFunctions)
194+ }
195+
196+ private def renameFunctions (fn : Seq [ExtractedFunction ], invEntries : Map [String , String ]) : Seq [ExtractedFunction ] = {
197+ fn.map{
198+ case ExtractedFunction (fname, argtypes, returnType, options, default) => {
199+ val optionsNew = options.map(x => x._1.map(y => renameFunction(y, invEntries)) -> renameFunction(x._2, invEntries))
200+ val defaultNew = renameFunction(default, invEntries)
201+ ExtractedFunction (fname, argtypes, returnType, optionsNew, defaultNew)
202+ }
203+ }
204+ }
205+
206+ private def renameFunction (entry: ExtractedModelEntry , invEntries : Map [String , String ]): ExtractedModelEntry = {
207+ entry match {
208+ case VarEntry (name, sort) => VarEntry (invEntries.get(name).getOrElse(name), sort)
209+ case UnprocessedModelEntry (unproEntry) => {
210+ unproEntry match {
211+ case ApplicationEntry (" $Snap.combine" , Seq (_, _)) => renameSnap(unproEntry)
212+ case ConstantEntry (" $Snap.unit" ) => renameSnap(unproEntry)
213+ case _ => entry
214+ }
215+ }
216+ case _ => entry
217+ }
218+ }
157219
158- s " $buf\n on return: \n ${converter.extractedModel.toString}"
220+ private def renameSnap (entry : ValueEntry ): ExtractedModelEntry = {
221+ if (! heapNames.contains(entry)) {
222+ heapNames += (entry -> (" heap_" + heapNames.size.toString))
223+ }
224+ UnprocessedModelEntry (ConstantEntry (
225+ heapNames.get(entry).orNull))
159226 }
160227
161228 override def withStore (s : Store ): SiliconCounterexample = {
162229 SiliconMappedCounterexample (s, heap, oldHeaps, nativeModel)
163230 }
164- }
231+ }
0 commit comments