Skip to content

Commit 0c1d573

Browse files
feat: added level methode to compute and which height we are in the lattice
1 parent aa3a1ed commit 0c1d573

18 files changed

Lines changed: 79 additions & 25 deletions

File tree

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ lazy val maf = crossProject(JVMPlatform, JSPlatform)
1414
name := "maf",
1515
organization := "soft",
1616
version := "2.0",
17-
scalaVersion := "3.1.0",
17+
scalaVersion := "3.3.7",
1818
//crossScalaVersions ++= Seq("2.13.6", "3.1.0"),
1919
/** Dependencies */
2020
libraryDependencies += "org.scala-lang.modules" %%% "scala-parser-combinators" % "2.0.0",

code/jvm/src/main/scala/maf/cli/experiments/incremental/IncrementalExperiment.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ trait IncrementalExperiment[E <: Expression]:
1818
// Analysis construction.
1919
def analysis(e: E, config: IncrementalConfiguration): Analysis
2020

21+
protected var dynamicConfigurations: List[IncrementalConfiguration] = List()
22+
2123
// The analysis configurations to use.
22-
var configurations: List[IncrementalConfiguration] = List()
24+
def configurations: List[IncrementalConfiguration] = dynamicConfigurations
2325

2426
// Parsing.
2527
def parse(string: String): E
@@ -42,7 +44,8 @@ trait IncrementalExperiment[E <: Expression]:
4244
def createOutput(): String
4345

4446
// Can be used for debugging.
45-
var catchErrors: Boolean = true
47+
protected var catchErrorsDynamic = true
48+
def catchErrors: Boolean = catchErrorsDynamic
4649

4750
// Runs measurements on the benchmarks in a given trait, or uses specific benchmarks if passed as an argument.
4851
def measure(bench: Set[String]): Unit =
@@ -76,8 +79,8 @@ trait IncrementalExperiment[E <: Expression]:
7679
/** Runs the benchmarks. Returns the path to the output file. */
7780
def execute(bench: Set[String], args: IncArgs): String =
7881
if executed then throw new Exception("Evaluation using this instance already executed. Create new instance of evaluation class.")
79-
if args.stopOnError then catchErrors = false
80-
if args.config.nonEmpty then configurations = List(args.config.get) else configurations = allConfigurations // Allows to override the default list of configurations of a setup.
82+
if args.stopOnError then catchErrorsDynamic = false
83+
if args.config.nonEmpty then dynamicConfigurations = List(args.config.get) else dynamicConfigurations = allConfigurations // Allows to override the default list of configurations of a setup.
8184
if args.timeout >= 0 then minutes = args.timeout
8285
executed = true
8386
val (writer, file): (Writer, String) = openTimeStampedGetName(outputDir + s"$minutes MIN " + outputFile)

code/jvm/src/main/scala/maf/cli/experiments/precision/PrecisionBenchmarks.scala

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ import maf.modular.scheme._
1111
import maf.util._
1212
import maf.util.benchmarks.Timeout
1313
import maf.language.scheme.interpreter.EmptyIO
14+
import maf.core.address.*
1415

15-
sealed trait BaseAddr extends Address { def printable = true; def idn: Identity }
16-
case class VarAddr(vrb: Identifier) extends BaseAddr { def idn: Identity = vrb.idn; override def toString = s"<variable $vrb>" }
17-
case class PtrAddr(exp: Expression) extends BaseAddr { def idn = exp.idn; override def toString = s"<pointer $exp>" }
18-
case class PrmAddr(nam: String) extends BaseAddr { def idn: Identity = Identity.none; override def toString = s"<primitive $nam>" }
1916

2017
abstract class PrecisionBenchmarks[Num: IntLattice, Rea: RealLattice, Bln: BoolLattice, Chr: CharLattice, Str: StringLattice, Smb: SymbolLattice]:
2118

