Package de.fosd.typechef.options

Source Code of de.fosd.typechef.options.FeatureModelOptions

package de.fosd.typechef.options;

import de.fosd.typechef.featureexpr.FeatureExpr;
import de.fosd.typechef.featureexpr.FeatureExprParserJava;
import de.fosd.typechef.featureexpr.FeatureModel;
import de.fosd.typechef.lexer.FeatureExprLib;
import de.fosd.typechef.lexer.options.ILexerOptions;
import de.fosd.typechef.lexer.options.PartialConfiguration;
import de.fosd.typechef.lexer.options.PartialConfigurationParser$;
import gnu.getopt.Getopt;
import gnu.getopt.LongOpt;
import scala.io.Source;

import java.util.List;

/**
* TypeChef uses two different feature models for different purposes, a small and a full
* feature model. In Linux smallFM = approx.fm and fullFM = dimacs file. The full feature
* model should contain all constraints of the small feature model (fullFM => smallFM).
* <p/>
* The key concern is performance since all SAT checks involving the feature model take
* more time. There are generally three different ways to call the SAT solver then
* <ul>
* <li>f.isSatisfiable()</li>
* <li>f.isSatisfiable(smallFM)</li>
* <li>f.isSatisfiable(fullFM)</li>
* </ul>
* The first is the fastest but may return that the formula is satisfiable even if
* it would not be satisfiable with the full feature model. The small feature model
* is more precise but also slower. The full feature model provides the reference answer
* but potentially at additional costs. (In Linux a check with fullFM takes about 0.5 seconds
* whereas the other two are essentially instantanious).
* <p/>
* A common strategy used throughout TypeChef is to use SAT checks without the
* feature model as long as possible and only use the
* full feature model before reporting bugs to a user. That way many infeasible
* paths are pruned early, but some may remain for additional computations.
* <p/>
* In the lexer and parser, we found that pruning only at the end when reporting error messages
* is too late and requires to track complex error conditions and perform many redundant
* computations. Running the TypeChef parser without any feature model is even slower than running
* it with the full feature model. Here the small feature model helps to prune more paths
* and safe computational effort.
* <p/>
* Feature models are used in TypeChef as follows:
* <ul>
* <li>parser and lexer use the small feature model (if available) in most checks and prune the result with the full feature model</li>
* <li>the type system computes without any feature model and only checks reported errors with the full feature model</li>
* <li>...</li>
* </ul>
* <p/>
* Users can specify small and full feature model separately using --featureModelDimacs or --featureModelFExpr
* for the small feature model and using --typeSystemFeatureModelDimacs for the full feature model.
* If the small feature model is not defined
* it is assumed to be empty. If the full feature model is not defined it is assumed to be the same
* as the small feature model.
*/
public abstract class FeatureModelOptions extends LexerOptions implements ILexerOptions {
    protected FeatureModel smallFeatureModel = null;
    protected FeatureModel fullFeatureModel = null;
    protected PartialConfiguration partialConfig = null;


    @Override
    public FeatureModel getSmallFeatureModel() {
        if (smallFeatureModel == null)
            return FeatureExprLib.featureModelFactory().empty();
        return smallFeatureModel;
    }

    //    @Override
    public FeatureModel getFullFeatureModel() {
        if (fullFeatureModel != null)
            return fullFeatureModel;
        if (smallFeatureModel == null)
            return FeatureExprLib.featureModelFactory().empty();
        return smallFeatureModel;
    }

    private static final char FM_DIMACS = Options.genOptionId();
    private static final char FM_FEXPR = Options.genOptionId();
    //    private static final char FM_CLASS = Options.genOptionId();
    private static final char FM_TSDIMACS = Options.genOptionId();
    private static final char FM_PARTIALCONFIG = Options.genOptionId();

