From d2c023dd110aa918c94cbcbe16102f5ce4d106db Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Fri, 31 Mar 2023 18:26:56 +0200
Subject: [PATCH 01/20] trying to add methods to thread classes
---
src/main/vct/main/stages/Transformation.scala | 4 +-
.../veymont/ParalleliseVeyMontThreads.scala | 85 +++++++++++++++++++
2 files changed, 88 insertions(+), 1 deletion(-)
create mode 100644 src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
diff --git a/src/main/vct/main/stages/Transformation.scala b/src/main/vct/main/stages/Transformation.scala
index 402360dcd7..fabab8fab9 100644
--- a/src/main/vct/main/stages/Transformation.scala
+++ b/src/main/vct/main/stages/Transformation.scala
@@ -25,6 +25,7 @@ import vct.options.Options
import vct.parsers.transform.BlameProvider
import vct.resources.Resources
import vct.result.VerificationError.SystemError
+import vct.rewrite.veymont.ParalleliseVeyMontThreads
object Transformation {
case class TransformationCheckError(pass: RewriterBuilder, errors: Seq[CheckError]) extends SystemError {
@@ -293,6 +294,7 @@ case class VeyMontTransformation(override val onBeforePassKey: Seq[(String, Veri
extends Transformation(onBeforePassKey, onAfterPassKey, Seq(
AddVeyMontAssignmentNodes,
AddVeyMontConditionNodes,
- StructureCheck
+ StructureCheck,
+ ParalleliseVeyMontThreads
))
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
new file mode 100644
index 0000000000..711f9e38d2
--- /dev/null
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -0,0 +1,85 @@
+package vct.rewrite.veymont
+
+import hre.util.ScopedStack
+import vct.col.ast.{BooleanValue, Class, ClassDeclaration, Declaration, InstanceField, InstanceMethod, Node, Program, VeyMontSeqProg, VeyMontThread}
+import vct.col.origin.{Origin, PreferredNameOrigin}
+import vct.col.rewrite.veymont.StructureCheck.VeyMontStructCheckError
+import vct.col.rewrite.{Generation, Rewriter, RewriterBuilder}
+import vct.col.typerules.CoercionUtils.o
+import vct.result.VerificationError.UserError
+import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ParalliseVeyMontThreadsError, ThreadClassOrigin}
+
+object ParalleliseVeyMontThreads extends RewriterBuilder {
+ override def key: String = "ParalleliseVeyMontThreads"
+
+ override def desc: String = "Generate classes for VeyMont threads in parallel program"
+
+ case class ParalliseVeyMontThreadsError(node : Node[_], msg: String) extends UserError {
+ override def code: String = "ParalleliseVeyMontThreadsError"
+
+ override def text: String = node.o.messageInContext(msg)
+ }
+
+ case class ThreadClassOrigin(thread: VeyMontThread[_]) extends Origin {
+ override def preferredName: String = thread.o.preferredName.toUpperCase() + "Thread"
+
+ override def context: String = thread.o.context
+
+ override def inlineContext: String = thread.o.inlineContext
+
+ override def shortPosition: String = thread.o.shortPosition
+ }
+}
+
+case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre] {
+
+ val inSeqProg: ScopedStack[VeyMontThread[Pre]] = ScopedStack()
+
+
+ override def dispatch(decl : Declaration[Pre]) : Unit = {
+ decl match {
+ case seqProg: VeyMontSeqProg[Pre] =>
+ val threadClasses = generateThreadClasses(seqProg)
+ for(tc <- threadClasses) {
+ globalDeclarations.declare(tc)
+ }
+ case other => rewriteDefault(other)
+ }
+ }
+
+
+ private def generateThreadClasses(seqProg: VeyMontSeqProg[Pre]) : Seq[Class[Post]] = {
+ val threadClasses = seqProg.threads.map { t =>
+ inSeqProg.push(t)
+ try {
+ classDeclarations.scope {
+ val threadField = new InstanceField[Post](dispatch(t.threadType), Set.empty)(t.o)
+ val methods: Seq[ClassDeclaration[Post]] = seqProg.methods.map {
+ case m: InstanceMethod[Pre] => getThreadMethod(t, m)
+ case _ => throw ParalliseVeyMontThreadsError(seqProg, "Methods of seq_program need to be of type InstanceMethod")
+ }
+ new Class[Post](
+ threadField +: methods,
+ Seq(),
+ BooleanValue(true)(t.o))(ThreadClassOrigin(t))
+ }
+ } finally {
+ inSeqProg.pop()
+ }
+ }
+ threadClasses
+ }
+
+
+ private def getThreadMethod(thread: VeyMontThread[Pre], method : InstanceMethod[Pre]): InstanceMethod[Post] = {
+ new InstanceMethod[Post](
+ dispatch(method.returnType),
+ variables.dispatch(method.args),
+ variables.dispatch(method.outArgs),
+ variables.dispatch(method.typeArgs),
+ method.body.map(dispatch),
+ dispatch(method.contract))(method.blame)(method.o)
+ }
+
+
+}
From 63b5ed684215ed4aae516c57b32bd0da5fccedc9 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Mon, 3 Apr 2023 17:19:17 +0200
Subject: [PATCH 02/20] partial code for adding channel fields
---
.../veymont-seq-progs/veymont-swap.pvl | 2 +-
.../veymont/ParalleliseVeyMontThreads.scala | 82 +++++++++++++++----
.../vct/rewrite/veymont/StructureCheck.scala | 8 ++
3 files changed, 76 insertions(+), 16 deletions(-)
diff --git a/examples/technical/veymont-seq-progs/veymont-swap.pvl b/examples/technical/veymont-seq-progs/veymont-swap.pvl
index 72e1c70988..a4d40454c8 100644
--- a/examples/technical/veymont-seq-progs/veymont-swap.pvl
+++ b/examples/technical/veymont-seq-progs/veymont-swap.pvl
@@ -28,7 +28,7 @@ seq_program SeqProgram(int x, int y) {
s1.temp = 5;
}
- void bar(int a) {}
+ //void bar(int a) {}
run {
if(s1.v == 5 && s2.v == 6) {
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 711f9e38d2..71d50038f5 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,14 +1,17 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.{BooleanValue, Class, ClassDeclaration, Declaration, InstanceField, InstanceMethod, Node, Program, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Eval, InstanceField, InstanceMethod, Loop, Node, Program, RunMethod, Scope, Statement, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
+import vct.col.ref.Ref
import vct.col.rewrite.veymont.StructureCheck.VeyMontStructCheckError
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilder}
import vct.col.typerules.CoercionUtils.o
import vct.result.VerificationError.UserError
import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ParalliseVeyMontThreadsError, ThreadClassOrigin}
+import scala.collection.immutable.Map
+
object ParalleliseVeyMontThreads extends RewriterBuilder {
override def key: String = "ParalleliseVeyMontThreads"
@@ -34,44 +37,48 @@ object ParalleliseVeyMontThreads extends RewriterBuilder {
case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre] {
val inSeqProg: ScopedStack[VeyMontThread[Pre]] = ScopedStack()
-
+ val inSeqThreadMap : ScopedStack[Map[VeyMontThread[Pre],InstanceField[Post]]] = ScopedStack()
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
- val threadClasses = generateThreadClasses(seqProg)
- for(tc <- threadClasses) {
- globalDeclarations.declare(tc)
+ val threadFieldMap = generateThreadFields(seqProg)
+ inSeqThreadMap.having(threadFieldMap) {
+ val threadClasses = generateThreadClasses(seqProg)
+ for (tc <- threadClasses) {
+ globalDeclarations.declare(tc)
+ }
}
+ case t: VeyMontThread[Pre] => //sucessor is threadField in threadClass constructed above
case other => rewriteDefault(other)
}
}
+ private def generateThreadFields(seqProg: VeyMontSeqProg[Pre]) : Map[VeyMontThread[Pre],InstanceField[Post]] =
+ seqProg.threads.map { thread => (thread -> new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)) }.toMap
private def generateThreadClasses(seqProg: VeyMontSeqProg[Pre]) : Seq[Class[Post]] = {
- val threadClasses = seqProg.threads.map { t =>
- inSeqProg.push(t)
- try {
+ val threadClasses = seqProg.threads.map { thread =>
+ inSeqProg.having(thread) {
+ val threadFieldMap = inSeqThreadMap.top
classDeclarations.scope {
- val threadField = new InstanceField[Post](dispatch(t.threadType), Set.empty)(t.o)
+ val channelFields = getChannelFields(collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg))
val methods: Seq[ClassDeclaration[Post]] = seqProg.methods.map {
- case m: InstanceMethod[Pre] => getThreadMethod(t, m)
+ case m: InstanceMethod[Pre] => getThreadMethod(m)
case _ => throw ParalliseVeyMontThreadsError(seqProg, "Methods of seq_program need to be of type InstanceMethod")
}
new Class[Post](
- threadField +: methods,
+ (threadFieldMap(thread) +: channelFields) ++ methods,
Seq(),
- BooleanValue(true)(t.o))(ThreadClassOrigin(t))
+ BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
}
- } finally {
- inSeqProg.pop()
}
}
threadClasses
}
- private def getThreadMethod(thread: VeyMontThread[Pre], method : InstanceMethod[Pre]): InstanceMethod[Post] = {
+ private def getThreadMethod(method : InstanceMethod[Pre]): InstanceMethod[Post] = {
new InstanceMethod[Post](
dispatch(method.returnType),
variables.dispatch(method.args),
@@ -81,5 +88,50 @@ case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre]
dispatch(method.contract))(method.blame)(method.o)
}
+ private def getChannelFields(chanDescr : Seq[(Type[Pre], String,Statement[Pre])]): Seq[InstanceField[Post]] = Seq.empty
+ //InstanceField[Post](dispatch(ChannelClassOfRightType), Set.empty)(ChannelOrigin)
+
+ private def collectChannelsFromRun(seqProg : VeyMontSeqProg[Pre]) =
+ seqProg.runMethod match {
+ case r: RunMethod[Pre] => getChannelsFromBody(r.body, r)
+ case other => throw ParalliseVeyMontThreadsError(other, "seq_program run method expected")
+ }
+
+ private def collectChannelsFromMethods(seqProg: VeyMontSeqProg[Pre]) =
+ seqProg.methods.flatMap {
+ case m: InstanceMethod[Pre] => getChannelsFromBody(m.body, m)
+ case other => throw ParalliseVeyMontThreadsError(other, "seq_program method expected")
+ }
+ private def getChannelsFromBody(body: Option[Statement[Pre]], method: ClassDeclaration[Pre]) = {
+ body match {
+ case None => throw ParalliseVeyMontThreadsError(method, "Method in seq_program needs to have non-empty body")
+ case Some(b) => getChannelNamesAndTypes(b)
+ }
+ }
+
+ private def getChannelNamesAndTypes(s : Statement[Pre]): Seq[(Type[Pre], String,Statement[Pre])] = {
+ s.collect{case e@VeyMontCommExpression(recv,sender,assign) =>
+ (recv.decl.threadType,recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel",e)}
+ }
+/*
+ override def dispatch(st : Statement[Pre]) : Statement[Post] = {
+ if (inSeqProg.nonEmpty) {
+ val thread = inSeqProg.top
+ val threadFieldMap = inSeqThreadMap.top
+ st match {
+ case VeyMontCommExpression(recv,sender,assign) => dispatch(assign)
+ case VeyMontAssignExpression(_, _) => rewriteDefault(st)
+ case Assign(_, _) => rewriteDefault(st)
+ case Branch(_) => rewriteDefault(st)
+ case Loop(_, _, _, _, _) => rewriteDefault(st)
+ case Scope(_, _) => rewriteDefault(st)
+ case Block(_) => rewriteDefault(st)
+ case Eval(expr) => dispatch(expr)
+ case Assert(_) => rewriteDefault(st)
+ case _ => throw VeyMontStructCheckError(st, "Statement not allowed in seq_program")
+ }
+ } else rewriteDefault(st)
+ }
+*/
}
diff --git a/src/rewrite/vct/rewrite/veymont/StructureCheck.scala b/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
index 897517f779..3ec673277d 100644
--- a/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
+++ b/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
@@ -30,6 +30,14 @@ case class StructureCheck[Pre <: Generation]() extends Rewriter[Pre] {
case dcl: VeyMontSeqProg[Pre] => inSeqProg.having(()) {
rewriteDefault(dcl)
}
+ case m: InstanceMethod[Pre] =>
+ if (inSeqProg.nonEmpty && m.args.nonEmpty)
+ throw VeyMontStructCheckError(m, "Methods in seq_program cannot have any arguments!")
+ else rewriteDefault(decl)
+ case r: RunMethod[Pre] =>
+ if(r.body.isEmpty)
+ throw VeyMontStructCheckError(r, "Method run in seq_program needs to have a body!")
+ else rewriteDefault(decl)
case _ => rewriteDefault(decl)
}
From 5353014bddb660dcfad0e80de5bbe22fbe5d1380 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 4 Apr 2023 17:12:17 +0200
Subject: [PATCH 03/20] importing Channel class
---
res/universal/res/include/IntegerChannel.java | 12 +++++-------
src/main/vct/importer/Util.scala | 19 +++++++++++++++++--
src/main/vct/main/stages/Transformation.scala | 13 ++++++++-----
src/main/vct/options/Options.scala | 2 ++
src/main/vct/resources/Resources.scala | 1 +
5 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/res/universal/res/include/IntegerChannel.java b/res/universal/res/include/IntegerChannel.java
index cabccaf06a..18d125e501 100644
--- a/res/universal/res/include/IntegerChannel.java
+++ b/res/universal/res/include/IntegerChannel.java
@@ -1,16 +1,14 @@
-package include;
-
-public final class IntegerChannel {
+public final class Channel {
private boolean transfering;
- private int exchangeValue;
+ private MessageType exchangeValue;
- public IntegerChannel() {
+ public Channel() {
transfering = true;
}
- public synchronized void writeValue(int v) {
+ public synchronized void writeValue(MessageType v) {
while (!transfering) {
try {
wait();
@@ -23,7 +21,7 @@ public synchronized void writeValue(int v) {
notify();
}
- public synchronized int readValue() {
+ public synchronized MessageType readValue() {
while (transfering) {
try {
wait();
diff --git a/src/main/vct/importer/Util.scala b/src/main/vct/importer/Util.scala
index ab582c2fd0..780eadd871 100644
--- a/src/main/vct/importer/Util.scala
+++ b/src/main/vct/importer/Util.scala
@@ -1,11 +1,11 @@
package vct.importer
import hre.io.Readable
-import vct.col.ast.Program
+import vct.col.ast.{JavaClass, JavaNamespace, Program}
import vct.col.origin.{Blame, VerificationFailure}
import vct.col.rewrite.Disambiguate
import vct.main.stages.Resolution
-import vct.parsers.ColPVLParser
+import vct.parsers.{ColJavaParser, ColPVLParser}
import vct.parsers.transform.{ConstantBlameProvider, ReadableOriginProvider}
import vct.result.VerificationError.UserError
@@ -27,4 +27,19 @@ case object Util {
val unambiguousProgram: Program[_] = Disambiguate().dispatch(context.tasks.head.program)
unambiguousProgram.asInstanceOf[Program[G]]
}
+
+ case class JavaLoadError(error: String) extends UserError {
+ override def code: String = "JavaClassLoadError"
+
+ override def text: String = error
+ }
+
+ def loadJavaClass[G](readable: Readable): JavaClass[G] =
+ ColJavaParser(ReadableOriginProvider(readable), ConstantBlameProvider(LibraryFileBlame)).parse(readable).decls match {
+ case Seq(javaNamespace: JavaNamespace[G]) => javaNamespace.declarations match {
+ case Seq(javaClass: JavaClass[G]) => javaClass
+ case seq => throw JavaLoadError("Expected to load exactly one Java class but found " + seq.size)
+ }
+ case seq => throw JavaLoadError("Expected to load exactly one Java name space but found " + seq.size)
+ }
}
diff --git a/src/main/vct/main/stages/Transformation.scala b/src/main/vct/main/stages/Transformation.scala
index fabab8fab9..f45e23c8a6 100644
--- a/src/main/vct/main/stages/Transformation.scala
+++ b/src/main/vct/main/stages/Transformation.scala
@@ -4,7 +4,7 @@ import com.typesafe.scalalogging.LazyLogging
import hre.debug.TimeTravel
import hre.progress.Progress
import hre.stages.Stage
-import vct.col.ast.{Deserialize, IterationContract, Procedure, Program, RunMethod, Serialize, SimplificationRule, Verification, VerificationContext}
+import vct.col.ast.{Deserialize, IterationContract, JavaClass, Procedure, Program, RunMethod, Serialize, SimplificationRule, Verification, VerificationContext}
import vct.col.check.CheckError
import vct.col.feature
import vct.col.feature.Feature
@@ -25,7 +25,7 @@ import vct.options.Options
import vct.parsers.transform.BlameProvider
import vct.resources.Resources
import vct.result.VerificationError.SystemError
-import vct.rewrite.veymont.ParalleliseVeyMontThreads
+import vct.rewrite.veymont.{ChannelClassGenerator, ParalleliseVeyMontThreads}
object Transformation {
case class TransformationCheckError(pass: RewriterBuilder, errors: Seq[CheckError]) extends SystemError {
@@ -73,7 +73,8 @@ object Transformation {
case Backend.Silicon | Backend.Carbon =>
VeyMontTransformation(
onBeforePassKey = writeOutFunctions(options.outputBeforePass),
- onAfterPassKey = writeOutFunctions(options.outputAfterPass)
+ onAfterPassKey = writeOutFunctions(options.outputAfterPass),
+ channelClass = Util.loadJavaClass(options.veymontChannel),
)
}
}
@@ -290,11 +291,13 @@ case class SilverTransformation
))
case class VeyMontTransformation(override val onBeforePassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil,
- override val onAfterPassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil)
+ override val onAfterPassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil,
+ val channelClass: JavaClass[_])
extends Transformation(onBeforePassKey, onAfterPassKey, Seq(
AddVeyMontAssignmentNodes,
AddVeyMontConditionNodes,
StructureCheck,
- ParalleliseVeyMontThreads
+ ParalleliseVeyMontThreads,
+ ChannelClassGenerator.withArg(channelClass)
))
diff --git a/src/main/vct/options/Options.scala b/src/main/vct/options/Options.scala
index c13812c03c..2f34e41df0 100644
--- a/src/main/vct/options/Options.scala
+++ b/src/main/vct/options/Options.scala
@@ -6,6 +6,7 @@ import vct.main.BuildInfo
import vct.main.stages.Parsing.Language
import vct.options.types.{Backend, ClassPathEntry, Mode, PathOrStd, ReadLanguage, Verbosity}
import vct.resources.Resources
+import vct.resources.Resources.getVeymontChannel
import java.nio.file.{Path, Paths}
import scala.collection.mutable
@@ -379,6 +380,7 @@ case class Options
// VeyMont options
veymontOutput: PathOrStd = null, // required
+ veymontChannel: PathOrStd = PathOrStd.Path(getVeymontChannel),
// VeSUV options
vesuvOutput: PathOrStd = null,
diff --git a/src/main/vct/resources/Resources.scala b/src/main/vct/resources/Resources.scala
index 9507218be9..3ac0480d5e 100644
--- a/src/main/vct/resources/Resources.scala
+++ b/src/main/vct/resources/Resources.scala
@@ -17,4 +17,5 @@ case object Resources {
def getJrePath: Path = getResource("/jdk")
def getCcPath: Path = Paths.get("clang")
def getSystemCConfig: Path = getResource("/systemc/config")
+ def getVeymontChannel: Path = getResource("/include/IntegerChannel.java")
}
From 1499e9363f2b042fd156fe01d7437a22b7135f88 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Wed, 31 May 2023 17:10:42 +0200
Subject: [PATCH 04/20] rewriting channel classes gives NoSuchElementException
---
src/main/vct/main/stages/Transformation.scala | 3 +-
.../veymont/ChannelClassGenerator.scala | 21 +++++
.../veymont/ParalleliseVeyMontThreads.scala | 88 ++++++++++++-------
3 files changed, 79 insertions(+), 33 deletions(-)
create mode 100644 src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala
diff --git a/src/main/vct/main/stages/Transformation.scala b/src/main/vct/main/stages/Transformation.scala
index f45e23c8a6..be200d3c06 100644
--- a/src/main/vct/main/stages/Transformation.scala
+++ b/src/main/vct/main/stages/Transformation.scala
@@ -297,7 +297,6 @@ case class VeyMontTransformation(override val onBeforePassKey: Seq[(String, Veri
AddVeyMontAssignmentNodes,
AddVeyMontConditionNodes,
StructureCheck,
- ParalleliseVeyMontThreads,
- ChannelClassGenerator.withArg(channelClass)
+ ParalleliseVeyMontThreads.withArg(channelClass),
))
diff --git a/src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala b/src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala
new file mode 100644
index 0000000000..71f26d53d4
--- /dev/null
+++ b/src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala
@@ -0,0 +1,21 @@
+package vct.rewrite.veymont
+
+import vct.col.ast.Type
+import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg}
+
+object ChannelClassGenerator extends RewriterBuilderArg[Type[_]] {
+ override def key: String = "ChannelClassGenerator"
+
+ override def desc: String = "Generate classes for channels of a VeyMont seq_program"
+
+}
+
+case class ChannelClassGenerator [Pre <: Generation](channelType: Type[_]) extends Rewriter[Pre] {
+
+ override def dispatch(t: Type[Pre]) : Type[Post] = {
+ if(t.o.preferredName == "MessageType")
+ dispatch(channelType.asInstanceOf[Type[Pre]])
+ else rewriteDefault(t)
+ }
+
+}
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 71d50038f5..7fc3575136 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,18 +1,14 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Eval, InstanceField, InstanceMethod, Loop, Node, Program, RunMethod, Scope, Statement, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.RewriteHelpers.RewriteJavaClass
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Eval, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, Node, Program, RunMethod, Scope, Statement, TClass, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
-import vct.col.ref.Ref
-import vct.col.rewrite.veymont.StructureCheck.VeyMontStructCheckError
-import vct.col.rewrite.{Generation, Rewriter, RewriterBuilder}
-import vct.col.typerules.CoercionUtils.o
+import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg}
import vct.result.VerificationError.UserError
-import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ParalliseVeyMontThreadsError, ThreadClassOrigin}
+import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelClassOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
-import scala.collection.immutable.Map
-
-object ParalleliseVeyMontThreads extends RewriterBuilder {
+object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
override def key: String = "ParalleliseVeyMontThreads"
override def desc: String = "Generate classes for VeyMont threads in parallel program"
@@ -32,9 +28,19 @@ object ParalleliseVeyMontThreads extends RewriterBuilder {
override def shortPosition: String = thread.o.shortPosition
}
+
+ case class ChannelClassOrigin(channelName: String, assign: Statement[_]) extends Origin {
+ override def preferredName: String = channelName
+
+ override def context: String = assign.o.context
+
+ override def inlineContext: String = assign.o.inlineContext
+
+ override def shortPosition: String = assign.o.shortPosition
+ }
}
-case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre] {
+case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] {
val inSeqProg: ScopedStack[VeyMontThread[Pre]] = ScopedStack()
val inSeqThreadMap : ScopedStack[Map[VeyMontThread[Pre],InstanceField[Post]]] = ScopedStack()
@@ -43,8 +49,14 @@ case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre]
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
val threadFieldMap = generateThreadFields(seqProg)
+ val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
+ val channelClasses = generateChannelClasses(channelInfo)
+ for (cc <- channelClasses.values) {
+ globalDeclarations.declare(cc)
+ }
+ val channelFields = getChannelFields(channelInfo, channelClasses)
inSeqThreadMap.having(threadFieldMap) {
- val threadClasses = generateThreadClasses(seqProg)
+ val threadClasses = generateThreadClasses(seqProg, channelFields)
for (tc <- threadClasses) {
globalDeclarations.declare(tc)
}
@@ -57,12 +69,11 @@ case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre]
private def generateThreadFields(seqProg: VeyMontSeqProg[Pre]) : Map[VeyMontThread[Pre],InstanceField[Post]] =
seqProg.threads.map { thread => (thread -> new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)) }.toMap
- private def generateThreadClasses(seqProg: VeyMontSeqProg[Pre]) : Seq[Class[Post]] = {
+ private def generateThreadClasses(seqProg: VeyMontSeqProg[Pre], channelFields: Seq[InstanceField[Post]]) : Seq[Class[Post]] = {
val threadClasses = seqProg.threads.map { thread =>
inSeqProg.having(thread) {
val threadFieldMap = inSeqThreadMap.top
classDeclarations.scope {
- val channelFields = getChannelFields(collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg))
val methods: Seq[ClassDeclaration[Post]] = seqProg.methods.map {
case m: InstanceMethod[Pre] => getThreadMethod(m)
case _ => throw ParalliseVeyMontThreadsError(seqProg, "Methods of seq_program need to be of type InstanceMethod")
@@ -77,21 +88,24 @@ case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre]
threadClasses
}
-
- private def getThreadMethod(method : InstanceMethod[Pre]): InstanceMethod[Post] = {
- new InstanceMethod[Post](
- dispatch(method.returnType),
- variables.dispatch(method.args),
- variables.dispatch(method.outArgs),
- variables.dispatch(method.typeArgs),
- method.body.map(dispatch),
- dispatch(method.contract))(method.blame)(method.o)
+ private def getChannelFields(channelInfo: Seq[(Type[Pre], String, Statement[Pre])], channelClasses: Map[Type[Pre],JavaClass[Post]]): Seq[InstanceField[Post]] = {
+ channelInfo.map { case (chanType, chanName, assign) =>
+ new InstanceField[Post](JavaTClass(channelClasses(chanType).ref,Seq.empty), Set.empty)(ChannelClassOrigin(chanName,assign)) }
}
- private def getChannelFields(chanDescr : Seq[(Type[Pre], String,Statement[Pre])]): Seq[InstanceField[Post]] = Seq.empty
- //InstanceField[Post](dispatch(ChannelClassOfRightType), Set.empty)(ChannelOrigin)
+ private def generateChannelClasses(channelInfo: Seq[(Type[Pre], String, Statement[Pre])]) : Map[Type[Pre],JavaClass[Post]] = {
+ val channelTypes = channelInfo.map(_._1).toSet
+ channelTypes.map(channelType =>
+ channelType -> {
+ val chanClassPre = channelClass.asInstanceOf[JavaClass[Pre]]
+ new RewriteJavaClass[Pre, Post](chanClassPre)(new ChannelClassGenerator[Pre](channelType)).rewrite(decls = classDeclarations.collect {
+ chanClassPre.decls.foreach(d => dispatch(d))
+ }._1)
+ }
+ ).toMap
+ }//new ChannelClassGenerator(channelType).globalDeclarations.dispatch(channelClass.unsafeTransmuteGeneration[JavaClass, Pre])
- private def collectChannelsFromRun(seqProg : VeyMontSeqProg[Pre]) =
+ private def collectChannelsFromRun(seqProg: VeyMontSeqProg[Pre]) =
seqProg.runMethod match {
case r: RunMethod[Pre] => getChannelsFromBody(r.body, r)
case other => throw ParalliseVeyMontThreadsError(other, "seq_program run method expected")
@@ -99,9 +113,9 @@ case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre]
private def collectChannelsFromMethods(seqProg: VeyMontSeqProg[Pre]) =
seqProg.methods.flatMap {
- case m: InstanceMethod[Pre] => getChannelsFromBody(m.body, m)
- case other => throw ParalliseVeyMontThreadsError(other, "seq_program method expected")
- }
+ case m: InstanceMethod[Pre] => getChannelsFromBody(m.body, m)
+ case other => throw ParalliseVeyMontThreadsError(other, "seq_program method expected")
+ }
private def getChannelsFromBody(body: Option[Statement[Pre]], method: ClassDeclaration[Pre]) = {
body match {
@@ -110,10 +124,22 @@ case class ParalleliseVeyMontThreads[Pre <: Generation]() extends Rewriter[Pre]
}
}
- private def getChannelNamesAndTypes(s : Statement[Pre]): Seq[(Type[Pre], String,Statement[Pre])] = {
- s.collect{case e@VeyMontCommExpression(recv,sender,assign) =>
- (recv.decl.threadType,recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel",e)}
+ private def getChannelNamesAndTypes(s: Statement[Pre]): Seq[(Type[Pre], String, Statement[Pre])] = {
+ s.collect { case e@VeyMontCommExpression(recv, sender, assign) =>
+ (recv.decl.threadType, recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel", e)
+ }
}
+
+ private def getThreadMethod(method : InstanceMethod[Pre]): InstanceMethod[Post] = {
+ new InstanceMethod[Post](
+ dispatch(method.returnType),
+ variables.dispatch(method.args),
+ variables.dispatch(method.outArgs),
+ variables.dispatch(method.typeArgs),
+ method.body.map(dispatch),
+ dispatch(method.contract))(method.blame)(method.o)
+ }
+
/*
override def dispatch(st : Statement[Pre]) : Statement[Post] = {
if (inSeqProg.nonEmpty) {
From 7f20f3f73e32f67b426714a3d5395e0e2edc1a28 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Wed, 31 May 2023 17:29:09 +0200
Subject: [PATCH 05/20] NoSuchElementException resolved
---
.../vct/rewrite/veymont/ParalleliseVeyMontThreads.scala | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 7fc3575136..5b3f3b1aae 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -51,9 +51,6 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
val threadFieldMap = generateThreadFields(seqProg)
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
val channelClasses = generateChannelClasses(channelInfo)
- for (cc <- channelClasses.values) {
- globalDeclarations.declare(cc)
- }
val channelFields = getChannelFields(channelInfo, channelClasses)
inSeqThreadMap.having(threadFieldMap) {
val threadClasses = generateThreadClasses(seqProg, channelFields)
From c67dc4ca6ca7a370b56406eee9ac13b4cc759af8 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Thu, 1 Jun 2023 12:29:58 +0200
Subject: [PATCH 06/20] running without errors but no thread classes printed
---
.../vct/rewrite/veymont/ChannelInfo.scala | 8 ++
.../veymont/ParalleliseVeyMontThreads.scala | 84 +++++++++++--------
.../veymont/ThreadBuildingBlocks.scala | 9 ++
3 files changed, 67 insertions(+), 34 deletions(-)
create mode 100644 src/rewrite/vct/rewrite/veymont/ChannelInfo.scala
create mode 100644 src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
diff --git a/src/rewrite/vct/rewrite/veymont/ChannelInfo.scala b/src/rewrite/vct/rewrite/veymont/ChannelInfo.scala
new file mode 100644
index 0000000000..294b180630
--- /dev/null
+++ b/src/rewrite/vct/rewrite/veymont/ChannelInfo.scala
@@ -0,0 +1,8 @@
+package vct.rewrite.veymont
+
+import vct.col.ast.{Type, VeyMontCommExpression}
+import vct.col.rewrite.Generation
+
+class ChannelInfo[Pre <: Generation](val comExpr: VeyMontCommExpression[Pre], val channelType: Type[Pre], val channelName: String) {
+
+}
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 5b3f3b1aae..422e9a0f55 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -4,6 +4,7 @@ import hre.util.ScopedStack
import vct.col.ast.RewriteHelpers.RewriteJavaClass
import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Eval, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, Node, Program, RunMethod, Scope, Statement, TClass, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
+import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg}
import vct.result.VerificationError.UserError
import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelClassOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
@@ -43,55 +44,64 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] {
val inSeqProg: ScopedStack[VeyMontThread[Pre]] = ScopedStack()
- val inSeqThreadMap : ScopedStack[Map[VeyMontThread[Pre],InstanceField[Post]]] = ScopedStack()
+ val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
- val threadFieldMap = generateThreadFields(seqProg)
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
val channelClasses = generateChannelClasses(channelInfo)
val channelFields = getChannelFields(channelInfo, channelClasses)
- inSeqThreadMap.having(threadFieldMap) {
- val threadClasses = generateThreadClasses(seqProg, channelFields)
- for (tc <- threadClasses) {
- globalDeclarations.declare(tc)
- }
+ threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods,channelFields)) {
+ seqProg.threads.foreach(t =>
+ inSeqProg.having(t) {
+ dispatch(t)
+ })
}
- case t: VeyMontThread[Pre] => //sucessor is threadField in threadClass constructed above
+ case thread: VeyMontThread[Pre] => {
+ if(threadBuildingBlocks.nonEmpty) {
+ val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
+ val threadRes: ThreadBuildingBlocks[Pre] = threadBuildingBlocks.top
+ val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
+ _.decl == thread
+ }.values.toSeq
+ val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
+ val threadMethods: Seq[ClassDeclaration[Post]] = threadRes.methods.map(getThreadMethodFromDecl(thread))
+ classDeclarations.scope {
+ //classDeclarations.collect {
+ val threadClass = new Class[Post](
+ (threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods),
+ Seq(),
+ BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
+ //globalDeclarations.declare(threadClass)
+ }
+ } else rewriteDefault(thread)
+ }
case other => rewriteDefault(other)
}
}
- private def generateThreadFields(seqProg: VeyMontSeqProg[Pre]) : Map[VeyMontThread[Pre],InstanceField[Post]] =
- seqProg.threads.map { thread => (thread -> new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)) }.toMap
+ private def getThreadMethodFromDecl(thread: VeyMontThread[Pre])(decl: ClassDeclaration[Pre]): InstanceMethod[Post] = decl match {
+ case m: InstanceMethod[Pre] => getThreadMethod(m)
+ case _ => throw ParalliseVeyMontThreadsError(thread, "Methods of seq_program need to be of type InstanceMethod")
+ }
- private def generateThreadClasses(seqProg: VeyMontSeqProg[Pre], channelFields: Seq[InstanceField[Post]]) : Seq[Class[Post]] = {
- val threadClasses = seqProg.threads.map { thread =>
- inSeqProg.having(thread) {
- val threadFieldMap = inSeqThreadMap.top
- classDeclarations.scope {
- val methods: Seq[ClassDeclaration[Post]] = seqProg.methods.map {
- case m: InstanceMethod[Pre] => getThreadMethod(m)
- case _ => throw ParalliseVeyMontThreadsError(seqProg, "Methods of seq_program need to be of type InstanceMethod")
- }
- new Class[Post](
- (threadFieldMap(thread) +: channelFields) ++ methods,
- Seq(),
- BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
- }
- }
- }
- threadClasses
+ private def getThreadRunFromDecl(thread: VeyMontThread[Pre], decl: ClassDeclaration[Pre]): RunMethod[Post] = decl match {
+ case m: RunMethod[Pre] => getThreadRunMethod(m)
+ case _ => throw ParalliseVeyMontThreadsError(thread, "RunMethod expected in seq_program")
}
- private def getChannelFields(channelInfo: Seq[(Type[Pre], String, Statement[Pre])], channelClasses: Map[Type[Pre],JavaClass[Post]]): Seq[InstanceField[Post]] = {
- channelInfo.map { case (chanType, chanName, assign) =>
- new InstanceField[Post](JavaTClass(channelClasses(chanType).ref,Seq.empty), Set.empty)(ChannelClassOrigin(chanName,assign)) }
+ private def generateThreadFields(seqProg: VeyMontSeqProg[Pre]) : Map[VeyMontThread[Pre],InstanceField[Post]] =
+ seqProg.threads.map { thread => (thread -> new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)) }.toMap
+
+ private def getChannelFields(channelInfo: Seq[ChannelInfo[Pre]], channelClasses: Map[Type[Pre],JavaClass[Post]]): Map[Ref[Pre, VeyMontThread[Pre]],InstanceField[Post]] = {
+ channelInfo.flatMap { chanInfo =>
+ val chanField = new InstanceField[Post](JavaTClass(channelClasses(chanInfo.channelType).ref,Seq.empty), Set.empty)(ChannelClassOrigin(chanInfo.channelName,chanInfo.comExpr.assign))
+ Set((chanInfo.comExpr.receiver, chanField), (chanInfo.comExpr.sender, chanField)) }.toMap
}
- private def generateChannelClasses(channelInfo: Seq[(Type[Pre], String, Statement[Pre])]) : Map[Type[Pre],JavaClass[Post]] = {
- val channelTypes = channelInfo.map(_._1).toSet
+ private def generateChannelClasses(channelInfo: Seq[ChannelInfo[Pre]]) : Map[Type[Pre],JavaClass[Post]] = {
+ val channelTypes = channelInfo.map(_.channelType).toSet
channelTypes.map(channelType =>
channelType -> {
val chanClassPre = channelClass.asInstanceOf[JavaClass[Pre]]
@@ -121,9 +131,9 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}
}
- private def getChannelNamesAndTypes(s: Statement[Pre]): Seq[(Type[Pre], String, Statement[Pre])] = {
+ private def getChannelNamesAndTypes(s: Statement[Pre]): Seq[ChannelInfo[Pre]] = {
s.collect { case e@VeyMontCommExpression(recv, sender, assign) =>
- (recv.decl.threadType, recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel", e)
+ new ChannelInfo(e,recv.decl.threadType, recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel")
}
}
@@ -137,6 +147,12 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
dispatch(method.contract))(method.blame)(method.o)
}
+ private def getThreadRunMethod(run: RunMethod[Pre]): RunMethod[Post] = {
+ new RunMethod[Post](
+ run.body.map(dispatch),
+ dispatch(run.contract))(run.blame)(run.o)
+ }
+
/*
override def dispatch(st : Statement[Pre]) : Statement[Post] = {
if (inSeqProg.nonEmpty) {
diff --git a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
new file mode 100644
index 0000000000..1a91662616
--- /dev/null
+++ b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
@@ -0,0 +1,9 @@
+package vct.rewrite.veymont
+
+import vct.col.ast.{ClassDeclaration, InstanceField, Statement, VeyMontThread}
+import vct.col.ref.Ref
+import vct.col.rewrite.{Generation, Rewritten}
+
+class ThreadBuildingBlocks[Pre <: Generation](val runMethod: ClassDeclaration[Pre], val methods: Seq[ClassDeclaration[Pre]], val channelFields: Map[Ref[Pre,VeyMontThread[Pre]],InstanceField[Rewritten[Pre]]]) {
+
+}
From 05f14d6ccea3039664b4ee73869d17f74ef5abca Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 6 Jun 2023 13:45:51 +0200
Subject: [PATCH 07/20] edit
---
.../vct/rewrite/veymont/ParalleliseVeyMontThreads.scala | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 422e9a0f55..11ddd58b47 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -59,7 +59,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
})
}
case thread: VeyMontThread[Pre] => {
- if(threadBuildingBlocks.nonEmpty) {
+ if(threadBuildingBlocks.nonEmpty && inSeqProg.nonEmpty && inSeqProg.top == thread) {
val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
val threadRes: ThreadBuildingBlocks[Pre] = threadBuildingBlocks.top
val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
@@ -73,7 +73,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
(threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods),
Seq(),
BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
- //globalDeclarations.declare(threadClass)
+ globalDeclarations.declare(threadClass)
}
} else rewriteDefault(thread)
}
From 563d310a714476469274cc13ef030bf2a0c666ac Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 6 Jun 2023 17:20:50 +0200
Subject: [PATCH 08/20] busy fixing refs but not working yet
---
.../veymont/ParalleliseVeyMontThreads.scala | 79 +++++++++++--------
.../veymont/ThreadBuildingBlocks.scala | 6 +-
2 files changed, 53 insertions(+), 32 deletions(-)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 11ddd58b47..617fde1457 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,11 +1,12 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.RewriteHelpers.RewriteJavaClass
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Eval, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, Node, Program, RunMethod, Scope, Statement, TClass, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, Node, Program, RunMethod, Scope, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg}
+import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelClassOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
@@ -43,25 +44,24 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] {
- val inSeqProg: ScopedStack[VeyMontThread[Pre]] = ScopedStack()
+ val inSeqProg: ScopedStack[Map[VeyMontThread[Pre],InstanceField[Post]]] = ScopedStack()
val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
+ val seqProgSucc: SuccessionMap[VeyMontThread[Pre],Class[Post]] = SuccessionMap()
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
+ val threadFieldMap = seqProg.threads.map(t => (t,new InstanceField[Post](dispatch(t.threadType), Set.empty)(t.o))).toMap
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
val channelClasses = generateChannelClasses(channelInfo)
val channelFields = getChannelFields(channelInfo, channelClasses)
- threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods,channelFields)) {
- seqProg.threads.foreach(t =>
- inSeqProg.having(t) {
- dispatch(t)
- })
+ threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods,threadFieldMap,channelFields)) {
+ seqProg.threads.foreach(dispatch)
}
case thread: VeyMontThread[Pre] => {
- if(threadBuildingBlocks.nonEmpty && inSeqProg.nonEmpty && inSeqProg.top == thread) {
- val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
+ if(threadBuildingBlocks.nonEmpty) {
val threadRes: ThreadBuildingBlocks[Pre] = threadBuildingBlocks.top
+ val threadField = threadRes.threadFieldMap(thread)
val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
_.decl == thread
}.values.toSeq
@@ -74,9 +74,12 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
Seq(),
BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
globalDeclarations.declare(threadClass)
+ seqProgSucc.update(thread,threadClass)
}
} else rewriteDefault(thread)
}
+ //case m: InstanceMethod[Pre] => getThreadMethod(m)
+ //case r: RunMethod[Pre] => getThreadRunMethod(r)
case other => rewriteDefault(other)
}
}
@@ -91,9 +94,6 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case _ => throw ParalliseVeyMontThreadsError(thread, "RunMethod expected in seq_program")
}
- private def generateThreadFields(seqProg: VeyMontSeqProg[Pre]) : Map[VeyMontThread[Pre],InstanceField[Post]] =
- seqProg.threads.map { thread => (thread -> new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)) }.toMap
-
private def getChannelFields(channelInfo: Seq[ChannelInfo[Pre]], channelClasses: Map[Type[Pre],JavaClass[Post]]): Map[Ref[Pre, VeyMontThread[Pre]],InstanceField[Post]] = {
channelInfo.flatMap { chanInfo =>
val chanField = new InstanceField[Post](JavaTClass(channelClasses(chanInfo.channelType).ref,Seq.empty), Set.empty)(ChannelClassOrigin(chanInfo.channelName,chanInfo.comExpr.assign))
@@ -153,24 +153,41 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
dispatch(run.contract))(run.blame)(run.o)
}
-/*
- override def dispatch(st : Statement[Pre]) : Statement[Post] = {
- if (inSeqProg.nonEmpty) {
- val thread = inSeqProg.top
- val threadFieldMap = inSeqThreadMap.top
- st match {
- case VeyMontCommExpression(recv,sender,assign) => dispatch(assign)
- case VeyMontAssignExpression(_, _) => rewriteDefault(st)
- case Assign(_, _) => rewriteDefault(st)
- case Branch(_) => rewriteDefault(st)
- case Loop(_, _, _, _, _) => rewriteDefault(st)
- case Scope(_, _) => rewriteDefault(st)
- case Block(_) => rewriteDefault(st)
- case Eval(expr) => dispatch(expr)
- case Assert(_) => rewriteDefault(st)
- case _ => throw VeyMontStructCheckError(st, "Statement not allowed in seq_program")
+ override def dispatch(node: Expr[Pre]): Expr[Post] = {
+ if(threadBuildingBlocks.nonEmpty) {
+ val threadFieldMap = threadBuildingBlocks.top.threadFieldMap
+ node match {
+ case d: Deref[Pre] => d.obj match {
+ case t: DerefVeyMontThread[Pre] =>
+ threadFieldMap.find{case (thread,_) => t.ref.decl == thread} match {
+ case Some((thread,threadField)) =>
+ d.rewrite(
+ obj = Deref(ThisObject(seqProgSucc.ref[Post, Class[Post]](thread))(thread.o), threadField.ref[InstanceField[Post]])(null)(d.o)
+ )
+ case _ => rewriteDefault(node)
+ }
+ }
+ case _ => rewriteDefault(node)
}
- } else rewriteDefault(st)
+ } else rewriteDefault(node)
}
-*/
+
+
+ override def dispatch(st : Statement[Pre]) : Statement[Post] = {
+ if (inSeqProg.nonEmpty) {
+ st match {
+ case VeyMontCommExpression(recv,sender,assign) => rewriteDefault(assign)
+ case VeyMontAssignExpression(_, _) => rewriteDefault(st)
+ case Assign(_, _) => rewriteDefault(st)
+ case Branch(_) => rewriteDefault(st)
+ case Loop(_, _, _, _, _) => rewriteDefault(st)
+ case Scope(_, _) => rewriteDefault(st)
+ case Block(_) => rewriteDefault(st)
+ case Eval(expr) => Eval(rewriteDefault(expr))(st.o)
+ case Assert(_) => rewriteDefault(st)
+ case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
+ }
+ } else rewriteDefault(st)
+ }
+
}
diff --git a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
index 1a91662616..37eca91e8c 100644
--- a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
+++ b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
@@ -4,6 +4,10 @@ import vct.col.ast.{ClassDeclaration, InstanceField, Statement, VeyMontThread}
import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewritten}
-class ThreadBuildingBlocks[Pre <: Generation](val runMethod: ClassDeclaration[Pre], val methods: Seq[ClassDeclaration[Pre]], val channelFields: Map[Ref[Pre,VeyMontThread[Pre]],InstanceField[Rewritten[Pre]]]) {
+class ThreadBuildingBlocks[Pre <: Generation](
+ val runMethod: ClassDeclaration[Pre],
+ val methods: Seq[ClassDeclaration[Pre]],
+ val threadFieldMap: Map[VeyMontThread[Pre],InstanceField[Rewritten[Pre]]],
+ val channelFields: Map[Ref[Pre,VeyMontThread[Pre]],InstanceField[Rewritten[Pre]]]) {
}
From b3e4cfb1c2ea01b6158a3a4a30b6229e7bc4056a Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Wed, 7 Jun 2023 16:04:41 +0200
Subject: [PATCH 09/20] rewritting method call not working because overloaded
dispatch for Ref
---
src/col/vct/col/ast/Node.scala | 1 +
.../vct/col/typerules/CoercingRewriter.scala | 1 +
.../veymont/ParalleliseVeyMontThreads.scala | 109 ++++++++++++------
.../veymont/ThreadBuildingBlocks.scala | 8 +-
4 files changed, 82 insertions(+), 37 deletions(-)
diff --git a/src/col/vct/col/ast/Node.scala b/src/col/vct/col/ast/Node.scala
index afb5c15f79..fc5922bc65 100644
--- a/src/col/vct/col/ast/Node.scala
+++ b/src/col/vct/col/ast/Node.scala
@@ -189,6 +189,7 @@ final case class WandApply[G](res: Expr[G])(val blame: Blame[WandApplyFailed])(i
final case class Havoc[G](loc: Expr[G])(implicit val o: Origin) extends NormallyCompletingStatement[G] with HavocImpl[G]
final case class FramedProof[G](pre: Expr[G], body: Statement[G], post: Expr[G])(val blame: Blame[FramedProofFailure])(implicit val o: Origin) extends NormallyCompletingStatement[G] with FramedProofImpl[G]
final case class Extract[G](contractedStatement: Statement[G])(implicit val o: Origin) extends NormallyCompletingStatement[G] with ExtractImpl[G]
+final case class Skip[G]()(implicit val o: Origin) extends NormallyCompletingStatement[G]
sealed trait ExceptionalStatement[G] extends Statement[G] with ExceptionalStatementImpl[G]
final case class Eval[G](expr: Expr[G])(implicit val o: Origin) extends ExceptionalStatement[G] with EvalImpl[G]
diff --git a/src/col/vct/col/typerules/CoercingRewriter.scala b/src/col/vct/col/typerules/CoercingRewriter.scala
index 21984d108d..149c959e5c 100644
--- a/src/col/vct/col/typerules/CoercingRewriter.scala
+++ b/src/col/vct/col/typerules/CoercingRewriter.scala
@@ -1574,6 +1574,7 @@ abstract class CoercingRewriter[Pre <: Generation]() extends AbstractRewriter[Pr
case ass @ SilverFieldAssign(obj, field, value) => SilverFieldAssign(ref(obj), field, coerce(value, field.decl.t))(ass.blame)
case SilverLocalAssign(v, value) => SilverLocalAssign(v, coerce(value, v.decl.t))
case SilverNewRef(v, fields) => SilverNewRef(v, fields)
+ case Skip() => Skip()
case SpecIgnoreEnd() => SpecIgnoreEnd()
case SpecIgnoreStart() => SpecIgnoreStart()
case Switch(expr, body) => Switch(expr, body)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 617fde1457..e5345cac30 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -2,14 +2,16 @@ package vct.rewrite.veymont
import hre.util.ScopedStack
import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, Node, Program, RunMethod, Scope, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
-import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg}
+import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg, Rewritten}
import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelClassOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
+import scala.collection.immutable.Seq
+
object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
override def key: String = "ParalleliseVeyMontThreads"
@@ -44,38 +46,27 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] {
- val inSeqProg: ScopedStack[Map[VeyMontThread[Pre],InstanceField[Post]]] = ScopedStack()
- val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
- val seqProgSucc: SuccessionMap[VeyMontThread[Pre],Class[Post]] = SuccessionMap()
+ private val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
+ private val threadClassSucc: SuccessionMap[VeyMontThread[Pre],Class[Post]] = SuccessionMap()
+ private val threadMethodSucc: SuccessionMap[(VeyMontThread[Pre],ClassDeclaration[Pre]),InstanceMethod[Post]] = SuccessionMap()
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
- val threadFieldMap = seqProg.threads.map(t => (t,new InstanceField[Post](dispatch(t.threadType), Set.empty)(t.o))).toMap
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
val channelClasses = generateChannelClasses(channelInfo)
val channelFields = getChannelFields(channelInfo, channelClasses)
- threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods,threadFieldMap,channelFields)) {
- seqProg.threads.foreach(dispatch)
- }
+ seqProg.threads.foreach(thread => {
+ val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
+ threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods, channelFields, channelClasses, thread, threadField)) {
+ dispatch(thread)
+ }
+ })
case thread: VeyMontThread[Pre] => {
if(threadBuildingBlocks.nonEmpty) {
val threadRes: ThreadBuildingBlocks[Pre] = threadBuildingBlocks.top
- val threadField = threadRes.threadFieldMap(thread)
- val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
- _.decl == thread
- }.values.toSeq
- val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
- val threadMethods: Seq[ClassDeclaration[Post]] = threadRes.methods.map(getThreadMethodFromDecl(thread))
- classDeclarations.scope {
- //classDeclarations.collect {
- val threadClass = new Class[Post](
- (threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods),
- Seq(),
- BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
- globalDeclarations.declare(threadClass)
- seqProgSucc.update(thread,threadClass)
- }
+ val threadMethods: Seq[ClassDeclaration[Post]] = createThreadMethod(thread, threadRes)
+ createThreadClass(thread, threadRes, threadMethods)
} else rewriteDefault(thread)
}
//case m: InstanceMethod[Pre] => getThreadMethod(m)
@@ -84,6 +75,30 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}
}
+ private def createThreadMethod(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre]) = {
+ threadRes.methods.map { preMethod =>
+ val postMethod = getThreadMethodFromDecl(thread)(preMethod)
+ threadMethodSucc.update((thread, preMethod), postMethod)
+ postMethod
+ }
+ }
+
+ private def createThreadClass(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre], threadMethods: Seq[ClassDeclaration[Post]]): Unit = {
+ val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
+ _.decl == thread
+ }.values.toSeq
+ val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
+ classDeclarations.scope {
+ //classDeclarations.collect {
+ val threadClass = new Class[Post](
+ (threadRes.threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods),
+ Seq(),
+ BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
+ globalDeclarations.declare(threadClass)
+ threadClassSucc.update(thread, threadClass)
+ }
+ }
+
private def getThreadMethodFromDecl(thread: VeyMontThread[Pre])(decl: ClassDeclaration[Pre]): InstanceMethod[Post] = decl match {
case m: InstanceMethod[Pre] => getThreadMethod(m)
case _ => throw ParalliseVeyMontThreadsError(thread, "Methods of seq_program need to be of type InstanceMethod")
@@ -155,17 +170,32 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
override def dispatch(node: Expr[Pre]): Expr[Post] = {
if(threadBuildingBlocks.nonEmpty) {
- val threadFieldMap = threadBuildingBlocks.top.threadFieldMap
+ val thread = threadBuildingBlocks.top.thread
node match {
+ case c: VeyMontCondition[Pre] => c.condition.find{ case (threadRef,_) =>
+ threadRef.decl == thread
+ } match {
+ case Some((_,threadExpr)) => dispatch(threadExpr)
+ case _ => throw ParalliseVeyMontThreadsError(node, "Condition of if statement or while loop must contain an expression for every thread")
+ }
+ case m: MethodInvocation[Pre] => threadMethodSucc.get((thread,m.ref.decl)) match {
+ case Some(postMethod) => MethodInvocation[Post](dispatch(m.obj),postMethod.ref,m.args.map(dispatch),
+ m.outArgs.map(dispatch),m.typeArgs.map(dispatch),
+ m.givenMap.map{ case (r,e) => (dispatch(r),dispatch(e))},
+ m.yields.map{case (e,r) => (dispatch(e),dispatch(r))})(m.blame)(m.o)
+ case None => throw ParalliseVeyMontThreadsError(m,"No successor for this method found")
+ }
+ case t: ThisObject[Pre] => ThisObject(threadClassSucc.ref[Post, Class[Post]](threadBuildingBlocks.top.thread))(threadBuildingBlocks.top.thread.o)
case d: Deref[Pre] => d.obj match {
case t: DerefVeyMontThread[Pre] =>
- threadFieldMap.find{case (thread,_) => t.ref.decl == thread} match {
- case Some((thread,threadField)) =>
- d.rewrite(
- obj = Deref(ThisObject(seqProgSucc.ref[Post, Class[Post]](thread))(thread.o), threadField.ref[InstanceField[Post]])(null)(d.o)
- )
- case _ => rewriteDefault(node)
+ val threadField = threadBuildingBlocks.top.threadField
+ if(t.ref.decl == thread) {
+ d.rewrite(
+ obj = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), threadField.ref[InstanceField[Post]])(null)(d.o)
+ )
}
+ else rewriteDefault(node)
+
}
case _ => rewriteDefault(node)
}
@@ -174,10 +204,21 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
override def dispatch(st : Statement[Pre]) : Statement[Post] = {
- if (inSeqProg.nonEmpty) {
+ if (threadBuildingBlocks.nonEmpty) {
+ val thread = threadBuildingBlocks.top.thread
st match {
- case VeyMontCommExpression(recv,sender,assign) => rewriteDefault(assign)
- case VeyMontAssignExpression(_, _) => rewriteDefault(st)
+ case VeyMontCommExpression(recv,sender,assign) =>
+ if (recv.decl == thread)
+ dispatch(assign)
+ else if(sender.decl == thread) {
+ //MethodInvocation(dispatch(sender),)
+ dispatch(assign)
+ }
+ else Skip()(assign.o)
+ case VeyMontAssignExpression(threadRef, assign) =>
+ if (threadRef.decl == thread)
+ dispatch(assign)
+ else Skip()(assign.o)
case Assign(_, _) => rewriteDefault(st)
case Branch(_) => rewriteDefault(st)
case Loop(_, _, _, _, _) => rewriteDefault(st)
diff --git a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
index 37eca91e8c..b9840dbab4 100644
--- a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
+++ b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
@@ -1,13 +1,15 @@
package vct.rewrite.veymont
-import vct.col.ast.{ClassDeclaration, InstanceField, Statement, VeyMontThread}
+import vct.col.ast.{ClassDeclaration, InstanceField, JavaClass, Statement, Type, VeyMontThread}
import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewritten}
class ThreadBuildingBlocks[Pre <: Generation](
val runMethod: ClassDeclaration[Pre],
val methods: Seq[ClassDeclaration[Pre]],
- val threadFieldMap: Map[VeyMontThread[Pre],InstanceField[Rewritten[Pre]]],
- val channelFields: Map[Ref[Pre,VeyMontThread[Pre]],InstanceField[Rewritten[Pre]]]) {
+ val channelFields: Map[Ref[Pre,VeyMontThread[Pre]],InstanceField[Rewritten[Pre]]],
+ val channelClasses: Map[Type[Pre],JavaClass[Rewritten[Pre]]],
+ val thread: VeyMontThread[Pre],
+ val threadField: InstanceField[Rewritten[Pre]]) {
}
From f362bdc2260f4c84095e1b1a75e79b8197d2f492 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Mon, 12 Jun 2023 14:32:29 +0200
Subject: [PATCH 10/20] rewriting method call works
---
.../veymont/ParalleliseVeyMontThreads.scala | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index e5345cac30..da4cee9d0c 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,7 +1,7 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass}
+import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
@@ -178,12 +178,12 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case Some((_,threadExpr)) => dispatch(threadExpr)
case _ => throw ParalliseVeyMontThreadsError(node, "Condition of if statement or while loop must contain an expression for every thread")
}
- case m: MethodInvocation[Pre] => threadMethodSucc.get((thread,m.ref.decl)) match {
- case Some(postMethod) => MethodInvocation[Post](dispatch(m.obj),postMethod.ref,m.args.map(dispatch),
- m.outArgs.map(dispatch),m.typeArgs.map(dispatch),
- m.givenMap.map{ case (r,e) => (dispatch(r),dispatch(e))},
- m.yields.map{case (e,r) => (dispatch(e),dispatch(r))})(m.blame)(m.o)
- case None => throw ParalliseVeyMontThreadsError(m,"No successor for this method found")
+ case m: MethodInvocation[Pre] => m.obj match {
+ case threadRef: DerefVeyMontThread[Pre] => m.rewrite(obj = dispatch(threadRef))
+ case _ => threadMethodSucc.get((thread, m.ref.decl)) match {
+ case Some(postMethod) => m.rewrite(obj = dispatch(m.obj), ref = postMethod.ref, m.args.map(dispatch))
+ case None => throw ParalliseVeyMontThreadsError(m, "No successor for this method found")
+ }
}
case t: ThisObject[Pre] => ThisObject(threadClassSucc.ref[Post, Class[Post]](threadBuildingBlocks.top.thread))(threadBuildingBlocks.top.thread.o)
case d: Deref[Pre] => d.obj match {
@@ -224,7 +224,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case Loop(_, _, _, _, _) => rewriteDefault(st)
case Scope(_, _) => rewriteDefault(st)
case Block(_) => rewriteDefault(st)
- case Eval(expr) => Eval(rewriteDefault(expr))(st.o)
+ case Eval(expr) => Eval(dispatch(expr))(st.o)
case Assert(_) => rewriteDefault(st)
case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
}
From a30bf5dfaab29c5c7c40a5e1c79333b151449d3b Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 13 Jun 2023 17:15:24 +0200
Subject: [PATCH 11/20] working on rewriting VeyMont Comm Expr
---
src/col/vct/col/ast/Node.scala | 2 +-
.../vct/col/typerules/CoercingRewriter.scala | 2 +-
.../veymont/AddVeyMontAssignmentNodes.scala | 2 +-
.../veymont/ParalleliseVeyMontThreads.scala | 36 +++++++++++++------
.../veymont/ThreadBuildingBlocks.scala | 5 +--
5 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/src/col/vct/col/ast/Node.scala b/src/col/vct/col/ast/Node.scala
index fc5922bc65..9c066f1b7d 100644
--- a/src/col/vct/col/ast/Node.scala
+++ b/src/col/vct/col/ast/Node.scala
@@ -671,7 +671,7 @@ final case class SuperType[G](left: Expr[G], right: Expr[G])(implicit val o: Ori
final case class IndeterminateInteger[G](min: Expr[G], max: Expr[G])(implicit val o: Origin) extends Expr[G] with IndeterminateIntegerImpl[G]
sealed trait AssignExpression[G] extends Expr[G] with AssignExpressionImpl[G]
-final case class VeyMontCommExpression[G](receiver: Ref[G,VeyMontThread[G]], sender : Ref[G,VeyMontThread[G]], assign: Statement[G])(implicit val o: Origin) extends Statement[G] with VeyMontCommImpl[G]
+final case class VeyMontCommExpression[G](receiver: Ref[G,VeyMontThread[G]], sender : Ref[G,VeyMontThread[G]], chanType: Type[G], assign: Statement[G])(implicit val o: Origin) extends Statement[G] with VeyMontCommImpl[G]
final case class VeyMontAssignExpression[G](thread : Ref[G,VeyMontThread[G]], assign: Statement[G])(implicit val o: Origin) extends Statement[G] with VeyMontAssignExpressionImpl[G]
final case class PreAssignExpression[G](target: Expr[G], value: Expr[G])(val blame: Blame[AssignFailed])(implicit val o: Origin) extends AssignExpression[G] with PreAssignExpressionImpl[G]
final case class PostAssignExpression[G](target: Expr[G], value: Expr[G])(val blame: Blame[AssignFailed])(implicit val o: Origin) extends AssignExpression[G] with PostAssignExpressionImpl[G]
diff --git a/src/col/vct/col/typerules/CoercingRewriter.scala b/src/col/vct/col/typerules/CoercingRewriter.scala
index 149c959e5c..99fd2b8945 100644
--- a/src/col/vct/col/typerules/CoercingRewriter.scala
+++ b/src/col/vct/col/typerules/CoercingRewriter.scala
@@ -1588,7 +1588,7 @@ abstract class CoercingRewriter[Pre <: Generation]() extends AbstractRewriter[Pr
case w @ WandApply(assn) => WandApply(res(assn))(w.blame)
case w @ WandPackage(expr, stat) => WandPackage(res(expr), stat)(w.blame)
case VeyMontAssignExpression(t,a) => VeyMontAssignExpression(t,a)
- case VeyMontCommExpression(r,s,a) => VeyMontCommExpression(r,s,a)
+ case VeyMontCommExpression(r,s,t,a) => VeyMontCommExpression(r,s,t,a)
}
}
diff --git a/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala b/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala
index f3c19ff228..b5411730e8 100644
--- a/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala
+++ b/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala
@@ -93,7 +93,7 @@ case class AddVeyMontAssignmentNodes[Pre <: Generation]() extends Rewriter[Pre]
new VeyMontAssignExpression[Post](succ(receiver), rewriteDefault(a))(a.o)
else if (derefs.size == 1) {
val sender = getAssignmentSender(derefs.head)
- new VeyMontCommExpression[Post](succ(receiver), succ(sender), rewriteDefault(a))(a.o)
+ new VeyMontCommExpression[Post](succ(receiver), succ(sender), dispatch(derefs.head.ref.decl.t), rewriteDefault(a))(a.o)
} else throw AddVeyMontAssignmentError(a.value, "The value of this assignment is not allowed to refer to multiple threads!")
}
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index da4cee9d0c..f435ab9a37 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -2,7 +2,7 @@ package vct.rewrite.veymont
import hre.util.ScopedStack
import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg, Rewritten}
@@ -54,8 +54,11 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
- val channelClasses = generateChannelClasses(channelInfo)
- val channelFields = getChannelFields(channelInfo, channelClasses)
+ val indexedChannelInfo : Seq[ChannelInfo[Pre]] = channelInfo.groupBy(_.channelName).values.flatMap(chanInfoSeq =>
+ if (chanInfoSeq.size <= 1) chanInfoSeq
+ else chanInfoSeq.zipWithIndex.map{ case (chanInfo,index) => new ChannelInfo(chanInfo.comExpr,chanInfo.channelType,chanInfo.channelName + index) }).toSeq
+ val channelClasses = generateChannelClasses(indexedChannelInfo)
+ val channelFields = getChannelFields(indexedChannelInfo, channelClasses)
seqProg.threads.foreach(thread => {
val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods, channelFields, channelClasses, thread, threadField)) {
@@ -109,10 +112,10 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case _ => throw ParalliseVeyMontThreadsError(thread, "RunMethod expected in seq_program")
}
- private def getChannelFields(channelInfo: Seq[ChannelInfo[Pre]], channelClasses: Map[Type[Pre],JavaClass[Post]]): Map[Ref[Pre, VeyMontThread[Pre]],InstanceField[Post]] = {
- channelInfo.flatMap { chanInfo =>
+ private def getChannelFields(channelInfo: Seq[ChannelInfo[Pre]], channelClasses: Map[Type[Pre],JavaClass[Post]]): Map[(VeyMontCommExpression[Pre],Origin),InstanceField[Post]] = {
+ channelInfo.map { chanInfo =>
val chanField = new InstanceField[Post](JavaTClass(channelClasses(chanInfo.channelType).ref,Seq.empty), Set.empty)(ChannelClassOrigin(chanInfo.channelName,chanInfo.comExpr.assign))
- Set((chanInfo.comExpr.receiver, chanField), (chanInfo.comExpr.sender, chanField)) }.toMap
+ ((chanInfo.comExpr,chanInfo.comExpr.o), chanField) }.toMap
}
private def generateChannelClasses(channelInfo: Seq[ChannelInfo[Pre]]) : Map[Type[Pre],JavaClass[Post]] = {
@@ -147,8 +150,8 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}
private def getChannelNamesAndTypes(s: Statement[Pre]): Seq[ChannelInfo[Pre]] = {
- s.collect { case e@VeyMontCommExpression(recv, sender, assign) =>
- new ChannelInfo(e,recv.decl.threadType, recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel")
+ s.collect { case e@VeyMontCommExpression(recv, sender, chanType, assign) =>
+ new ChannelInfo(e,chanType, recv.decl.o.preferredName + sender.decl.o.preferredName + "Channel")
}
}
@@ -207,12 +210,16 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
if (threadBuildingBlocks.nonEmpty) {
val thread = threadBuildingBlocks.top.thread
st match {
- case VeyMontCommExpression(recv,sender,assign) =>
+ case v@VeyMontCommExpression(recv,sender,chanType,assign) =>
+ val channelField = threadBuildingBlocks.top.channelFields((v,v.o))
+ val channelClass = threadBuildingBlocks.top.channelClasses(chanType)
+ val assignment = assign.asInstanceOf[Assign[Pre]]
if (recv.decl == thread)
dispatch(assign)
else if(sender.decl == thread) {
- //MethodInvocation(dispatch(sender),)
- dispatch(assign)
+ val writeMethod = findChannelClassMethod(v, channelClass, "writeValue")
+ val thisChanField = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), channelField.ref[InstanceField[Post]])(null)(assign.o)
+ Eval(MethodInvocation(thisChanField,writeMethod.ref[InstanceMethod[Post]],Seq(dispatch(assignment.value)),Seq.empty,Seq.empty,Seq.empty,Seq.empty)(null)(v.o))(v.o)
}
else Skip()(assign.o)
case VeyMontAssignExpression(threadRef, assign) =>
@@ -231,4 +238,11 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
} else rewriteDefault(st)
}
+ private def findChannelClassMethod(v: VeyMontCommExpression[Pre], channelClass: JavaClass[Post], methodName: String) = {
+ val writeMethod = channelClass.decls.find { case m: InstanceMethod[Pre] => m.o.preferredName == methodName } match {
+ case Some(m: InstanceMethod[Post]) => m
+ case _ => throw ParalliseVeyMontThreadsError(v, "Could not find method `" + methodName + "' for channelClass")
+ }
+ writeMethod
+ }
}
diff --git a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
index b9840dbab4..89140d8ec2 100644
--- a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
+++ b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
@@ -1,13 +1,14 @@
package vct.rewrite.veymont
-import vct.col.ast.{ClassDeclaration, InstanceField, JavaClass, Statement, Type, VeyMontThread}
+import vct.col.ast.{ClassDeclaration, InstanceField, JavaClass, Statement, Type, VeyMontCommExpression, VeyMontThread}
+import vct.col.origin.Origin
import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewritten}
class ThreadBuildingBlocks[Pre <: Generation](
val runMethod: ClassDeclaration[Pre],
val methods: Seq[ClassDeclaration[Pre]],
- val channelFields: Map[Ref[Pre,VeyMontThread[Pre]],InstanceField[Rewritten[Pre]]],
+ val channelFields: Map[(VeyMontCommExpression[Pre],Origin),InstanceField[Rewritten[Pre]]],
val channelClasses: Map[Type[Pre],JavaClass[Rewritten[Pre]]],
val thread: VeyMontThread[Pre],
val threadField: InstanceField[Rewritten[Pre]]) {
From f4961fc4e71166895ce8f175d121dbd6035189db Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Fri, 16 Jun 2023 16:00:03 +0200
Subject: [PATCH 12/20] rewriting of statements working but channel class type
is not rewritten
---
.../veymont-seq-progs/veymont-swap.pvl | 2 +-
.../veymont/AddVeyMontAssignmentNodes.scala | 12 ++++-
.../veymont/ParalleliseVeyMontThreads.scala | 54 ++++++++++++-------
.../vct/rewrite/veymont/StructureCheck.scala | 2 +-
4 files changed, 48 insertions(+), 22 deletions(-)
diff --git a/examples/technical/veymont-seq-progs/veymont-swap.pvl b/examples/technical/veymont-seq-progs/veymont-swap.pvl
index a4d40454c8..471c083458 100644
--- a/examples/technical/veymont-seq-progs/veymont-swap.pvl
+++ b/examples/technical/veymont-seq-progs/veymont-swap.pvl
@@ -25,7 +25,7 @@ seq_program SeqProgram(int x, int y) {
int num() {}
void foo() {
- s1.temp = 5;
+ s1.temp = 7;
}
//void bar(int a) {}
diff --git a/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala b/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala
index b5411730e8..1b0bf1bbaa 100644
--- a/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala
+++ b/src/rewrite/vct/rewrite/veymont/AddVeyMontAssignmentNodes.scala
@@ -92,8 +92,16 @@ case class AddVeyMontAssignmentNodes[Pre <: Generation]() extends Rewriter[Pre]
if (derefs.isEmpty)
new VeyMontAssignExpression[Post](succ(receiver), rewriteDefault(a))(a.o)
else if (derefs.size == 1) {
- val sender = getAssignmentSender(derefs.head)
- new VeyMontCommExpression[Post](succ(receiver), succ(sender), dispatch(derefs.head.ref.decl.t), rewriteDefault(a))(a.o)
+ val thread = derefs.head.obj match {
+ case t: DerefVeyMontThread[Pre] => t
+ case _ => throw AddVeyMontAssignmentError(a.value, "The value of this assignment is expected to be a Deref of a thread!")
+ }
+ if(thread.ref.decl == receiver)
+ new VeyMontAssignExpression[Post](succ(receiver),rewriteDefault(a))(a.o)
+ else {
+ val sender = getAssignmentSender(derefs.head)
+ new VeyMontCommExpression[Post](succ(receiver), succ(sender), dispatch(derefs.head.ref.decl.t), rewriteDefault(a))(a.o)
+ }
} else throw AddVeyMontAssignmentError(a.value, "The value of this assignment is not allowed to refer to multiple threads!")
}
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index f435ab9a37..6463da6c60 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,10 +1,13 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast
+import vct.col.ast.RewriteHelpers.{RewriteAssign, RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaInvocation, JavaMethod, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
+import vct.col.resolve.ctx.RefJavaMethod
+import vct.col.rewrite.veymont.AddVeyMontAssignmentNodes.getDerefsFromExpr
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg, Rewritten}
import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
@@ -88,7 +91,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
private def createThreadClass(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre], threadMethods: Seq[ClassDeclaration[Post]]): Unit = {
val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
- _.decl == thread
+ case (comExpr,_) => comExpr.receiver.decl == thread || comExpr.sender.decl == thread
}.values.toSeq
val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
classDeclarations.scope {
@@ -188,7 +191,6 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case None => throw ParalliseVeyMontThreadsError(m, "No successor for this method found")
}
}
- case t: ThisObject[Pre] => ThisObject(threadClassSucc.ref[Post, Class[Post]](threadBuildingBlocks.top.thread))(threadBuildingBlocks.top.thread.o)
case d: Deref[Pre] => d.obj match {
case t: DerefVeyMontThread[Pre] =>
val threadField = threadBuildingBlocks.top.threadField
@@ -213,36 +215,52 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case v@VeyMontCommExpression(recv,sender,chanType,assign) =>
val channelField = threadBuildingBlocks.top.channelFields((v,v.o))
val channelClass = threadBuildingBlocks.top.channelClasses(chanType)
+ val thisChanField = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), channelField.ref[InstanceField[Post]])(null)(assign.o)
val assignment = assign.asInstanceOf[Assign[Pre]]
- if (recv.decl == thread)
- dispatch(assign)
- else if(sender.decl == thread) {
+ if (recv.decl == thread) {
+ val readMethod = findChannelClassMethod(v, channelClass, "readValue")
+ val assignValue = JavaInvocation(Some(thisChanField),Seq.empty, "readValue",Seq.empty, Seq.empty,Seq.empty)(null)(v.o)
+ assignValue.ref = Some(RefJavaMethod(readMethod))
+ Assign(dispatch(assignment.target),assignValue)(null)(v.o)
+ } else if(sender.decl == thread) {
val writeMethod = findChannelClassMethod(v, channelClass, "writeValue")
- val thisChanField = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), channelField.ref[InstanceField[Post]])(null)(assign.o)
- Eval(MethodInvocation(thisChanField,writeMethod.ref[InstanceMethod[Post]],Seq(dispatch(assignment.value)),Seq.empty,Seq.empty,Seq.empty,Seq.empty)(null)(v.o))(v.o)
+ val writeInvoc = JavaInvocation(Some(thisChanField),Seq.empty,"writeValue",Seq(dispatch(assignment.value)),Seq.empty,Seq.empty)(null)(v.o)
+ writeInvoc.ref = Some(RefJavaMethod(writeMethod))
+ Eval(writeInvoc)(v.o)
}
else Skip()(assign.o)
- case VeyMontAssignExpression(threadRef, assign) =>
+ case v@VeyMontAssignExpression(threadRef, assign) =>
if (threadRef.decl == thread)
dispatch(assign)
else Skip()(assign.o)
- case Assign(_, _) => rewriteDefault(st)
+ case a: Assign[Pre] => rewriteDefault(st)
case Branch(_) => rewriteDefault(st)
case Loop(_, _, _, _, _) => rewriteDefault(st)
case Scope(_, _) => rewriteDefault(st)
case Block(_) => rewriteDefault(st)
- case Eval(expr) => Eval(dispatch(expr))(st.o)
- case Assert(_) => rewriteDefault(st)
+ case Eval(expr) => expr match {
+ case m: MethodInvocation[Pre] => m.obj match {
+ case _: ThisSeqProg[Pre] => Eval(dispatch(expr))(st.o)
+ case d: DerefVeyMontThread[Pre] => if(d.ref.decl == thread) Eval(dispatch(expr))(st.o) else Skip()(st.o)
+ case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
+ }
+ case _ => rewriteDefault(st)
+ }
+ case _: Assert[Pre] => Skip()(st.o)
case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
}
} else rewriteDefault(st)
}
- private def findChannelClassMethod(v: VeyMontCommExpression[Pre], channelClass: JavaClass[Post], methodName: String) = {
- val writeMethod = channelClass.decls.find { case m: InstanceMethod[Pre] => m.o.preferredName == methodName } match {
- case Some(m: InstanceMethod[Post]) => m
- case _ => throw ParalliseVeyMontThreadsError(v, "Could not find method `" + methodName + "' for channelClass")
+ private def findChannelClassMethod(v: VeyMontCommExpression[Pre], channelClass: JavaClass[Post], methodName: String): JavaMethod[Post] = {
+ val method = channelClass.decls.find {
+ case jm: JavaMethod[Post] => jm.name == methodName
+ case _ => false
+ }
+ method match {
+ case Some(m : JavaMethod[Post]) => m
+ case _ => throw ParalliseVeyMontThreadsError(v, "Could not find method `" + methodName + "' for channel class " + channelClass.name)
}
- writeMethod
}
+
}
diff --git a/src/rewrite/vct/rewrite/veymont/StructureCheck.scala b/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
index 3ec673277d..8af88c94f6 100644
--- a/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
+++ b/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
@@ -56,7 +56,7 @@ case class StructureCheck[Pre <: Generation]() extends Rewriter[Pre] {
override def dispatch(st : Statement[Pre]) : Statement[Post] = {
if(inSeqProg.nonEmpty)
st match {
- case VeyMontCommExpression(_,_,_) => rewriteDefault(st)
+ case VeyMontCommExpression(_,_,_,_) => rewriteDefault(st)
case VeyMontAssignExpression(_,_) => rewriteDefault (st)
case Assign(_,_) => rewriteDefault (st)
case Branch(_) => rewriteDefault(st)
From 6c93b76c0b2305cc1afb1df3699dfdebbb6c7410 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 27 Jun 2023 13:57:44 +0200
Subject: [PATCH 13/20] rewriting MessageType now compiling
---
src/main/vct/main/stages/Transformation.scala | 2 +-
.../veymont/ChannelClassGenerator.scala | 21 ----------------
.../veymont/ParalleliseVeyMontThreads.scala | 24 +++++++++++++++----
3 files changed, 20 insertions(+), 27 deletions(-)
delete mode 100644 src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala
diff --git a/src/main/vct/main/stages/Transformation.scala b/src/main/vct/main/stages/Transformation.scala
index 96681e195a..ad04613619 100644
--- a/src/main/vct/main/stages/Transformation.scala
+++ b/src/main/vct/main/stages/Transformation.scala
@@ -22,7 +22,7 @@ import vct.options.Options
import vct.options.types.{Backend, PathOrStd}
import vct.resources.Resources
import vct.result.VerificationError.SystemError
-import vct.rewrite.veymont.{ChannelClassGenerator, ParalleliseVeyMontThreads}
+import vct.rewrite.veymont.ParalleliseVeyMontThreads
object Transformation {
case class TransformationCheckError(pass: RewriterBuilder, errors: Seq[CheckError]) extends SystemError {
diff --git a/src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala b/src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala
deleted file mode 100644
index 71f26d53d4..0000000000
--- a/src/rewrite/vct/rewrite/veymont/ChannelClassGenerator.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package vct.rewrite.veymont
-
-import vct.col.ast.Type
-import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg}
-
-object ChannelClassGenerator extends RewriterBuilderArg[Type[_]] {
- override def key: String = "ChannelClassGenerator"
-
- override def desc: String = "Generate classes for channels of a VeyMont seq_program"
-
-}
-
-case class ChannelClassGenerator [Pre <: Generation](channelType: Type[_]) extends Rewriter[Pre] {
-
- override def dispatch(t: Type[Pre]) : Type[Post] = {
- if(t.o.preferredName == "MessageType")
- dispatch(channelType.asInstanceOf[Type[Pre]])
- else rewriteDefault(t)
- }
-
-}
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 6463da6c60..3a747e4731 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -3,7 +3,7 @@ package vct.rewrite.veymont
import hre.util.ScopedStack
import vct.col.ast
import vct.col.ast.RewriteHelpers.{RewriteAssign, RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaInvocation, JavaMethod, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaInvocation, JavaMethod, JavaNamedType, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
import vct.col.resolve.ctx.RefJavaMethod
@@ -47,7 +47,7 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
}
}
-case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] {
+case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] { outer =>
private val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
private val threadClassSucc: SuccessionMap[VeyMontThread[Pre],Class[Post]] = SuccessionMap()
@@ -126,12 +126,26 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
channelTypes.map(channelType =>
channelType -> {
val chanClassPre = channelClass.asInstanceOf[JavaClass[Pre]]
- new RewriteJavaClass[Pre, Post](chanClassPre)(new ChannelClassGenerator[Pre](channelType)).rewrite(decls = classDeclarations.collect {
- chanClassPre.decls.foreach(d => dispatch(d))
+ val rw = new ChannelClassGenerator(channelType)
+ new RewriteJavaClass[Pre, Post](chanClassPre)(rw).rewrite(decls = classDeclarations.collect {
+ chanClassPre.decls.foreach(d => rw.dispatch(d))
}._1)
}
).toMap
- }//new ChannelClassGenerator(channelType).globalDeclarations.dispatch(channelClass.unsafeTransmuteGeneration[JavaClass, Pre])
+ }
+
+ case class ChannelClassGenerator(channelType: Type[_]) extends Rewriter[Pre] {
+ override val allScopes = outer.allScopes
+
+ override def dispatch(t: Type[Pre]): Type[Post] = t match {
+ // case jt: JavaType[Pre] => jt match {
+ case jnt: JavaNamedType[Pre] =>
+ if (jnt.names.head._1 == "MessageType") {
+ dispatch(channelType.asInstanceOf[Type[Pre]])
+ } else rewriteDefault(jnt)
+ case _ => rewriteDefault(t)
+ }
+ }
private def collectChannelsFromRun(seqProg: VeyMontSeqProg[Pre]) =
seqProg.runMethod match {
From 8cb1d51bf0089f298c35cf26f99d4d54c278fa90 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 4 Jul 2023 15:20:48 +0200
Subject: [PATCH 14/20] method invokation refs fixed
---
.../ParallelCommExprBuildingBlocks.scala | 9 +
.../veymont/ParalleliseVeyMontThreads.scala | 197 +++++++++++-------
.../veymont/ThreadBuildingBlocks.scala | 3 +-
3 files changed, 128 insertions(+), 81 deletions(-)
create mode 100644 src/rewrite/vct/rewrite/veymont/ParallelCommExprBuildingBlocks.scala
diff --git a/src/rewrite/vct/rewrite/veymont/ParallelCommExprBuildingBlocks.scala b/src/rewrite/vct/rewrite/veymont/ParallelCommExprBuildingBlocks.scala
new file mode 100644
index 0000000000..9faf3047be
--- /dev/null
+++ b/src/rewrite/vct/rewrite/veymont/ParallelCommExprBuildingBlocks.scala
@@ -0,0 +1,9 @@
+package vct.rewrite.veymont
+
+import vct.col.ast.{Assign, Deref, InstanceField, JavaClass}
+import vct.col.rewrite.{Generation, Rewritten}
+
+class ParallelCommExprBuildingBlocks[Pre <: Generation](val channelField: InstanceField[Rewritten[Pre]], val channelClass: JavaClass[Rewritten[Pre]],
+ val thisChanField: Deref[Rewritten[Pre]], val assign: Assign[Pre] ) {
+
+}
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 3a747e4731..3e13008df4 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -3,7 +3,7 @@ package vct.rewrite.veymont
import hre.util.ScopedStack
import vct.col.ast
import vct.col.ast.RewriteHelpers.{RewriteAssign, RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaInvocation, JavaMethod, JavaNamedType, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Skip, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaInvocation, JavaMethod, JavaNamedType, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.{Origin, PreferredNameOrigin}
import vct.col.ref.Ref
import vct.col.resolve.ctx.RefJavaMethod
@@ -56,31 +56,42 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
case seqProg: VeyMontSeqProg[Pre] =>
- val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
- val indexedChannelInfo : Seq[ChannelInfo[Pre]] = channelInfo.groupBy(_.channelName).values.flatMap(chanInfoSeq =>
- if (chanInfoSeq.size <= 1) chanInfoSeq
- else chanInfoSeq.zipWithIndex.map{ case (chanInfo,index) => new ChannelInfo(chanInfo.comExpr,chanInfo.channelType,chanInfo.channelName + index) }).toSeq
- val channelClasses = generateChannelClasses(indexedChannelInfo)
- val channelFields = getChannelFields(indexedChannelInfo, channelClasses)
- seqProg.threads.foreach(thread => {
- val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
- threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods, channelFields, channelClasses, thread, threadField)) {
- dispatch(thread)
- }
- })
+ val (channelClasses,channelFields) = extractChannelInfo(seqProg)
+ dispatchThreads(seqProg, channelClasses, channelFields)
case thread: VeyMontThread[Pre] => {
- if(threadBuildingBlocks.nonEmpty) {
- val threadRes: ThreadBuildingBlocks[Pre] = threadBuildingBlocks.top
- val threadMethods: Seq[ClassDeclaration[Post]] = createThreadMethod(thread, threadRes)
- createThreadClass(thread, threadRes, threadMethods)
- } else rewriteDefault(thread)
+ dispatchThread(thread)
}
- //case m: InstanceMethod[Pre] => getThreadMethod(m)
- //case r: RunMethod[Pre] => getThreadRunMethod(r)
case other => rewriteDefault(other)
}
}
+ private def dispatchThread(thread: VeyMontThread[Pre]): Unit = {
+ if (threadBuildingBlocks.nonEmpty) {
+ val threadRes: ThreadBuildingBlocks[Pre] = threadBuildingBlocks.top
+ val threadMethods: Seq[ClassDeclaration[Post]] = createThreadMethod(thread, threadRes)
+ createThreadClass(thread, threadRes, threadMethods)
+ } else rewriteDefault(thread)
+ }
+
+ private def dispatchThreads(seqProg: VeyMontSeqProg[Pre], channelClasses: Map[Type[Pre], JavaClass[Post]], channelFields: Map[(VeyMontCommExpression[Pre], Origin), InstanceField[Post]]): Unit = {
+ seqProg.threads.foreach(thread => {
+ val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
+ threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods, channelFields, channelClasses, thread, threadField)) {
+ dispatch(thread)
+ }
+ })
+ }
+
+ private def extractChannelInfo(seqProg: VeyMontSeqProg[Pre]): (Map[Type[Pre], JavaClass[Post]], Map[(VeyMontCommExpression[Pre], Origin), InstanceField[Post]]) = {
+ val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
+ val indexedChannelInfo: Seq[ChannelInfo[Pre]] = channelInfo.groupBy(_.channelName).values.flatMap(chanInfoSeq =>
+ if (chanInfoSeq.size <= 1) chanInfoSeq
+ else chanInfoSeq.zipWithIndex.map { case (chanInfo, index) => new ChannelInfo(chanInfo.comExpr, chanInfo.channelType, chanInfo.channelName + index) }).toSeq
+ val channelClasses = generateChannelClasses(indexedChannelInfo)
+ val channelFields = getChannelFields(indexedChannelInfo, channelClasses)
+ (channelClasses, channelFields)
+ }
+
private def createThreadMethod(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre]) = {
threadRes.methods.map { preMethod =>
val postMethod = getThreadMethodFromDecl(thread)(preMethod)
@@ -95,11 +106,8 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}.values.toSeq
val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
classDeclarations.scope {
- //classDeclarations.collect {
val threadClass = new Class[Post](
- (threadRes.threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods),
- Seq(),
- BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
+ (threadRes.threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods), Seq(), BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
globalDeclarations.declare(threadClass)
threadClassSucc.update(thread, threadClass)
}
@@ -126,7 +134,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
channelTypes.map(channelType =>
channelType -> {
val chanClassPre = channelClass.asInstanceOf[JavaClass[Pre]]
- val rw = new ChannelClassGenerator(channelType)
+ val rw = ChannelClassGenerator(channelType)
new RewriteJavaClass[Pre, Post](chanClassPre)(rw).rewrite(decls = classDeclarations.collect {
chanClassPre.decls.foreach(d => rw.dispatch(d))
}._1)
@@ -138,7 +146,6 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
override val allScopes = outer.allScopes
override def dispatch(t: Type[Pre]): Type[Post] = t match {
- // case jt: JavaType[Pre] => jt match {
case jnt: JavaNamedType[Pre] =>
if (jnt.names.head._1 == "MessageType") {
dispatch(channelType.asInstanceOf[Type[Pre]])
@@ -192,80 +199,112 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
if(threadBuildingBlocks.nonEmpty) {
val thread = threadBuildingBlocks.top.thread
node match {
- case c: VeyMontCondition[Pre] => c.condition.find{ case (threadRef,_) =>
- threadRef.decl == thread
- } match {
- case Some((_,threadExpr)) => dispatch(threadExpr)
- case _ => throw ParalliseVeyMontThreadsError(node, "Condition of if statement or while loop must contain an expression for every thread")
- }
- case m: MethodInvocation[Pre] => m.obj match {
- case threadRef: DerefVeyMontThread[Pre] => m.rewrite(obj = dispatch(threadRef))
- case _ => threadMethodSucc.get((thread, m.ref.decl)) match {
- case Some(postMethod) => m.rewrite(obj = dispatch(m.obj), ref = postMethod.ref, m.args.map(dispatch))
- case None => throw ParalliseVeyMontThreadsError(m, "No successor for this method found")
- }
- }
- case d: Deref[Pre] => d.obj match {
- case t: DerefVeyMontThread[Pre] =>
- val threadField = threadBuildingBlocks.top.threadField
- if(t.ref.decl == thread) {
- d.rewrite(
- obj = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), threadField.ref[InstanceField[Post]])(null)(d.o)
- )
- }
- else rewriteDefault(node)
-
- }
+ case c: VeyMontCondition[Pre] => paralleliseThreadCondition(node, thread, c)
+ case m: MethodInvocation[Pre] => updateThreadRefMethodInvoc(thread, m)
+ case d: Deref[Pre] => updateThreadRefInDeref(node, thread, d)
+ case t: DerefVeyMontThread[Pre] => updateThreadRefVeyMontDeref(node, thread, t)
case _ => rewriteDefault(node)
}
} else rewriteDefault(node)
}
+ private def updateThreadRefVeyMontDeref(node: Expr[Pre], thread: VeyMontThread[Pre], t: DerefVeyMontThread[Pre]) = {
+ if (t.ref.decl == thread) {
+ getThisVeyMontDeref(thread, t.o, threadBuildingBlocks.top.threadField)
+ } else rewriteDefault(node)
+ }
- override def dispatch(st : Statement[Pre]) : Statement[Post] = {
+ private def updateThreadRefInDeref(node: Expr[Pre], thread: VeyMontThread[Pre], d: Deref[Pre]) = {
+ d.obj match {
+ case t: DerefVeyMontThread[Pre] =>
+ if (t.ref.decl == thread) {
+ d.rewrite(
+ obj = getThisVeyMontDeref(thread, d.o, threadBuildingBlocks.top.threadField)
+ )
+ }
+ else rewriteDefault(node)
+ }
+ }
+
+ private def updateThreadRefMethodInvoc(thread: VeyMontThread[Pre], m: MethodInvocation[Pre]) = {
+ m.obj match {
+ case threadRef: DerefVeyMontThread[Pre] => m.rewrite(obj = dispatch(threadRef))
+ case _ => threadMethodSucc.get((thread, m.ref.decl)) match {
+ case Some(postMethod) => m.rewrite(obj = dispatch(m.obj), ref = postMethod.ref, m.args.map(dispatch))
+ case None => throw ParalliseVeyMontThreadsError(m, "No successor for this method found")
+ }
+ }
+ }
+
+ private def paralleliseThreadCondition(node: Expr[Pre], thread: VeyMontThread[Pre], c: VeyMontCondition[Pre]) = {
+ c.condition.find { case (threadRef, _) =>
+ threadRef.decl == thread
+ } match {
+ case Some((_, threadExpr)) => dispatch(threadExpr)
+ case _ => throw ParalliseVeyMontThreadsError(node, "Condition of if statement or while loop must contain an expression for every thread")
+ }
+ }
+
+ private def getThisVeyMontDeref(thread: VeyMontThread[Pre], o: Origin, threadField: InstanceField[Rewritten[Pre]]) = {
+ Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), threadField.ref[InstanceField[Post]])(null)(o)
+ }
+
+ override def dispatch(st : Statement[Pre]) : Statement[Post] = {
if (threadBuildingBlocks.nonEmpty) {
val thread = threadBuildingBlocks.top.thread
st match {
- case v@VeyMontCommExpression(recv,sender,chanType,assign) =>
- val channelField = threadBuildingBlocks.top.channelFields((v,v.o))
- val channelClass = threadBuildingBlocks.top.channelClasses(chanType)
- val thisChanField = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), channelField.ref[InstanceField[Post]])(null)(assign.o)
- val assignment = assign.asInstanceOf[Assign[Pre]]
- if (recv.decl == thread) {
- val readMethod = findChannelClassMethod(v, channelClass, "readValue")
- val assignValue = JavaInvocation(Some(thisChanField),Seq.empty, "readValue",Seq.empty, Seq.empty,Seq.empty)(null)(v.o)
- assignValue.ref = Some(RefJavaMethod(readMethod))
- Assign(dispatch(assignment.target),assignValue)(null)(v.o)
- } else if(sender.decl == thread) {
- val writeMethod = findChannelClassMethod(v, channelClass, "writeValue")
- val writeInvoc = JavaInvocation(Some(thisChanField),Seq.empty,"writeValue",Seq(dispatch(assignment.value)),Seq.empty,Seq.empty)(null)(v.o)
- writeInvoc.ref = Some(RefJavaMethod(writeMethod))
- Eval(writeInvoc)(v.o)
- }
- else Skip()(assign.o)
+ case v: VeyMontCommExpression[Pre] =>
+ paralleliseVeyMontCommExpr(thread, v, createParComBlocks(thread, v))
case v@VeyMontAssignExpression(threadRef, assign) =>
if (threadRef.decl == thread)
dispatch(assign)
- else Skip()(assign.o)
- case a: Assign[Pre] => rewriteDefault(st)
+ else Block(Seq.empty)(assign.o)
+ case a: Assign[Pre] => Assign(dispatch(a.target),dispatch(a.value))(a.blame)(a.o)
case Branch(_) => rewriteDefault(st)
case Loop(_, _, _, _, _) => rewriteDefault(st)
case Scope(_, _) => rewriteDefault(st)
case Block(_) => rewriteDefault(st)
- case Eval(expr) => expr match {
- case m: MethodInvocation[Pre] => m.obj match {
- case _: ThisSeqProg[Pre] => Eval(dispatch(expr))(st.o)
- case d: DerefVeyMontThread[Pre] => if(d.ref.decl == thread) Eval(dispatch(expr))(st.o) else Skip()(st.o)
- case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
- }
- case _ => rewriteDefault(st)
- }
- case _: Assert[Pre] => Skip()(st.o)
+ case Eval(expr) => paralleliseMethodInvocation(st, thread, expr)
+ case _: Assert[Pre] => Block(Seq.empty)(st.o)
case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
}
} else rewriteDefault(st)
}
+ private def createParComBlocks(thread: VeyMontThread[Pre], v: VeyMontCommExpression[Pre]): ParallelCommExprBuildingBlocks[Pre] = {
+ val channelField = threadBuildingBlocks.top.channelFields((v, v.o))
+ val channelClass = threadBuildingBlocks.top.channelClasses(v.chanType)
+ val thisChanField = Deref(ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), channelField.ref[InstanceField[Post]])(null)(v.assign.o)
+ val assignment = v.assign.asInstanceOf[Assign[Pre]]
+ new ParallelCommExprBuildingBlocks(channelField, channelClass, thisChanField, assignment)
+ }
+
+ private def paralleliseMethodInvocation(st: Statement[Pre], thread: VeyMontThread[Pre], expr: Expr[Pre]): Statement[Post] = {
+ expr match {
+ case m: MethodInvocation[Pre] => m.obj match {
+ case _: ThisSeqProg[Pre] => Eval(m.rewrite(obj = ThisObject(threadClassSucc.ref[Post, Class[Post]](thread))(thread.o), ref = threadMethodSucc.ref((thread, m.ref.decl))))(st.o)
+ case d: DerefVeyMontThread[Pre] => if (d.ref.decl == thread) Eval(dispatch(expr))(st.o) else Block(Seq.empty)(st.o)
+ case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
+ }
+ case _ => throw ParalliseVeyMontThreadsError(st, "Statement not allowed in seq_program")
+ }
+ }
+
+ private def paralleliseVeyMontCommExpr(thread: VeyMontThread[Pre], v: VeyMontCommExpression[Pre], blocks: ParallelCommExprBuildingBlocks[Pre]): Statement[Post] = {
+ if (v.receiver.decl == thread) {
+ val readMethod = findChannelClassMethod(v, blocks.channelClass, "readValue")
+ val assignValue = JavaInvocation(Some(blocks.thisChanField), Seq.empty, "readValue", Seq.empty, Seq.empty, Seq.empty)(null)(v.o)
+ assignValue.ref = Some(RefJavaMethod(readMethod))
+ Assign(dispatch(blocks.assign.target), assignValue)(null)(v.o)
+ } else if (v.sender.decl == thread) {
+ val writeMethod = findChannelClassMethod(v, blocks.channelClass, "writeValue")
+ val writeInvoc = JavaInvocation(Some(blocks.thisChanField), Seq.empty, "writeValue", Seq(dispatch(blocks.assign.value)), Seq.empty, Seq.empty)(null)(v.o)
+ writeInvoc.ref = Some(RefJavaMethod(writeMethod))
+ Eval(writeInvoc)(v.o)
+ }
+ else Block(Seq.empty)(blocks.assign.o)
+ }
+
private def findChannelClassMethod(v: VeyMontCommExpression[Pre], channelClass: JavaClass[Post], methodName: String): JavaMethod[Post] = {
val method = channelClass.decls.find {
case jm: JavaMethod[Post] => jm.name == methodName
diff --git a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
index 89140d8ec2..8e7cead537 100644
--- a/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
+++ b/src/rewrite/vct/rewrite/veymont/ThreadBuildingBlocks.scala
@@ -1,8 +1,7 @@
package vct.rewrite.veymont
-import vct.col.ast.{ClassDeclaration, InstanceField, JavaClass, Statement, Type, VeyMontCommExpression, VeyMontThread}
+import vct.col.ast.{ClassDeclaration, InstanceField, JavaClass, Type, VeyMontCommExpression, VeyMontThread}
import vct.col.origin.Origin
-import vct.col.ref.Ref
import vct.col.rewrite.{Generation, Rewritten}
class ThreadBuildingBlocks[Pre <: Generation](
From c102654f3d14dad4d1a1960e7f31482012cdf94e Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Wed, 12 Jul 2023 17:25:41 +0200
Subject: [PATCH 15/20] stuck at NoSuchElementException
---
src/col/vct/col/ast/Node.scala | 1 -
.../vct/col/typerules/CoercingRewriter.scala | 1 -
.../veymont/ParalleliseVeyMontThreads.scala | 71 +++++++++++--------
3 files changed, 40 insertions(+), 33 deletions(-)
diff --git a/src/col/vct/col/ast/Node.scala b/src/col/vct/col/ast/Node.scala
index 9c066f1b7d..9d0d937320 100644
--- a/src/col/vct/col/ast/Node.scala
+++ b/src/col/vct/col/ast/Node.scala
@@ -189,7 +189,6 @@ final case class WandApply[G](res: Expr[G])(val blame: Blame[WandApplyFailed])(i
final case class Havoc[G](loc: Expr[G])(implicit val o: Origin) extends NormallyCompletingStatement[G] with HavocImpl[G]
final case class FramedProof[G](pre: Expr[G], body: Statement[G], post: Expr[G])(val blame: Blame[FramedProofFailure])(implicit val o: Origin) extends NormallyCompletingStatement[G] with FramedProofImpl[G]
final case class Extract[G](contractedStatement: Statement[G])(implicit val o: Origin) extends NormallyCompletingStatement[G] with ExtractImpl[G]
-final case class Skip[G]()(implicit val o: Origin) extends NormallyCompletingStatement[G]
sealed trait ExceptionalStatement[G] extends Statement[G] with ExceptionalStatementImpl[G]
final case class Eval[G](expr: Expr[G])(implicit val o: Origin) extends ExceptionalStatement[G] with EvalImpl[G]
diff --git a/src/col/vct/col/typerules/CoercingRewriter.scala b/src/col/vct/col/typerules/CoercingRewriter.scala
index 99fd2b8945..508ff96ce1 100644
--- a/src/col/vct/col/typerules/CoercingRewriter.scala
+++ b/src/col/vct/col/typerules/CoercingRewriter.scala
@@ -1574,7 +1574,6 @@ abstract class CoercingRewriter[Pre <: Generation]() extends AbstractRewriter[Pr
case ass @ SilverFieldAssign(obj, field, value) => SilverFieldAssign(ref(obj), field, coerce(value, field.decl.t))(ass.blame)
case SilverLocalAssign(v, value) => SilverLocalAssign(v, coerce(value, v.decl.t))
case SilverNewRef(v, fields) => SilverNewRef(v, fields)
- case Skip() => Skip()
case SpecIgnoreEnd() => SpecIgnoreEnd()
case SpecIgnoreStart() => SpecIgnoreStart()
case Switch(expr, body) => Switch(expr, body)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 3e13008df4..a109e8adec 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,19 +1,14 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast
-import vct.col.ast.RewriteHelpers.{RewriteAssign, RewriteDeref, RewriteJavaClass, RewriteMethodInvocation}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaInvocation, JavaMethod, JavaNamedType, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
-import vct.col.origin.{Origin, PreferredNameOrigin}
-import vct.col.ref.Ref
+import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass, RewriteJavaConstructor, RewriteMethodInvocation}
+import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaMethod, JavaNamedType, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.origin.Origin
import vct.col.resolve.ctx.RefJavaMethod
-import vct.col.rewrite.veymont.AddVeyMontAssignmentNodes.getDerefsFromExpr
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg, Rewritten}
import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
-import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelClassOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
-
-import scala.collection.immutable.Seq
+import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelFieldOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
override def key: String = "ParalleliseVeyMontThreads"
@@ -36,7 +31,7 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
override def shortPosition: String = thread.o.shortPosition
}
- case class ChannelClassOrigin(channelName: String, assign: Statement[_]) extends Origin {
+ case class ChannelFieldOrigin(channelName: String, assign: Statement[_]) extends Origin {
override def preferredName: String = channelName
override def context: String = assign.o.context
@@ -52,15 +47,13 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
private val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
private val threadClassSucc: SuccessionMap[VeyMontThread[Pre],Class[Post]] = SuccessionMap()
private val threadMethodSucc: SuccessionMap[(VeyMontThread[Pre],ClassDeclaration[Pre]),InstanceMethod[Post]] = SuccessionMap()
+ private val channelClassSucc: SuccessionMap[Type[Pre],JavaClass[Post]] = SuccessionMap()
+ private val channelClassName = "Channel"
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
- case seqProg: VeyMontSeqProg[Pre] =>
- val (channelClasses,channelFields) = extractChannelInfo(seqProg)
- dispatchThreads(seqProg, channelClasses, channelFields)
- case thread: VeyMontThread[Pre] => {
- dispatchThread(thread)
- }
+ case seqProg: VeyMontSeqProg[Pre] => dispatchThreads(seqProg)
+ case thread: VeyMontThread[Pre] => dispatchThread(thread)
case other => rewriteDefault(other)
}
}
@@ -73,23 +66,28 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
} else rewriteDefault(thread)
}
- private def dispatchThreads(seqProg: VeyMontSeqProg[Pre], channelClasses: Map[Type[Pre], JavaClass[Post]], channelFields: Map[(VeyMontCommExpression[Pre], Origin), InstanceField[Post]]): Unit = {
+ private def dispatchThreads(seqProg: VeyMontSeqProg[Pre]): Unit = {
+ val (channelClasses,indexedChannelInfo) = extractChannelInfo(seqProg)
+ channelClasses.foreach{ case (t,c) =>
+ globalDeclarations.declare(c)
+ channelClassSucc.update(t,c)
+ }
seqProg.threads.foreach(thread => {
val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
+ val channelFields = getChannelFields(thread, indexedChannelInfo, channelClasses)
threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods, channelFields, channelClasses, thread, threadField)) {
dispatch(thread)
}
})
}
- private def extractChannelInfo(seqProg: VeyMontSeqProg[Pre]): (Map[Type[Pre], JavaClass[Post]], Map[(VeyMontCommExpression[Pre], Origin), InstanceField[Post]]) = {
+ private def extractChannelInfo(seqProg: VeyMontSeqProg[Pre]): (Map[Type[Pre], JavaClass[Post]], Seq[ChannelInfo[Pre]]) = {
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
val indexedChannelInfo: Seq[ChannelInfo[Pre]] = channelInfo.groupBy(_.channelName).values.flatMap(chanInfoSeq =>
if (chanInfoSeq.size <= 1) chanInfoSeq
else chanInfoSeq.zipWithIndex.map { case (chanInfo, index) => new ChannelInfo(chanInfo.comExpr, chanInfo.channelType, chanInfo.channelName + index) }).toSeq
val channelClasses = generateChannelClasses(indexedChannelInfo)
- val channelFields = getChannelFields(indexedChannelInfo, channelClasses)
- (channelClasses, channelFields)
+ (channelClasses, indexedChannelInfo)
}
private def createThreadMethod(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre]) = {
@@ -101,13 +99,10 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}
private def createThreadClass(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre], threadMethods: Seq[ClassDeclaration[Post]]): Unit = {
- val channelFieldsForThread = threadRes.channelFields.view.filterKeys {
- case (comExpr,_) => comExpr.receiver.decl == thread || comExpr.sender.decl == thread
- }.values.toSeq
val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
classDeclarations.scope {
val threadClass = new Class[Post](
- (threadRes.threadField +: channelFieldsForThread) ++ (threadRun +: threadMethods), Seq(), BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
+ (threadRes.threadField +: threadRes.channelFields.values.toSeq) ++ (threadRun +: threadMethods), Seq(), BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
globalDeclarations.declare(threadClass)
threadClassSucc.update(thread, threadClass)
}
@@ -123,21 +118,30 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case _ => throw ParalliseVeyMontThreadsError(thread, "RunMethod expected in seq_program")
}
- private def getChannelFields(channelInfo: Seq[ChannelInfo[Pre]], channelClasses: Map[Type[Pre],JavaClass[Post]]): Map[(VeyMontCommExpression[Pre],Origin),InstanceField[Post]] = {
- channelInfo.map { chanInfo =>
- val chanField = new InstanceField[Post](JavaTClass(channelClasses(chanInfo.channelType).ref,Seq.empty), Set.empty)(ChannelClassOrigin(chanInfo.channelName,chanInfo.comExpr.assign))
- ((chanInfo.comExpr,chanInfo.comExpr.o), chanField) }.toMap
+ private def getChannelFields(thread: VeyMontThread[Pre], channelInfo: Seq[ChannelInfo[Pre]], channelClasses: Map[Type[Pre],JavaClass[Post]]): Map[(VeyMontCommExpression[Pre],Origin),InstanceField[Post]] = {
+ channelInfo
+ .filter( chanInfo => chanInfo.comExpr.receiver.decl == thread || chanInfo.comExpr.sender.decl == thread)
+ .map { chanInfo =>
+ val chanFieldOrigin = ChannelFieldOrigin(chanInfo.channelName,chanInfo.comExpr.assign)
+ val chanField = new InstanceField[Post](JavaTClass(channelClassSucc.ref(chanInfo.channelType),Seq.empty), Set.empty)(chanFieldOrigin)
+ ((chanInfo.comExpr, chanInfo.comExpr.o), chanField)
+ }.toMap
}
+ private def getChannelClassName(channelType: Type[_]): String =
+ channelType.toString.capitalize + channelClassName
+
private def generateChannelClasses(channelInfo: Seq[ChannelInfo[Pre]]) : Map[Type[Pre],JavaClass[Post]] = {
val channelTypes = channelInfo.map(_.channelType).toSet
channelTypes.map(channelType =>
channelType -> {
val chanClassPre = channelClass.asInstanceOf[JavaClass[Pre]]
val rw = ChannelClassGenerator(channelType)
- new RewriteJavaClass[Pre, Post](chanClassPre)(rw).rewrite(decls = classDeclarations.collect {
- chanClassPre.decls.foreach(d => rw.dispatch(d))
- }._1)
+ new RewriteJavaClass[Pre, Post](chanClassPre)(rw).rewrite(
+ name = getChannelClassName(channelType),
+ decls = classDeclarations.collect {
+ chanClassPre.decls.foreach(d => rw.dispatch(d))
+ }._1)
}
).toMap
}
@@ -152,6 +156,11 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
} else rewriteDefault(jnt)
case _ => rewriteDefault(t)
}
+
+ override def dispatch(decl: Declaration[Pre]): Unit = decl match {
+ case jc: JavaConstructor[Pre] => classDeclarations.declare(jc.rewrite(name = getChannelClassName(channelType))) //TODO: deze rewrite verwijderd de constructor..
+ case other => rewriteDefault(other)
+ }
}
private def collectChannelsFromRun(seqProg: VeyMontSeqProg[Pre]) =
From f36c2ba2d4ee979f98c7fd87326c99f95f6710f4 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Thu, 13 Jul 2023 17:26:15 +0200
Subject: [PATCH 16/20] VeyMont produces output
---
src/main/vct/main/modes/VeyMont.scala | 2 +-
src/main/vct/main/stages/CodeGeneration.scala | 67 +++++++++++++++++++
src/main/vct/main/stages/Stages.scala | 5 +-
src/main/vct/main/stages/Transformation.scala | 9 ++-
.../veymont/ParalleliseVeyMontThreads.scala | 2 +-
5 files changed, 76 insertions(+), 9 deletions(-)
create mode 100644 src/main/vct/main/stages/CodeGeneration.scala
diff --git a/src/main/vct/main/modes/VeyMont.scala b/src/main/vct/main/modes/VeyMont.scala
index c9405ebe20..cb51f3a472 100644
--- a/src/main/vct/main/modes/VeyMont.scala
+++ b/src/main/vct/main/modes/VeyMont.scala
@@ -14,7 +14,7 @@ object VeyMont extends LazyLogging {
def verifyWithOptions(options: Options, inputs: Seq[PathOrStd]) = {
val collector = BlameCollector()
- val stages = Stages.veymontOfOptions(options, ConstantBlameProvider(collector))
+ val stages = Stages.veymontTransformationOfOptions(options, ConstantBlameProvider(collector))
logger.debug("Stages: " ++ stages.flatNames.map(_._1).mkString(", "))
stages.run(inputs) match {
case Left(value) => logger.error(value.text)
diff --git a/src/main/vct/main/stages/CodeGeneration.scala b/src/main/vct/main/stages/CodeGeneration.scala
new file mode 100644
index 0000000000..0e350061f2
--- /dev/null
+++ b/src/main/vct/main/stages/CodeGeneration.scala
@@ -0,0 +1,67 @@
+package vct.main.stages
+
+import hre.progress.Progress
+import hre.stages.Stage
+import vct.col.ast.{JavaClass, Node, Verification}
+import vct.col.print.Ctx
+import vct.col.rewrite.{Generation, PrettifyBlocks, RewriterBuilder}
+import vct.importer.Util
+import vct.main.stages.Transformation.writeOutFunctions
+import vct.options.Options
+import vct.options.types.{Backend, PathOrStd}
+import vct.rewrite.veymont.ParalleliseVeyMontThreads
+
+object CodeGeneration {
+
+ private def writeOutFunctions(m: Map[String, PathOrStd]): Seq[(String, Verification[_ <: Generation] => Unit)] =
+ m.toSeq.map {
+ case (key, out) => (key, (program: Verification[_ <: Generation]) => out.write { writer =>
+ program.write(writer)(Ctx().namesIn(program))
+ })
+ }
+
+ def veymontGenerationOfOptions(options: Options): VeyMontGeneration =
+ options.backend match {
+ case Backend.Silicon | Backend.Carbon =>
+ VeyMontGeneration(
+ onBeforePassKey = writeOutFunctions(options.outputBeforePass),
+ onAfterPassKey = writeOutFunctions(options.outputAfterPass),
+ channelClass = Util.loadJavaClass(options.veymontChannel),
+ )
+ }
+}
+
+class CodeGeneration(val onBeforePassKey: Seq[(String, Verification[_ <: Generation] => Unit)],
+ val onAfterPassKey: Seq[(String, Verification[_ <: Generation] => Unit)],
+ val passes: Seq[RewriterBuilder]
+ ) extends Stage[Verification[_ <: Generation], Verification[_ <: Generation]] {
+ override def friendlyName: String = "Generating VeyMont output"
+
+ override def progressWeight: Int = 1
+
+ override def run(input: Verification[_ <: Generation]): Verification[_ <: Generation] = {
+ var result: Verification[_ <: Generation] = input
+ Progress.foreach(passes, (pass: RewriterBuilder) => pass.key) { pass =>
+ onBeforePassKey.foreach {
+ case (key, action) => if (pass.key == key) action(result)
+ }
+
+ result = pass().dispatch(result)
+
+ onAfterPassKey.foreach {
+ case (key, action) => if (pass.key == key) action(result)
+ }
+
+ result = PrettifyBlocks().dispatch(result)
+ }
+ result
+ }
+
+}
+
+case class VeyMontGeneration(override val onBeforePassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil,
+ override val onAfterPassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil,
+ channelClass: JavaClass[_])
+ extends CodeGeneration(onBeforePassKey, onAfterPassKey, Seq(
+ ParalleliseVeyMontThreads.withArg(channelClass),
+ ))
diff --git a/src/main/vct/main/stages/Stages.scala b/src/main/vct/main/stages/Stages.scala
index cc7155ebda..2be2b1151a 100644
--- a/src/main/vct/main/stages/Stages.scala
+++ b/src/main/vct/main/stages/Stages.scala
@@ -58,10 +58,11 @@ case object Stages {
.thenRun(ExpectedErrors.ofOptions(options))
}
- def veymontOfOptions(options: Options, blameProvider: BlameProvider): Stages[Seq[Readable], Unit] = {
+ def veymontTransformationOfOptions(options: Options, blameProvider: BlameProvider): Stages[Seq[Readable], Unit] = {
Parsing.ofOptions(options, blameProvider)
.thenRun(Resolution.ofOptions(options, blameProvider))
- .thenRun(Transformation.veymontOfOptions(options))
+ .thenRun(Transformation.veymontTransformationOfOptions(options))
+ .thenRun(CodeGeneration.veymontGenerationOfOptions(options))
.thenRun(Output.veymontOfOptions(options))
}
diff --git a/src/main/vct/main/stages/Transformation.scala b/src/main/vct/main/stages/Transformation.scala
index ad04613619..11131f15ef 100644
--- a/src/main/vct/main/stages/Transformation.scala
+++ b/src/main/vct/main/stages/Transformation.scala
@@ -65,13 +65,12 @@ object Transformation {
)
}
- def veymontOfOptions(options: Options): Transformation =
+ def veymontTransformationOfOptions(options: Options): Transformation =
options.backend match {
case Backend.Silicon | Backend.Carbon =>
VeyMontTransformation(
onBeforePassKey = writeOutFunctions(options.outputBeforePass),
onAfterPassKey = writeOutFunctions(options.outputAfterPass),
- channelClass = Util.loadJavaClass(options.veymontChannel),
)
}
}
@@ -289,12 +288,12 @@ case class SilverTransformation
))
case class VeyMontTransformation(override val onBeforePassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil,
- override val onAfterPassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil,
- val channelClass: JavaClass[_])
+ override val onAfterPassKey: Seq[(String, Verification[_ <: Generation] => Unit)] = Nil)
extends Transformation(onBeforePassKey, onAfterPassKey, Seq(
AddVeyMontAssignmentNodes,
AddVeyMontConditionNodes,
StructureCheck,
- ParalleliseVeyMontThreads.withArg(channelClass),
))
+
+
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index a109e8adec..99158fa3ec 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -158,7 +158,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}
override def dispatch(decl: Declaration[Pre]): Unit = decl match {
- case jc: JavaConstructor[Pre] => classDeclarations.declare(jc.rewrite(name = getChannelClassName(channelType))) //TODO: deze rewrite verwijderd de constructor..
+ case jc: JavaConstructor[Pre] => classDeclarations.declare(jc.rewrite(name = getChannelClassName(channelType)))
case other => rewriteDefault(other)
}
}
From 58664396d62b8fb1dc9e84f020412dd0e4a7c4ae Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Mon, 17 Jul 2023 19:21:37 +0200
Subject: [PATCH 17/20] A reference to the successor of this declaration was
made, but it has no successor.
---
src/col/vct/col/ast/Node.scala | 3 +-
src/col/vct/col/ast/lang/JavaFieldsImpl.scala | 2 +-
.../ast/lang/JavaLocalDeclarationImpl.scala | 2 +-
src/col/vct/col/ast/lang/JavaMethodImpl.scala | 2 +-
src/col/vct/col/ast/lang/JavaParamImpl.scala | 9 ++
src/col/vct/col/ast/type/TUnionImpl.scala | 2 +
.../col/ast/type/TVeyMontChannelImpl.scala | 9 ++
.../veymont/ParalleliseVeyMontThreads.scala | 127 ++++++++++++++++--
8 files changed, 139 insertions(+), 17 deletions(-)
create mode 100644 src/col/vct/col/ast/lang/JavaParamImpl.scala
create mode 100644 src/col/vct/col/ast/type/TVeyMontChannelImpl.scala
diff --git a/src/col/vct/col/ast/Node.scala b/src/col/vct/col/ast/Node.scala
index 9d0d937320..1d000bf8b5 100644
--- a/src/col/vct/col/ast/Node.scala
+++ b/src/col/vct/col/ast/Node.scala
@@ -141,6 +141,7 @@ final case class TAnyClass[G]()(implicit val o: Origin = DiagnosticOrigin) exten
final case class TAxiomatic[G](adt: Ref[G, AxiomaticDataType[G]], args: Seq[Type[G]])(implicit val o: Origin = DiagnosticOrigin) extends DeclaredType[G] with TAxiomaticImpl[G]
final case class TEnum[G](enum: Ref[G, Enum[G]])(implicit val o: Origin = DiagnosticOrigin) extends DeclaredType[G]
final case class TProverType[G](ref: Ref[G, ProverType[G]])(implicit val o: Origin = DiagnosticOrigin) extends DeclaredType[G] with TProverTypeImpl[G]
+final case class TVeyMontChannel[G](channelType: String)(implicit val o: Origin = DiagnosticOrigin) extends DeclaredType[G] with TVeyMontChannelImpl[G]
sealed trait ParRegion[G] extends NodeFamily[G] with ParRegionImpl[G]
final case class ParParallel[G](regions: Seq[ParRegion[G]])(val blame: Blame[ParPreconditionFailed])(implicit val o: Origin) extends ParRegion[G] with ParParallelImpl[G]
@@ -994,7 +995,7 @@ sealed trait JavaClassDeclaration[G] extends ClassDeclaration[G] with JavaClassD
final class JavaSharedInitialization[G](val isStatic: Boolean, val initialization: Statement[G])(implicit val o: Origin) extends JavaClassDeclaration[G] with JavaSharedInitializationImpl[G]
final class JavaFields[G](val modifiers: Seq[JavaModifier[G]], val t: Type[G], val decls: Seq[JavaVariableDeclaration[G]])(implicit val o: Origin) extends JavaClassDeclaration[G] with JavaFieldsImpl[G]
final class JavaConstructor[G](val modifiers: Seq[JavaModifier[G]], val name: String, val parameters: Seq[JavaParam[G]], val typeParameters: Seq[Variable[G]], val signals: Seq[Type[G]], val body: Statement[G], val contract: ApplicableContract[G])(val blame: Blame[ConstructorFailure])(implicit val o: Origin) extends JavaClassDeclaration[G] with JavaConstructorImpl[G]
-final class JavaParam[G](val modifiers: Seq[JavaModifier[G]], val name: String, val t: Type[G])(implicit val o: Origin) extends Declaration[G]
+final class JavaParam[G](val modifiers: Seq[JavaModifier[G]], val name: String, val t: Type[G])(implicit val o: Origin) extends Declaration[G] with JavaParamImpl[G]
final class JavaMethod[G](val modifiers: Seq[JavaModifier[G]], val returnType: Type[G], val dims: Int, val name: String, val parameters: Seq[JavaParam[G]], val typeParameters: Seq[Variable[G]], val signals: Seq[Type[G]], val body: Option[Statement[G]], val contract: ApplicableContract[G])(val blame: Blame[CallableFailure])(implicit val o: Origin) extends JavaClassDeclaration[G] with JavaMethodImpl[G]
final class JavaAnnotationMethod[G](val returnType: Type[G], val name: String, val default: Option[Expr[G]])(implicit val o: Origin) extends JavaClassDeclaration[G] with JavaAnnotationMethodImpl[G]
diff --git a/src/col/vct/col/ast/lang/JavaFieldsImpl.scala b/src/col/vct/col/ast/lang/JavaFieldsImpl.scala
index b5cce4b2cb..9749895420 100644
--- a/src/col/vct/col/ast/lang/JavaFieldsImpl.scala
+++ b/src/col/vct/col/ast/lang/JavaFieldsImpl.scala
@@ -7,5 +7,5 @@ trait JavaFieldsImpl[G] { this: JavaFields[G] =>
override def isStatic = modifiers.contains(JavaStatic[G]())
override def layout(implicit ctx: Ctx): Doc =
- Doc.lspread(modifiers) <> t <+> Doc.spread(decls) <> ";"
+ Doc.rspread(modifiers) <> t <+> Doc.spread(decls) <> ";"
}
\ No newline at end of file
diff --git a/src/col/vct/col/ast/lang/JavaLocalDeclarationImpl.scala b/src/col/vct/col/ast/lang/JavaLocalDeclarationImpl.scala
index ae4b1c024b..c2c1d5668a 100644
--- a/src/col/vct/col/ast/lang/JavaLocalDeclarationImpl.scala
+++ b/src/col/vct/col/ast/lang/JavaLocalDeclarationImpl.scala
@@ -5,5 +5,5 @@ import vct.col.print.{Ctx, Doc, Group}
trait JavaLocalDeclarationImpl[G] { this: JavaLocalDeclaration[G] =>
override def layout(implicit ctx: Ctx): Doc =
- Group(Doc.lspread(modifiers) <> t <+> Doc.args(decls))
+ Group(Doc.rspread(modifiers) <> t <+> Doc.args(decls))
}
\ No newline at end of file
diff --git a/src/col/vct/col/ast/lang/JavaMethodImpl.scala b/src/col/vct/col/ast/lang/JavaMethodImpl.scala
index ce9b1a7fc9..9a3c00bb0d 100644
--- a/src/col/vct/col/ast/lang/JavaMethodImpl.scala
+++ b/src/col/vct/col/ast/lang/JavaMethodImpl.scala
@@ -12,7 +12,7 @@ trait JavaMethodImpl[G] extends Declarator[G] { this: JavaMethod[G] =>
Doc.stack(Seq(
contract,
Group(Group(Group(
- Doc.lspread(modifiers) <>
+ Doc.rspread(modifiers) <>
(if(typeParameters.isEmpty) Empty else Text("<") <> Doc.args(typeParameters) <> ">" <+> Empty) <>
returnType <+> name <> "[]".repeat(dims)) <> "(" <> Doc.args(parameters) <> ")") <>
(if(signals.isEmpty) Empty else Empty <>> Group(Text("throws") <+> Doc.args(signals)))
diff --git a/src/col/vct/col/ast/lang/JavaParamImpl.scala b/src/col/vct/col/ast/lang/JavaParamImpl.scala
new file mode 100644
index 0000000000..9f3b2e1b99
--- /dev/null
+++ b/src/col/vct/col/ast/lang/JavaParamImpl.scala
@@ -0,0 +1,9 @@
+package vct.col.ast.lang
+
+import vct.col.ast.JavaParam
+import vct.col.print.{Ctx, Doc, Text}
+
+trait JavaParamImpl[G] { this: JavaParam[G] =>
+ override def layout(implicit ctx: Ctx): Doc = Text(t + " " + name)
+
+}
diff --git a/src/col/vct/col/ast/type/TUnionImpl.scala b/src/col/vct/col/ast/type/TUnionImpl.scala
index c598defaa8..af0f33e3e1 100644
--- a/src/col/vct/col/ast/type/TUnionImpl.scala
+++ b/src/col/vct/col/ast/type/TUnionImpl.scala
@@ -1,7 +1,9 @@
package vct.col.ast.`type`
import vct.col.ast.TUnion
+import vct.col.print.{Ctx, Doc}
trait TUnionImpl[G] { this: TUnion[G] =>
+ override def layout(implicit ctx: Ctx): Doc = Doc.spread(types)
}
\ No newline at end of file
diff --git a/src/col/vct/col/ast/type/TVeyMontChannelImpl.scala b/src/col/vct/col/ast/type/TVeyMontChannelImpl.scala
new file mode 100644
index 0000000000..7c73695267
--- /dev/null
+++ b/src/col/vct/col/ast/type/TVeyMontChannelImpl.scala
@@ -0,0 +1,9 @@
+package vct.col.ast.`type`
+
+import vct.col.ast.TVeyMontChannel
+import vct.col.print.{Ctx, Doc, Text}
+
+trait TVeyMontChannelImpl[G] { this: TVeyMontChannel[G] =>
+ override def layout(implicit ctx: Ctx): Doc =
+ Text(this.channelType)
+}
\ No newline at end of file
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index 99158fa3ec..ebe3107304 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,20 +1,33 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.RewriteHelpers.{RewriteDeref, RewriteJavaClass, RewriteJavaConstructor, RewriteMethodInvocation}
-import vct.col.ast.{Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaMethod, JavaNamedType, JavaTClass, Local, Loop, MethodInvocation, Node, Program, RunMethod, Scope, Statement, TClass, ThisObject, ThisSeqProg, Type, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.RewriteHelpers.{RewriteClass, RewriteDeref, RewriteJavaClass, RewriteJavaConstructor, RewriteMethodInvocation}
+import vct.col.ast.{ApplicableContract, Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaLocal, JavaMethod, JavaNamedType, JavaParam, JavaPublic, JavaTClass, Local, Loop, MethodInvocation, NewObject, Node, Procedure, Program, RunMethod, Scope, Statement, TClass, TVeyMontChannel, ThisObject, ThisSeqProg, Type, UnitAccountedPredicate, Variable, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.Origin
import vct.col.resolve.ctx.RefJavaMethod
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg, Rewritten}
import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
-import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelFieldOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin}
+import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelFieldOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin, getChannelClassName, getThreadClassName, getVarName}
+
+import java.lang
object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
override def key: String = "ParalleliseVeyMontThreads"
override def desc: String = "Generate classes for VeyMont threads in parallel program"
+ private val channelClassName = "Channel"
+ private val threadClassName = "Thread"
+
+ def getChannelClassName(channelType: Type[_]): String =
+ channelType.toString.capitalize + channelClassName
+
+ def getThreadClassName(thread: VeyMontThread[_]) : String =
+ thread.o.preferredName.capitalize + threadClassName
+
+ def getVarName(v: Variable[_]) = v.o.preferredName
+
case class ParalliseVeyMontThreadsError(node : Node[_], msg: String) extends UserError {
override def code: String = "ParalleliseVeyMontThreadsError"
@@ -22,7 +35,7 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
}
case class ThreadClassOrigin(thread: VeyMontThread[_]) extends Origin {
- override def preferredName: String = thread.o.preferredName.toUpperCase() + "Thread"
+ override def preferredName: String = getThreadClassName(thread)
override def context: String = thread.o.context
@@ -47,11 +60,13 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
private val threadBuildingBlocks: ScopedStack[ThreadBuildingBlocks[Pre]] = ScopedStack()
private val threadClassSucc: SuccessionMap[VeyMontThread[Pre],Class[Post]] = SuccessionMap()
private val threadMethodSucc: SuccessionMap[(VeyMontThread[Pre],ClassDeclaration[Pre]),InstanceMethod[Post]] = SuccessionMap()
- private val channelClassSucc: SuccessionMap[Type[Pre],JavaClass[Post]] = SuccessionMap()
- private val channelClassName = "Channel"
+ private val givenClassSucc: SuccessionMap[Type[Pre],Class[Post]] = SuccessionMap()
+ private val givenClassConstrSucc: SuccessionMap[Type[Pre],Procedure[Pre]] = SuccessionMap()
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
+ case p: Procedure[Pre] => givenClassConstrSucc.update(p.returnType,p)
+ case c : Class[Pre] => globalDeclarations.declare(dispatchGivenClass(c))
case seqProg: VeyMontSeqProg[Pre] => dispatchThreads(seqProg)
case thread: VeyMontThread[Pre] => dispatchThread(thread)
case other => rewriteDefault(other)
@@ -70,10 +85,9 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
val (channelClasses,indexedChannelInfo) = extractChannelInfo(seqProg)
channelClasses.foreach{ case (t,c) =>
globalDeclarations.declare(c)
- channelClassSucc.update(t,c)
}
seqProg.threads.foreach(thread => {
- val threadField = new InstanceField[Post](dispatch(thread.threadType), Set.empty)(thread.o)
+ val threadField = new InstanceField[Post](TClass(givenClassSucc.ref(thread.threadType)), Set.empty)(thread.o)
val channelFields = getChannelFields(thread, indexedChannelInfo, channelClasses)
threadBuildingBlocks.having(new ThreadBuildingBlocks(seqProg.runMethod, seqProg.methods, channelFields, channelClasses, thread, threadField)) {
dispatch(thread)
@@ -81,6 +95,65 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
})
}
+ private def dispatchGivenClass(c: Class[Pre]): Class[Post] = {
+ val rw = GivenClassRewriter()
+ val gc = new RewriteClass[Pre, Post](c)(rw).rewrite(
+ declarations = classDeclarations.collect {
+ (givenClassConstrSucc.get(TClass(c.ref)).get +: c.declarations).foreach(d => rw.dispatch(d))
+ }._1)
+ givenClassSucc.update(TClass(c.ref),gc)
+ gc
+ }
+
+ case class GivenClassRewriter() extends Rewriter[Pre] {
+ override val allScopes = outer.allScopes
+
+ val rewritingConstr: ScopedStack[(Seq[Variable[Pre]],TClass[Pre])] = ScopedStack()
+
+ override def dispatch(decl: Declaration[Pre]): Unit = decl match {
+ case p: Procedure[Pre] => p.returnType match {
+ case tc: TClass[Pre] => rewritingConstr.having(p.args,tc){ classDeclarations.declare(createClassConstructor(p)) };
+ case _ => ??? //("This procedure is expected to have a class as return type");
+ }
+ case other => rewriteDefault(other)
+ }
+
+ def createClassConstructor(p: Procedure[Pre]): JavaConstructor[Post] =
+ new JavaConstructor[Post](Seq(JavaPublic[Post]()(p.o)),
+ rewritingConstr.top._2.cls.decl.o.preferredName,
+ p.args.map(createJavaParam),
+ variables.dispatch(p.typeArgs),
+ Seq.empty, dispatch(p.body.get),
+ dispatch(p.contract))(null)(p.o)
+
+ def createJavaParam(v: Variable[Pre]): JavaParam[Post] =
+ new JavaParam[Post](Seq.empty, getVarName(v), dispatch(v.t))(v.o)
+
+ override def dispatch(e: Expr[Pre]): Expr[Post] = e match {
+ case l: Local[Pre] =>
+ if(rewritingConstr.nonEmpty && rewritingConstr.top._1.contains(l.ref.decl))
+ JavaLocal[Post](getVarName(l.ref.decl))(null)(e.o)
+ else rewriteDefault(l)
+ case no: NewObject[Pre] =>
+ val newClassType = TClass(no.cls)
+ if(rewritingConstr.nonEmpty && rewritingConstr.top._2 == newClassType)
+ NewObject(givenClassSucc.ref[Post,Class[Post]](newClassType))(no.o)
+ else rewriteDefault(no)
+ case t: ThisObject[Pre] =>
+ val thisClassType = TClass(t.cls)
+ if(rewritingConstr.nonEmpty && rewritingConstr.top._2 == thisClassType)
+ ThisObject(givenClassSucc.ref[Post,Class[Post]](thisClassType))(t.o)
+ else rewriteDefault(t)
+ case other => rewriteDefault(other)
+ }
+
+ override def dispatch(t: Type[Pre]): Type[Post] = {
+ if(rewritingConstr.nonEmpty && rewritingConstr.top._2 == t)
+ TClass(givenClassSucc.ref(t))
+ else rewriteDefault(t)
+ }
+ }
+
private def extractChannelInfo(seqProg: VeyMontSeqProg[Pre]): (Map[Type[Pre], JavaClass[Post]], Seq[ChannelInfo[Pre]]) = {
val channelInfo = collectChannelsFromRun(seqProg) ++ collectChannelsFromMethods(seqProg)
val indexedChannelInfo: Seq[ChannelInfo[Pre]] = channelInfo.groupBy(_.channelName).values.flatMap(chanInfoSeq =>
@@ -99,15 +172,46 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
}
private def createThreadClass(thread: VeyMontThread[Pre], threadRes: ThreadBuildingBlocks[Pre], threadMethods: Seq[ClassDeclaration[Post]]): Unit = {
+ val threadConstr = createThreadClassConstructor(thread,threadRes.threadField)
val threadRun = getThreadRunFromDecl(thread, threadRes.runMethod)
classDeclarations.scope {
val threadClass = new Class[Post](
- (threadRes.threadField +: threadRes.channelFields.values.toSeq) ++ (threadRun +: threadMethods), Seq(), BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
+ (threadRes.threadField +: threadRes.channelFields.values.toSeq) ++ (threadConstr +: threadRun +: threadMethods), Seq(), BooleanValue(true)(thread.o))(ThreadClassOrigin(thread))
globalDeclarations.declare(threadClass)
threadClassSucc.update(thread, threadClass)
}
}
+ private def createThreadClassConstructor(thread: VeyMontThread[Pre], threadField: InstanceField[Post]): JavaConstructor[Post] = {
+ val threadConstrArgBlocks = thread.args.map{
+ case l: Local[Pre] => (l.ref.decl.o.preferredName,dispatch(l.t))
+ case other => throw ParalliseVeyMontThreadsError(other,"This node is expected to be an argument of seq_prog, and have type Local")
+ }
+ val threadConstrArgs: Seq[JavaParam[Post]] =
+ threadConstrArgBlocks.map{ case (a,t) => new JavaParam[Post](Seq.empty, a, t)(ThreadClassOrigin(thread)) }
+ val passedArgs = threadConstrArgs.map(a => JavaLocal[Post](a.name)(null)(ThreadClassOrigin(thread)))
+ val ThreadTypeName = thread.threadType match {
+ case tc: TClass[Pre] => tc.cls.decl.o.preferredName
+ case _ => throw ParalliseVeyMontThreadsError(thread.threadType,"This type is expected to be a class")
+ }
+ val threadConstrBody = {
+ Assign(getThisVeyMontDeref(thread,ThreadClassOrigin(thread),threadField),
+ JavaInvocation[Post](None, Seq.empty, "new " + ThreadTypeName, passedArgs, Seq.empty, Seq.empty)(null)(ThreadClassOrigin(thread)))(null)(ThreadClassOrigin(thread))
+ }
+ val threadConstrContract = new ApplicableContract[Post](
+ UnitAccountedPredicate[Post](BooleanValue(true)(ThreadClassOrigin(thread)))(ThreadClassOrigin(thread)),
+ UnitAccountedPredicate[Post](BooleanValue(true)(ThreadClassOrigin(thread)))(ThreadClassOrigin(thread)),
+ BooleanValue(true)(ThreadClassOrigin(thread)),
+ Seq.empty, Seq.empty, Seq.empty, None)(null)(ThreadClassOrigin(thread))
+ new JavaConstructor[Post](
+ Seq(JavaPublic[Post]()(ThreadClassOrigin(thread))),
+ getThreadClassName(thread),
+ threadConstrArgs,
+ Seq.empty, Seq.empty,
+ threadConstrBody,
+ threadConstrContract)(ThreadClassOrigin(thread))(ThreadClassOrigin(thread))
+ }
+
private def getThreadMethodFromDecl(thread: VeyMontThread[Pre])(decl: ClassDeclaration[Pre]): InstanceMethod[Post] = decl match {
case m: InstanceMethod[Pre] => getThreadMethod(m)
case _ => throw ParalliseVeyMontThreadsError(thread, "Methods of seq_program need to be of type InstanceMethod")
@@ -123,14 +227,11 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
.filter( chanInfo => chanInfo.comExpr.receiver.decl == thread || chanInfo.comExpr.sender.decl == thread)
.map { chanInfo =>
val chanFieldOrigin = ChannelFieldOrigin(chanInfo.channelName,chanInfo.comExpr.assign)
- val chanField = new InstanceField[Post](JavaTClass(channelClassSucc.ref(chanInfo.channelType),Seq.empty), Set.empty)(chanFieldOrigin)
+ val chanField = new InstanceField[Post](TVeyMontChannel(getChannelClassName(chanInfo.channelType)), Set.empty)(chanFieldOrigin)
((chanInfo.comExpr, chanInfo.comExpr.o), chanField)
}.toMap
}
- private def getChannelClassName(channelType: Type[_]): String =
- channelType.toString.capitalize + channelClassName
-
private def generateChannelClasses(channelInfo: Seq[ChannelInfo[Pre]]) : Map[Type[Pre],JavaClass[Post]] = {
val channelTypes = channelInfo.map(_.channelType).toSet
channelTypes.map(channelType =>
From 308204b4e6aeb15eaa3571416cb7daf119f61e88 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Mon, 17 Jul 2023 22:44:19 +0200
Subject: [PATCH 18/20] rewriting constructor to original format
---
.../veymont/ParalleliseVeyMontThreads.scala | 39 ++++++++++---------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index ebe3107304..c01acdae6e 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -1,11 +1,11 @@
package vct.rewrite.veymont
import hre.util.ScopedStack
-import vct.col.ast.RewriteHelpers.{RewriteClass, RewriteDeref, RewriteJavaClass, RewriteJavaConstructor, RewriteMethodInvocation}
-import vct.col.ast.{ApplicableContract, Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaLocal, JavaMethod, JavaNamedType, JavaParam, JavaPublic, JavaTClass, Local, Loop, MethodInvocation, NewObject, Node, Procedure, Program, RunMethod, Scope, Statement, TClass, TVeyMontChannel, ThisObject, ThisSeqProg, Type, UnitAccountedPredicate, Variable, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.RewriteHelpers.{RewriteApplicableContract, RewriteClass, RewriteDeref, RewriteJavaClass, RewriteJavaConstructor, RewriteMethodInvocation}
+import vct.col.ast.{AbstractRewriter, ApplicableContract, Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaLocal, JavaMethod, JavaNamedType, JavaParam, JavaPublic, JavaTClass, Local, Loop, MethodInvocation, NewObject, Node, Procedure, Program, RunMethod, Scope, Statement, TClass, TVeyMontChannel, ThisObject, ThisSeqProg, Type, UnitAccountedPredicate, Variable, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.Origin
import vct.col.resolve.ctx.RefJavaMethod
-import vct.col.rewrite.{Generation, Rewriter, RewriterBuilderArg, Rewritten}
+import vct.col.rewrite.{Generation, Rewriter, RewriterBuilder, RewriterBuilderArg, Rewritten}
import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelFieldOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin, getChannelClassName, getThreadClassName, getVarName}
@@ -123,8 +123,15 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
rewritingConstr.top._2.cls.decl.o.preferredName,
p.args.map(createJavaParam),
variables.dispatch(p.typeArgs),
- Seq.empty, dispatch(p.body.get),
- dispatch(p.contract))(null)(p.o)
+ Seq.empty,
+ p.body match {
+ case Some(s: Scope[Pre]) => s.body match {
+ case b: Block[Pre] => dispatch(Block(b.statements.tail.dropRight(1))(p.o))
+ case other => dispatch(other)
+ }
+ case None => Block(Seq.empty)(p.o)
+ },
+ p.contract.rewrite(ensures = UnitAccountedPredicate[Post](BooleanValue(true)(p.o))(p.o)))(null)(p.o)
def createJavaParam(v: Variable[Pre]): JavaParam[Post] =
new JavaParam[Post](Seq.empty, getVarName(v), dispatch(v.t))(v.o)
@@ -134,24 +141,20 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
if(rewritingConstr.nonEmpty && rewritingConstr.top._1.contains(l.ref.decl))
JavaLocal[Post](getVarName(l.ref.decl))(null)(e.o)
else rewriteDefault(l)
- case no: NewObject[Pre] =>
- val newClassType = TClass(no.cls)
- if(rewritingConstr.nonEmpty && rewritingConstr.top._2 == newClassType)
- NewObject(givenClassSucc.ref[Post,Class[Post]](newClassType))(no.o)
- else rewriteDefault(no)
case t: ThisObject[Pre] =>
val thisClassType = TClass(t.cls)
if(rewritingConstr.nonEmpty && rewritingConstr.top._2 == thisClassType)
ThisObject(givenClassSucc.ref[Post,Class[Post]](thisClassType))(t.o)
else rewriteDefault(t)
+ case d: Deref[Pre] =>
+ if(rewritingConstr.nonEmpty)
+ d.obj match {
+ case _: Local[Pre] => d.rewrite(obj = ThisObject(givenClassSucc.ref[Post,Class[Post]](rewritingConstr.top._2))(d.o))
+ case other => rewriteDefault(other)
+ }
+ else rewriteDefault(d)
case other => rewriteDefault(other)
}
-
- override def dispatch(t: Type[Pre]): Type[Post] = {
- if(rewritingConstr.nonEmpty && rewritingConstr.top._2 == t)
- TClass(givenClassSucc.ref(t))
- else rewriteDefault(t)
- }
}
private def extractChannelInfo(seqProg: VeyMontSeqProg[Pre]): (Map[Type[Pre], JavaClass[Post]], Seq[ChannelInfo[Pre]]) = {
@@ -190,13 +193,13 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
val threadConstrArgs: Seq[JavaParam[Post]] =
threadConstrArgBlocks.map{ case (a,t) => new JavaParam[Post](Seq.empty, a, t)(ThreadClassOrigin(thread)) }
val passedArgs = threadConstrArgs.map(a => JavaLocal[Post](a.name)(null)(ThreadClassOrigin(thread)))
- val ThreadTypeName = thread.threadType match {
+ val threadTypeName = thread.threadType match { //TODO: replace by using givenClassSucc
case tc: TClass[Pre] => tc.cls.decl.o.preferredName
case _ => throw ParalliseVeyMontThreadsError(thread.threadType,"This type is expected to be a class")
}
val threadConstrBody = {
Assign(getThisVeyMontDeref(thread,ThreadClassOrigin(thread),threadField),
- JavaInvocation[Post](None, Seq.empty, "new " + ThreadTypeName, passedArgs, Seq.empty, Seq.empty)(null)(ThreadClassOrigin(thread)))(null)(ThreadClassOrigin(thread))
+ JavaInvocation[Post](None, Seq.empty, "new " + threadTypeName, passedArgs, Seq.empty, Seq.empty)(null)(ThreadClassOrigin(thread)))(null)(ThreadClassOrigin(thread))
}
val threadConstrContract = new ApplicableContract[Post](
UnitAccountedPredicate[Post](BooleanValue(true)(ThreadClassOrigin(thread)))(ThreadClassOrigin(thread)),
From 0a16fa69249f0d44204781e3fb03298aaa13326f Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Tue, 18 Jul 2023 13:13:00 +0200
Subject: [PATCH 19/20] compiling Java code
---
.../veymont-seq-progs/veymont-swap.pvl | 2 +-
.../veymont/ParalleliseVeyMontThreads.scala | 27 ++++++++++++++-----
.../vct/rewrite/veymont/StructureCheck.scala | 2 ++
3 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/examples/technical/veymont-seq-progs/veymont-swap.pvl b/examples/technical/veymont-seq-progs/veymont-swap.pvl
index 471c083458..e39a0abd21 100644
--- a/examples/technical/veymont-seq-progs/veymont-swap.pvl
+++ b/examples/technical/veymont-seq-progs/veymont-swap.pvl
@@ -22,7 +22,7 @@ seq_program SeqProgram(int x, int y) {
thread s1 = Storage(x);
thread s2 = Storage(y);
- int num() {}
+ //int num() {}
void foo() {
s1.temp = 7;
diff --git a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
index c01acdae6e..3d98b04c76 100644
--- a/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
+++ b/src/rewrite/vct/rewrite/veymont/ParalleliseVeyMontThreads.scala
@@ -2,13 +2,13 @@ package vct.rewrite.veymont
import hre.util.ScopedStack
import vct.col.ast.RewriteHelpers.{RewriteApplicableContract, RewriteClass, RewriteDeref, RewriteJavaClass, RewriteJavaConstructor, RewriteMethodInvocation}
-import vct.col.ast.{AbstractRewriter, ApplicableContract, Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaLocal, JavaMethod, JavaNamedType, JavaParam, JavaPublic, JavaTClass, Local, Loop, MethodInvocation, NewObject, Node, Procedure, Program, RunMethod, Scope, Statement, TClass, TVeyMontChannel, ThisObject, ThisSeqProg, Type, UnitAccountedPredicate, Variable, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
+import vct.col.ast.{AbstractRewriter, ApplicableContract, Assert, Assign, Block, BooleanValue, Branch, Class, ClassDeclaration, Declaration, Deref, DerefVeyMontThread, Eval, Expr, InstanceField, InstanceMethod, JavaClass, JavaConstructor, JavaInvocation, JavaLocal, JavaMethod, JavaNamedType, JavaParam, JavaPublic, JavaTClass, Local, Loop, MethodInvocation, NewObject, Node, Procedure, Program, RunMethod, Scope, Statement, TClass, TVeyMontChannel, TVoid, ThisObject, ThisSeqProg, Type, UnitAccountedPredicate, Variable, VeyMontAssignExpression, VeyMontCommExpression, VeyMontCondition, VeyMontSeqProg, VeyMontThread}
import vct.col.origin.Origin
import vct.col.resolve.ctx.RefJavaMethod
import vct.col.rewrite.{Generation, Rewriter, RewriterBuilder, RewriterBuilderArg, Rewritten}
import vct.col.util.SuccessionMap
import vct.result.VerificationError.UserError
-import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelFieldOrigin, ParalliseVeyMontThreadsError, ThreadClassOrigin, getChannelClassName, getThreadClassName, getVarName}
+import vct.rewrite.veymont.ParalleliseVeyMontThreads.{ChannelFieldOrigin, ParalliseVeyMontThreadsError, RunMethodOrigin, ThreadClassOrigin, getChannelClassName, getThreadClassName, getVarName}
import java.lang
@@ -53,6 +53,16 @@ object ParalleliseVeyMontThreads extends RewriterBuilderArg[JavaClass[_]] {
override def shortPosition: String = assign.o.shortPosition
}
+
+ case class RunMethodOrigin(runMethod: RunMethod[_]) extends Origin {
+ override def preferredName: String = "run"
+
+ override def context: String = runMethod.o.context
+
+ override def inlineContext: String = runMethod.o.inlineContext
+
+ override def shortPosition: String = runMethod.o.shortPosition
+ }
}
case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[_]) extends Rewriter[Pre] { outer =>
@@ -66,7 +76,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
override def dispatch(decl : Declaration[Pre]) : Unit = {
decl match {
case p: Procedure[Pre] => givenClassConstrSucc.update(p.returnType,p)
- case c : Class[Pre] => globalDeclarations.declare(dispatchGivenClass(c))
+ case c : Class[Pre] => globalDeclarations.succeed(c, dispatchGivenClass(c))
case seqProg: VeyMontSeqProg[Pre] => dispatchThreads(seqProg)
case thread: VeyMontThread[Pre] => dispatchThread(thread)
case other => rewriteDefault(other)
@@ -220,7 +230,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
case _ => throw ParalliseVeyMontThreadsError(thread, "Methods of seq_program need to be of type InstanceMethod")
}
- private def getThreadRunFromDecl(thread: VeyMontThread[Pre], decl: ClassDeclaration[Pre]): RunMethod[Post] = decl match {
+ private def getThreadRunFromDecl(thread: VeyMontThread[Pre], decl: ClassDeclaration[Pre]): InstanceMethod[Post] = decl match {
case m: RunMethod[Pre] => getThreadRunMethod(m)
case _ => throw ParalliseVeyMontThreadsError(thread, "RunMethod expected in seq_program")
}
@@ -243,6 +253,7 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
val rw = ChannelClassGenerator(channelType)
new RewriteJavaClass[Pre, Post](chanClassPre)(rw).rewrite(
name = getChannelClassName(channelType),
+ modifiers = Seq.empty,
decls = classDeclarations.collect {
chanClassPre.decls.foreach(d => rw.dispatch(d))
}._1)
@@ -302,10 +313,12 @@ case class ParalleliseVeyMontThreads[Pre <: Generation](channelClass: JavaClass[
dispatch(method.contract))(method.blame)(method.o)
}
- private def getThreadRunMethod(run: RunMethod[Pre]): RunMethod[Post] = {
- new RunMethod[Post](
+ private def getThreadRunMethod(run: RunMethod[Pre]): InstanceMethod[Post] = {
+ new InstanceMethod[Post](
+ TVoid[Post](),
+ Seq.empty,Seq.empty,Seq.empty,
run.body.map(dispatch),
- dispatch(run.contract))(run.blame)(run.o)
+ dispatch(run.contract))(run.blame)(RunMethodOrigin(run))
}
override def dispatch(node: Expr[Pre]): Expr[Post] = {
diff --git a/src/rewrite/vct/rewrite/veymont/StructureCheck.scala b/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
index 8af88c94f6..28380a2822 100644
--- a/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
+++ b/src/rewrite/vct/rewrite/veymont/StructureCheck.scala
@@ -33,6 +33,8 @@ case class StructureCheck[Pre <: Generation]() extends Rewriter[Pre] {
case m: InstanceMethod[Pre] =>
if (inSeqProg.nonEmpty && m.args.nonEmpty)
throw VeyMontStructCheckError(m, "Methods in seq_program cannot have any arguments!")
+ else if(inSeqProg.nonEmpty && m.returnType != TVoid[Pre]())
+ throw VeyMontStructCheckError(m, "Methods in seq_program cannot have a non-void return type!")
else rewriteDefault(decl)
case r: RunMethod[Pre] =>
if(r.body.isEmpty)
From 07bd995d1db0036d09458a37b60bfdf7da32d1b2 Mon Sep 17 00:00:00 2001
From: Petra van den Bos
Date: Thu, 20 Jul 2023 14:17:25 +0200
Subject: [PATCH 20/20] layout fixes
---
src/col/vct/col/ast/lang/JavaParamImpl.scala | 2 +-
src/col/vct/col/ast/type/TUnionImpl.scala | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/col/vct/col/ast/lang/JavaParamImpl.scala b/src/col/vct/col/ast/lang/JavaParamImpl.scala
index 9f3b2e1b99..0bbc63523b 100644
--- a/src/col/vct/col/ast/lang/JavaParamImpl.scala
+++ b/src/col/vct/col/ast/lang/JavaParamImpl.scala
@@ -4,6 +4,6 @@ import vct.col.ast.JavaParam
import vct.col.print.{Ctx, Doc, Text}
trait JavaParamImpl[G] { this: JavaParam[G] =>
- override def layout(implicit ctx: Ctx): Doc = Text(t + " " + name)
+ override def layout(implicit ctx: Ctx): Doc = t.show <+> name
}
diff --git a/src/col/vct/col/ast/type/TUnionImpl.scala b/src/col/vct/col/ast/type/TUnionImpl.scala
index af0f33e3e1..6aabe6796f 100644
--- a/src/col/vct/col/ast/type/TUnionImpl.scala
+++ b/src/col/vct/col/ast/type/TUnionImpl.scala
@@ -4,6 +4,6 @@ import vct.col.ast.TUnion
import vct.col.print.{Ctx, Doc}
trait TUnionImpl[G] { this: TUnion[G] =>
- override def layout(implicit ctx: Ctx): Doc = Doc.spread(types)
+ override def layout(implicit ctx: Ctx): Doc = Doc.fold(types)(_ <+> "|" <+> _)
}
\ No newline at end of file