Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -171,17 +170,40 @@ 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
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 7 additions & 5 deletions example/src/main/scala/it/unibo/scafi/GradientInline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down Expand Up @@ -85,7 +85,12 @@ 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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading