package br.ufpe.cin.dfa4spl.plverifier.alloy;
import java.util.ArrayList;
import java.util.List;
import br.ufpe.cin.dfa4spl.plverifier.alloy.io.CannotReadAlloyFileException;
import edu.mit.csail.sdg.alloy4.A4Reporter;
import edu.mit.csail.sdg.alloy4.Err;
import edu.mit.csail.sdg.alloy4.ErrorWarning;
import edu.mit.csail.sdg.alloy4.Pos;
import edu.mit.csail.sdg.alloy4.SafeList;
import edu.mit.csail.sdg.alloy4compiler.ast.Command;
import edu.mit.csail.sdg.alloy4compiler.ast.Expr;
import edu.mit.csail.sdg.alloy4compiler.ast.ExprBinary;
import edu.mit.csail.sdg.alloy4compiler.ast.ExprCall;
import edu.mit.csail.sdg.alloy4compiler.ast.Func;
import edu.mit.csail.sdg.alloy4compiler.ast.Sig;
import edu.mit.csail.sdg.alloy4compiler.parser.CompModule;
import edu.mit.csail.sdg.alloy4compiler.parser.CompUtil;
import edu.mit.csail.sdg.alloy4compiler.translator.A4Options;
import edu.mit.csail.sdg.alloy4compiler.translator.A4Solution;
import edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod;
public class AlloyNodes {
private A4Reporter rep;
private CompModule module;
private static final String PRED_PREFIX = "<b>pred</b> this/";
private static final String SIG_PREFIX = "<b>sig</b> this/";
private static final String SIG_SUFFIX = " <i>{this/Bool}</i>";
public AlloyNodes(String filePath) throws CannotReadAlloyFileException {
rep = new A4Reporter() {
// For example, here we choose to display each "warning" by printing it to System.out
@Override
public void warning(ErrorWarning msg) {
System.out.print("Relevance Warning:\n" + (msg.toString().trim()) + "\n\n");
System.out.flush();
}
};
try {
module = CompUtil.parseEverything_fromFile(rep, null, filePath);
} catch (Err e) {
throw new CannotReadAlloyFileException("File: " + filePath, e);
}
}
public Expr makeAND(List<Expr> sigNames) {
List<Expr> args = new ArrayList<Expr>();
args.add(sigNames.get(0));
if (sigNames.size() == 1) {
return sigNames.get(0);
} else {
Expr expressionCall = sigNames.remove(0);
return ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, expressionCall, makeAND(sigNames));
}
}
public Expr makeOR(List<Expr> sigNames) {
List<Expr> args = new ArrayList<Expr>();
args.add(sigNames.get(0));
if (sigNames.size() == 1) {
return sigNames.get(0);
} else {
Expr expressionCall = sigNames.remove(0);
return ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, expressionCall, makeOR(sigNames));
}
}
public void setFuncBody(Func func, Expr newBody) {
try {
func.setBody(newBody);
} catch (Err e) {
e.printStackTrace();
}
}
public Func getFunc(String funcName) throws CannotFindFunc {
SafeList<Func> allFunc = module.getAllFunc();
Func resultFunc = null;
for (Func func : allFunc) {
if (func.getDescription().equals(AlloyNodes.PRED_PREFIX + funcName)) {
resultFunc = func;
}
}
if (resultFunc == null) {
throw new CannotFindFunc("Func name: " + funcName);
}
return resultFunc;
}
public Sig getBooleanSig(String booleanSigName) throws CannotFindBooleanSig {
SafeList<Sig> allSigs = module.getAllSigs();
Sig resultSig = null;
for (Sig sig : allSigs) {
if (sig.getDescription().equals(AlloyNodes.SIG_PREFIX + booleanSigName + AlloyNodes.SIG_SUFFIX)) {
resultSig = sig;
}
}
if (resultSig == null) {
throw new CannotFindBooleanSig("Boolean sig name: " + booleanSigName);
}
return resultSig;
}
public boolean executeCommand(String commandName, String type) {
boolean result = false;
A4Options options = new A4Options();
options.solver = A4Options.SatSolver.SAT4J;
for (Command command : module.getAllCommands()) {
// Execute the command
A4Solution ans = null;
try {
ans = TranslateAlloyToKodkod.execute_command(rep, module.getAllReachableSigs(), command, options);
} catch (Err e) {
e.printStackTrace();
}
// If satisfiable...
if (ans.satisfiable()) {
result = true;
break;
}
}
return result;
}
}