
de.tla2b.analysis.SpecAnalyser 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.Set;
import de.tla2b.config.ConfigfileEvaluator;
import de.tla2b.exceptions.ConfigFileErrorException;
import de.tla2b.exceptions.FrontEndException;
import de.tla2b.exceptions.NotImplementedException;
import de.tla2b.exceptions.SemanticErrorException;
import de.tla2b.global.BBuiltInOPs;
import de.tla2b.global.TranslationGlobals;
import de.tla2b.translation.BDefinitionsFinder;
import de.tla2b.translation.OperationsFinder;
import de.tla2b.translation.UsedDefinitionsFinder;
import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.ExprOrOpArgNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SymbolNode;
import tlc2.tool.BuiltInOPs;
import tlc2.tool.ToolGlobals;
public class SpecAnalyser extends BuiltInOPs implements ASTConstants,
ToolGlobals, TranslationGlobals {
private OpDefNode spec;
private OpDefNode init;
private OpDefNode next;
private ArrayList invariants = new ArrayList();
private OpDefNode expressionOpdefNode;
private Hashtable namingHashTable = new Hashtable();
private final ModuleNode moduleNode;
private ExprNode nextExpr;
private ArrayList bConstants;
// used to check if a b constant has arguments and is not overriden in the
// configfile
private ArrayList bOperations = new ArrayList();
private ArrayList inits = new ArrayList();
private Set bDefinitionsSet = new HashSet();
// set of OpDefNodes which will appear in the resulting B Machine
private Set usedDefinitions = new HashSet();
// definitions which are used for the type inference algorithm
private Hashtable letParams = new Hashtable();
// additional parameters of an let Operator, these parameters are from the
// surrounding operator
private ArrayList definitionMacros = new ArrayList();
private ArrayList recursiveFunctions = new ArrayList();
private ArrayList recursiveDefinitions = new ArrayList();
private ConfigfileEvaluator configFileEvaluator;
private SpecAnalyser(ModuleNode m) {
this.moduleNode = m;
this.bConstants = new ArrayList();
}
public static SpecAnalyser createSpecAnalyser(ModuleNode m,
ConfigfileEvaluator conEval) {
SpecAnalyser specAnalyser = new SpecAnalyser(m);
specAnalyser.spec = conEval.getSpecNode();
specAnalyser.init = conEval.getInitNode();
specAnalyser.next = conEval.getNextNode();
specAnalyser.invariants = conEval.getInvariants();
specAnalyser.bConstants = conEval.getbConstantList();
specAnalyser.configFileEvaluator = conEval;
return specAnalyser;
}
public static SpecAnalyser createSpecAnalyserForTlaExpression(ModuleNode m) {
SpecAnalyser specAnalyser = new SpecAnalyser(m);
specAnalyser.expressionOpdefNode = m.getOpDefs()[m.getOpDefs().length - 1];
specAnalyser.usedDefinitions.add(specAnalyser.expressionOpdefNode);
specAnalyser.bDefinitionsSet.add(specAnalyser.expressionOpdefNode);
return specAnalyser;
}
public static SpecAnalyser createSpecAnalyser(ModuleNode m) {
SpecAnalyser specAnalyser = new SpecAnalyser(m);
Hashtable definitions = new Hashtable();
for (int i = 0; i < m.getOpDefs().length; i++) {
definitions.put(m.getOpDefs()[i].getName().toString(),
m.getOpDefs()[i]);
}
specAnalyser.spec = definitions.get("Spec");
specAnalyser.init = definitions.get("Init");
specAnalyser.next = definitions.get("Next");
if (definitions.containsKey("Inv")) {
specAnalyser.invariants.add(definitions.get("Inv"));
}
// TODO are constant in the right order
specAnalyser.bConstants.addAll(Arrays.asList(m.getConstantDecls()));
return specAnalyser;
}
public void start() throws SemanticErrorException, FrontEndException,
ConfigFileErrorException, NotImplementedException {
if (spec != null) {
evalSpec();
} else {
evalInit();
evalNext();
}
for (OpDefNode inv : new ArrayList(invariants)) {
try {
OpApplNode opApplNode = (OpApplNode) inv.getBody();
OpDefNode opDefNode = (OpDefNode) opApplNode.getOperator();
if (opDefNode.getKind() == UserDefinedOpKind
&& !BBuiltInOPs.contains(opDefNode.getName())) {
int i = invariants.indexOf(inv);
invariants.set(i, opDefNode);
}
} catch (ClassCastException e) {
}
}
OperationsFinder operationsFinder = new OperationsFinder(this);
bOperations = operationsFinder.getBOperations();
UsedDefinitionsFinder definitionFinder = new UsedDefinitionsFinder(this);
this.usedDefinitions = definitionFinder.getUsedDefinitions();
BDefinitionsFinder bDefinitionFinder = new BDefinitionsFinder(this);
this.bDefinitionsSet = bDefinitionFinder.getBDefinitionsSet();
// usedDefinitions.addAll(bDefinitionsSet);
// test whether there is a init predicate if there is a variable
if (moduleNode.getVariableDecls().length > 0 && inits == null) {
throw new SemanticErrorException("No initial predicate is defined.");
}
// check if there is B constant with arguments.
for (int i = 0; i < bConstants.size(); i++) {
OpDeclNode con = bConstants.get(i);
if (con.getArity() > 0) {
throw new ConfigFileErrorException(
String.format(
"Constant '%s' must be overriden in the configuration file.",
con.getName()));
}
}
findRecursiveConstructs();
for (OpDeclNode var : moduleNode.getVariableDecls()) {
namingHashTable.put(var.getName().toString(), var);
}
for (OpDeclNode con : moduleNode.getConstantDecls()) {
namingHashTable.put(con.getName().toString(), con);
}
for (OpDefNode def : usedDefinitions) {
namingHashTable.put(def.getName().toString(), def);
}
}
private void evalInit() {
if (init != null) {
inits.add(init.getBody());
}
}
private void evalNext() throws FrontEndException {
if (next != null) {
this.nextExpr = next.getBody();
}
}
public void evalSpec() throws SemanticErrorException, FrontEndException {
if (spec != null) {
processConfigSpec(spec.getBody());
}
}
private void processConfigSpec(ExprNode exprNode)
throws SemanticErrorException, FrontEndException {
if (exprNode instanceof OpApplNode) {
OpApplNode opApp = (OpApplNode) exprNode;
ExprOrOpArgNode[] args = opApp.getArgs();
if (args.length == 0) {
SymbolNode opNode = opApp.getOperator();
if (opNode instanceof OpDefNode) {
OpDefNode def = (OpDefNode) opNode;
ExprNode body = def.getBody();
body.levelCheck(1);
if (body.getLevel() == 1) {
inits.add(exprNode);
} else {
processConfigSpec(body);
}
return;
}
throw new SemanticErrorException(
"Can not handle specification conjunction.");
}
int opcode = BuiltInOPs.getOpCode(opApp.getOperator().getName());
if (opcode == OPCODE_cl || opcode == OPCODE_land) {
for (int i = 0; i < args.length; i++) {
this.processConfigSpec((ExprNode) args[i]);
}
return;
}
if (opcode == OPCODE_box) {
SemanticNode boxArg = args[0];
if ((boxArg instanceof OpApplNode)
&& BuiltInOPs.getOpCode(((OpApplNode) boxArg)
.getOperator().getName()) == OPCODE_sa) {
ExprNode next = (ExprNode) ((OpApplNode) boxArg).getArgs()[0];
this.nextExpr = next;
return;
}
}
}
if (exprNode.getLevel() <= 1) {
// init
inits.add(exprNode);
} else if (exprNode.getLevel() == 3) {
// temporal
} else {
throw new SemanticErrorException(
"Can not handle specification conjunction.");
}
}
private void findRecursiveConstructs() throws NotImplementedException {
Set set = new HashSet(usedDefinitions);
for (OpDefNode def : set) {
if (def.getInRecursive()) {
throw new NotImplementedException(
"Recursive definitions are currently not supported: " + def.getName() + "\n" + def.getLocation() );
// bDefinitionsSet.remove(def);
// RecursiveDefinition rd = new RecursiveDefinition(def);
// recursiveDefinitions.add(rd);
} else if (def.getBody() instanceof OpApplNode) {
OpApplNode o = (OpApplNode) def.getBody();
switch (getOpCode(o.getOperator().getName())) {
case OPCODE_rfs: { // recursive Function
bDefinitionsSet.remove(def);
recursiveFunctions.add(def);
}
}
}
}
}
public ArrayList getBOperations() {
return this.bOperations;
}
public ArrayList getInits() {
return this.inits;
}
public ExprNode getNext() {
return this.nextExpr;
}
public Set getBDefinitions() {
return bDefinitionsSet;
}
public Hashtable getLetParams() {
return new Hashtable(letParams);
}
public ArrayList getDefinitionMacros() {
return definitionMacros;
}
public Set getUsedDefinitions() {
return usedDefinitions;
}
public ArrayList getRecursiveFunctions() {
return recursiveFunctions;
}
public ArrayList getRecursiveDefinitions() {
return recursiveDefinitions;
}
public ModuleNode getModuleNode() {
return this.moduleNode;
}
public ConfigfileEvaluator getConfigFileEvaluator() {
return configFileEvaluator;
}
public ArrayList getInvariants() {
return invariants;
}
public OpDefNode getInitDef() {
return init;
}
public OpDefNode getExpressionOpdefNode() {
return expressionOpdefNode;
}
public SymbolNode getSymbolNodeByName(String name) {
return namingHashTable.get(name);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy