diff --git a/src/main/java/de/tla2b/analysis/TypeChecker.java b/src/main/java/de/tla2b/analysis/TypeChecker.java
index ceaebf0b26a4b2a21da32781c2ac408b6dcb3ae5..31764fe443a508be4d22c26dca4685ca569816c7 100644
--- a/src/main/java/de/tla2b/analysis/TypeChecker.java
+++ b/src/main/java/de/tla2b/analysis/TypeChecker.java
@@ -266,18 +266,18 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo
 		throw new NotImplementedException(exprNode.toString(2));
 	}
 
-	private void setType(SemanticNode node, TLAType type, int paramId) {
+	private static void setType(SemanticNode node, TLAType type, int paramId) {
 		node.setToolObject(paramId, type);
 		if (type instanceof AbstractHasFollowers) {
 			((AbstractHasFollowers) type).addFollower(node);
 		}
 	}
 
-	private void setType(SemanticNode node, TLAType type) {
+	public static void setType(SemanticNode node, TLAType type) {
 		setType(node, type, TYPE_ID);
 	}
 
-	private TLAType getType(SemanticNode n) {
+	public static TLAType getType(SemanticNode n) {
 		return (TLAType) n.getToolObject(TYPE_ID);
 	}
 
diff --git a/src/main/java/de/tla2bAst/ExpressionTranslator.java b/src/main/java/de/tla2bAst/ExpressionTranslator.java
index 0ca914166e02655b9f45a7bb256d10775783ab3f..1a64adade9e8d27c440d28c0c58a3ac730234452 100644
--- a/src/main/java/de/tla2bAst/ExpressionTranslator.java
+++ b/src/main/java/de/tla2bAst/ExpressionTranslator.java
@@ -7,14 +7,19 @@ import de.tla2b.analysis.TypeChecker;
 import de.tla2b.exceptions.ExpressionTranslationException;
 import de.tla2b.exceptions.TLA2BException;
 import de.tla2b.exceptions.TLA2BFrontEndException;
-import de.tla2b.exceptions.TypeErrorException;
+import de.tla2b.global.BBuiltInOPs;
+import de.tla2b.util.TlaUtils;
 import tla2sany.drivers.FrontEndException;
 import tla2sany.drivers.InitException;
 import tla2sany.drivers.SANY;
 import tla2sany.modanalyzer.ParseUnit;
 import tla2sany.modanalyzer.SpecObj;
 import tla2sany.parser.ParseException;
+import tla2sany.semantic.FormalParamNode;
 import tla2sany.semantic.ModuleNode;
+import tla2sany.semantic.OpDeclNode;
+import tla2sany.semantic.OpDefNode;
+import tla2sany.semantic.SymbolNode;
 import tla2sany.st.SyntaxTreeConstants;
 import tla2sany.st.TreeNode;
 import util.ToolIO;
@@ -22,53 +27,67 @@ import util.ToolIO;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static de.tla2b.global.TranslationGlobals.STANDARD_MODULES;
 
 public class ExpressionTranslator implements SyntaxTreeConstants {
 
 	private final String tlaExpression;
-	private final ArrayList<String> variables = new ArrayList<>();
-	private final ArrayList<String> noVariables = new ArrayList<>();
-	private Start expressionStart;
+	private final List<String> variables = new ArrayList<>();
+	private final List<String> noVariables = new ArrayList<>();
+	private final Map<String, FormalParamNode[]> definitions = new HashMap<>();
+	private final Map<String, SymbolNode> namingMap = new HashMap<>();
 	private ModuleNode moduleNode;
 	private String expr;
 	private Translator translator;
 
-	public Start getBExpressionParseUnit() {
-		return expressionStart;
-	}
-
+	/**
+	 * @deprecated Internal use only. Use {@link #translate(String)} instead.
+	 */
+	@Deprecated
 	public ExpressionTranslator(String tlaExpression) {
 		this.tlaExpression = tlaExpression;
 	}
 
+	/**
+	 * @deprecated Internal use only. Use {@link #translate(String, Translator)} instead.
+	 */
+	@Deprecated
 	public ExpressionTranslator(String tlaExpression, Translator translator) {
 		this.tlaExpression = tlaExpression;
 		this.translator = translator;
+		ModuleNode moduleContext = translator.getSpecAnalyser().getModuleNode(); // NOT this.moduleNode !
+		// this is the module in whose context the expression is to be evaluated
+		this.namingMap.putAll(TlaUtils.getDeclarationsMap(moduleContext.getVariableDecls()));
+		this.namingMap.putAll(TlaUtils.getDeclarationsMap(moduleContext.getConstantDecls()));
+		// we need all definitions of the context module, not only the translated ones
+		this.namingMap.putAll(TlaUtils.getOpDefsMap(moduleContext.getOpDefs()));
 	}
 
+	/**
+	 * @deprecated Internal use only. Use {@link #translate(String)} or {@link #translate(String,Translator)} instead.
+	 */
+	@Deprecated
 	public void parse() {
 		String dir = System.getProperty("java.io.tmpdir");
 		ToolIO.setUserDir(dir);
 
 		File tempFile;
-		String moduleName;
-		String module;
 		try {
 			tempFile = File.createTempFile("Testing", ".tla");
-			moduleName = tempFile.getName().substring(0,tempFile.getName().indexOf("."));
+		} catch (IOException e) {
+			throw new ExpressionTranslationException("Can not create temporary file in directory '" + dir + "'");
+		}
 
-			module = "----MODULE " + moduleName + " ----\n" + "Expression == "
-				+ tlaExpression + "\n====";
+		String moduleName = tempFile.getName().substring(0,tempFile.getName().indexOf("."));
+		String module = "----MODULE " + moduleName + " ----\n" + "Expression == " + tlaExpression + "\n====";
 
-			FileWriter fw = new FileWriter(tempFile);
+		try (FileWriter fw = new FileWriter(tempFile)) {
 			fw.write(module);
-			fw.close();
 		} catch (IOException e) {
-			throw new ExpressionTranslationException(
-				"Can not create temporary file in directory '" + dir + "'");
+			throw new ExpressionTranslationException("Can not write module to temporary file " + tempFile.getAbsolutePath());
 		}
 
 		SpecObj spec = parseModuleWithoutSemanticAnalyse(moduleName, module);
@@ -79,31 +98,42 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 		sb.append("EXTENDS Naturals, Integers, Reals, Sequences, FiniteSets \n");
 		if (!variables.isEmpty()) {
 			sb.append("VARIABLES ");
-			for (int i = 0; i < variables.size(); i++) {
-				if (i != 0) {
-					sb.append(", ");
-				}
-				sb.append(variables.get(i));
-			}
+			sb.append(String.join(", ", variables));
 			sb.append("\n");
 		}
+		if (!definitions.isEmpty()) {
+			// just add def with dummy tuple; node will be replaced later
+			definitions.forEach((name, params) -> {
+				List<String> paramNames = Arrays.stream(definitions.getOrDefault(name, new FormalParamNode[0]))
+						.map(p -> p.getName().toString())
+						.collect(Collectors.toList());
+				sb.append(name);
+				if (!paramNames.isEmpty()) {
+					sb.append("(");
+					sb.append(String.join(", ", paramNames));
+					sb.append(")");
+				}
+				sb.append(" == <<");
+				if (!paramNames.isEmpty()) {
+					sb.append(String.join(", ", paramNames));
+				}
+				sb.append(">>\n");
+			});
+		}
 		sb.append("Expression");
 		sb.append(" == ");
 		sb.append(tlaExpression);
 		sb.append("\n====================");
 
-		try {
-			FileWriter fw = new FileWriter(tempFile);
-			fw.write(sb.toString());
-			fw.close();
+		this.expr = sb.toString();
+		try (FileWriter fw = new FileWriter(tempFile)) {
+			fw.write(expr);
 			tempFile.deleteOnExit();
 		} catch (IOException e) {
 			throw new ExpressionTranslationException(e.getMessage());
 		}
 		ToolIO.reset();
 
-		this.expr = sb.toString();
-
 		this.moduleNode = null;
 		try {
 			moduleNode = parseModule(moduleName, sb.toString());
@@ -112,52 +142,48 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 		}
 	}
 
-	public Start translateIncludingModel() throws TLA2BException {
-		SpecAnalyser specAnalyser = SpecAnalyser.createSpecAnalyserForTlaExpression(moduleNode);
-		TypeChecker tc = translator.getTypeChecker();
-		try {
-			// here we add typing for known identifiers from the module
-			tc.visitOpDefNode(specAnalyser.getExpressionOpdefNode());
-		} catch (TypeErrorException e) {
-			// ignore type errors; new free variables will always throw an exception here
-			// (they have no type, which is correct as they are not part of the module);
-			// real type errors are checked below
-		}
+	public static Start translate(String tlaExpression) {
+		ExpressionTranslator expressionTranslator = new ExpressionTranslator(tlaExpression);
+		expressionTranslator.parse();
+		return expressionTranslator.translate();
+	}
 
-		TypeChecker tc2 = new TypeChecker(moduleNode, specAnalyser);
-		try {
-			// here we add the typing for new variables
-			// the types of module variables are also checked
-			tc2.start();
-		} catch (TypeErrorException e) {
-			String message = "****TypeError****\n" + e.getLocalizedMessage() + "\n" + expr + "\n";
-			throw new ExpressionTranslationException(message);
-		}
-		SymbolRenamer.run(moduleNode, specAnalyser);
-		return this.expressionStart = new BAstCreator(moduleNode, specAnalyser).getStartNode();
+	public static Start translate(String tlaExpression, Translator translator) {
+		ExpressionTranslator expressionTranslator = new ExpressionTranslator(tlaExpression, translator);
+		expressionTranslator.parse();
+		expressionTranslator.setTypesOfExistingNodes();
+		return expressionTranslator.translate();
 	}
 
-	public Start translateWithoutModel() {
+	/**
+	 * @deprecated Internal use only. Use {@link #translate(String)} or {@link #translate(String,Translator)} instead.
+	 */
+	@Deprecated
+	public Start translate() {
 		SpecAnalyser specAnalyser = SpecAnalyser.createSpecAnalyserForTlaExpression(moduleNode);
 		TypeChecker tc = new TypeChecker(moduleNode, specAnalyser);
 		try {
 			tc.start();
 		} catch (TLA2BException e) {
-			String message = "****TypeError****\n" + e.getLocalizedMessage()
-					+ "\n" + expr + "\n";
+			String message = "****TypeError****\n" + e.getLocalizedMessage() + "\n" + expr + "\n";
 			throw new ExpressionTranslationException(message);
 		}
 		SymbolRenamer.run(moduleNode, specAnalyser);
-		return this.expressionStart = new BAstCreator(moduleNode, specAnalyser).getStartNode();
+		return new BAstCreator(moduleNode, specAnalyser).getStartNode();
 	}
 
 	@Deprecated
-	public Start translate() {
-		return this.translateWithoutModel();
+	public Start translateIncludingModel() {
+		setTypesOfExistingNodes();
+		return translate();
 	}
 
-	public static ModuleNode parseModule(String moduleName, String module)
-		throws TLA2BFrontEndException {
+	@Deprecated
+	public Start translateWithoutModel() {
+		return translate();
+	}
+
+	private ModuleNode parseModule(String moduleName, String module) throws TLA2BFrontEndException {
 		SpecObj spec = new SpecObj(moduleName, null);
 		try {
 			SANY.frontEndMain(spec, moduleName, ToolIO.out);
@@ -192,19 +218,15 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 
 	private SpecObj parseModuleWithoutSemanticAnalyse(String moduleFileName, String module) {
 		SpecObj spec = new SpecObj(moduleFileName, null);
-
 		try {
-			SANY.frontEndInitialize(spec, ToolIO.out);
-			SANY.frontEndParse(spec, ToolIO.out);
-
-		} catch (InitException | ParseException e1) {
-			System.out.println(e1);
+			SANY.frontEndInitialize(spec, ToolIO.err);
+			SANY.frontEndParse(spec, ToolIO.err);
+		} catch (InitException | ParseException e) {
+			throw new ExpressionTranslationException(e.getLocalizedMessage());
 		}
 
 		if (spec.parseErrors.isFailure()) {
-			String message = module + "\n\n";
-			message += allMessagesToString(ToolIO.getAllMessages());
-			throw new ExpressionTranslationException(message);
+			throw new ExpressionTranslationException(module + "\n\n" + allMessagesToString(ToolIO.getAllMessages()));
 		}
 		return spec;
 	}
@@ -213,8 +235,8 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 		ParseUnit p = spec.parseUnitContext.get(moduleName);
 		TreeNode n_module = p.getParseTree();
 		TreeNode n_body = n_module.heirs()[2];
-		TreeNode n_operatorDefintion = n_body.heirs()[0];
-		TreeNode expr = n_operatorDefintion.heirs()[2];
+		TreeNode n_operatorDefinition = n_body.heirs()[0];
+		TreeNode expr = n_operatorDefinition.heirs()[2];
 		searchVarInSyntaxTree(expr);
 
 		// this code seems to assume that there is no variable clash between outer and nested variables
@@ -222,7 +244,6 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 		for (String noVariable : noVariables) {
 			variables.remove(noVariable);
 		}
-
 	}
 
 	private final static Set<String> KEYWORDS = new HashSet<>();
@@ -234,6 +255,7 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 		KEYWORDS.add("Nat");
 		KEYWORDS.add("Int");
 		KEYWORDS.add("Real");
+		KEYWORDS.add("Infinity");
 		KEYWORDS.add("Cardinality");
 		KEYWORDS.add("IsFiniteSet");
 		KEYWORDS.add("Append");
@@ -252,7 +274,7 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 	}
 
 	/**
-	 *
+	 * collect variables and definitions from syntax tree
 	 */
 	private void searchVarInSyntaxTree(TreeNode treeNode) {
 		// System.out.println(treeNode.getKind() + " " + treeNode.getImage());
@@ -260,7 +282,13 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 			case N_GeneralId: {
 				String con = treeNode.heirs()[1].getImage();
 				if (!variables.contains(con) && !KEYWORDS.contains(con)) {
-					variables.add(con);
+					SymbolNode existingNode = namingMap.get(con);
+					if (existingNode instanceof OpDefNode) {
+						// if the identifier corresponds to an existing def, add as def, otherwise as variable
+						definitions.put(con, ((OpDefNode) existingNode).getParams());
+					} else {
+						variables.add(con);
+					}
 				}
 				break;
 			}
@@ -279,12 +307,11 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 				noVariables.add(treeNode.heirs()[0].getImage());
 				break;
 			}
-			case
-				N_UnboundQuant: { // TODO: check: is this an unbounded quantifier with infinite domain or a quantifier that does not hide the quantified variables?
+			case N_UnboundQuant: { // TODO: check: is this an unbounded quantifier with infinite domain or a quantifier that does not hide the quantified variables?
 				TreeNode[] children = treeNode.heirs();
-				for (int i = 1; i < children.length - 2; i = i + 2) {
+				//for (int i = 1; i < children.length - 2; i = i + 2) {
 					// System.out.println("N_UnboundQuant: "+children[i].getImage());
-				}
+				//}
 				searchVarInSyntaxTree(treeNode.heirs()[children.length - 1]);
 				break;
 			}
@@ -323,11 +350,48 @@ public class ExpressionTranslator implements SyntaxTreeConstants {
 				searchVarInSyntaxTree(treeNode.heirs()[5]); // e
 				break;
 			}
+		}
 
+		for (TreeNode heir : treeNode.heirs()) {
+			searchVarInSyntaxTree(heir);
 		}
+	}
+
+	private void setTypesOfExistingNodes() {
+		if (translator != null) {
+			for (OpDeclNode node : moduleNode.getConstantDecls())
+				setTypeExistingDeclNode(node);
+			for (OpDeclNode node : moduleNode.getVariableDecls())
+				setTypeExistingDeclNode(node);
+			for (OpDefNode node : moduleNode.getOpDefs()) {
+				SymbolNode fromSpec = namingMap.get(node.getName().toString());
+				if (fromSpec != null) { // a definition with the same name exists in module context
+					// check if def in translated B definitions
+					if (translator.getSpecAnalyser().getBDefinitions().contains((OpDefNode) fromSpec)) {
+						// replace body of dummy definition with body of the real definition
+						node.setBody(((OpDefNode) fromSpec).getBody());
+						// not sure if we should also replace defNode in Context:
+						// nCtx.addSymbolToContext(node.getName(), fromSpec);
+						// this should be redundant and not necessary:
+						// TypeChecker.setType(node, TypeChecker.getType(fromSpec));
+					} else if (!(BBuiltInOPs.contains(node.getName())
+							&& STANDARD_MODULES.contains(node.getSource().getOriginallyDefinedInModuleNode().getName().toString()))) {
+						// throw error if def is not included in translation and not a built-in definition
+						throw new ExpressionTranslationException("Evaluation error:\n"
+								+ "Definition '" + fromSpec.getName() + "' is not included in the B translation.\n");
+					}
+				}
+			}
+		}
+	}
 
-		for (int i = 0; i < treeNode.heirs().length; i++) {
-			searchVarInSyntaxTree(treeNode.heirs()[i]);
+	private void setTypeExistingDeclNode(OpDeclNode node) {
+		SymbolNode fromSpec = namingMap.get(node.getName().toString());
+		if (fromSpec != null) { // a constant or variable declaration with the same name exists in module context
+			// replace all decl nodes by the known decl from the real module
+			// nCtx.addSymbolToContext(node.getName(), fromSpec);
+			// set the type of the declaration in the dummy module (CONSTANTS/VARIABLES section)
+			TypeChecker.setType(node, TypeChecker.getType(fromSpec));
 		}
 	}
 
diff --git a/src/main/java/de/tla2bAst/Translator.java b/src/main/java/de/tla2bAst/Translator.java
index a347fff90e2a93e81113eef5a309f5c14cf28e7f..80046ca64e70219b41ac3eae7ef3bdb844798fc9 100644
--- a/src/main/java/de/tla2bAst/Translator.java
+++ b/src/main/java/de/tla2bAst/Translator.java
@@ -18,8 +18,6 @@ import de.tla2b.exceptions.TLA2BFrontEndException;
 import de.tla2b.exceptions.TLA2BException;
 import de.tla2b.global.TranslationGlobals;
 import de.tla2b.output.TlaTypePrinter;
-import de.tla2b.translation.BMacroHandler;
-import de.tla2b.translation.RecursiveFunctionHandler;
 import de.tla2b.types.TLAType;
 import de.tla2b.util.FileUtils;
 import tla2sany.drivers.FrontEndException;
@@ -260,21 +258,17 @@ public class Translator implements TranslationGlobals {
 		return rml;
 	}
 
-	public Start translateExpressionIncludingModel(String tlaExpression) throws TLA2BException {
-		ExpressionTranslator expressionTranslator = new ExpressionTranslator(tlaExpression, this);
-		expressionTranslator.parse();
-		return expressionTranslator.translateIncludingModel();
+	public Start translateExpressionIncludingModel(String tlaExpression) {
+		return ExpressionTranslator.translate(tlaExpression, this);
 	}
 
 	@Deprecated
-	public Start translateExpression(String tlaExpression) throws TLA2BException {
+	public Start translateExpression(String tlaExpression) {
 		return this.translateExpressionIncludingModel(tlaExpression);
 	}
 
 	public static Start translateExpressionWithoutModel(String tlaExpression) {
-		ExpressionTranslator expressionTranslator = new ExpressionTranslator(tlaExpression);
-		expressionTranslator.parse();
-		return expressionTranslator.translateWithoutModel();
+		return ExpressionTranslator.translate(tlaExpression);
 	}
 
 	@Deprecated