@@ -29,9 +26,9 @@ abstract class PrecisionBenchmarks[Num: IntLattice, Rea: RealLattice, Bln: BoolL
2926
implicit def cpAnalysis(anl: ModularSchemeDomain): Analysis = anl.asInstanceOf[Analysis]
3027

3128
private def convertAddr(addr: Address): BaseAddr = addr match
32-
case maf.modular.scheme.VarAddr(vrb, _) => VarAddr(vrb)
33-
case maf.modular.scheme.PtrAddr(exp, _) => PtrAddr(exp)
34-
case maf.modular.scheme.PrmAddr(nam) => PrmAddr(nam)
29+
case maf.modular.scheme.VarAddr(vrb, _) => maf.core.address.VarAddr(vrb)
30+
case maf.modular.scheme.PtrAddr(exp, _) => maf.core.address.PtrAddr(exp)
31+
case maf.modular.scheme.PrmAddr(nam) => maf.core.address.PrmAddr(nam)
3532
case a: maf.modular.scheme.aam.AAMScheme#SchemeAddress => a.toBaseAddr
3633

3734
val baseDomain = new ModularSchemeLattice[BaseAddr, Str, Bln, Num, Rea, Chr, Smb]
@@ -61,9 +58,9 @@ abstract class PrecisionBenchmarks[Num: IntLattice, Rea: RealLattice, Bln: BoolL
6158
case analysis.modularLatticeWrapper.modularLattice.Elements(vs) => baseDomain.Elements(vs.map(convertV(analysis)))
6259

6360
private def convertConcreteAddr(addr: ConcreteValues.Addr): BaseAddr = addr._2 match
64-
case ConcreteValues.AddrInfo.VarAddr(v) => VarAddr(v)
65-
case ConcreteValues.AddrInfo.PtrAddr(p) => PtrAddr(p)
66-
case ConcreteValues.AddrInfo.PrmAddr(p) => PrmAddr(p)
61+
case ConcreteValues.AddrInfo.VarAddr(v) => maf.core.address.VarAddr(v)
62+
case ConcreteValues.AddrInfo.PtrAddr(p) => maf.core.address.PtrAddr(p)
63+
case ConcreteValues.AddrInfo.PrmAddr(p) => maf.core.address.PrmAddr(p)
6764

6865
protected def convertConcreteValue(value: ConcreteValues.Value): BaseValue = value match
6966
case ConcreteValues.Value.Nil => baseLattice.nil

code/jvm/src/main/scala/maf/cli/experiments/scv/CountFalsePositives.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ object CountFalsePositives:
8282
case Error =>
8383
(List(), table.add(name, s"${analysis}_blames", "ERROR"))
8484

85-
val remainingMetrics = metrics.map(_.name).toSet -- addedMetrics.toSet
85+
val remainingMetrics = metrics.map(_.toString).toSet -- addedMetrics.toSet
8686

8787
remainingMetrics.foldLeft(resTable)((table, metric) => table.add(name, s"${analysis}_${metric}", "-"))
8888

code/shared/src/main/scala/maf/aam/scheme/SchemeAAMSemantics.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ trait BaseSchemeAAMSemantics(prog: SchemeExp) extends maf.aam.AAMAnalysis[Scheme
106106
case V(v1) => s"V($v1)"
107107
case K(k1) => s"K($k1)"
108108
def refs(x: Storable): Set[Address] = throw new Exception("NYI -- storableLattice.refs(x)")
109+
def level(x: Storable): Int = ???
109110

110111
/**
111112
* An address under which a continuation is stored. To preserve call-return semantics, this address should be (e, p) where e is the call targets
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package maf.core
2+
3+
package address {
4+
5+
sealed trait BaseAddr extends Address { def printable = true; def idn: Identity }
6+
case class VarAddr(vrb: Identifier) extends BaseAddr { def idn: Identity = vrb.idn; override def toString = s"<variable $vrb>" }
7+
case class PtrAddr(exp: Expression) extends BaseAddr { def idn = exp.idn; override def toString = s"<pointer $exp>" }
8+
case class PrmAddr(nam: String) extends BaseAddr { def idn: Identity = Identity.none; override def toString = s"<primitive $nam>" }
9+
}

code/shared/src/main/scala/maf/core/Lattice.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ trait Lattice[L] extends PartialOrdering[L] with Show[L] with Serializable:
3737
/** For PartialOrdering[L]: a lattice has a partial order, defined by subsumes... */
3838
final def lteq(x: L, y: L): Boolean = subsumes(y, x)
3939

40+
/** Computes the number of levels upto the current value */
41+
def level(v: L): Int
42+
/** Computes the number of levels to the top value if one exists,
43+
otherwise Int.MAX_INT is returned */
44+
def levelToTop(v: L): Int =
45+
try level(top) - level(v)
46+
catch { case _ => Int.MaxValue }
47+
4048
/** ...and elements of the lattice can be compared */
4149
final def tryCompare(x: L, y: L): Option[Int] = (subsumes(x, y), subsumes(y, x)) match
4250
case (true, true) => Some(0) // x >= y and y >= x => x = y
@@ -55,6 +63,7 @@ object Lattice:
5563
def subsumes(x: Set[A], y: => Set[A]): Boolean = y.subsetOf(x)
5664
def eql[B: BoolLattice](x: Set[A], y: Set[A]) = ???
5765
def ceq(x: Set[A], y: => Set[A]): Boolean = x == y
66+
def level(v: Set[A]): Int = v.size // the number of levels is the amount of elements in the size
5867

5968
implicit def setLattice[A: Show]: Lattice[Set[A]] = new SetLattice[A]
6069

@@ -65,6 +74,7 @@ object Lattice:
6574
def join(x: Unit, y: => Unit): Unit = ()
6675
def subsumes(x: Unit, y: => Unit): Boolean = true
6776
def eql[B: BoolLattice](x: Unit, y: Unit): B = BoolLattice[B].inject(true)
77+
def level(v: Unit): Int = 1
6878

6979
def foldMapL[X, L: Lattice](xs: Iterable[X], f: X => L): L =
7080
if xs.isEmpty then Lattice[L].bottom

code/shared/src/main/scala/maf/language/scheme/lattices/ModularSchemeLattice.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class ModularSchemeLattice[A <: Address, S: StringLattice, B: BoolLattice, I: In
9191

9292
// TODO: this in ad-hoc lattice, we should make a PairLattice instead somewhere
9393
val lattice: Lattice[Abstract] = new Lattice[Abstract] {
94+
def level(v: (L, L)): scala.Int = Lattice[L].level(v._1) * Lattice[L].level(v._2)
9495
def show(v: (L, L)): String = s"(${v._1},${v._2})"
9596
def top = throw LatticeTopUndefined
9697
def bottom = ???
@@ -108,6 +109,14 @@ class ModularSchemeLattice[A <: Address, S: StringLattice, B: BoolLattice, I: In
108109
override def extract(v: Vec) = v
109110
// TODO: ad-hoc implementation, should create a VectorLattice
110111
val lattice: Lattice[Vec] = new Lattice[Vec] {
112+
def level(v: Vec): scala.Int =
113+
Lattice[I]
114+
.level(v.size) *
115+
v.elements.keys.map(Lattice[I].level).foldLeft(1)(_ * _) *
116+
v.elements.values
117+
.map(Lattice[L].level)
118+
.foldLeft(1)(_ * _)
119+
111120
def show(v: Vec) = v.toString
112121
def top = throw LatticeTopUndefined
113122
def bottom = Vec(IntLattice[I].bottom, Map())
@@ -271,8 +280,7 @@ class ModularSchemeLattice[A <: Address, S: StringLattice, B: BoolLattice, I: In
271280
def typeName = "PNTR"
272281
val tpy = PointerT
273282
override def toString: String =
274-
if ptrs.size > 3
275-
then s"{${ptrs.size} pointers}"
283+
if ptrs.size > 3 then s"{${ptrs.size} pointers}"
276284
else ptrs.mkString("Pointers{", ", ", "}")
277285

278286
case class Cons(car: L, cdr: L) extends Value:
@@ -927,6 +935,7 @@ class ModularSchemeLattice[A <: Address, S: StringLattice, B: BoolLattice, I: In
927935

928936
// TODO: field SchemeLattice only exists for backwards compatibility reasons, but for the sake of simplification should also be removed, and the methods be included within the class itself
929937
val schemeLattice: SchemeLattice[L, A] = new SchemeLattice[L, A] { lat =>
938+
def level(x: L): scala.Int = x.keys.map(key => x.getAbstract(key).map(key.lattice.level(_)).foldLeft(1)(_ * _)).foldLeft(1)(_ * _)
930939
def show(x: L): String = x.toString /* TODO[easy]: implement better */
931940
def isTrue(x: L): Boolean = x.elements[Value].foldMap(Value.isTrue(_))(boolOrMonoid)
932941
def isFalse(x: L): Boolean = x.elements[Value].foldMap(Value.isFalse(_))(boolOrMonoid)

code/shared/src/main/scala/maf/language/scheme/lattices/Product2SchemeLattice.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Product2ModularSchemeLattice[
4040
PL(f(left), right)
4141

4242
def product2Lattice: Product2SchemeLattice[PL, O, A] = new Product2SchemeLattice:
43+
def level(v: PL): scala.Int = Lattice[L].level(v.left) * Lattice[O].level(v.right)
4344
def show(x: PL): String = x.toString
4445
def refs(x: PL): Set[Address] = schemeLattice.refs(x.left)
4546
def isTrue(x: PL): Boolean = schemeLattice.isTrue(x.left)

code/shared/src/main/scala/maf/language/symbolic/lattices/SymbolicLattice.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ object SymbolicLattice:
7070
* used in an actual analysis. Such a widening operation is implemented in the `widen` function
7171
*/
7272
class SymbolicLattice[B: BoolLattice] extends Lattice[Set[Symbolic]]:
73+
def level(v: Set[Symbolic]) = v.size
7374
type L = Set[Symbolic]
7475
def bottom: L = Set()
7576
override def isBottom(x: L): Boolean = x.isEmpty

0 commit comments

Comments
 (0)