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 } } }