Skip to content

Commit

Permalink
Merge pull request #33 from alexrhein/alexmaster
Browse files Browse the repository at this point in the history
optional simplification of presence condtions after parsing
  • Loading branch information
ckaestne committed Jan 22, 2015
2 parents 3e729f0 + 6862568 commit dd7cd8e
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 5 deletions.
53 changes: 50 additions & 3 deletions CParser/src/main/scala/de/fosd/typechef/parser/c/ParserMain.scala
Expand Up @@ -5,9 +5,11 @@ import de.fosd.typechef.parser._
import java.io.{FileWriter, File}
import FeatureExprFactory.True
import java.util.Collections
import de.fosd.typechef.error.Position
import de.fosd.typechef.conditional.Opt
import de.fosd.typechef.error.{WithPosition, Position}
import de.fosd.typechef.conditional.{One, Choice, Opt}
import de.fosd.typechef.lexer.LexerFrontend
import org.kiama.rewriting.Rewriter._
import org.kiama.rewriting.Strategy

object MyUtil {
implicit def runnable(f: () => Unit): Runnable =
Expand Down Expand Up @@ -99,7 +101,52 @@ class ParserMain(p: CParser) {


//return null (if parsing failed in all branches) or a single AST combining all parse results
mergeResultsIntoSingleAST(ctx, result)
val ast = mergeResultsIntoSingleAST(ctx, result)
if (parserOptions.simplifyPresenceConditions) {
if (FeatureExprFactory.default == FeatureExprFactory.bdd) {
return simplifyPresenceConditions(ast, FeatureExprFactory.True)
} else {
print("\"-bdd\" option required to simplify AST presence conditions.\n")
}
}

ast
}
/**
* Simplifies presence conditions on ast nodes in the AST.
* AST is not changed but a new AST with changed pcs is returned. Positions are copied.
* This method is based on Florian Garbe's method prepareASTforIfdef in de.fosd.typechef.cifdeftoif.IfdefToIf in the Hercules fork of TypeChef.
*/
def simplifyPresenceConditions(ast: TranslationUnit, ctx: FeatureExpr = FeatureExprFactory.True): TranslationUnit = {
val astEnv = de.fosd.typechef.parser.c.CASTEnv.createASTEnv(ast)
def traverseASTrecursive[T <: Product](t: T, currentContext: FeatureExpr = FeatureExprFactory.True): T = {
val r = alltd(rule[Any] {
case l: List[_] =>
l.flatMap(x => x match {
case o@Opt(ft: FeatureExpr, entry) =>
if (!ft.and(currentContext).isSatisfiable()) {
// current context makes ft impossible (-> ft == false and we can omit the node)
List()
} else {
List(traverseASTrecursive(Opt(ft.simplify(currentContext), entry), ft.and(currentContext)))
}
})
case c@Choice(ft, thenBranch, elseBranch) =>
val ctx = astEnv.featureExpr(c)
val newChoiceFeature = ft.simplify(ctx)
val result = Choice(newChoiceFeature,
traverseASTrecursive(thenBranch,ctx.and(newChoiceFeature)) ,
traverseASTrecursive(elseBranch,ctx.and(newChoiceFeature.not)))
result
})
r(t) match {
case None =>
t
case k =>
k.get.asInstanceOf[T]
}
}
traverseASTrecursive(ast, ctx)
}

/**
Expand Down
Expand Up @@ -12,6 +12,7 @@ import de.fosd.typechef.error.Position
*/

trait ParserOptions {
def simplifyPresenceConditions : Boolean
def printParserResult: Boolean
def printParserStatistics: Boolean

Expand All @@ -23,10 +24,12 @@ trait ParserOptions {
object DefaultParserOptions extends ParserOptions {
def printParserResult = true
def printParserStatistics = true
def simplifyPresenceConditions = false
}


object SilentParserOptions extends ParserOptions {
def printParserResult = false
def printParserStatistics = false
def simplifyPresenceConditions = false
}
Expand Up @@ -117,7 +117,7 @@ abstract class Conditional[+T] extends Product {
def select(selectedFeatures: Set[String]): T
}

case class Choice[+T](condition: FeatureExpr, thenBranch: Conditional[T], elseBranch: Conditional[T]) extends Conditional[T] {
case class Choice[+T](val condition: FeatureExpr, thenBranch: Conditional[T], elseBranch: Conditional[T]) extends Conditional[T] {
def flatten[U >: T](f: (FeatureExpr, U, U) => U): U = f(condition, thenBranch.flatten(f), elseBranch.flatten(f))
override def equals(x: Any) = x match {
case Choice(f, t, e) => f.equivalentTo(condition) && (thenBranch == t) && (elseBranch == e)
Expand Down
Expand Up @@ -19,6 +19,7 @@ class ErrorFeature(msg: String, f: FeatureExpr) extends FeatureExpr {
def or(that: FeatureExpr) = error
def and(that: FeatureExpr) = error
def not() = error
def simplify(that: FeatureExpr) = error
def unique(x:SingleFeatureExpr) = error
override def evaluate(selectedFeatures: Set[String]) = false

Expand Down
Expand Up @@ -21,6 +21,15 @@ trait FeatureExpr extends Serializable {
def and(that: FeatureExpr): FeatureExpr
def not(): FeatureExpr

/**
* Informal: Returns all the information in this that is not present in b.
* this.simplify(b) is equivialent to this if the context b is guaranteed
* Formal: (b implies (this.simplify(b) equiv this))
* @param b
* @return
*/
def simplify(b:FeatureExpr) : FeatureExpr

//equals, hashcode


Expand Down
Expand Up @@ -42,6 +42,8 @@ class BDDFeatureExpr(private[featureexpr] val bdd: BDD) extends FeatureExpr {
}
def not(): FeatureExpr = FExprBuilder.not(this)

def simplify(b:FeatureExpr) : FeatureExpr = new BDDFeatureExpr(this.bdd.simplify(asBDDFeatureExpr(b).bdd))

/**
* frees the space occupied by this bdd in the bdd library.
* This is done without any safety-measures!
Expand Down
Expand Up @@ -77,6 +77,9 @@ sealed abstract class SATFeatureExpr extends FeatureExpr {
def notS(): SATFeatureExpr = FExprBuilder.not(this)
def not(): SATFeatureExpr = notS()

// we dont have a good implementation in SAT, and a satisfies the contract
def simplify(b:FeatureExpr): SATFeatureExpr = this

override def unique(feature: SingleFeatureExpr): FeatureExpr = substitute(feature, False) xor substitute(feature, True)

def substitute(feature: SingleFeatureExpr, replacement: SATFeatureExpr): SATFeatureExpr
Expand Down
Expand Up @@ -28,6 +28,7 @@ public class FrontendOptions extends CAnalysisOptions implements ParserOptions {
recordTiming = false,
parserStatistics = false,
parserResults = true,
simplifyPresenceConditions = false,
writePI = false,
printInclude = false,
printVersion = false;
Expand All @@ -47,6 +48,7 @@ public class FrontendOptions extends CAnalysisOptions implements ParserOptions {
private final static char F_RECORDTIMING = Options.genOptionId();
private final static char F_FILEPC = Options.genOptionId();
private final static char F_PARSERSTATS = Options.genOptionId();
private final static char F_SIMPLIFYPRESENCECONDITIONS = Options.genOptionId();
private final static char F_HIDEPARSERRESULTS = Options.genOptionId();
private final static char F_BDD = Options.genOptionId();
private final static char F_ERRORXML = Options.genOptionId();
Expand Down Expand Up @@ -101,7 +103,9 @@ public List<Options.OptionGroup> getOptionGroups() {
new Option("hideparserresults", LongOpt.NO_ARGUMENT, F_HIDEPARSERRESULTS, null,
"Do not show parser results."),
new Option("parserstatistics", LongOpt.NO_ARGUMENT, F_PARSERSTATS, null,
"Print parser statistics.")
"Print parser statistics."),
new Option("simplifyPresenceConditions", LongOpt.NO_ARGUMENT, F_SIMPLIFYPRESENCECONDITIONS, null,
"Simplify presence conditions after parsing.")
));
r.add(new OptionGroup("Misc", 1000,
new Option("printIncludes", LongOpt.NO_ARGUMENT, TY_DEBUG_INCLUDES, null,
Expand Down Expand Up @@ -148,6 +152,8 @@ public boolean interpretOption(int c, Getopt g) throws OptionException {
parserResults = false;
} else if (c == F_PARSERSTATS) {
parserStatistics = true;
} else if (c == F_SIMPLIFYPRESENCECONDITIONS) {
simplifyPresenceConditions = true;
} else if (c == F_WRITEPI) {
writePI = true;
} else if (c == F_BDD) {
Expand Down Expand Up @@ -260,6 +266,10 @@ public void setRenderParserError(Function3<FeatureExpr, String, Position, Object
}


public boolean simplifyPresenceConditions() {
return simplifyPresenceConditions;
}

public boolean printParserResult() {
return parserResults;
}
Expand Down

0 comments on commit dd7cd8e

Please sign in to comment.