Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
hu.bme.mit.theta.frontend.chc.ChcForwardXcfaBuilder Maven / Gradle / Ivy
/*
* Copyright 2024 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package hu.bme.mit.theta.frontend.chc;
import static hu.bme.mit.theta.frontend.chc.ChcUtils.*;
import hu.bme.mit.theta.chc.frontend.dsl.gen.CHCBaseVisitor;
import hu.bme.mit.theta.chc.frontend.dsl.gen.CHCParser;
import hu.bme.mit.theta.core.decl.Decls;
import hu.bme.mit.theta.core.decl.VarDecl;
import hu.bme.mit.theta.core.stmt.AssignStmt;
import hu.bme.mit.theta.core.stmt.HavocStmt;
import hu.bme.mit.theta.core.type.Type;
import hu.bme.mit.theta.xcfa.model.*;
import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChcForwardXcfaBuilder extends CHCBaseVisitor implements ChcXcfaBuilder {
private final ProcedurePassManager procedurePassManager;
private XcfaProcedureBuilder builder;
private XcfaLocation initLocation;
private XcfaLocation errorLocation;
private final Map locations = new HashMap<>();
public ChcForwardXcfaBuilder(final ProcedurePassManager procedurePassManager) {
this.procedurePassManager = procedurePassManager;
}
@Override
public XcfaBuilder buildXcfa(CHCParser parser) {
XcfaBuilder xcfaBuilder = new XcfaBuilder("chc");
builder = new XcfaProcedureBuilder("main", procedurePassManager);
builder.createInitLoc();
builder.createErrorLoc();
builder.createFinalLoc();
initLocation = builder.getInitLoc();
errorLocation = builder.getErrorLoc().get();
locations.put(initLocation.getName(), new UPred(initLocation, new ArrayList<>()));
locations.put(errorLocation.getName(), new UPred(initLocation, new ArrayList<>()));
visit(parser.benchmark());
xcfaBuilder.addProcedure(builder);
xcfaBuilder.addEntryPoint(builder, new ArrayList<>());
return xcfaBuilder;
}
@Override
public Object visitFun_decl(CHCParser.Fun_declContext ctx) {
String name = ctx.symbol().getText();
if (ctx.symbol().quotedSymbol() != null) name = name.replaceAll("\\|", "");
int i = 0;
List> vars = new ArrayList<>();
for (CHCParser.SortContext sort : ctx.sort()) {
String varName = name + "_" + i++;
Type type = transformSort(sort);
VarDecl> var = Decls.Var(varName, type);
vars.add(var);
builder.addVar(var);
transformConst(Decls.Const(varName, type), true);
}
XcfaLocation location = new XcfaLocation(name, EmptyMetaData.INSTANCE);
locations.put(name, new UPred(location, vars));
locations.put(ctx.symbol().getText(), new UPred(location, vars));
builder.addLoc(location);
return super.visitFun_decl(ctx);
}
@Override
public Object visitChc_assert(CHCParser.Chc_assertContext ctx) {
XcfaLocation from;
XcfaLocation to;
List labels = new ArrayList<>();
if (ctx.chc_tail() != null) {
from = getTailFrom(ctx.chc_tail());
to = getHeadTo(ctx.chc_head());
Map> vars = createVars(builder, ctx.var_decl());
labels.addAll(getIncomingAssignments(ctx.chc_tail(), vars));
labels.addAll(getTailConditionLabels(ctx.chc_tail(), vars));
labels.addAll(getTargetAssignments(ctx.chc_head(), vars));
} else {
String locName;
if (ctx.chc_head() != null) {
locName = ctx.chc_head().u_pred_atom().u_predicate().getText();
} else {
locName = ctx.u_predicate().getText();
}
from = initLocation;
to = locations.get(locName).location;
}
XcfaEdge edge = new XcfaEdge(from, to, new SequenceLabel(labels), EmptyMetaData.INSTANCE);
builder.addEdge(edge);
return super.visitChc_assert(ctx);
}
@Override
public Object visitChc_query(CHCParser.Chc_queryContext ctx) {
XcfaLocation from = getTailFrom(ctx.chc_tail());
Map> vars = createVars(builder, ctx.var_decl());
List labels = new ArrayList<>();
labels.addAll(getIncomingAssignments(ctx.chc_tail(), vars));
labels.addAll(getTailConditionLabels(ctx.chc_tail(), vars));
XcfaEdge edge =
new XcfaEdge(
from, errorLocation, new SequenceLabel(labels), EmptyMetaData.INSTANCE);
builder.addEdge(edge);
return super.visitChc_query(ctx);
}
private List getIncomingAssignments(
CHCParser.Chc_tailContext tail, Map> localVars) {
List labels = new ArrayList<>();
UPred from = locations.get(getTailFrom(tail).getName());
tail.u_pred_atom()
.forEach(
u_pred -> {
List extends VarDecl>> params =
u_pred.symbol().stream()
.map(symbol -> localVars.get(symbol.getText()))
.toList();
localVars
.values()
.forEach(
var -> {
if (!params.contains(var))
labels.add(new StmtLabel(HavocStmt.of(var)));
});
labels.addAll(getParamAssignments(params, from.vars));
});
return labels;
}
private List getTargetAssignments(
CHCParser.Chc_headContext head, Map> localVars) {
List extends VarDecl>> params =
head.u_pred_atom().symbol().stream()
.map(symbol -> localVars.get(symbol.getText()))
.toList();
UPred to = locations.get(getHeadTo(head).getName());
return getParamAssignments(to.vars, params);
}
private XcfaLocation getTailFrom(CHCParser.Chc_tailContext tail) {
XcfaLocation from;
if (tail.u_pred_atom() != null && !tail.u_pred_atom().isEmpty()) {
if (tail.u_pred_atom().size() != 1)
throw new UnsupportedOperationException(
"Non-linear CHCs are not supported with forward transformation, try using"
+ " the --chc-transformation BACKWARD flag.");
from = locations.get(tail.u_pred_atom().get(0).u_predicate().getText()).location;
} else {
from = initLocation;
}
return from;
}
private XcfaLocation getHeadTo(CHCParser.Chc_headContext head) {
return locations.get(head.u_pred_atom().u_predicate().getText()).location;
}
private List getParamAssignments(
List extends VarDecl>> lhs, List extends VarDecl>> rhs) {
List labels = new ArrayList<>();
for (int i = 0; i < lhs.size(); ++i) {
labels.add(new StmtLabel(AssignStmt.create(lhs.get(i), rhs.get(i).getRef())));
}
return labels;
}
static class UPred {
final XcfaLocation location;
final List> vars;
UPred(XcfaLocation location, List> vars) {
this.location = location;
this.vars = vars;
}
}
}