-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding a Viper plugin #2
base: master
Are you sure you want to change the base?
Changes from all commits
c872beb
d943fc2
f5aa5cd
d3541a9
0b548c7
3877682
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "silver"] | ||
path = silver | ||
url = https://github.com/viperproject/silver.git |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
sbt.version=1.4.4 | ||
sbt.version=1.6.2 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,6 +125,21 @@ case class SIFLowExp(exp: Exp, comparator: Option[String] = None, typVarMap: Map | |
override val extensionIsPure: Boolean = exp.isPure | ||
} | ||
|
||
case class SIFRelExp(exp: Exp, i: IntLit) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you using |
||
(val pos: Position = NoPosition, | ||
val info: Info = NoInfo, | ||
val errT: ErrorTrafo = NoTrafos) extends ExtensionExp { | ||
override def extensionSubnodes: Seq[Node] = Seq(exp, i) | ||
|
||
override def typ: Type = exp.typ | ||
|
||
override def verifyExtExp(): VerificationResult = ??? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to comment why this can be unimplemented or instead throw some error message. |
||
|
||
override def prettyPrint: PrettyPrintPrimitives#Cont = (text("rel") <> parens(show(exp) <> "," <+> show(i))) | ||
|
||
override val extensionIsPure: Boolean = exp.isPure | ||
} | ||
|
||
case class SIFLowEventExp()(val pos: Position = NoPosition, | ||
val info: Info = NoInfo, | ||
val errT: ErrorTrafo = NoTrafos) extends ExtensionExp { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -134,8 +134,9 @@ trait SIFExtendedTransformer { | |
p.methods.map(m => translateMethod(m)) | ||
} | ||
|
||
p.copy(domains = newDomains, fields = newFields, functions = newFunctions, predicates = newPredicates, | ||
val res = p.copy(domains = newDomains, fields = newFields, functions = newFunctions, predicates = newPredicates, | ||
methods = newMethods)(p.pos, p.info, p.errT) | ||
res | ||
Comment on lines
-137
to
+139
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. intentionally? |
||
} | ||
|
||
def getName(orig: String) : String = { | ||
|
@@ -1271,7 +1272,9 @@ trait SIFExtendedTransformer { | |
val relVars = e.filter{ | ||
case _: SIFLowExp => true | ||
case _: SIFLowEventExp => true | ||
case f@DomainFuncApp("Low", args, _) => true | ||
case _: SIFRelExp => true | ||
case f@DomainFuncApp("Low", _, _) => true | ||
case f@DomainFuncApp("LowEvent", Seq(), _) => true | ||
case _ => false | ||
} | ||
relVars.isEmpty | ||
|
@@ -1395,6 +1398,8 @@ trait SIFExtendedTransformer { | |
// for the domain method low, used e.g. for list resource | ||
case f@DomainFuncApp("Low", args, _) => translateSIFAss( | ||
SIFLowExp(args.head, None)(f.pos, f.info, f.errT), ctx, relAssertCtx) | ||
case f@DomainFuncApp("LowEvent", Seq(), _) => translateSIFAss( | ||
SIFLowEventExp()(f.pos, f.info, f.errT), ctx, relAssertCtx) | ||
case pap@PredicateAccessPredicate(pred, _) => | ||
val (lowFunc, lhs) = getPredicateLowFuncExp(pred.predicateName, ctx, Some((p1, p2))) | ||
lowFunc match { | ||
|
@@ -1450,7 +1455,9 @@ trait SIFExtendedTransformer { | |
case pa@PredicateAccess(args, name) => PredicateAccess(args.map(a => translatePrime(a, p1, p2)), | ||
primedNames(name))(pa.pos, pa.info, pa.errT) | ||
case l: SIFLowExp => Implies(And(p1, p2)(), translateSIFLowExpComparison(l, p1, p2))() | ||
case SIFRelExp(e, i) => if(i.i == BigInt.int2bigInt(1)) translatePrime(e, p1, p2) else translateNormal(e, p1, p2) | ||
case f@DomainFuncApp("Low", args, _) => TrueLit()() | ||
case f@DomainFuncApp("LowEvent", Seq(), _) => TrueLit()() | ||
case f@ForPerm(vars, location, body) => ForPerm(vars, | ||
translateResourceAccess(location), | ||
translatePrime(body, p1, p2))(f.pos, f.info, f.errT) | ||
|
@@ -1460,6 +1467,7 @@ trait SIFExtendedTransformer { | |
def translateNormal[T <: Exp](e: T, p1: Exp, p2: Exp): T = { | ||
e.transform{ | ||
case l: SIFLowExp => Implies(And(p1, p2)(), translateSIFLowExpComparison(l, p1, p2))() | ||
case SIFRelExp(e, i) => if(i.i == BigInt.int2bigInt(1)) translatePrime(e, p1, p2) else translateNormal(e, p1, p2) | ||
case f@DomainFuncApp("Low", args, _) => Implies(And(p1, p2)(), translateSIFLowExpComparison(SIFLowExp(args.head)(), p1, p2))() | ||
} | ||
} | ||
|
@@ -1475,7 +1483,8 @@ trait SIFExtendedTransformer { | |
def translateToUnary(e: Exp): Exp = { | ||
val transformed = e.transform{ | ||
case _: SIFLowExp => TrueLit()() | ||
case f@DomainFuncApp("Low", args, _) => TrueLit()() | ||
case DomainFuncApp("Low", args, _) => TrueLit()() | ||
case DomainFuncApp("LowEvent", Seq(), _) => TrueLit()() | ||
case Implies(_: SIFLowExp, _: SIFLowExp) => TrueLit()() | ||
case i@Implies(lhs, rhs) => Implies(lhs, translateToUnary(rhs))(i.pos, i.info, i.errT) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// 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-2020 ETH Zurich. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not 2023? |
||
|
||
package viper.silver.sif | ||
|
||
import viper.silver.ast.{ExtensionExp, IntLit, NoPosition, Position} | ||
import viper.silver.parser.{NameAnalyser, PExp, PExtender, PIntLit, PNode, PType, PTypeSubstitution, Translator, TypeChecker, TypeHelper} | ||
|
||
case class PLowExp(e: PExp)(val pos: (Position, Position) = (NoPosition, NoPosition)) extends PExtender with PExp { | ||
typ = TypeHelper.Bool | ||
|
||
override def typeSubstitutions = e.typeSubstitutions | ||
|
||
override def forceSubstitution(ts: PTypeSubstitution): Unit = { | ||
e.forceSubstitution(ts) | ||
} | ||
|
||
override def typecheck(t: TypeChecker, n: NameAnalyser, expected: PType): Option[Seq[String]] = { | ||
t.checkTopTyped(e, None) | ||
if (expected == TypeHelper.Bool || expected == TypeHelper.Impure) | ||
None | ||
else | ||
Some(Seq(s"Expected type ${expected}, but got Bool")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just making sure that all error messages intentionally do not end with a period. |
||
} | ||
|
||
override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = { | ||
t.checkTopTyped(e, None) | ||
None | ||
} | ||
|
||
override def translateExp(t: Translator): ExtensionExp = { | ||
SIFLowExp(t.exp(e))(t.liftPos(this)) | ||
} | ||
} | ||
|
||
case class PLowEventExp()(val pos: (Position, Position) = (NoPosition, NoPosition)) extends PExtender with PExp { | ||
typ = TypeHelper.Bool | ||
|
||
override def typeSubstitutions = Seq() | ||
|
||
override def forceSubstitution(ts: PTypeSubstitution): Unit = {} | ||
|
||
override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = None | ||
|
||
override def typecheck(t: TypeChecker, n: NameAnalyser, expected: PType): Option[Seq[String]] = { | ||
if (expected == TypeHelper.Bool || expected == TypeHelper.Impure) | ||
None | ||
else | ||
Some(Seq(s"Expected type ${expected}, but got Bool")) | ||
} | ||
|
||
override def translateExp(t: Translator): ExtensionExp = { | ||
SIFLowEventExp()(t.liftPos(this)) | ||
} | ||
} | ||
|
||
case class PRelExp(e: PExp, i: PIntLit)(val pos: (Position, Position) = (NoPosition, NoPosition)) extends PExtender with PExp { | ||
|
||
override def typeSubstitutions = e.typeSubstitutions | ||
|
||
override def forceSubstitution(ts: PTypeSubstitution): Unit = { | ||
e.forceSubstitution(ts) | ||
} | ||
|
||
override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = { | ||
t.checkTopTyped(e, None) | ||
t.checkTopTyped(i, Some(TypeHelper.Int)) | ||
typ = e.typ | ||
if (i.i == BigInt.int2bigInt(0) || i.i == BigInt.int2bigInt(1)) | ||
None | ||
else | ||
Some(Seq(s"Second argument of rel must be 0 or 1, but is ${i.i}")) | ||
} | ||
|
||
override def typecheck(t: TypeChecker, n: NameAnalyser, expected: PType): Option[Seq[String]] = { | ||
t.checkTopTyped(e, None) | ||
t.checkTopTyped(i, Some(TypeHelper.Int)) | ||
typ = e.typ | ||
if (i.i == BigInt.int2bigInt(0) || i.i == BigInt.int2bigInt(1)) { | ||
if (expected == e.typ) | ||
None | ||
else | ||
Some(Seq(s"Expected type ${expected}, but got ${e.typ}")) | ||
} else { | ||
Some(Seq(s"Second argument of rel must be 0 or 1, but is ${i.i}")) | ||
} | ||
} | ||
|
||
override def translateExp(t: Translator): ExtensionExp = { | ||
SIFRelExp(t.exp(e), t.exp(i).asInstanceOf[IntLit])(t.liftPos(this)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// 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-2020 ETH Zurich. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not 2023? |
||
|
||
|
||
package viper.silver.sif | ||
|
||
import fastparse._ | ||
import viper.silver.ast.Program | ||
import viper.silver.parser.{FastParser, PKeywordLang, PKw} | ||
import viper.silver.plugin.{ParserPluginTemplate, SilverPlugin} | ||
import viper.silver.parser.FastParserCompanion.whitespace | ||
|
||
import scala.annotation.unused | ||
|
||
case object PLowKeyword extends PKw("low") with PKeywordLang | ||
case object PLowEventKeyword extends PKw("lowEvent") with PKeywordLang | ||
case object PRelKeyword extends PKw("rel") with PKeywordLang | ||
|
||
|
||
class SIFPlugin(@unused reporter: viper.silver.reporter.Reporter, | ||
@unused logger: ch.qos.logback.classic.Logger, | ||
config: viper.silver.frontend.SilFrontendConfig, | ||
fp: FastParser) extends SilverPlugin with ParserPluginTemplate { | ||
|
||
import fp.{exp, integer, ParserExtension, lineCol, _file} | ||
import viper.silver.parser.FastParserCompanion.{PositionParsing, reservedKw, whitespace} | ||
|
||
def low[$: P]: P[PLowExp] = P(P(PLowKeyword) ~ "(" ~ exp ~ ")").map { case (_, e) => PLowExp(e)(_) }.pos | ||
def rel[$: P]: P[PRelExp] = P(P(PRelKeyword) ~ "(" ~ exp ~ "," ~ integer ~ ")").map { case (_, e, i) => PRelExp(e, i)(_) }.pos | ||
def lowEvent[$: P]: P[PLowEventExp] = P(P(PLowEventKeyword)).map { case (_) => PLowEventExp()(_) }.pos | ||
|
||
override def beforeParse(input: String, isImported: Boolean): String = { | ||
ParserExtension.addNewKeywords(Set(PLowKeyword, PLowEventKeyword, PRelKeyword)) | ||
ParserExtension.addNewExpAtEnd(low(_)) | ||
ParserExtension.addNewExpAtEnd(rel(_)) | ||
ParserExtension.addNewExpAtEnd(lowEvent(_)) | ||
input | ||
} | ||
|
||
override def beforeVerify(input: Program): Program = { | ||
SIFExtendedTransformer.transform(input, false) | ||
} | ||
Comment on lines
+43
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not familiar with how we deal with these things in plugins. To my knowledge, the plugin does not support magic wands or gotos jumping outside of loops. Should programs containing unsupported features cause a warning? |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intentionally commented out?