Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persisting the analysis state #38

Open
wants to merge 97 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
9a9e7e3
fix: Scala doesn't find `AnsiColor`
Merlijn-D Nov 25, 2023
006478a
feat(save): Save name of analysis
Merlijn-D Nov 25, 2023
7119c9c
feat(save): Map and Array based encoders
Merlijn-D Nov 25, 2023
4ca2629
feat(save): Save components
Merlijn-D Nov 25, 2023
98c0db1
feat(save): Save dependencies
Merlijn-D Nov 25, 2023
a3e3e1a
refactor(save): Rename files
Merlijn-D Nov 25, 2023
8437bd3
refactor(save): Extension methods in `EncapsulatedEncoder` use normal…
Merlijn-D Dec 3, 2023
78ec551
refactor(save): Put extension methods of `EncapsulatedEncoder` in object
Merlijn-D Dec 3, 2023
9212aae
feat(save): Save `PrmAddr` and `PtrAddr`
Merlijn-D Dec 3, 2023
a35c6bd
feat(save): Save the store
Merlijn-D Dec 3, 2023
d302112
feat(save): Save Scheme expressions
Merlijn-D Feb 3, 2024
eb94b37
refactor(save): Put the encoder in a variable
Merlijn-D Feb 5, 2024
9476f18
feat(save): Save environment
Merlijn-D Feb 5, 2024
b7a1b9c
feat(save): Save environment
Merlijn-D Feb 6, 2024
34a35bd
refactor(save): Remove type parameter from `AbstractEncoder`
Merlijn-D Feb 6, 2024
3a96226
feat(load): Add decoder and load name of analysis
Merlijn-D Feb 6, 2024
513422e
feat(repl): Add `-s` and `-l` as CLI arguments
Merlijn-D Feb 6, 2024
cea7b0b
fix(save): Scheme address is not saving everything
Merlijn-D Feb 6, 2024
860f688
feat(load): Load components
Merlijn-D Feb 8, 2024
a59ed78
refactor(save): Move save logic and load logic to separate folders
Merlijn-D Feb 8, 2024
de74846
refactor(save): Move shared encoders into separate encoders
Merlijn-D Feb 8, 2024
1f9a2ec
refactor(save): Require keys to be strings
Merlijn-D Feb 8, 2024
7f5113f
feat(load): Add ArrayDecoder and ArrayKeyDecoder
Merlijn-D Feb 8, 2024
c80e47d
feat(load): Load dependencies
Merlijn-D Feb 8, 2024
0c35ecb
feat(save): Save lattices correctly
Merlijn-D Feb 8, 2024
77aaf8f
fix(load): Using wrong decoder when decoding dependencies
Merlijn-D Feb 9, 2024
1ae25ad
feat(load): Load store
Merlijn-D Feb 9, 2024
f9dc359
feat(load): Load everything into an analysis
Merlijn-D Feb 9, 2024
f926be6
refactor(save): Add `SaveComponentID`
Merlijn-D Feb 9, 2024
e979a58
refactor(load): Use class to store result instead of future
Merlijn-D Feb 9, 2024
f13c632
docs(save): Add code documentation
Merlijn-D Feb 10, 2024
ed19604
refactor(save, load): Change name of Context type
Merlijn-D Feb 11, 2024
922ba73
docs(load): Add code documentation
Merlijn-D Feb 11, 2024
8d4a89a
refactor(load): Remove LoadComponentID from LoadComponents
Merlijn-D Feb 12, 2024
da20987
refactor(load): Use abstract type for component ID
Merlijn-D Feb 12, 2024
0806e6e
fix(load): `ArrayKeyDecoder` isn't setting `mapBasedDecoder` to false
Merlijn-D Feb 12, 2024
747126e
feat(save): Add componentEncoder that uses integer IDs
Merlijn-D Feb 12, 2024
ef12608
feat(load): Add componentDecoder that uses integer IDs
Merlijn-D Feb 12, 2024
b905bca
feat(save): Add support for more scheme expressions
Merlijn-D Feb 12, 2024
22bbe1a
feat(save): Add support for more scheme lattices
Merlijn-D Feb 12, 2024
f9e2c1c
feat(load): Add support for more scheme expressions
Merlijn-D Feb 12, 2024
c210f9f
feat(load): Add support for more scheme lattices
Merlijn-D Feb 12, 2024
5840d44
fix(save): Encoder for `ReturnAddr` uses context instead of component
Merlijn-D Feb 12, 2024
6b57209
fix(save): In CBOR, the arrays/maps where not closed correctly
Merlijn-D Feb 29, 2024
37ee511
fix(save): Order of saved objects not consistent
Merlijn-D Mar 7, 2024
0137547
feat(save): Save expressions separately
Merlijn-D Mar 7, 2024
71b63c3
feat(load): Make `LoadComponents` more generic
Merlijn-D Mar 8, 2024
339425f
fix(load): Order of loaded objects not consistent
Merlijn-D Mar 8, 2024
c33e327
fix(load): Can't lattices that where encoded correctly
Merlijn-D Mar 8, 2024
8e0169b
feat(load): Decode expressions separately
Merlijn-D Mar 8, 2024
ce23d18
feat(save): Make 'SaveComponents' save either IDs or components
Merlijn-D Mar 9, 2024
c356cb2
feat(save): Save worklist
Merlijn-D Mar 12, 2024
d911fba
feat(load): Load worklist
Merlijn-D Mar 12, 2024
6f15887
feat(save): Add ability to only save some elements
Merlijn-D Mar 12, 2024
4e4a697
feat(load): Add ability to only load some elements
Merlijn-D Mar 12, 2024
b22bb1f
refactor(load, save): Use 'AnalysisEntry' as a basis instead of 'ModA…
Merlijn-D Mar 13, 2024
e1d90f3
feat(load): Allow for extra map elements
Merlijn-D Mar 13, 2024
275b440
feat(save): Save expressions normally for certain AST heights
Merlijn-D Mar 13, 2024
3f25287
feat(save): Save initialized state
Merlijn-D Mar 13, 2024
8f49c32
feat(load): Load initialized state
Merlijn-D Mar 13, 2024
487811b
feat(save): Encode vector lattices
Merlijn-D Mar 27, 2024
315debb
feat(load): Decode vector lattice
Merlijn-D Mar 27, 2024
37c5689
fix(load): `nilLattice` and `voidLattice` aren't decoded correctly
Merlijn-D Mar 29, 2024
cab4f8a
chore: Only add `Save` and `Load` traits to contextInsensitiveAnalysis
Merlijn-D Apr 19, 2024
59005e9
chore(Repl): Time the time it takes to load in the result
Merlijn-D Apr 19, 2024
ee9cc5d
refactor(Save): Use actual encoder type instead of abstract encoder
Merlijn-D Apr 19, 2024
ef0d2da
refactor(Load): Use actual decoder type instead of abstract decoder
Merlijn-D Apr 19, 2024
bcdac9e
refactor(persistence): Change name of folder
Merlijn-D Apr 19, 2024
0359f76
feat(save): Add way to encode option
Merlijn-D Apr 21, 2024
e9ab5c0
feat(load): Add way to decode option
Merlijn-D Apr 21, 2024
2ff267a
fix(save): When saving the environment save the option and not the value
Merlijn-D Apr 22, 2024
24c2b63
chore(save): Remove unnecessary traits in `saveComponents`
Merlijn-D Apr 22, 2024
1a4e6df
fix(save): Encode the correct worklist
Merlijn-D Apr 22, 2024
52a5424
chore(load): Remove unnecessary traits from `LoadComponent`
Merlijn-D Apr 22, 2024
1a09290
fix(load): `NestedEnv` was not decoded correctly
Merlijn-D Apr 22, 2024
6d3f1a2
refactor(load): Use `Component` when decoding the worklist
Merlijn-D Apr 22, 2024
226d058
test(persistence): Add tests
Merlijn-D Apr 22, 2024
5650b5f
feat(load): Add CBOR support
Merlijn-D Jun 3, 2024
e395058
feat(load): Add extra functions to decoder
Merlijn-D Jun 3, 2024
fb43e41
feat(load): Load main Scheme body
Merlijn-D Jun 3, 2024
8f48aef
feat(load): Add more decodable lattices and seperate them into a trait
Merlijn-D Jun 3, 2024
2acbeef
fix(load): Components not loaded correctly
Merlijn-D Jun 3, 2024
fe480f4
perf(persistence): Add performance tests
Merlijn-D Jul 8, 2024
c9697db
fix: Scheme assert has incorrect height
Merlijn-D Jul 8, 2024
4a0c3b0
refactor(load): Remove unnecessary abstraction
Merlijn-D Jul 8, 2024
a5e6cfa
feat(save): Add ability to save as CBOR
Merlijn-D Jul 8, 2024
a308643
feat(save): Add function that runs before saving
Merlijn-D Jul 8, 2024
ad57a4a
feat(save): Allow for saving of main body
Merlijn-D Jul 9, 2024
f992aa7
refactor(save): Create separate trait for lattices
Merlijn-D Jul 9, 2024
b25e94c
feat(save): Change the way options are saved
Merlijn-D Jul 9, 2024
363f1fa
fix(save): Use correct encoder when encoding expressions
Merlijn-D Jul 9, 2024
a6ba6fe
feat(save): Add ability to save expressions from worklist
Merlijn-D Jul 9, 2024
a6b1563
refactor(save): Make saving worklist more abstract
Merlijn-D Jul 9, 2024
a6a3e6d
chore(save): Change symbol that represents no context
Merlijn-D Jul 9, 2024
800c894
fix(save): Saving components
Merlijn-D Jul 9, 2024
cb99eb7
chore(save): Change used traits for saving
Merlijn-D Jul 9, 2024
ab3bdb3
test(persistance): Update test suite
Merlijn-D Jul 9, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ out/
*.zo
__pycache__
stats/
res.json
2 changes: 2 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ lazy val maf = crossProject(JVMPlatform, JSPlatform)
libraryDependencies += ("com.typesafe.akka" %% "akka-actor-typed" % "2.6.18").cross(CrossVersion.for3Use2_13),
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.10",
libraryDependencies += "com.typesafe" % "config" % "1.4.1",
libraryDependencies += "io.bullet" %% "borer-core" % "1.10.0",
libraryDependencies += "io.bullet" %% "borer-derivation" % "1.10.0",
/** Compilation options */
maxErrors := 5,
/** Configuration for running the tests */
Expand Down
12 changes: 11 additions & 1 deletion code/jvm/src/main/scala/maf/cli/experiments/SchemeAnalyses.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import maf.modular.scheme.modactor.mirrors.ModActorWithMirrors
import maf.modular.scheme.modactor.mirrors.SimpleModActorWithMirrors
import maf.language.racket.RacketLoaderSemantics
import maf.language.racket.RacketLoader
import maf.save.LoadFIFOWorklist
import maf.save.LoadModF
import maf.save.SaveModF

