Skip to content

Commit aa3a1ed

Browse files
committed
setup program analysis with customisable priority WL algorithm
1 parent 0d3f743 commit aa3a1ed

1 file changed

Lines changed: 43 additions & 80 deletions

File tree

code/jvm/src/main/scala/maf/cli/runnables/AnalyzeProgram.scala

Lines changed: 43 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -16,93 +16,56 @@ import maf.modular.taint.scheme.SchemeModFBigStepTaintSemantics
1616
import maf.modular.worklist.*
1717
import maf.util.Reader
1818
import maf.util.benchmarks.{Timeout, Timer}
19+
import maf.modular.scheme.modf._
20+
import maf.modular.scheme.modf.SchemeModFComponent._
21+
import maf.language.scheme._
1922

2023
import scala.concurrent.duration.*
2124

2225
// null values are used here due to Java interop
2326
import scala.language.unsafeNulls
2427

2528
object AnalyzeProgram extends App:
26-
def runAnalysis[A <: ModAnalysis[SchemeExp] with GlobalStore[SchemeExp]](bench: String, analysis: SchemeExp => A, timeout: () => Timeout.T): A =
27-
val text = TaintSchemeParser.parseProgram(Reader.loadFile(bench))
28-
val a = analysis(text)
29-
print(s"Analysis of $bench ")
30-
try {
31-
val time = Timer.timeOnly {
32-
a.analyzeWithTimeout(timeout())
33-
println(a.store.filterNot(_.toString().contains("PrmAddr")).size)
34-
//println(a.program.prettyString())
35-
}
36-
println(s"terminated in ${time / 1000000} ms.")
37-
//a.deps.toSet[(Dependency, Set[a.Component])].flatMap({ case (d, cmps) => cmps.map(c => (d, c).toString()) }).foreach(println)
38-
} catch {
39-
case t: Throwable =>
40-
println(s"raised exception.")
41-
System.err.println(t.getMessage)
42-
t.printStackTrace()
43-
System.err.flush()
44-
}
45-
a
4629

47-
val bench: List[String] = List("test/DEBUG2.scm")
30+
enum AnalysisResult:
31+
case Terminated(iterationCount: Int, time: Long)
32+
case TimedOut
4833

49-
// Used by webviz.
50-
def newStandardAnalysis(text: String) =
51-
val program = SchemeParser.parseProgram(text)
52-
new SimpleSchemeModFAnalysis(program)
53-
with SchemeModFNoSensitivity
54-
with SchemeConstantPropagationDomain
55-
with DependencyTracking[SchemeExp]
56-
with FIFOWorklistAlgorithm[SchemeExp] {
57-
override def intraAnalysis(cmp: SchemeModFComponent) =
58-
new IntraAnalysis(cmp) with BigStepModFIntra with DependencyTrackingIntra
59-
}
34+
// timeout can be set e.g., using Timeout.start(Duration(1, MINUTES))
35+
def analyze(file: String, timeout: Timeout.T = Timeout.none): AnalysisResult =
36+
val text = Reader.loadFile(file)
37+
val prog = SchemeParser.parseProgram(text)
38+
var iterations = 0
39+
val analysis =
40+
new SimpleSchemeModFAnalysis(prog)
41+
with SchemeModFNoSensitivity
42+
with SchemeConstantPropagationDomain
43+
with PriorityQueueWorklistAlgorithm[SchemeExp]:
44+
/** Example implementation of priority **/
45+
lazy val ordering = Ordering.by(priority) // currently, ordering is based on calculated priority
46+
// alternatively, could also just implement `compare` here
47+
def priority(cmp: Component): Int =
48+
cmp match
49+
case Main => 0 // "main" (= top-level program code) gets priority 0
50+
case Call((lam, env), ctx) => priority(lam) // TODO: could also take lexical environment + context into account
51+
def priority(lam: SchemeLambdaExp): Int =
52+
42 // TODO: determine the priority for each lambda in the program
53+
/** Analysis setup **/
54+
override def intraAnalysis(cmp: SchemeModFComponent) =
55+
new IntraAnalysis(cmp) with BigStepModFIntra
56+
override def step(timeout: Timeout.T) =
57+
iterations += 1
58+
super.step(timeout)
59+
val time = Timer.timeOnly { analysis.analyzeWithTimeout(timeout) }
60+
if analysis.finished then
61+
AnalysisResult.Terminated(iterations, time/1000000)
62+
else
63+
AnalysisResult.TimedOut
6064

61-
// Used by incremental analyses.
62-
def newNonIncAnalysis(program: SchemeExp) =
63-
new ModAnalysis[SchemeExp](program)
64-
with StandardSchemeModFComponents
65-
with SchemeModFNoSensitivity
66-
with SchemeModFSemanticsM
67-
with LIFOWorklistAlgorithm[SchemeExp]
68-
with BigStepModFSemantics
69-
with SchemeTypeDomain
70-
with GlobalStore[SchemeExp] {
71-
var cnt = 0
72-
override def run(timeout: Timeout.T) =
73-
super.run(timeout)
74-
println(cnt)
75-
override def intraAnalysis(cmp: Component) = new IntraAnalysis(cmp) with BigStepModFIntra with GlobalStoreIntra {
76-
override def analyzeWithTimeout(timeout: Timeout.T): Unit =
77-
cnt = cnt + 1
78-
super.analyzeWithTimeout(timeout)
79-
}
80-
}
81-
82-
def taintAnalysis(program: SchemeExp) =
83-
new ModAnalysis[SchemeExp](program)
84-
with StandardSchemeModFComponents
85-
with SchemeModFNoSensitivity
86-
with SchemeModFSemanticsM
87-
with LIFOWorklistAlgorithm[SchemeExp]
88-
with SchemeModFBigStepTaintSemantics
89-
with IncrementalSchemeTypeDomain
90-
with GlobalStoreTaint[SchemeExp] {
91-
override def intraAnalysis(
92-
cmp: SchemeModFComponent
93-
): SchemeModFBigStepTaintIntra = new IntraAnalysis(cmp) with SchemeModFBigStepTaintIntra with GlobalStoreTaintIntra
94-
}
95-
96-
bench.foreach({ b =>
97-
// for(i <- 1 to 10) {
98-
//runAnalysis(b, program => SchemeAnalyses.kCFAAnalysis(program, 0), () => Timeout.start(Duration(2, MINUTES)))
99-
val a = runAnalysis(b, program => taintAnalysis(program), () => Timeout.start(Duration(1, MINUTES)))
100-
println(b)
101-
println(a.taintResult())
102-
println()
103-
//println(a.program.prettyString())
104-
// a.dataFlowR.foreach(println)
105-
//println()
106-
//println()
107-
//a.implicitFlowsCut.foreach({ case (c, as) => as.foreach(a => println(s"$c $a")) })
108-
})
65+
analyze("test/R5RS/gabriel/boyer.scm") match
66+
case AnalysisResult.Terminated(iterations, timeMs) =>
67+
println("*** Analysis terminated ***")
68+
println(s"-> iterations: $iterations")
69+
println(s"-> time: ${timeMs}ms")
70+
case AnalysisResult.TimedOut =>
71+
println("*** Analysis timed out ***")

0 commit comments

Comments
 (0)