Skip to content
Snippets Groups Projects
Select Git revision
  • 501a06cec331573a42a4f7d57f98a7547606a515
  • master default protected
  • release/1.1.4
  • release/1.1.3
  • release/1.1.1
  • 1.4.2
  • 1.4.1
  • 1.4.0
  • 1.3.0
  • 1.2.1
  • 1.2.0
  • 1.1.5
  • 1.1.4
  • 1.1.3
  • 1.1.1
  • 1.1.0
  • 1.0.9
  • 1.0.8
  • 1.0.7
  • v1.0.5
  • 1.0.5
21 results

SymbolRenamer.java

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    SymbolRenamer.java 10.42 KiB
    /**
     * @author Dominik Hansen <Dominik.Hansen at hhu.de>
     **/
    
    package de.tla2b.analysis;
    
    
    import java.util.HashSet;
    import java.util.Hashtable;
    import java.util.Set;
    
    import de.tla2b.global.BBuiltInOPs;
    import de.tla2b.global.TranslationGlobals;
    
    import tla2sany.semantic.ASTConstants;
    import tla2sany.semantic.AssumeNode;
    import tla2sany.semantic.FormalParamNode;
    import tla2sany.semantic.LetInNode;
    import tla2sany.semantic.ModuleNode;
    import tla2sany.semantic.OpApplNode;
    import tla2sany.semantic.OpDeclNode;
    import tla2sany.semantic.OpDefNode;
    import tla2sany.semantic.SemanticNode;
    import tlc2.tool.BuiltInOPs;
    
    public class SymbolRenamer extends BuiltInOPs implements TranslationGlobals,
    		ASTConstants {
    
    	private final static Set<String> KEYWORDS = new HashSet<String>();
    	static {
    		KEYWORDS.add("seq");
    		KEYWORDS.add("left");
    		KEYWORDS.add("right");
    		KEYWORDS.add("max");
    		KEYWORDS.add("min");
    		KEYWORDS.add("succ");
    		KEYWORDS.add("pred");
    		KEYWORDS.add("dom");
    		KEYWORDS.add("ran");
    		KEYWORDS.add("fnc");
    		KEYWORDS.add("rel");
    		KEYWORDS.add("id");
    		KEYWORDS.add("card");
    		KEYWORDS.add("POW");
    		KEYWORDS.add("POW1");
    		KEYWORDS.add("FIN");
    		KEYWORDS.add("FIN1");
    		KEYWORDS.add("size");
    		KEYWORDS.add("rev");
    		KEYWORDS.add("first");
    		KEYWORDS.add("last");
    		KEYWORDS.add("front");
    		KEYWORDS.add("tail");
    		KEYWORDS.add("conc");
    		KEYWORDS.add("struct");
    		KEYWORDS.add("rec");
    		KEYWORDS.add("tree");
    		KEYWORDS.add("btree");
    		KEYWORDS.add("skip");
    		KEYWORDS.add("ANY");
    		KEYWORDS.add("WHERE");
    		KEYWORDS.add("END");
    		KEYWORDS.add("BE");
    		KEYWORDS.add("VAR");
    		KEYWORDS.add("ASSERT");
    		KEYWORDS.add("CHOICE");
    		KEYWORDS.add("OR");
    		KEYWORDS.add("SELECT");
    		KEYWORDS.add("EITHER");
    		KEYWORDS.add("WHEN");
    		KEYWORDS.add("BEGIN");
    		KEYWORDS.add("MACHINE");
    		KEYWORDS.add("REFINEMENT");
    		KEYWORDS.add("IMPLEMENTATION");
    		KEYWORDS.add("SETS");
    		KEYWORDS.add("CONSTRAINTS");
    		KEYWORDS.add("MODEL");
    		KEYWORDS.add("SYSTEM");
    		KEYWORDS.add("MACHINE");
    		KEYWORDS.add("EVENTS");
    		KEYWORDS.add("OPERATIONS");
    	}
    
    	private final static Hashtable<String, String> INFIX_OPERATOR = new Hashtable<String, String>();
    	static {
    		INFIX_OPERATOR.put("!!", "exclamationmark2");
    		INFIX_OPERATOR.put("??", "questionmark2");
    		INFIX_OPERATOR.put("&", "ampersand1");
    		INFIX_OPERATOR.put("&&", "ampersand2");
    		INFIX_OPERATOR.put("@@", "at2");
    		INFIX_OPERATOR.put("++", "plus2");
    		INFIX_OPERATOR.put("--", "minus2");
    		INFIX_OPERATOR.put("^", "circumflex1");
    		INFIX_OPERATOR.put("^^", "circumflex2");
    		INFIX_OPERATOR.put("##", "hash2");
    		INFIX_OPERATOR.put("%%", "percent2");
    		INFIX_OPERATOR.put("$", "dollar1");
    		INFIX_OPERATOR.put("$$", "dollar2");
    		INFIX_OPERATOR.put("|", "pipe1");
    		INFIX_OPERATOR.put("||", "pipe2");
    		INFIX_OPERATOR.put("//", "slash2");
    		INFIX_OPERATOR.put("**", "mult2");
    		INFIX_OPERATOR.put("...", "dot3");
    	}
    
    	private final static Hashtable<String, String> BBUILTIN_OPERATOR = new Hashtable<String, String>();
    	static {
    		BBUILTIN_OPERATOR.put("+", "plus");
    		BBUILTIN_OPERATOR.put("-", "minus");
    		BBUILTIN_OPERATOR.put("*", "mult");
    		BBUILTIN_OPERATOR.put("^", "power");
    		BBUILTIN_OPERATOR.put("<", "lt");
    		BBUILTIN_OPERATOR.put(">", "gt");
    		BBUILTIN_OPERATOR.put("\\leq", "leq");
    		BBUILTIN_OPERATOR.put("\\geq", "geq");
    		BBUILTIN_OPERATOR.put("%", "modulo");
    		BBUILTIN_OPERATOR.put("\\div", "div");
    		BBUILTIN_OPERATOR.put("..", "dot2");
    	}
    
    	private ModuleNode moduleNode;
    	private Set<OpDefNode> usedDefinitions;
    
    	private Set<String> globalNames = new HashSet<String>();
    	private Hashtable<OpDefNode, Set<String>> usedNamesTable = new Hashtable<OpDefNode, Set<String>>();
    
    	/**
    	 * @param moduleNode2
    	 * @param specAnalyser
    	 */
    	public SymbolRenamer(ModuleNode moduleNode, SpecAnalyser specAnalyser) {
    		this.moduleNode = moduleNode;
    		this.usedDefinitions = specAnalyser.getUsedDefinitions();
    	}
    
    	public SymbolRenamer(ModuleNode moduleNode) {
    		this.moduleNode = moduleNode;
    		usedDefinitions = new HashSet<OpDefNode>();
    		OpDefNode[] defs = moduleNode.getOpDefs();
    		usedDefinitions.add(defs[defs.length - 1]);
    	}
    
    	public void start() {
    		// Variables
    		for (int i = 0; i < moduleNode.getVariableDecls().length; i++) {
    			OpDeclNode v = moduleNode.getVariableDecls()[i];
    			String newName = incName(v.getName().toString());
    			globalNames.add(newName);
    			v.setToolObject(NEW_NAME, newName);
    		}
    
    		// constants
    		for (int i = 0; i < moduleNode.getConstantDecls().length; i++) {
    			OpDeclNode c = moduleNode.getConstantDecls()[i];
    			String newName = incName(c.getName().toString());
    			globalNames.add(newName);
    			c.setToolObject(NEW_NAME, newName);
    		}
    
    		for (int i = 0; i < moduleNode.getOpDefs().length; i++) {
    			OpDefNode def = moduleNode.getOpDefs()[i];
    			String newName = getOperatorName(def);
    			globalNames.add(newName);
    			def.setToolObject(NEW_NAME, newName);
    			usedNamesTable.put(def, new HashSet<String>());
    		}
    
    		for (int i = 0; i < moduleNode.getAssumptions().length; i++) {
    			AssumeNode assumeNode = moduleNode.getAssumptions()[i];
    			visitNode(assumeNode.getAssume(), new HashSet<String>());
    		}
    
    		for (int i = moduleNode.getOpDefs().length - 1; i >= 0; i--) {
    			OpDefNode def = moduleNode.getOpDefs()[i];
    			Set<String> usedNames = usedNamesTable.get(def);
    			for (int j = 0; j < def.getParams().length; j++) {
    				FormalParamNode p = def.getParams()[j];
    				String paramName = p.getName().toString();
    				String newParamName = incName(paramName);
    				p.setToolObject(NEW_NAME, newParamName);
    				//Parameter of different definitions calling each other can have the same name
    				//usedNames.add(newParamName);
    			}
    			visitNode(def.getBody(), usedNames);
    		}
    
    	}
    
    	private void visitNode(SemanticNode n, Set<String> usedNames) {
    		// System.out.println(n.toString(1)+ " "+ n.getKind());
    
    		switch (n.getKind()) {
    
    		case LetInKind: {
    			LetInNode letInNode = (LetInNode) n;
    			OpDefNode[] defs = letInNode.getLets();
    
    			// Initialize all local definitions (get a new name, get an empty
    			// list)
    			for (int i = 0; i < defs.length; i++) {
    				OpDefNode def = defs[i];
    				String newName = getOperatorName(def);
    				globalNames.add(newName);
    				def.setToolObject(NEW_NAME, newName);
    				usedNamesTable.put(def, new HashSet<String>(usedNames));
    			}
    
    			// first visit the IN expression
    			visitNode(letInNode.getBody(), usedNames);
    
    			// visit the definition itself
    			for (int i = defs.length - 1; i >= 0; i--) {
    				OpDefNode def = defs[i];
    				Set<String> usedNamesOfDef = usedNamesTable.get(def);
    				for (int j = 0; j < def.getParams().length; j++) {
    					FormalParamNode p = def.getParams()[j];
    					String paramName = p.getName().toString();
    					String newParamName = incName(paramName);
    					p.setToolObject(NEW_NAME, newParamName);
    					//usedNamesOfDef.add(newParamName);
    				}
    				visitNode(def.getBody(), usedNamesOfDef);
    			}
    			return;
    		}
    
    		case OpApplKind: {
    			OpApplNode opApplNode = (OpApplNode) n;
    			switch (opApplNode.getOperator().getKind()) {
    
    			case BuiltInKind: {
    				visitBuiltinNode(opApplNode, usedNames);
    				return;
    			}
    
    			case UserDefinedOpKind: {
    				OpDefNode def = (OpDefNode) opApplNode.getOperator();
    				if (BBuiltInOPs.contains(def.getName())) {
    					break;
    				}
    
    				usedNamesTable.get(def).addAll(usedNames);
    				for (int i = 0; i < n.getChildren().length; i++) {
    					visitNode(opApplNode.getArgs()[i], usedNames);
    				}
    				return;
    			}
    			}
    
    			for (int i = 0; i < opApplNode.getArgs().length; i++) {
    				visitNode(opApplNode.getArgs()[i], usedNames);
    			}
    			return;
    		}
    		}
    
    		if (n.getChildren() != null) {
    			for (int i = 0; i < n.getChildren().length; i++) {
    				visitNode(n.getChildren()[i], usedNames);
    			}
    		}
    	}
    
    	private void visitBuiltinNode(OpApplNode opApplNode, Set<String> usedNames) {
    
    		switch (getOpCode(opApplNode.getOperator().getName())) {
    
    		case OPCODE_nrfs:
    		case OPCODE_fc: // Represents [x \in S |-> e]
    		case OPCODE_bc: // CHOOSE x \in S: P
    		case OPCODE_soa: // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2}
    		case OPCODE_sso: // $SubsetOf Represents {x \in S : P}
    		case OPCODE_bf: // \A x \in S : P
    		case OPCODE_be: // \E x \in S : P
    		{
    			FormalParamNode[][] params = opApplNode.getBdedQuantSymbolLists();
    			Set<String> newUsedNames = new HashSet<String>(usedNames);
    			for (int i = 0; i < params.length; i++) {
    				for (int j = 0; j < params[i].length; j++) {
    					FormalParamNode param = params[i][j];
    					String paramName = param.getName().toString();
    					String newName = incName(paramName, usedNames);
    					param.setToolObject(NEW_NAME, newName);
    					newUsedNames.add(newName);
    				}
    			}
    			for (int i = 0; i < opApplNode.getBdedQuantBounds().length; i++) {
    				visitNode(opApplNode.getBdedQuantBounds()[i], usedNames);
    			}
    
    			visitNode(opApplNode.getArgs()[0], newUsedNames);
    
    			return;
    		}
    
    		default:
    			for (int i = 0; i < opApplNode.getArgs().length; i++) {
    				if (opApplNode.getArgs()[i] != null) {
    					visitNode(opApplNode.getArgs()[i], usedNames);
    				}
    			}
    
    		}
    	}
    
    	private String getOperatorName(OpDefNode def) {
    		String newName = def.getName().toString();
    
    		if (BBUILTIN_OPERATOR.containsKey(newName)) {
    			// a B built-in operator is defined outside of a standard module
    			if (!STANDARD_MODULES.contains(def.getSource()
    					.getOriginallyDefinedInModuleNode().getName().toString())) {
    				return incName(BBUILTIN_OPERATOR.get(newName));
    			}
    		}
    
    		// replace invalid infix operator names
    		for (String e : INFIX_OPERATOR.keySet()) {
    			if (newName.contains(e)) {
    				newName = newName.replace(e, INFIX_OPERATOR.get(e));
    			}
    		}
    
    		// replace exclamation marks
    		if (newName.contains("!")) {
    			newName = newName.replace('!', '_');
    		}
    
    		// replace slashes
    		if (newName.contains("\\")) {
    			newName = newName.replace("\\", "");
    		}
    
    		return incName(newName);
    	}
    
    	private Boolean existingName(String name) {
    		if (globalNames.contains(name) || KEYWORDS.contains(name)) {
    			return true;
    		} else
    			return false;
    	}
    
    	private String incName(String name) {
    		String res = name;
    		for (int i = 1; existingName(res); i++) {
    			res = name + "_" + i;
    		}
    		return res;
    	}
    
    	private String incName(String name, Set<String> tempSet) {
    		String res = name;
    		for (int i = 1; existingName(res) || tempSet.contains(res); i++) {
    			res = name + "_" + i;
    		}
    		return res;
    	}
    }