LARA

package minijava.controlflow
 
object CFGTrees {
  import analyzer.Symbols._
  import analyzer.Types._
 
  sealed abstract class CFGTree {
    override def toString = stringRepr(this)
  }
 
  sealed abstract class CFGStatement extends CFGTree
  case class CFGAssign(variable: CFGVariable, expr: CFGExpression) extends CFGStatement
 
  case class CFGAssignBinary(variable: CFGVariable,
                             lhs: CFGSimpleValue,
                             binOp: CFGBinaryOperator,
                             rhs: CFGSimpleValue) extends CFGStatement
 
  case class CFGAssignUnary(variable: CFGVariable,
                            unOp: CFGUnaryOperator,
                            expr: CFGSimpleValue) extends CFGStatement
 
  case class CFGAssignMethodCall(variable: CFGVariable,
                                 receiver: CFGSimpleValue,
                                 id: parser.Trees.Identifier,
                                 params: List[CFGSimpleValue]) extends CFGStatement
 
  case class CFGArrayAssign(arr: CFGVariable, index: CFGSimpleValue, expr: CFGSimpleValue) extends CFGStatement
  case class CFGPrintln(expr: CFGSimpleValue) extends CFGStatement
  case class CFGAssume(lhs: CFGSimpleValue, relOp: CFGRelationalOperator, rhs: CFGSimpleValue) extends CFGStatement
  case object CFGSkip extends CFGStatement
 
  sealed abstract class CFGExpression extends CFGTree with Typed
  sealed abstract class CFGSimpleValue extends CFGExpression
  sealed abstract class CFGVariable extends CFGSimpleValue
 
  /** Used to represent the identifiers from the original program. */
  case class CFGIdentifier(symbol: VariableSymbol) extends CFGVariable with Symbolic[VariableSymbol] with Positional {
    override def getSymbol = symbol
    override def setSymbol(s: VariableSymbol) = this
    override def getType = symbol.getType
    override def setType(t: Type) = this
  }
 
  /** Used to represent intermediate values (fresh identifiers). */
  case class CFGTempID(value: String) extends CFGVariable
 
  case class CFGNumLit(value: Int) extends CFGSimpleValue
  case class CFGStringLit(value: String) extends CFGSimpleValue
  case object CFGTrue extends CFGSimpleValue
  case object CFGFalse extends CFGSimpleValue
  case object CFGThis extends CFGSimpleValue
  case class CFGNew(tpe: parser.Trees.Identifier) extends CFGSimpleValue
 
  sealed abstract class CFGBinaryOperator
  sealed trait CFGRelationalOperator
  case object PLUS extends CFGBinaryOperator { override def toString = "+" }
  case object MINUS extends CFGBinaryOperator { override def toString = "-" }
  case object TIMES extends CFGBinaryOperator { override def toString = "*" }
  case object DIV extends CFGBinaryOperator { override def toString = "/" }
  case object AND extends CFGBinaryOperator { override def toString = "&&" }
  case object OR extends CFGBinaryOperator { override def toString = "||" }
  case object LT extends CFGBinaryOperator with CFGRelationalOperator { override def toString = "<" }
  case object GEQ extends CFGBinaryOperator with CFGRelationalOperator { override def toString = ">=" }
  case object EQUALS extends CFGBinaryOperator with CFGRelationalOperator { override def toString = "==" }
  case object NOTEQUALS extends CFGBinaryOperator with CFGRelationalOperator { override def toString = "!=" }
  case object ARRAYREAD extends CFGBinaryOperator
 
  sealed abstract class CFGUnaryOperator
  case object NOT extends CFGUnaryOperator { override def toString = "!" }
  case object NEWINTARRAY extends CFGUnaryOperator
  case object ARRAYLENGTH extends CFGUnaryOperator
 
  def stringRepr(tree: CFGTree): String = {
    val assOp = " := "
 
    tree match {
      case CFGAssignMethodCall(v, r, mid, p) => v + assOp + r + "." + mid.value + p.mkString("(", ", ", ")")
      case CFGAssignBinary(v, l, ARRAYREAD, r) => v + assOp + l + "[" + r + "]"
      case CFGAssignBinary(v, l, b, r) => v + assOp + l + " " + b + " " + r
      case CFGAssignUnary(v, NEWINTARRAY, e) => v + assOp + "new int[" + e + "]"
      case CFGAssignUnary(v, ARRAYLENGTH, e) => v + assOp + e + ".length"
      case CFGAssignUnary(v, u, e) => v + assOp + u + e
      case CFGAssign(v, e) => v + assOp + e
      case CFGArrayAssign(a, i, e) => a + "[" + i + "]" + assOp + e
      case CFGPrintln(v) => "print(" + v +")"
      case CFGSkip => "..."
      case CFGAssume(l, o, r) => "[" + l + o + r + "]"
      case CFGStringLit(value) => "\"" + value + "\""
      case CFGNumLit(value) => value.toString
      case CFGNew(tpe) => "new " + tpe.value + "()"
      case CFGTrue => "true"
      case CFGFalse => "false"
      case CFGThis => "this"
      case CFGIdentifier(sym) => sym.name
      case CFGTempID(value) => value
    }
  }
}