/*
* Copyright (C) 2014-2015 Daniel Dietsch (dietsch@informatik.uni-freiburg.de)
* Copyright (C) 2012-2015 Matthias Heizmann (heizmann@informatik.uni-freiburg.de)
* Copyright (C) 2012-2015 University of Freiburg
*
* This file is part of the ULTIMATE ModelCheckerUtils Library.
*
* The ULTIMATE ModelCheckerUtils Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ULTIMATE ModelCheckerUtils Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ULTIMATE ModelCheckerUtils Library. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify the ULTIMATE ModelCheckerUtils Library, or any covered work, by linking
* or combining it with Eclipse RCP (or a modified version of Eclipse RCP),
* containing parts covered by the terms of the Eclipse Public License, the
* licensors of the ULTIMATE ModelCheckerUtils Library grant you additional permission
* to convey the resulting work.
*/
package de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.boogie;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.uni_freiburg.informatik.ultimate.boogie.DeclarationInformation;
import de.uni_freiburg.informatik.ultimate.boogie.DeclarationInformation.StorageClass;
import de.uni_freiburg.informatik.ultimate.boogie.ast.Axiom;
import de.uni_freiburg.informatik.ultimate.boogie.ast.BoogieASTNode;
import de.uni_freiburg.informatik.ultimate.core.lib.results.UnsupportedSyntaxResult;
import de.uni_freiburg.informatik.ultimate.core.model.services.IUltimateServiceProvider;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.ModelCheckerUtils;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.boogie.Expression2Term.IIdentifierTranslator;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.SmtFunctionsAndAxioms;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.variables.IProgramVar;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.variables.ProgramConst;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.TermVarsFuns;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.scripttransfer.HistoryRecordingScript;
import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.ManagedScript;
import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.SmtUtils;
import de.uni_freiburg.informatik.ultimate.logic.QuotedObject;
import de.uni_freiburg.informatik.ultimate.logic.Script;
import de.uni_freiburg.informatik.ultimate.logic.Term;
/**
* Main class for the translation from Boogie to SMT. Constructs other objects needed for this translation.
*
* @author Matthias Heizmann
*
*/
public class Boogie2SMT {
private final BoogieDeclarations mBoogieDeclarations;
private final ManagedScript mScript;
private final TypeSortTranslator mTypeSortTranslator;
private final IOperationTranslator mOperationTranslator;
private final Boogie2SmtSymbolTable mBoogie2SmtSymbolTable;
private final Expression2Term mExpression2Term;
private final Term2Expression mTerm2Expression;
private final Statements2TransFormula mStatements2TransFormula;
private final SmtFunctionsAndAxioms mSmtFunctionsAndAxioms;
private final IUltimateServiceProvider mServices;
public Boogie2SMT(final ManagedScript mgdScript, final BoogieDeclarations boogieDeclarations,
final IUltimateServiceProvider services, final boolean simplePartialSkolemization) {
mServices = services;
mBoogieDeclarations = boogieDeclarations;
mScript = mgdScript;
final Script script = mScript.getScript();
mTypeSortTranslator = new TypeSortTranslator(boogieDeclarations.getTypeDeclarations(), script, mServices);
mBoogie2SmtSymbolTable = new Boogie2SmtSymbolTable(boogieDeclarations, mScript, mTypeSortTranslator);
mOperationTranslator = new DefaultOperationTranslator(mBoogie2SmtSymbolTable, script);
mExpression2Term = new Expression2Term(mServices, script, mTypeSortTranslator, mBoogie2SmtSymbolTable,
mOperationTranslator, mScript);
final List axiomList = declareAxioms(boogieDeclarations, script, mExpression2Term,
mBoogie2SmtSymbolTable);
final TermVarsFuns tvp = TermVarsFuns.computeTermVarsFuns(SmtUtils.and(script, axiomList), mScript,
mBoogie2SmtSymbolTable);
assert tvp.getVars().isEmpty() : "axioms must not have variables";
if (!(script instanceof HistoryRecordingScript)) {
throw new AssertionError("need HistoryRecordingScript");
}
mSmtFunctionsAndAxioms = new SmtFunctionsAndAxioms(tvp.getClosedFormula(), tvp.getFuns(), mScript);
mStatements2TransFormula = new Statements2TransFormula(this, mServices, mExpression2Term,
simplePartialSkolemization);
mTerm2Expression = new Term2Expression(mTypeSortTranslator, mBoogie2SmtSymbolTable, mScript);
}
private static List declareAxioms(final BoogieDeclarations boogieDeclarations, final Script script,
final Expression2Term expression2Term, final Boogie2SmtSymbolTable boogie2SmtSymbolTable) {
final List axiomList = new ArrayList<>(boogieDeclarations.getAxioms().size());
script.echo(new QuotedObject("Start declaration of axioms"));
for (final Axiom decl : boogieDeclarations.getAxioms()) {
final ConstOnlyIdentifierTranslator coit = new ConstOnlyIdentifierTranslator(boogie2SmtSymbolTable);
final IIdentifierTranslator[] its = new IIdentifierTranslator[] { coit };
final Term closedTerm = expression2Term.translateToTerm(its, decl.getFormula()).getTerm();
script.assertTerm(closedTerm);
final Term term = closedTerm;
axiomList.add(term);
}
script.echo(new QuotedObject("Finished declaration of axioms"));
return axiomList;
}
public Script getScript() {
return mScript.getScript();
}
public ManagedScript getManagedScript() {
return mScript;
}
public Term2Expression getTerm2Expression() {
return mTerm2Expression;
}
public Expression2Term getExpression2Term() {
return mExpression2Term;
}
static String quoteId(final String id) {
return id;
}
public Boogie2SmtSymbolTable getBoogie2SmtSymbolTable() {
return mBoogie2SmtSymbolTable;
}
public Statements2TransFormula getStatements2TransFormula() {
return mStatements2TransFormula;
}
public BoogieDeclarations getBoogieDeclarations() {
return mBoogieDeclarations;
}
public TypeSortTranslator getTypeSortTranslator() {
return mTypeSortTranslator;
}
public SmtFunctionsAndAxioms getSmtFunctionsAndAxioms() {
return mSmtFunctionsAndAxioms;
}
public ConstOnlyIdentifierTranslator createConstOnlyIdentifierTranslator() {
return new ConstOnlyIdentifierTranslator(mBoogie2SmtSymbolTable);
}
public static void reportUnsupportedSyntax(final BoogieASTNode astNode, final String longDescription,
final IUltimateServiceProvider services) {
final UnsupportedSyntaxResult result = new UnsupportedSyntaxResult<>(astNode,
ModelCheckerUtils.PLUGIN_ID, services.getBacktranslationService(), longDescription);
services.getResultService().reportResult(ModelCheckerUtils.PLUGIN_ID, result);
services.getProgressMonitorService().cancelToolchain();
}
public static final class ConstOnlyIdentifierTranslator implements IIdentifierTranslator {
private final Set mNonTheoryConsts = new HashSet<>();
private final Boogie2SmtSymbolTable mBoogie2SmtSymbolTable;
public ConstOnlyIdentifierTranslator(final Boogie2SmtSymbolTable boogie2SmtSymbolTable) {
mBoogie2SmtSymbolTable = boogie2SmtSymbolTable;
}
@Override
public Term getSmtIdentifier(final String id, final DeclarationInformation declInfo, final boolean isOldContext,
final BoogieASTNode boogieASTNode) {
if (declInfo.getStorageClass() != StorageClass.GLOBAL) {
throw new AssertionError();
}
final ProgramConst pc = mBoogie2SmtSymbolTable.getBoogieConst(id);
if (!pc.belongsToSmtTheory()) {
mNonTheoryConsts.add(pc);
}
return pc.getDefaultConstant();
}
public Set getNonTheoryConsts() {
return mNonTheoryConsts;
}
}
/**
* Simple translator for local variables and global variables that does not provide any side-effects for getting
* inVars or outVars. Use this in combination with {@link ConstOnlyIdentifierTranslator} to get a translator that
* has the capability to translate expression to terms.
*
*/
public class LocalVarAndGlobalVarTranslator implements IIdentifierTranslator {
@Override
public Term getSmtIdentifier(final String id, final DeclarationInformation declInfo, final boolean isOldContext,
final BoogieASTNode boogieASTNode) {
final IProgramVar pv = mBoogie2SmtSymbolTable.getBoogieVar(id, declInfo, isOldContext);
if (pv == null) {
return null;
}
return pv.getTermVariable();
}
}
}