-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathFieldValueFunctionsContributor.scala
More file actions
126 lines (97 loc) · 4.87 KB
/
Copy pathFieldValueFunctionsContributor.scala
File metadata and controls
126 lines (97 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2011-2019 ETH Zurich.
package viper.silicon.supporters.qps
import viper.silver.ast
import viper.silver.ast.utility.QuantifiedPermissions.QuantifiedPermissionAssertion
import viper.silicon.common.collections.immutable.InsertionOrderedSet
import viper.silicon.{Config, Map}
import viper.silicon.interfaces.{PreambleContributor, PreambleReader}
import viper.silicon.interfaces.decider.{ProverLike, TermConverter}
import viper.silicon.state.SymbolConverter
import viper.silicon.state.terms.{SortDecl, sorts}
import viper.silver.ast.{FieldAccess, Forall}
trait FieldValueFunctionsContributor[SO, SY, AX] extends PreambleContributor[SO, SY, AX]
class DefaultFieldValueFunctionsContributor(preambleReader: PreambleReader[String, String],
symbolConverter: SymbolConverter,
termConverter: TermConverter[String, String, String],
config: Config)
extends FieldValueFunctionsContributor[sorts.FieldValueFunction, String, String] {
/* PreambleBlock = Comment x Lines */
private type PreambleBlock = (String, Iterable[String])
private var collectedFields: InsertionOrderedSet[ast.Field] = InsertionOrderedSet.empty
private var collectedSorts: InsertionOrderedSet[sorts.FieldValueFunction] = InsertionOrderedSet.empty
private var collectedFunctionDecls: Iterable[PreambleBlock] = Seq.empty
private var collectedAxioms: Iterable[PreambleBlock] = Seq.empty
/* Lifetime */
def reset(): Unit = {
collectedFields = InsertionOrderedSet.empty
collectedSorts = InsertionOrderedSet.empty
collectedFunctionDecls = Seq.empty
collectedAxioms = Seq.empty
}
def stop(): Unit = {}
def start(): Unit = {}
/* Functionality */
def analyze(program: ast.Program): Unit = {
/* TODO: Use viper.silver.ast.utility.QuantifiedPermissions.quantifiedFields instead? */
program visit {
case QuantifiedPermissionAssertion(_, _, acc: ast.FieldAccessPredicate) =>
collectedFields += acc.loc.field
case Forall(_, triggers, _) =>
val trigExps = triggers flatMap (_.exps)
val fieldAccesses = trigExps flatMap (e => e.deepCollect {case fa: FieldAccess => fa})
collectedFields ++= (fieldAccesses map (_.field))
}
// WARNING: DefaultSetsContributor contributes a sort that is due to QPs over fields
collectedSorts = (
collectedFields.map(f => sorts.FieldValueFunction(symbolConverter.toSort(f.typ), f.name)))
collectedFunctionDecls = generateFunctionDecls
collectedAxioms = generateAxioms
}
private def extractPreambleLines(from: Iterable[PreambleBlock]*): Iterable[String] =
from.flatten.flatMap(_._2)
private def emitPreambleLines(sink: ProverLike, from: Iterable[PreambleBlock]*): Unit = {
from.flatten foreach { case (comment, declarations) =>
sink.comment(comment)
sink.emit(declarations)
}
}
def generateFunctionDecls: Iterable[PreambleBlock] = {
val templateFile = "/field_value_functions_declarations.smt2"
collectedFields map (f => {
val sort = symbolConverter.toSort(f.typ)
val id = f.name
val substitutions = Map("$FLD$" -> id, "$S$" -> termConverter.convert(sort), "$T$" -> termConverter.convertSanitized(sort))
val declarations = preambleReader.readParametricPreamble(templateFile, substitutions)
(s"$templateFile [$id: $sort]", declarations)
})
}
def generateAxioms: Iterable[PreambleBlock] = {
val templateFile =
if (config.disableISCTriggers()) "/field_value_functions_axioms_no_triggers.smt2"
else "/field_value_functions_axioms.smt2"
collectedFields map (f => {
val sort = symbolConverter.toSort(f.typ)
val id = f.name
val substitutions = Map("$FLD$" -> id, "$S$" -> termConverter.convert(sort), "$T$" -> termConverter.convertSanitized(sort))
val declarations = preambleReader.readParametricPreamble(templateFile, substitutions)
(s"$templateFile [$id: $sort]", declarations)
})
}
def sortsAfterAnalysis: InsertionOrderedSet[sorts.FieldValueFunction] = collectedSorts
def declareSortsAfterAnalysis(sink: ProverLike): Unit = {
sortsAfterAnalysis foreach (s => sink.declare(SortDecl(s)))
}
val symbolsAfterAnalysis: Iterable[String] =
extractPreambleLines(collectedFunctionDecls)
def declareSymbolsAfterAnalysis(sink: ProverLike): Unit =
emitPreambleLines(sink, collectedFunctionDecls)
val axiomsAfterAnalysis: Iterable[String] =
extractPreambleLines(collectedAxioms)
def emitAxiomsAfterAnalysis(sink: ProverLike): Unit =
emitPreambleLines(sink, collectedAxioms)
def updateGlobalStateAfterAnalysis(): Unit = { /* Nothing to contribute*/ }
}