diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98e59e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# .gitignore padrão Scala, SBT no VSCode com plugin Scala Metals +*.class +*.log +.bloop/ +.metals/ +.vscode/ +.scalafmt.conf +project/ + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Simple Build Tool +# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control + +dist/* +target/ +lib_managed/ +src_managed/ +.history +.cache +.lib/ diff --git a/src/main/scala/br/unb/cic/wlang/AvailableExpression.scala b/src/main/scala/br/unb/cic/wlang/AvailableExpression.scala new file mode 100644 index 0000000..45cfbae --- /dev/null +++ b/src/main/scala/br/unb/cic/wlang/AvailableExpression.scala @@ -0,0 +1,56 @@ +package br.unb.cic.wlang +import scala.collection.mutable + +/** Implementation of the Available Expression algorithm. + */ + +object AvailableExpression { +// TODO getNonTrivialExpressionSet +// TODO setInitialValues = Emptyset +// TODO Naive Chaotic Iteration on AvailableExpression.execute + type Abstraction = Set[(String, Stmt)] + type DS = mutable.HashMap[Stmt, Abstraction] + + val empty: Abstraction = Set.empty + + def execute(program: WhileProgram): (DS, DS) = { + val cfg = CFGBuilder.build(program) + val stmts = CFGBuilder.stmts(program) + + // initialization + val universalSet = initUniversalSet(program.stmt) + val out = initOutSet(stmts) + val in = new DS() + + var fixedPoint = false + + // while (!fixedPoint) {} //TODO + (in, out) //é o return (DS, DS) + } + + def initOutSet(stmts: Set[Stmt]): DS = { //inicializa os sets dos stmts como vazio? ok! + val out = new DS() + stmts.foreach(s => out += s -> empty) + out + } + + def initUniversalSet(stmt: Stmt): Abstraction = stmt match { + case Assignment(v, _, _) => Set((v, stmt)) + case Skip(_) => Set.empty + case IfThenElse(_, s1, s2, _) => + initUniversalSet(s1) union initUniversalSet(s2) + case While(_, s, _) => initUniversalSet(s) + case Sequence(s1, s2) => initUniversalSet(s1) union initUniversalSet(s2) + } + + def kill(stmt: Stmt, universalSet: Abstraction): Abstraction = stmt match { + case Assignment(v, _, _) => universalSet.filter(t => v == t._1) + case _ => Set.empty + } + + def gen(stmt: Stmt): Abstraction = stmt match { + case Assignment(v, _, _) => Set((v, stmt)) + case _ => Set.empty + } + +} diff --git a/src/main/scala/br/unb/cic/wlang/ReachDefinition.scala b/src/main/scala/br/unb/cic/wlang/ReachDefinition.scala index 282e52f..1e257af 100644 --- a/src/main/scala/br/unb/cic/wlang/ReachDefinition.scala +++ b/src/main/scala/br/unb/cic/wlang/ReachDefinition.scala @@ -27,25 +27,25 @@ object ReachDefinition { while(!fixedPoint) { val (oldIn, oldOut) = (in.clone(), out.clone()) for(s <- stmts) { - //IN[S] = U {OUT[from] | (from, to) in cfg, S == to} + //IN[S] = U {OUT[from] | (from, to) in cfg, S == to} //OK conforme definição do livro para o RDEntry(to) //This is not so beautiful in Scala =( - in(s) = (for { (from,to) <- cfg if to == s } yield out(from)).foldLeft(empty)(_ union _) + in(s) = (for { (from,to) <- cfg if to == s } yield out(from)).foldLeft(empty)(_ union _) //não consegui ler esse trecho - //OUT[S] = GEN(S) U (IN[S] - KILL[S]) - out(s) = gen(s) union (in.getOrElse(s, empty) diff kill(s, universalSet)) + //OUT[S] = GEN(S) U (IN[S] - KILL[S]) //OK conforme definição do livro para o RDexit(to) + out(s) = gen(s) union (in.getOrElse(s, empty) diff kill(s, universalSet)) //não consegui ler esse trecho } - fixedPoint = (oldIn, oldOut) == (in, out) + fixedPoint = (oldIn, oldOut) == (in, out) //Se não há mais alterações nos conjuntos entre RDentry(from), RDexit(from) e RDentry(to), RDexit(to) então chegou no fixed point e sai do laço } (in, out) } - def initOutSet(stmts: Set[Stmt]): DS = { + def initOutSet(stmts: Set[Stmt]): DS = { //inicializa os sets dos stmts como vazio? ok! val out = new DS() stmts.foreach(s => out += s -> empty) out } - def initUniversalSet(stmt: Stmt): Abstraction = stmt match { + def initUniversalSet(stmt: Stmt): Abstraction = stmt match { //não entendi a necessidade desse inituniversal case Assignment(v, _, _) => Set((v, stmt)) case Skip(_) => Set.empty case IfThenElse(_, s1, s2, _) => initUniversalSet(s1) union initUniversalSet(s2) @@ -54,12 +54,12 @@ object ReachDefinition { } def kill(stmt: Stmt, universalSet: Abstraction): Abstraction = stmt match { - case Assignment(v, _, _) => universalSet.filter(t => v == t._1) + case Assignment(v, _, _) => universalSet.filter(t => v == t._1) //filtra true/false mas não entendi como o 't._1' é true somente p/ assignments a 'v' case _ => Set.empty } def gen(stmt: Stmt): Abstraction = stmt match { - case Assignment(v, _, _) => Set((v,stmt)) + case Assignment(v, _, _) => Set((v,stmt)) //v = nome da variável que está sendo definida no Assignment case _ => Set.empty } diff --git a/src/test/scala/br/unb/cic/wlang/AvailableExpressionTest.scala b/src/test/scala/br/unb/cic/wlang/AvailableExpressionTest.scala new file mode 100644 index 0000000..12bdd17 --- /dev/null +++ b/src/test/scala/br/unb/cic/wlang/AvailableExpressionTest.scala @@ -0,0 +1,22 @@ +package br.unb.cic.wlang + +import org.scalatest.funsuite.AnyFunSuite + +class AvailableExpressionTest extends AnyFunSuite { + + /* + * x := a+b; + * y := a*b; + * while y > a+b do + * a := a+l; + * x := a+b; +*/ + + val s1 = Assignment("x", Add(Var("a"), Var("b")), 1) + val s2 = Assignment("y", Mult(Var("a"), Var("b")), 2) + val s4 = Assignment("a", Add(Var("a"), Const(1)), 4) + val s5 = Assignment("x", Add(Var("a"), Var("b")), 5) + val s3 = While(GT(Var("y"), Add(Var("a"), Var("b"))), s2, 4) + val p = WhileProgram(Sequence(s1, Sequence(s2, Sequence(s3, Sequence(s4, s5))))) + +}