Skip to content

Commit 8bd26f5

Browse files
authored
Merge pull request #732 from viperproject/meilers_term_plugin_deactive_flag
SilFrontend API for Viper frontend usage
2 parents c3cf35a + 3522af7 commit 8bd26f5

4 files changed

Lines changed: 91 additions & 8 deletions

File tree

src/main/scala/viper/silver/frontend/SilFrontEndConfig.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ abstract class SilFrontendConfig(args: Seq[String], private var projectName: Str
8282
hidden = true
8383
)
8484

85+
val disableDefaultPlugins = opt[Boolean]("disableDefaultPlugins",
86+
descr = "Deactivate all default plugins.",
87+
default = Some(false),
88+
noshort = true,
89+
hidden = true
90+
)
91+
8592
val plugin = opt[String]("plugin",
8693
descr = "Load plugin(s) with given class name(s). Several plugins can be separated by ':'. " +
8794
"The fully qualified class name of the plugin should be specified.",

src/main/scala/viper/silver/frontend/SilFrontend.scala

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ trait SilFrontend extends DefaultFrontend {
5252
}
5353
}
5454

55+
def resetPlugins(): Unit = {
56+
val pluginsArg: Option[String] = if (_config != null) {
57+
// concat defined plugins and default plugins
58+
val list = _config.plugin.toOption ++ (if (_config.disableDefaultPlugins()) Seq() else defaultPlugins)
59+
if (list.isEmpty) {
60+
None
61+
} else {
62+
Some(list.mkString(":"))
63+
}
64+
} else {
65+
None
66+
}
67+
_plugins = SilverPluginManager(pluginsArg)(reporter, logger, _config, fp)
68+
}
69+
5570
/**
5671
* Create the verifier. The full command is parsed for debugging purposes only,
5772
* since the command line arguments will be passed later on via
@@ -184,13 +199,7 @@ trait SilFrontend extends DefaultFrontend {
184199
super.reset(input)
185200

186201
if(_config != null) {
187-
188-
// concat defined plugins and default plugins
189-
val pluginsArg: Option[String] = {
190-
val list = _config.plugin.toOption ++ defaultPlugins
191-
if (list.isEmpty) { None } else { Some(list.mkString(":")) }
192-
}
193-
_plugins = SilverPluginManager(pluginsArg)(reporter, logger, _config, fp)
202+
resetPlugins()
194203
}
195204
}
196205

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package viper.silver.frontend
2+
3+
import viper.silver.ast.Program
4+
import viper.silver.verifier.VerificationResult
5+
6+
7+
/**
8+
* Trait that can be mixed into SilFrontends to make them easily usable by actual Viper frontends that do not use
9+
* Viper's parser, type checker, etc., but instead directly consistency-check and verify a Viper AST.
10+
* Compared to working directly with an instance of [[viper.silver.verifier.Verifier]], SilFrontend manages plugins
11+
* automatically.
12+
* To use it:
13+
* - create an instance f of a specific SilFrontend with ViperFrontendAPI mixed in
14+
* - call f.initialize(args), where args are the command line arguments without any file name.
15+
* - (potentially repeatedly) call f.verify(p), where p is the program to verify
16+
* - call f.stop() when done
17+
* Plugin usage must be managed via command line arguments.
18+
* Existing implementations are SiliconFrontendAPI and CarbonFrontendAPI
19+
*/
20+
trait ViperFrontendAPI extends SilFrontend {
21+
22+
private var initialized = false
23+
override val phases: Seq[Phase] = Seq(ConsistencyCheck, Verification)
24+
val dummyInputFilename = "dummy-file-to-prevent-cli-parser-from-complaining-about-missing-file-name.silver"
25+
26+
def initialize(args: Seq[String]): Unit = {
27+
// create verifier
28+
// parse args on frontend, set on verifier
29+
val v = createVerifier(args.mkString(" "))
30+
setVerifier(v)
31+
_verifier = Some(v)
32+
parseCommandLine(args :+ "--ignoreFile" :+ dummyInputFilename)
33+
resetPlugins()
34+
initialized = true
35+
}
36+
37+
protected def setStartingState() = {
38+
_state = DefaultStates.ConsistencyCheck
39+
}
40+
41+
def verify(p: Program): VerificationResult = {
42+
if (!initialized)
43+
throw new IllegalStateException("Not initialized")
44+
setStartingState()
45+
_program = Some(p)
46+
runAllPhases()
47+
result
48+
}
49+
50+
def stop(): Unit = {
51+
if (!initialized)
52+
throw new IllegalStateException("Not initialized")
53+
_verifier.foreach(_.stop())
54+
}
55+
56+
}
57+
58+
/**
59+
* Version of ViperFrontendAPI that skips the consistency check phase.
60+
*/
61+
trait MinimalViperFrontendAPI extends ViperFrontendAPI {
62+
override val phases: Seq[Phase] = Seq(Verification)
63+
64+
override protected def setStartingState() = {
65+
_state = DefaultStates.ConsistencyCheck
66+
}
67+
}

src/main/scala/viper/silver/verifier/VerificationError.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ case class MapEntry(options: Map[Seq[ValueEntry], ValueEntry], default: ValueEnt
9393
val indices = args.map(_.get._1)
9494
// We expect the arguments in the order 0, 1, ..., n-1; if we get something else, reject.
9595
// TODO: Find out if this order is always guaranteed,
96-
if (indices != (0 until indices.size))
96+
if (indices != (0 until indices.size).map(_.toString))
9797
None
9898
else
9999
Some(args.map(_.get._2))

0 commit comments

Comments
 (0)