object SchemeAnalysesBoundedDomain:
object NoSensitivity:
Expand Down Expand Up @@ -55,8 +58,15 @@ object SchemeAnalyses:

def contextInsensitiveAnalysis(
prg: SchemeExp
) = new SimpleSchemeModFAnalysis(prg) with SchemeModFNoSensitivity with SchemeConstantPropagationDomain with FIFOWorklistAlgorithm[SchemeExp] {
) = new SimpleSchemeModFAnalysis(prg)
with SchemeModFNoSensitivity
with SchemeConstantPropagationDomain
with FIFOWorklistAlgorithm[SchemeExp]
with SaveModF
with LoadModF
with LoadFIFOWorklist[SchemeExp] {
override def toString = "no-sensitivity"
override val analysisName: String = "modf"
}

//def contextInsensitiveAnalysisRacket(
Expand Down

Large diffs are not rendered by default.

37 changes: 32 additions & 5 deletions code/jvm/src/main/scala/maf/cli/runnables/Repl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ object Repl:
| * -t TIMEOUT: run the analysis with the given timeout (in seconds). Defaults to 10.
| * -dot set flag to enable outputting a FILENAME.dot file that contains a visualisation of results of the analysis, only works with "-f"
| * -m load the given Racket module, use instead of "-f"
| * -s FILENAME: the name of the file where the analysis should be saved to when finished
| * -l FILENAME: the name of the file where the analysis should be loaded from
""".stripMargin

private val configurationsHelp: Map[String, String] = Map(
Expand Down Expand Up @@ -79,7 +81,9 @@ object Repl:
interactive: Boolean = false,
performance: Boolean = false,
dot: Boolean = false,
timeout: Long = 10):
timeout: Long = 10,
saveFile: Option[String] = None,
loadFile: Option[String] = None):
def isEmpty: Boolean = remaining.isEmpty
def continue(remaining: List[String]): ArgParser = this.copy(remaining = remaining)
def setAnalysis(analysis: String): ArgParser =
Expand All @@ -90,6 +94,14 @@ object Repl:
ensureNotSet(this.filename, "filename")
this.copy(filename = Some(filename))

def setSaveFilename(filename: String): ArgParser =
ensureNotSet(this.saveFile, "saveFile")
this.copy(saveFile = Some(filename))

def setLoadFilename(filename: String): ArgParser =
ensureNotSet(this.loadFile, "loadFile")
this.copy(loadFile = Some(filename))

def setParser(parser: String): ArgParser =
ensureNotSet(this.parser, "parser")
this.copy(parser = Some(parser))
Expand Down Expand Up @@ -132,6 +144,12 @@ object Repl:
case "-dot" :: rest =>
parse(parser.copy(dot = true).continue(rest))

case "-s" :: filename :: rest =>
parse(parser.setSaveFilename(filename).continue(rest))

case "-l" :: filename :: rest =>
parse(parser.setLoadFilename(filename).continue(rest))

case arg =>
throw new Exception(s"invalid arguments $arg")

Expand Down Expand Up @@ -171,19 +189,25 @@ object Repl:
performance: Boolean,
timeout: Long,
dot: Boolean,
saveFile: Option[String] = None,
loadFile: Option[String] = None,
someLoader: Option[String => SchemeExp] = None
): Unit =
val loader: String => SchemeExp = someLoader.getOrElse(Reader.loadFile andThen parser.parse)
// Regardless of the performance mode, we parse the file only once.
val exp = loader(filename)
def runSingle(): Long =
val anl = makeAnalysis(exp)
val (elapsed, _) = Timer.time { anl.analyzeWithTimeout(Timeout.start(timeout.seconds)) }
if loadFile.isDefined then
val (elapsed, _) = Timer.time { anl.load(loadFile.get) } //anl.analyzeWithTimeout(Timeout.start(timeout.seconds)) }
println(s"load time: ${elapsed / 1000000}")
val (elapsed, _) = Timer.time { anl.analyze() } //anl.analyzeWithTimeout(Timeout.start(timeout.seconds)) }
// Do not print results if we are in perfomance testing mode
if !performance then
if !anl.finished then println("Analysis timed out")
anl.printResult
println(s"Analysis took ${elapsed / (1000 * 1000)} ms")
if saveFile.isDefined then anl.save(saveFile.get)
// Print a dot graph if the dot option has been enabled
if dot then anl.toDot(filename.replace("/", "_").nn + ".dot")
elapsed
Expand Down Expand Up @@ -221,7 +245,7 @@ object Repl:
else runSingle()

/** Runs a REPL that can be used to interactively test the abstract interpreter */
private def runRepl(parser: P, makeAnalysis: A): Unit =
private def runRepl(parser: P, makeAnalysis: A, saveFile: Option[String]): Unit =
def repl(): Unit =
print(">")
val program = readLine().trim().nn
Expand All @@ -232,6 +256,7 @@ object Repl:

anl.printResult
println(s"Analysis took ${elapsed / (1000 * 1000)} ms")
if saveFile.isDefined then anl.save(saveFile.get)
repl()
repl()

Expand All @@ -251,6 +276,8 @@ object Repl:
assert(if options.dot then options.filename.isDefined else true, "-dot can only be combined with -f")
// ensure that "-m" is not combined with "-f"
assert(if options.module.isDefined then !options.filename.isDefined else true, "-m can not be combined with -f")
// ensure that "-i" is not combined with "-l"
assert(!(options.interactive && options.loadFile.isDefined), "-i can not be combined with -l")
// setup the parser
val parser = setupParser(options.parser)
// setup the loader
Expand All @@ -261,8 +288,8 @@ object Repl:
val analysisFactory = setupAnalysis(options.analysis.get)
// setup the loader of the file/module
// either run the file or the repl
if options.interactive then runRepl(parser, analysisFactory)
if options.interactive then runRepl(parser, analysisFactory, options.saveFile)
else
// retrieve the file or module name
val path = options.filename.getOrElse(options.module.get)
runFile(path, parser, analysisFactory, options.performance, options.timeout, options.dot, loader)
runFile(path, parser, analysisFactory, options.performance, options.timeout, options.dot, options.saveFile, options.loadFile, loader)
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ sealed trait SchemeLettishExp extends SchemeExp:
val body: List[SchemeExp]
val idn: Identity
override type T <: SchemeLettishExp
override val height: Int = 1 + bindings.foldLeft(0)((mx, b) => mx.max(b._2.height).max(body.foldLeft(0)((mx, e) => mx.max(e.height))))
override val height: Int = 1 + bindings.foldLeft(0)((mx, b) => mx.max(b._2.height)).max(body.foldLeft(0)((mx, e) => mx.max(e.height)))
def subexpressions: List[Expression] = bindings.foldLeft(List[Expression]())((a, b) => b._2 :: b._1 :: a) ::: body
override def isomorphic(other: Expression): Boolean = super.isomorphic(other) && body.length == other.asInstanceOf[SchemeLettishExp].body.length
override def eql(other: Expression): Boolean = super.eql(other) && body.length == other.asInstanceOf[SchemeLettishExp].body.length
Expand Down Expand Up @@ -1048,6 +1048,7 @@ case class SchemeAssert(exp: SchemeExp, idn: Identity) extends SchemeExp:
override def toString: String = s"(assert $exp)"
def fv: Set[String] = exp.fv
val label: Label = ASS
override val height: Int = 1 + exp.height

override def deepDropIdentifier(id: Identifier): Option[SchemeExp] =
exp.deepDropIdentifier(id) match
Expand Down
42 changes: 41 additions & 1 deletion code/shared/src/main/scala/maf/modular/ModAnalysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ case class Metric(name: String, result: Double)

/** Super type of all analyses in MAF, provides basic entry points to the analysis */
trait AnalysisEntry[Exp <: Expression]:
/** The name of the analysis */
val analysisName: String = "None"

/** Returns a boolean indicating whether the analysis has finished. Implementation should be provided by the work list algorithm. */
def finished: Boolean

Expand All @@ -40,6 +43,42 @@ trait AnalysisEntry[Exp <: Expression]:
/** Method that defines how to print the result of the analysis */
def printResult: Unit = println(result)

/**
* This saves the current analysis to a file
*
* @param filename
* The file to save to
*/
def save(filename: String): Unit = System.err.nn.println("Save functionality is not implemented for this analysis")

/**
* This saves the current analysis to a file, but only the elements that are in save
*
* @param filename
* The file to save to
* @param save
* The elements to save
*/
def save(filename: String, save: Set[String]): Unit = System.err.nn.println("Save functionality is not implemented for this analysis")

/**
* Load an analysis from a given file
*
* @param filename
* The file to load the analysis from
*/
def load(filename: String): Unit = System.err.nn.println("Load functionality is not implemented for this analysis")

/**
* Load the given elements of an analysis from a given file
*
* @param filename
* The file to load the analysis from
* @param load
* The elements to load
*/
def load(filename: String, load: Set[String]): Unit = System.err.nn.println("Load functionality is not implemented for this analysis")

/**
* Method that renders a Dot graph of the components and the dependencies between them and writes it to a file
*
Expand Down Expand Up @@ -134,6 +173,8 @@ abstract class ModAnalysis[Expr <: Expression](val program: Expr) extends Clonea

// flag to indicate if the analysis has already been initialized (see method `init`)
private var initialized: Boolean = false
def analysisInitialized = initialized
def analysisInitialized_=(init: Boolean) = initialized = init

/* Runs the analysis with a timeout. Implementation should be provided by the worklist algorithm. */
protected def run(timeout: Timeout.T): Unit
Expand Down Expand Up @@ -167,5 +208,4 @@ abstract class ModAnalysis[Expr <: Expression](val program: Expr) extends Clonea
// Print analysis information.

def configString(): String = "Modular analysis"

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import maf.util._
import maf.core.IdentityMonad.given
import maf.core.Monad.MonadIterableOps
import maf.core.Monad.MonadSyntaxOps
import maf.save.SaveModF
import maf.save.Savable
import maf.save.LoadModF

trait BaseEvalM[M[_]] extends Monad[M] with MonadError[M, Error] with MonadJoin[M]

Expand Down Expand Up @@ -71,7 +74,7 @@ trait BaseSchemeModFSemanticsM
caller: Component
): M[ComponentContext] = Monad[M].unit(allocCtx(clo, args, call, caller))

lazy val mainBody = program
var mainBody = program
def expr(cmp: Component): SchemeExp = body(cmp)
def body(cmp: Component): SchemeExp = body(view(cmp))
def body(cmp: SchemeModFComponent): SchemeExp = cmp match
Expand Down
122 changes: 122 additions & 0 deletions code/shared/src/main/scala/maf/persistence/load/Analysis.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package maf.save

import io.bullet.borer.Decoder
import io.bullet.borer.Json
import maf.core.Expression
import java.nio.file.Paths
import java.nio.file.Files
import maf.language.scheme.SchemeExp
import io.bullet.borer.Reader
import scala.collection.mutable.HashMap
import maf.modular.AnalysisEntry
import maf.modular.ModAnalysis
import scala.collection.mutable.ListBuffer
import io.bullet.borer.Cbor

/**
* Contains info about the top-level objects that need to be loaded.
*
* @param load
* Function that should be called with the value after it was decoded
* @param decoder
* Decodes the value
* @tparam T
* The type of the value the needs to be loaded
*/
case class Loadable[T](val load: (T) => Unit)(using val decoder: Decoder[T])

/**
* The base trait for saving an analysis.
*
* Implementing this allows you to load your analysis, by default it will only load the name of your analysis and you should mixin other traits like
* [[LoadComponents]] to also load components.
*
* @tparam Expr
* The type of expression used in the analysis
*/
trait Load[Expr <: Expression] extends AnalysisEntry[Expr]:
/** Decode an analysis. */
given analysisDecoder: Decoder[Load[Expr]] with
override def read(reader: Reader): Load[Expr] =
val loadInfo = Load.this.loadInfo
loadSet = loadInfo.map(_._1).toSet
reader.read[Load[Expr]]()
loadSet = Set[String]()
return Load.this

protected var loadSet = Set[String]()
protected given excludedAnalysisDecoder: MapDecoder[Load[Expr]] with
override def read(reader: Reader): Load[Expr] =
reader.start()
for (key, value) <- loadInfo do
if loadSet.contains(key) then
val result = reader.readMember(key)(using value.decoder)
value.load(result)
reader.close()
return Load.this

def startLoad(): Unit = return

override def load(filename: String): Unit =
startLoad()
val bytes = Files.readAllBytes(Paths.get(filename))
if bytes != null then Json.decode(bytes).to[Load[Expr]](using analysisDecoder).value

override def load(filename: String, load: Set[String]): Unit =
startLoad()
val bytes = Files.readAllBytes(Paths.get(filename))
if bytes != null then Json.decode(bytes).to[Load[Expr]](using excludedAnalysisDecoder).value

/**
* Returns a map strings and [[Loadable]] s.
*
* This map defines all top-level objects that should be loaded in your analysis, and the key with which they should be loaded. If you want to
* load something else, you can override this method and add something to it.
*
* {{{
* override def loadInfo: Map[String, Loadable[_]] =
* super.loadInfo + ("< key >" -> Loadable[< loadType >]((< loaded object >: < SaveType >) => < put loaded object into analysis >))
* }}}
*/
def loadInfo: List[(String, Loadable[_])] = List(("name", Loadable((name: String) => ())))

trait LoadCbor[Expr <: Expression] extends Load[Expr]:
override def load(filename: String): Unit =
startLoad()
val bytes = Files.readAllBytes(Paths.get(filename))
if bytes != null then Cbor.decode(bytes).to[Load[Expr]](using analysisDecoder).value

override def load(filename: String, load: Set[String]): Unit =
startLoad()
val bytes = Files.readAllBytes(Paths.get(filename))
if bytes != null then Json.decode(bytes).to[Load[Expr]](using excludedAnalysisDecoder).value

trait LoadInitialized[Expr <: Expression] extends ModAnalysis[Expr] with Load[Expr]:
override def loadInfo: List[(String, Loadable[?])] =
super.loadInfo ++ List(
("initialized",
Loadable((initialized: Boolean) =>
if !visited.contains(initialComponent) then visited = visited + initialComponent
analysisInitialized = initialized
)
)
)

/** The trait used to load the modF analysis. */
trait LoadModF
extends Load[SchemeExp]
with LoadInitialized[SchemeExp]
with LoadSchemeExpressions
// with LoadExpressionIntID[SchemeExp]
with LoadActualExpressions[SchemeExp]
with LoadMainSchemeBody
with LoadComponents[SchemeExp]
// with LoadComponentIntID[SchemeExp]
with LoadActualComponents[SchemeExp]
with LoadStandardSchemeComponents
with LoadNoContext[SchemeExp]
with LoadSchemeAddr
with LoadDependency[SchemeExp]
with LoadAddrDependency[SchemeExp]
with LoadGlobalStore[SchemeExp]
with LoadModularSchemeDomain
Loading
Loading