From 8e7bbcbd4a870548a9078edbabb3a4cd4e5a3747 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 24 Jan 2026 09:29:30 +0000 Subject: [PATCH 1/8] chore(core-deps): update dependency scala to v3.8.1 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 80fde92b..c3683d59 100644 --- a/build.sbt +++ b/build.sbt @@ -7,7 +7,7 @@ import sbtcrossproject.CrossProject import scala.scalanative.build.{ BuildTarget, GC, LTO, Mode } val projectName = "scafi3" -val scala3Version = "3.7.3" +val scala3Version = "3.8.1" ThisBuild / scalaVersion := scala3Version ThisBuild / organization := "it.unibo.scafi" From d33c6013f07a193f75d6a21389c83909008c420f Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 15:53:12 +0200 Subject: [PATCH 2/8] refactor: removed unused given and removed deprecated App trait --- .../main/scala/it/unibo/scafi/GradientInline.scala | 12 +++++++----- .../scafi/language/xc/FieldBasedSharedData.scala | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/example/src/main/scala/it/unibo/scafi/GradientInline.scala b/example/src/main/scala/it/unibo/scafi/GradientInline.scala index 4dcd789d..dd93e5b2 100644 --- a/example/src/main/scala/it/unibo/scafi/GradientInline.scala +++ b/example/src/main/scala/it/unibo/scafi/GradientInline.scala @@ -2,8 +2,10 @@ package it.unibo.scafi import it.unibo.alchemist.boundary.LoadAlchemist -object GradientInline extends App: - val simulationFile = getClass.getResource("/it/unibo/scafi/inline-gradient.yml").getPath - val loader = LoadAlchemist.from(simulationFile) - val simulation = loader.getDefault[Any, Nothing]() - simulation.run() +object GradientInline: + @main + def runInline(): Unit = + val simulationFile = getClass.getResource("/it/unibo/scafi/inline-gradient.yml").getPath + val loader = LoadAlchemist.from(simulationFile) + val simulation = loader.getDefault[Any, Nothing]() + simulation.run() diff --git a/scafi3-core/src/main/scala/it/unibo/scafi/language/xc/FieldBasedSharedData.scala b/scafi3-core/src/main/scala/it/unibo/scafi/language/xc/FieldBasedSharedData.scala index 65ed0d45..dd81bc32 100644 --- a/scafi3-core/src/main/scala/it/unibo/scafi/language/xc/FieldBasedSharedData.scala +++ b/scafi3-core/src/main/scala/it/unibo/scafi/language/xc/FieldBasedSharedData.scala @@ -117,7 +117,6 @@ trait FieldBasedSharedData: override given sharedDataApplicative: Applicative[Field] = new Applicative[Field]: override def pure[A](x: A): Field[A] = Field(x) override def ap[A, B](ff: Field[A => B])(fa: Field[A]): Field[B] = - given [BB] => CanEqual[BB, BB] = CanEqual.derived val default = ff.defaultValue(fa.defaultValue) val allDevices = ff.devices ++ fa.devices val overrides = allDevices @@ -132,7 +131,6 @@ trait FieldBasedSharedData: override given sharedDataOps: SharedDataOps[Field] = new SharedDataOps[Field]: extension [A](field: Field[A]) override def withoutSelf: SafeIterable[A] = - given CanEqual[A, A] = CanEqual.derived SafeIterable(field.devices.toList.filterNot(_ == localId).map(field.apply)) override def onlySelf: A = field(localId) From 3c59ec155a1598cb9817cf459f34e0b7d002f7b3 Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 16:25:54 +0200 Subject: [PATCH 3/8] refactor: use () invoking next resolving the compiler warning --- .../main/scala/it/unibo/scafi/libraries/FoldhoodLibrary.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scafi3-core/src/main/scala/it/unibo/scafi/libraries/FoldhoodLibrary.scala b/scafi3-core/src/main/scala/it/unibo/scafi/libraries/FoldhoodLibrary.scala index 1cbf0823..3d669f4a 100644 --- a/scafi3-core/src/main/scala/it/unibo/scafi/libraries/FoldhoodLibrary.scala +++ b/scafi3-core/src/main/scala/it/unibo/scafi/libraries/FoldhoodLibrary.scala @@ -119,7 +119,7 @@ object FoldhoodLibrary: zippedNeighbouringValues.foldWithoutSelf(if withSelf then f(base, selfExprValue) else base): (acc, values) => val iterator = values.iterator val context: FoldhoodContext[L] = new FoldhoodContext[L]: - override def current[X](expr: (lang: L) ?=> lang.SharedData[X]): X = iterator.next match + override def current[X](expr: (lang: L) ?=> lang.SharedData[X]): X = iterator.next() match case x: X @unchecked => x case _ => throw new ClassCastException("Type mismatch") val result = expr(using context) From a48f6f6b4a6bade4e182bffb970c064d6cd308fe Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 16:26:21 +0200 Subject: [PATCH 4/8] test: remove explicit CanEqual as not needed --- .../it/unibo/scafi/context/xc/ExchangeAggregateContextTest.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/scafi3-core/src/test/scala/it/unibo/scafi/context/xc/ExchangeAggregateContextTest.scala b/scafi3-core/src/test/scala/it/unibo/scafi/context/xc/ExchangeAggregateContextTest.scala index ae94fa8b..2c393567 100644 --- a/scafi3-core/src/test/scala/it/unibo/scafi/context/xc/ExchangeAggregateContextTest.scala +++ b/scafi3-core/src/test/scala/it/unibo/scafi/context/xc/ExchangeAggregateContextTest.scala @@ -34,7 +34,6 @@ class ExchangeAggregateContextTest private val lang = exchangeContextFactory(NeighborsNetworkManager[Int](0, Set(1, 2, 4, 6)), ValueTree.empty) private given [A: Arbitrary] => Arbitrary[lang.SharedData[A]] = Arbitrary: - given CanEqual[A, A] = CanEqual.derived for default <- Arbitrary.arbitrary[A] // Generate a random set (non empty) of device IDs between 0 and 10 From ccb724ce1549efb19a88acaa8aba099d646580b9 Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 16:27:58 +0200 Subject: [PATCH 5/8] refactor: use custom logic for compiling scala code as JSR223 no longer supported in scala3 --- .../unibo/alchemist/Scafi3Incarnation.scala | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala b/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala index d33ada4b..4248b2e7 100644 --- a/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala +++ b/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala @@ -3,7 +3,6 @@ package it.unibo.alchemist import java.io.File import java.net.URLClassLoader import java.nio.file.Files -import javax.script.ScriptEngineManager import it.unibo.alchemist.Scafi3Incarnation.CACHE_SIZE import it.unibo.alchemist.actions.RunScafi3Program @@ -171,17 +170,39 @@ class Scafi3Incarnation[T, Position <: AlchemistPosition[Position]] extends Inca (reporter.hasErrors, List(reporter.summary)) private object ScalaScriptEngine: - private val engine = ScriptEngineManager().getEngineByName("scala").nn + private var idCounter = 0 + + @SuppressWarnings(Array("scalafix:DisableSyntax.asInstanceOf")) + private def eval[A](code: String): A = + code match + case "true" => true.asInstanceOf[A] + case "false" => false.asInstanceOf[A] + case s if s.toDoubleOption.isDefined => + val d = s.toDouble + if d.isValidInt then d.toInt.asInstanceOf[A] else d.asInstanceOf[A] + case _ => + idCounter += 1 + val className = s"Eval_$idCounter" + val src = s"""class $className { def eval = $code }""" + val inputFolder = Files.createTempDirectory("scafi3-eval") + val outputFolder = Files.createTempDirectory("scafi3-eval-out") + val sourceFilePath = Files.writeString(inputFolder.resolve(s"$className.scala"), src) + val (hasErrors, errors) = compileWithOptions(sourceFilePath.toAbsolutePath.toString, outputFolder.toAbsolutePath.toString) + if hasErrors then throw new IllegalArgumentException(s"Could not compile $code: $errors") + val url = outputFolder.toFile.toURI.toURL + val cl = new URLClassLoader(Array(url), Thread.currentThread().getContextClassLoader) + val cls = cl.loadClass(className) + val instance = cls.getDeclaredConstructor().newInstance() + cls.getMethod("eval").invoke(instance).asInstanceOf[A] val concentrationCache: LoadingCache[String, Any] = - Caffeine.newBuilder().nn.build[String, Any](engine.eval).nn + Caffeine.newBuilder().nn.build[String, Any](eval[Any]).nn - @SuppressWarnings(Array("scalafix:DisableSyntax.asInstanceOf")) val propertyCache: LoadingCache[String, Any => Double] = Caffeine .newBuilder() .nn .build[String, Any => Double] { property => - engine.eval(property).asInstanceOf[Any => Double] + eval[Any => Double](property) } .nn end ScalaScriptEngine From ac6c61d2fc9df9c5b1bd07bd2371b04603284864 Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 16:29:39 +0200 Subject: [PATCH 6/8] style: code refactoring --- .../src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala b/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala index 4248b2e7..42a83411 100644 --- a/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala +++ b/alchemist-incarnation-scafi3/src/main/scala/it/unibo/alchemist/Scafi3Incarnation.scala @@ -187,7 +187,8 @@ class Scafi3Incarnation[T, Position <: AlchemistPosition[Position]] extends Inca val inputFolder = Files.createTempDirectory("scafi3-eval") val outputFolder = Files.createTempDirectory("scafi3-eval-out") val sourceFilePath = Files.writeString(inputFolder.resolve(s"$className.scala"), src) - val (hasErrors, errors) = compileWithOptions(sourceFilePath.toAbsolutePath.toString, outputFolder.toAbsolutePath.toString) + val (hasErrors, errors) = + compileWithOptions(sourceFilePath.toAbsolutePath.toString, outputFolder.toAbsolutePath.toString) if hasErrors then throw new IllegalArgumentException(s"Could not compile $code: $errors") val url = outputFolder.toFile.toURI.toURL val cl = new URLClassLoader(Array(url), Thread.currentThread().getContextClassLoader) From 45fc1013a9b0f92539b73c009d5d8c1524f1a3a8 Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 17:24:53 +0200 Subject: [PATCH 7/8] test: fix problem with code coverage --- .../src/main/scala/it/unibo/scafi/message/ValueTree.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala b/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala index 1d2acaee..1b92927f 100644 --- a/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala +++ b/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala @@ -38,7 +38,7 @@ trait ValueTree: * an Option containing the value associated to the given [[Path]] if it exists, otherwise None. */ def get[Value](path: Path): Option[Value] = - try Some(apply(path)) + try Some(apply[Value](path)) catch case _: NoPathFoundException => None /** @@ -85,7 +85,11 @@ object ValueTree: override def equals(obj: Any): Boolean = obj match case that: ValueTree => - try this.paths == that.paths && this.paths.forall(path => this(path) == that(path)) + try this.paths == that.paths && this.paths.forall(path => { + val a = this.apply[Any](path) + val b = that.apply[Any](path) + a.equals(b) + }) catch case _: NoPathFoundException => false case _ => false From 621a05e51116da9744c0802c20635741a07097cf Mon Sep 17 00:00:00 2001 From: Nicolas Farabegoli Date: Mon, 15 Jun 2026 17:26:11 +0200 Subject: [PATCH 8/8] style: code refactoring --- .../main/scala/it/unibo/scafi/message/ValueTree.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala b/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala index 1b92927f..51aa5bb1 100644 --- a/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala +++ b/scafi3-core/src/main/scala/it/unibo/scafi/message/ValueTree.scala @@ -85,11 +85,12 @@ object ValueTree: override def equals(obj: Any): Boolean = obj match case that: ValueTree => - try this.paths == that.paths && this.paths.forall(path => { - val a = this.apply[Any](path) - val b = that.apply[Any](path) - a.equals(b) - }) + try + this.paths == that.paths && this.paths.forall(path => + val a = this.apply[Any](path) + val b = that.apply[Any](path) + a.equals(b), + ) catch case _: NoPathFoundException => false case _ => false