    @Override
    protected List<Options.OptionGroup> getOptionGroups() {
        List<Options.OptionGroup> r = super.getOptionGroups();

        r.add(new OptionGroup("Feature models", 100,
                new Option("featureModelDimacs", LongOpt.REQUIRED_ARGUMENT, FM_DIMACS, "file",
                        "Dimacs file describing a feature model."),
                new Option("featureModelFExpr", LongOpt.REQUIRED_ARGUMENT, FM_FEXPR, "file",
                        "File in FExpr format describing a feature model."),
//                new Option("featureModelClass", LongOpt.REQUIRED_ARGUMENT, FM_CLASS, "classname",
//                        "Class describing a feature model."),
                new Option("typeSystemFeatureModelDimacs", LongOpt.REQUIRED_ARGUMENT, FM_TSDIMACS, "file",
                        "Extended feature model for error checking."),
                new Option("partialConfiguration", LongOpt.REQUIRED_ARGUMENT, FM_PARTIALCONFIG, "file",
                        "Loads a partial configuration to the type-system feature model (file with #define and #undef lines).")
        ));

        return r;

    }

    @Override
    protected boolean interpretOption(int c, Getopt g) throws OptionException {
        if (c == FM_DIMACS) {       //--featureModelDimacs
            if (smallFeatureModel != null)
                throw new OptionException("cannot load feature model from dimacs file. feature model already exists.");
            checkFileExists(g.getOptarg());
            // case studies busybox and load a specialized feature model
            // all others load a standard feature model in which the prefix is set to "" (default is "CONFIG_"),
            // which is used in busybox and linux
            if (g.getOptarg().contains("linux") || g.getOptarg().contains("busybox"))
                smallFeatureModel = FeatureExprLib.featureModelFactory().createFromDimacsFilePrefix(g.getOptarg(),"CONFIG_");
            else
                smallFeatureModel = FeatureExprLib.featureModelFactory().createFromDimacsFilePrefix(g.getOptarg(),"");
        } else if (c == FM_FEXPR) {     //--featureModelFExpr
            checkFileExists(g.getOptarg());
            FeatureExpr f = new FeatureExprParserJava(FeatureExprLib.l()).parseFile(g.getOptarg());
            if (smallFeatureModel == null)
                smallFeatureModel = FeatureExprLib.featureModelFactory().create(f);
            else smallFeatureModel = smallFeatureModel.and(f);
//        } else if (c == FM_CLASS) {//--featureModelClass
//            try {
//                FeatureModelFactory factory = (FeatureModelFactory) Class.forName(g.getOptarg()).newInstance();
//                smallFeatureModel = factory.createFeatureModel();
//            } catch (Exception e) {
//                throw new OptionException("cannot instantiate feature model: " + e.getMessage());
//            }
        } else if (c == FM_TSDIMACS) {
            checkFileExists(g.getOptarg());
            fullFeatureModel = FeatureExprLib.featureModelFactory().createFromDimacsFilePrefix(g.getOptarg(),"CONFIG_");
        } else if (c == FM_PARTIALCONFIG) {
            checkFileExists(g.getOptarg());
            if (partialConfig != null)
                throw new OptionException("cannot load a second partial configuration");
            partialConfig = PartialConfigurationParser$.MODULE$.load(g.getOptarg());
            FeatureExpr f = partialConfig.getFeatureExpr();
            if (fullFeatureModel == null)
                fullFeatureModel = FeatureExprLib.featureModelFactory().empty();

            for (String featureName : partialConfig.getDefinedFeatures())
                fullFeatureModel = fullFeatureModel.assumeTrue(featureName);
            for (String featureName : partialConfig.getUndefinedFeatures())
                fullFeatureModel = fullFeatureModel.assumeFalse(featureName);
        } else
            return super.interpretOption(c, g);
        return true;
    }


    public void setSmallFeatureModel(FeatureModel fm) {
        smallFeatureModel = fm;
    }
    public void setFullFeatureModel(FeatureModel fm) {
        fullFeatureModel = fm;
    }

    @Override
    public PartialConfiguration getLexerPartialConfiguration() {
        return partialConfig;
    }
}
TOP

Related Classes of de.fosd.typechef.options.FeatureModelOptions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.