Skip to content

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package edu.colorado.plv.cuanto
package scoot.domains

/** Generic abstraction of numeric types.
*/
trait ArithDom {
type D

def neg(e: D): D

def add(e1: D)(e2: D): D
def sub(e1: D)(e2: D): D
def mul(e1: D)(e2: D): D
def div(e1: D)(e2: D): D
}
34 changes: 34 additions & 0 deletions src/main/scala/edu/colorado/plv/cuanto/scoot/domains/IntDom.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package edu.colorado.plv.cuanto
package scoot.domains

import abstracting._

/** Concrete domain of integer values.
*/
case class IntDom(i: Int) extends ArithDom
with Abstractable[Int,IntDom] {
override type D = IntDom

override def represent(i: Int): IntDom = IntDom(i)

override def neg(e: IntDom): IntDom = e match {
case IntDom(i) => i * -1
}

override def add(e1: IntDom)(e2: IntDom): IntDom =
(e1,e2) match {
case (IntDom(i1),IntDom(i2)) => i1 + i2
}
override def sub(e1: IntDom)(e2: IntDom): IntDom =
(e1,e2) match {
case (IntDom(i1),IntDom(i2)) => i1 - i2
}
override def mul(e1: IntDom)(e2: IntDom): IntDom =
(e1,e2) match {
case (IntDom(i1),IntDom(i2)) => i1 * i2
}
override def div(e1: IntDom)(e2: IntDom): IntDom =
(e1,e2) match {
case (IntDom(i1),IntDom(i2)) => i1 / i2
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package edu.colorado.plv.cuanto.scoot

package domains {
trait Result[A <: ArithDom]
case class Arith[A <: ArithDom](a: A) extends Result[A]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package edu.colorado.plv.cuanto.scoot.interpreter
package control

import soot.{Unit => SootUnit}
import soot.toolkits.graph.UnitGraph

import expression.Env

/** Interpret soot Units that affect control-flow */
package object control {

/** Find the next Unit, given an environment */
def succ(graph: UnitGraph)(env: Env, unit: SootUnit):
Option[SootUnit] = ???

def next[D](graph: UnitGraph, unit: SootUnit): Traversable[(Unit,D)] = ???

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package edu.colorado.plv.cuanto.scoot
package interpreter.expression

import soot._
import soot.jimple._

import domains._
import domains.IntDom

/** Sub-interpreter for arithmetic nodes */
object Arithmetic {

private def omerge[A,B](t: (Option[A],Option[B])): Option[(A,B)] =
for (a <- t._1; b <- t._2) yield (a,b)


/** Interpret an arithmetic operator node */
def interpNode(v: Value)(r: Value => Option[RFun]):
Option[RFun] = v match {
// case v: Local => env get v
case v: IntConstant => Some(_ => Some(Arith(IntDom(v.value))))
case v: BinopExpr => for {
op <- bop(v)
arg1 <- r(v.getOp1())
arg2 <- r(v.getOp2())
} yield { e: Env => op(arg1(e), arg2(e)) }
case v: UnopExpr => for {
op <- uop(v)
arg <- r(v.getOp())
} yield { e: Env => op(arg(e)) }
case _ => None
}

/** Interpret an arithmetic unary operator node, getting back a
* function that performs the operation */
private def uop(op: UnopExpr):
Option[Option[R] => Option[R]] = {
def tryOp(f: IntDom => IntDom)(a: Option[R]): Option[R] = a match {
case Some(Arith(a)) => Some(Arith(f(a)))
case _ => None
}
op match {
case _: NegExpr => Some(tryOp((i: IntDom) => i.neg(i)))
case _ => None
}
}

/** Interpret an arithemetic binary operator node, getting back a
* function that performs the operation */
private def bop(op: BinopExpr):
Option[(Option[R], Option[R]) => Option[R]] = {
def tryOp(f: (IntDom,IntDom) => IntDom)(a: Option[R], b: Option[R]):
Option[R] =
(a,b) match {
case (Some(Arith(a)),(Some(Arith(b)))) => Some(Arith(f(a,b)))
case _ => None
}
op match {
case _: AddExpr => Some(tryOp((i1: IntDom,i2: IntDom) => i1.add(i1)(i2)))
case _: SubExpr => Some(tryOp((i1: IntDom,i2: IntDom) => i1.sub(i1)(i2)))
case _: DivExpr => Some(tryOp((i1: IntDom,i2: IntDom) => i1.div(i1)(i2)))
case _: MulExpr => Some(tryOp((i1: IntDom,i2: IntDom) => i1.mul(i1)(i2)))
case _ => None
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package edu.colorado.plv.cuanto.scoot
package arithmetic
package edu.colorado.plv.cuanto.scoot.interpreter
package expression

import soot.{Value, IntType, Local, Immediate}
import soot.jimple._
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package edu.colorado.plv.cuanto
package scoot.interpreter

import scala.collection.immutable.{Map, HashMap}
import soot._

import scoot.domains._

/** Interpreter for expressions (soot Values). This depends on
* expression evaluation not having side-effects.
*/
package object expression {
/** A sum type of possible types that an expression can evaluate to */
type R = Result[IntDom]

/** Evaluation environment */
type Env = Map[String,R]
type RFun = Env => Option[R]

/** The empty environment */
val emptyEnv: Env = new HashMap[String,R]()

/** Interpret a value under a particular environment */
def interpret(v: Value, env: Env = emptyEnv): Option[R] = (for {
rfun <- interpR(v)
} yield rfun(env)).flatten

private def interpR(v: Value): Option[RFun] =
anyOf(Seq(Arithmetic.interpNode(v)(interpR), Locals.interpNode(v)(interpR)))

private def anyOf(is: Traversable[Option[RFun]]): Option[RFun] =
is.flatten.headOption

/** Sub-interpreter for looking up Local values in the environment */
object Locals {
/** Interpret a Local node */
def interpNode(v: Value)(r: Value => Option[RFun]):
Option[RFun] = v match {
case v: Local => Some(_ get v.getName())
case _ => None
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package edu.colorado.plv.cuanto.scoot.interpreter
package mutation

import soot._
import soot.jimple._

import expression._

/** Interpreter for soot Units that modify the evaluation
* environment */
package object mutation {

private def some[A](a: A): Option[A] = Some(a)

/** Step an environment forward over a single statement */
def step(stmt: AssignStmt)(env: Env): Option[Env] = {
val varNameO: Option[Local] = stmt.getLeftOp() match {
case l: Local => Some(l)
case _ => None
}
val newValueO: Option[R] = expression.interpret(stmt.getRightOp(), env)
for {
varName <- varNameO
newValue <- newValueO
} yield env + (varName.getName() -> newValue)
}

/** Interpret the integer value of a variable mutated over a sequence
* of assignment statements */
def interpret(ss: Traversable[AssignStmt], v: String): Option[R] =
interpret(ss).flatMap(_ get v)

def interpret(ss: Traversable[AssignStmt]): Option[Env] =
ss.foldLeft(some(emptyEnv))((env,stmt) => env.flatMap(step(stmt)))
}

This file was deleted.

Loading