
de.tla2b.analysis.BOperation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tla2bAST Show documentation
Show all versions of tla2bAST Show documentation
Translator from TLA+ to ProB's AST representation.
/**
* @author Dominik Hansen
**/
package de.tla2b.analysis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import de.be4.classicalb.core.parser.node.AAnySubstitution;
import de.be4.classicalb.core.parser.node.AAssignSubstitution;
import de.be4.classicalb.core.parser.node.ABlockSubstitution;
import de.be4.classicalb.core.parser.node.AMemberPredicate;
import de.be4.classicalb.core.parser.node.AOperation;
import de.be4.classicalb.core.parser.node.ASelectSubstitution;
import de.be4.classicalb.core.parser.node.ASkipSubstitution;
import de.be4.classicalb.core.parser.node.PExpression;
import de.be4.classicalb.core.parser.node.PPredicate;
import de.tla2b.global.BBuiltInOPs;
import de.tla2b.global.TranslationGlobals;
import de.tla2b.types.TLAType;
import de.tla2bAst.BAstCreator;
import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.ExprOrOpArgNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.LetInNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SubstInNode;
import tla2sany.semantic.SymbolNode;
import tlc2.tool.BuiltInOPs;
import tlc2.tool.ToolGlobals;
public class BOperation extends BuiltInOPs implements ASTConstants,
ToolGlobals, TranslationGlobals {
private final String name;
private final ExprNode node;
private final ArrayList existQuans;
private ArrayList opParams;
private ArrayList formalParams;
private ArrayList unchangedVariables;
private final ArrayList unchangedVariablesList;
private final ArrayList guards;
private final ArrayList beforeAfterPredicates;
private LinkedHashMap assignments = new LinkedHashMap();
private List anyVariables;
private final SpecAnalyser specAnalyser;
public BOperation(String name, ExprNode n,
ArrayList existQuans, SpecAnalyser specAnalyser) {
this.name = name;
this.node = n;
this.existQuans = existQuans;
this.specAnalyser = specAnalyser;
this.unchangedVariablesList = new ArrayList();
this.guards = new ArrayList();
this.beforeAfterPredicates = new ArrayList();
anyVariables = new ArrayList(Arrays.asList(specAnalyser
.getModuleNode().getVariableDecls()));
evalParams();
findUnchangedVariables();
separateGuardsAndBeforeAfterPredicates(node);
findAssignments();
}
public AOperation getBOperation(BAstCreator bASTCreator) {
AOperation operation = new AOperation();
List paramList = new ArrayList();
ArrayList whereList = new ArrayList();
for (int j = 0; j < this.getFormalParams().size(); j++) {
paramList.add(bASTCreator.createIdentifierNode(this
.getFormalParams().get(j)));
}
for (int j = 0; j < this.getExistQuans().size(); j++) {
OpApplNode o = this.getExistQuans().get(j);
whereList.add(bASTCreator.visitBoundsOfLocalVariables(o));
}
operation.setOpName(BAstCreator.createTIdentifierLiteral(name));
operation.setParameters(paramList);
operation.setReturnValues(new ArrayList());
for (ExprOrOpArgNode g : guards) {
whereList.add(bASTCreator.visitExprOrOpArgNodePredicate(g));
}
ArrayList leftSideOfAssigment = new ArrayList();
ArrayList rightSideOfAssigment = new ArrayList();
for (Entry entry : assignments.entrySet()) {
leftSideOfAssigment.add(bASTCreator.createIdentifierNode(entry
.getKey()));
rightSideOfAssigment.add(bASTCreator
.visitExprOrOpArgNodeExpression(entry.getValue()));
}
AAssignSubstitution assign = new AAssignSubstitution();
if (anyVariables.size() > 0) { // ANY x_n WHERE P THEN A END
AAnySubstitution any = new AAnySubstitution();
any = new AAnySubstitution();
List anyParams = new ArrayList();
for (OpDeclNode var : anyVariables) {
String varName = var.getName().toString();
String nextName = varName + "_n";
anyParams.add(BAstCreator.createIdentifierNode(nextName));
AMemberPredicate member = new AMemberPredicate();
member.setLeft(BAstCreator.createIdentifierNode(nextName));
TLAType t = (TLAType) var.getToolObject(TYPE_ID);
member.setRight(t.getBNode());
whereList.add(member);
leftSideOfAssigment.add(bASTCreator.createIdentifierNode(var));
rightSideOfAssigment.add(BAstCreator
.createIdentifierNode(nextName));
}
any.setIdentifiers(anyParams);
whereList.addAll(createBeforeAfterPredicates(bASTCreator));
any.setWhere(bASTCreator.createConjunction(whereList));
any.setThen(assign);
operation.setOperationBody(any);
} else if (whereList.size() > 0) { // SELECT P THEN A END
ASelectSubstitution select = new ASelectSubstitution();
whereList.addAll(createBeforeAfterPredicates(bASTCreator));
for (ExprOrOpArgNode e : beforeAfterPredicates) {
whereList.add(bASTCreator.visitExprOrOpArgNodePredicate(e));
}
select.setCondition(bASTCreator.createConjunction(whereList));
select.setThen(assign);
operation.setOperationBody(select);
} else { // BEGIN A END
ABlockSubstitution block = new ABlockSubstitution(assign);
operation.setOperationBody(block);
}
if (leftSideOfAssigment.size() > 0) {
assign.setLhsExpression(leftSideOfAssigment);
assign.setRhsExpressions(rightSideOfAssigment);
} else { // skip
assign.replaceBy(new ASkipSubstitution());
}
return operation;
}
private ArrayList createBeforeAfterPredicates(
BAstCreator bAstCreator) {
ArrayList predicates = new ArrayList();
for (ExprOrOpArgNode e : beforeAfterPredicates) {
PPredicate body = null;
if (e instanceof OpApplNode) {
OpApplNode opApplNode = (OpApplNode) e;
if (opApplNode.getOperator().getKind() == UserDefinedOpKind
&& !BBuiltInOPs.contains(opApplNode.getOperator()
.getName())) {
OpDefNode def = (OpDefNode) opApplNode.getOperator();
FormalParamNode[] params = def.getParams();
for (int j = 0; j < params.length; j++) {
FormalParamNode param = params[j];
param.setToolObject(SUBSTITUTE_PARAM,
opApplNode.getArgs()[j]);
}
body = bAstCreator.visitExprNodePredicate(def.getBody());
}
}
if (body == null) {
body = bAstCreator.visitExprOrOpArgNodePredicate(e);
}
predicates.add(body);
}
return predicates;
}
private void findAssignments() {
PrimedVariablesFinder primedVariablesFinder = new PrimedVariablesFinder(
beforeAfterPredicates);
for (ExprOrOpArgNode node : new ArrayList(
beforeAfterPredicates)) {
if (node instanceof OpApplNode) {
OpApplNode opApplNode = (OpApplNode) node;
if (opApplNode.getOperator().getKind() == BuiltInKind) {
if (OPCODE_eq == getOpCode(opApplNode.getOperator()
.getName())) {
ExprOrOpArgNode arg1 = opApplNode.getArgs()[0];
try {
OpApplNode arg11 = (OpApplNode) arg1;
if (getOpCode(arg11.getOperator().getName()) == OPCODE_prime) {
OpApplNode v = (OpApplNode) arg11.getArgs()[0];
SymbolNode var = v.getOperator();
if (!primedVariablesFinder
.getTwiceUsedVariables().contains(var)) {
// var is only used once in all before after
// predicates
assignments.put(v.getOperator(),
opApplNode.getArgs()[1]);
beforeAfterPredicates.remove(node);
}
}
} catch (ClassCastException e) {
}
}
}
}
}
anyVariables = new ArrayList();
for (OpDeclNode var : specAnalyser.getModuleNode().getVariableDecls()) {
anyVariables.add(var);
}
// for (SymbolNode symbol : primedVariablesFinder.getAllVariables()) {
// anyVariables.add((OpDeclNode) symbol);
// }
anyVariables.removeAll(assignments.keySet());
//anyVariables.removeAll(unchangedVariablesList);
}
private void separateGuardsAndBeforeAfterPredicates(ExprOrOpArgNode node) {
if (node instanceof OpApplNode) {
OpApplNode opApplNode = (OpApplNode) node;
if (opApplNode.getOperator().getKind() == BuiltInKind) {
switch (getOpCode(opApplNode.getOperator().getName())) {
case OPCODE_land: // \land
{
separateGuardsAndBeforeAfterPredicates(opApplNode.getArgs()[0]);
separateGuardsAndBeforeAfterPredicates(opApplNode.getArgs()[1]);
return;
}
case OPCODE_cl: // $ConjList
{
for (int i = 0; i < opApplNode.getArgs().length; i++) {
separateGuardsAndBeforeAfterPredicates(opApplNode
.getArgs()[i]);
}
return;
}
default: {
if (opApplNode.level < 2) {
guards.add(node);
return;
} else {
beforeAfterPredicates.add(node);
return;
}
}
}
}
}
if (node.level < 2) {
guards.add(node);
return;
} else {
beforeAfterPredicates.add(node);
return;
}
// beforeAfterPredicates.add(node);
}
private void evalParams() {
opParams = new ArrayList();
formalParams = new ArrayList();
for (int i = 0; i < existQuans.size(); i++) {
OpApplNode n = existQuans.get(i);
FormalParamNode[][] params = n.getBdedQuantSymbolLists();
for (int k = 0; k < params.length; k++) {
for (int j = 0; j < params[k].length; j++) {
formalParams.add(params[k][j]);
opParams.add(params[k][j].getName().toString());
}
}
}
}
public SymbolNode getSymbolNode() {
if (node instanceof OpApplNode) {
OpApplNode n = ((OpApplNode) node);
if (n.getOperator().getKind() == UserDefinedOpKind) {
return ((OpApplNode) node).getOperator();
}
}
return null;
}
public String getName() {
return name;
}
public ExprNode getNode() {
return node;
}
public ArrayList getExistQuans() {
return new ArrayList(existQuans);
}
public ArrayList getOpParams() {
return opParams;
}
public ArrayList getFormalParams() {
return formalParams;
}
public ArrayList getUnchangedVariables() {
return unchangedVariables;
}
private void findUnchangedVariables() {
unchangedVariables = new ArrayList();
findUnchangedVaribalesInSemanticNode(node);
}
/**
* @param node2
*/
private void findUnchangedVaribalesInSemanticNode(SemanticNode node) {
switch (node.getKind()) {
case OpApplKind: {
findUnchangedVariablesInOpApplNode((OpApplNode) node);
return;
}
case LetInKind: {
LetInNode letNode = (LetInNode) node;
findUnchangedVaribalesInSemanticNode(letNode.getBody());
return;
}
case SubstInKind: {
SubstInNode substInNode = (SubstInNode) node;
findUnchangedVaribalesInSemanticNode(substInNode.getBody());
return;
}
}
}
/**
* @param node2
*/
private void findUnchangedVariablesInOpApplNode(OpApplNode n) {
int kind = n.getOperator().getKind();
if (kind == UserDefinedOpKind
&& !BBuiltInOPs.contains(n.getOperator().getName())) {
OpDefNode def = (OpDefNode) n.getOperator();
findUnchangedVaribalesInSemanticNode(def.getBody());
return;
} else if (kind == BuiltInKind) {
int opcode = BuiltInOPs.getOpCode(n.getOperator().getName());
switch (opcode) {
case OPCODE_land: // \land
case OPCODE_cl: { // $ConjList
for (int i = 0; i < n.getArgs().length; i++) {
findUnchangedVaribalesInSemanticNode(n.getArgs()[i]);
}
return;
}
case OPCODE_unchanged: {
n.setToolObject(USED, false);
OpApplNode k = (OpApplNode) n.getArgs()[0];
if (k.getOperator().getKind() == VariableDeclKind) {
unchangedVariablesList.add((OpDeclNode) k.getOperator());
String name = k.getOperator().getName().toString();
unchangedVariables.add(name);
} else {
// Tuple
for (int i = 0; i < k.getArgs().length; i++) {
OpApplNode var = (OpApplNode) k.getArgs()[i];
unchangedVariablesList.add((OpDeclNode) var
.getOperator());
String name = var.getOperator().getName().toString();
unchangedVariables.add(name);
}
}
}
}
}
}
}
class PrimedVariablesFinder extends AbstractASTVisitor {
private final Set all;
private final Set twiceUsedVariables;
private final Hashtable> table;
private Set currentSet;
public PrimedVariablesFinder(ArrayList list) {
this.all = new HashSet();
this.twiceUsedVariables = new HashSet();
this.table = new Hashtable>();
for (ExprOrOpArgNode exprOrOpArgNode : list) {
findPrimedVariables(exprOrOpArgNode);
}
}
public void findPrimedVariables(ExprOrOpArgNode n) {
currentSet = new HashSet();
this.visitExprOrOpArgNode(n);
table.put(n, currentSet);
}
public void visitBuiltInNode(OpApplNode n) {
switch (getOpCode(n.getOperator().getName())) {
case OPCODE_prime: // prime
{
if (n.getArgs()[0] instanceof OpApplNode) {
OpApplNode varNode = (OpApplNode) n.getArgs()[0];
SymbolNode var = varNode.getOperator();
currentSet.add(var);
if (all.contains(var)) {
twiceUsedVariables.add(var);
} else {
all.add(var);
}
}
}
default: {
super.visitBuiltInNode(n);
}
}
}
public Set getTwiceUsedVariables() {
return this.twiceUsedVariables;
}
public Set getAllVariables() {
return this.all;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy