All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.tla2b.analysis.SymbolRenamer Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
/**
 * @author Dominik Hansen 
 **/

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 KEYWORDS = new HashSet();
	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 INFIX_OPERATOR = new Hashtable();
	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 BBUILTIN_OPERATOR = new Hashtable();
	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 usedDefinitions;

	private Set globalNames = new HashSet();
	private Hashtable> usedNamesTable = new Hashtable>();

	/**
	 * @param moduleNode
	 * @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[] 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());
		}

		for (int i = 0; i < moduleNode.getAssumptions().length; i++) {
			AssumeNode assumeNode = moduleNode.getAssumptions()[i];
			visitNode(assumeNode.getAssume(), new HashSet());
		}

		for (int i = moduleNode.getOpDefs().length - 1; i >= 0; i--) {
			OpDefNode def = moduleNode.getOpDefs()[i];
			Set 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 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(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 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;
				}
				Set set = usedNamesTable.get(def);
				if (set!=null){
					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 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 newUsedNames = new HashSet(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 tempSet) {
		String res = name;
		for (int i = 1; existingName(res) || tempSet.contains(res); i++) {
			res = name + "_" + i;
		}
		return res;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy