Skip to content
Snippets Groups Projects
Select Git revision
  • 48d3f4a593c7276d45650c5365c235a0a9d3588e
  • main default protected
2 results

lsh_test.pl

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    SpecAnalyser.java 9.97 KiB
    /**
     * @author Dominik Hansen <Dominik.Hansen at hhu.de>
     **/
    
    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 de.tla2b.types.IType;
    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<OpDefNode> invariants = new ArrayList<OpDefNode>();
    
    	private OpDefNode expressionOpdefNode;
    	private Hashtable<String, SymbolNode> namingHashTable = new Hashtable<String, SymbolNode>();
    	
    	
    	private final ModuleNode moduleNode;
    	private ExprNode nextExpr;
    
    	private ArrayList<OpDeclNode> bConstants;
    	// used to check if a b constant has arguments and is not overriden in the
    	// configfile
    
    	private ArrayList<BOperation> bOperations = new ArrayList<BOperation>();
    	private ArrayList<ExprNode> inits = new ArrayList<ExprNode>();
    
    	private Set<OpDefNode> bDefinitionsSet = new HashSet<OpDefNode>();
    	// set of OpDefNodes which will appear in the resulting B Machine
    	private Set<OpDefNode> usedDefinitions = new HashSet<OpDefNode>();
    	// definitions which are used for the type inference algorithm
    	private Hashtable<OpDefNode, FormalParamNode[]> letParams = new Hashtable<OpDefNode, FormalParamNode[]>();
    	// additional parameters of an let Operator, these parameters are from the
    	// surrounding operator
    	private ArrayList<String> definitionMacros = new ArrayList<String>();
    
    	private ArrayList<OpDefNode> recursiveFunctions = new ArrayList<OpDefNode>();
    
    	private ArrayList<RecursiveDefinition> recursiveDefinitions = new ArrayList<RecursiveDefinition>();
    
    	private ConfigfileEvaluator configFileEvaluator;
    
    	private SpecAnalyser(ModuleNode m) {
    		this.moduleNode = m;
    		this.bConstants = new ArrayList<OpDeclNode>();
    	}
    
    	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<String, OpDefNode> definitions = new Hashtable<String, OpDefNode>();
    		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");
    		// 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<OpDefNode>(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<OpDefNode> set = new HashSet<OpDefNode>(usedDefinitions);
    		for (OpDefNode def : set) {
    			if (def.getInRecursive()) {
    				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<BOperation> getBOperations() {
    		return this.bOperations;
    	}
    
    	public ArrayList<ExprNode> getInits() {
    		return this.inits;
    	}
    
    	public ExprNode getNext() {
    		return this.nextExpr;
    	}
    
    	public Set<OpDefNode> getBDefinitions() {
    		return bDefinitionsSet;
    	}
    
    	public Hashtable<OpDefNode, FormalParamNode[]> getLetParams() {
    		return letParams;
    	}
    
    	public ArrayList<String> getDefinitionMacros() {
    		return definitionMacros;
    	}
    
    	public Set<OpDefNode> getUsedDefinitions() {
    		return usedDefinitions;
    	}
    
    	public ArrayList<OpDefNode> getRecursiveFunctions() {
    		return recursiveFunctions;
    	}
    
    	public ArrayList<RecursiveDefinition> getRecursiveDefinitions() {
    		return recursiveDefinitions;
    	}
    
    	public ModuleNode getModuleNode() {
    		return this.moduleNode;
    	}
    
    	public ConfigfileEvaluator getConfigFileEvaluator(){
    		return configFileEvaluator;
    	}
    	
    	public ArrayList<OpDefNode> getInvariants(){
    		return invariants;
    	}
    	
    	public OpDefNode getInitDef(){
    		return init;
    	}
    	
    	public OpDefNode getExpressionOpdefNode(){
    		return expressionOpdefNode;
    	}
    	
    	public SymbolNode getSymbolNodeByName(String name){
    		return namingHashTable.get(name);
    	}
    	
    }