Refactor to eliminate inheritance

diff --git a/plugins/org.eclipse.epsilon.executors/META-INF/MANIFEST.MF b/plugins/org.eclipse.epsilon.executors/META-INF/MANIFEST.MF
index c5f3dcf..563b068 100644
--- a/plugins/org.eclipse.epsilon.executors/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.epsilon.executors/META-INF/MANIFEST.MF
@@ -8,6 +8,7 @@
 Export-Package: org.eclipse.epsilon.executors,
  org.eclipse.epsilon.executors.ecl,
  org.eclipse.epsilon.executors.egl,
+ org.eclipse.epsilon.executors.eml,
  org.eclipse.epsilon.executors.eol,
  org.eclipse.epsilon.executors.etl,
  org.eclipse.epsilon.executors.evl,
@@ -19,4 +20,6 @@
  org.eclipse.epsilon.egl.engine;bundle-version="1.6.0",
  org.eclipse.epsilon.etl.engine;bundle-version="1.6.0",
  org.eclipse.epsilon.evl.engine;bundle-version="1.6.0",
- org.eclipse.epsilon.ecl.engine
+ org.eclipse.epsilon.ecl.engine,
+ org.eclipse.epsilon.eml.engine,
+ org.eclipse.epsilon.erl.engine
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/AbstractLanguageExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/AbstractLanguageExecutor.java
deleted file mode 100644
index 7f2a4e4..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/AbstractLanguageExecutor.java
+++ /dev/null
@@ -1,505 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors;
-
-import static org.eclipse.epsilon.common.util.OperatingSystem.getJavaVersion;
-import static org.eclipse.epsilon.common.util.OperatingSystem.getOsNameAndVersion;
-import static org.eclipse.epsilon.common.util.profiling.BenchmarkUtils.getCpuName;
-import static org.eclipse.epsilon.common.util.profiling.BenchmarkUtils.getNumberOfHardwareThreads;
-import static org.eclipse.epsilon.common.util.profiling.BenchmarkUtils.getTime;
-
-import java.nio.file.Path;
-import java.time.Duration;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.Set;
-
-import org.eclipse.epsilon.common.parse.problem.ParseProblem;
-import org.eclipse.epsilon.eol.IEolModule;
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.eclipse.epsilon.eol.models.IModel;
-import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
-import org.eclipse.epsilon.erl.IErlModule;
-import org.eclipse.epsilon.erl.dom.NamedRule;
-import org.eclipse.epsilon.erl.execute.RuleProfiler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A base class to provide generic executor API for all engines.
- * 
- * @author Horacio Hoyos Rodriguez
- *
- */
-public abstract class AbstractLanguageExecutor implements IEpsilonLanguageExecutor {
-
-    private static final Logger logger = LoggerFactory.getLogger(AbstractLanguageExecutor.class);
-
-    /**
-     * The Epsilon Module that implements the specific language engine.
-     */
-    protected final IEolModule module;
-    
-    /**
-     * The Script to be executed. Alternatively a block of code can be provided, see {@link #code}
-     */
-    protected Path script;
-    
-    /**
-     * The Code to be executed. Alternatively a script file can be provided, see {@link #script}.
-     */
-    protected String code;
-    
-    /**
-     * The runtime parameters.
-     */
-    protected Map<String, Object> parameters = new HashMap<>(4);
-    
-    /**
-     * The Models used during execution.
-     */
-    protected Set<IModel> models = new HashSet<>(4);
-    
-    /**
-     * The Result of the execution. Not all models provide a result.
-     */
-    protected Object result;
-    
-    /**
-     * The Native Type delegates used during execution.
-     */
-    protected Set<IToolNativeTypeDelegate> nativeDelegates = new HashSet<>(8);
-
-    /**
-     * The Dispose Models flag indicates if models will be disposed after execution.
-     */
-    protected boolean disposeModels = true;
-
-    /**
-     * The Profile Execution flag indicates if the execution should be measured.
-     */
-    protected boolean profileExecution = false;
-    
-    
-    protected ExecutionInfo executionInfo;
-    
-    /**
-     * Instantiates a new Abstract executor engine.
-     *
-     * @param module the module
-     */
-    protected AbstractLanguageExecutor(final IEolModule module) {
-        this.module = module;
-    }
-    
-    @Override
-	public ExecutionInfo getExecutionInfo() {
-		return executionInfo;
-	}
-
-	@Override
-    public IEolModule getModule() {
-        return module;
-    }
-
-    @Override
-    public String getName() {
-        return module.getClass().getSimpleName();
-    }
-
-    @Override
-    public String getCode() {
-        return code;
-    }
-
-    @Override
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    @Override
-    public Path getScript() {
-        return script;
-    }
-
-    @Override
-    public void setScript(Path script) {
-        this.script = script;
-    }
-
-    @Override
-    public Set<IModel> getModels() {
-        return Collections.unmodifiableSet(models);
-    }
-
-    @Override
-    public boolean addModel(IModel model) {
-        return models.add(model);
-    }
-
-    @Override
-    public boolean addModels(Collection<IModel> models) {
-        return this.models.addAll(models);
-    }
-
-    @Override
-    public boolean removeModel(IModel model) {
-        return models.remove(model);
-    }
-
-    @Override
-    public boolean removeModels(Collection<IModel> models) {
-        return this.models.removeAll(models);
-    }
-
-    @Override
-    public Object getResult() {
-        return result;
-    }
-    
-    /**
-     * A class that keeps track of the execution durations of the different stages of execution, and
-     * about the execution of the scripts and its rules (if rule based langauge).
-     * @author Horacio Hoyos Rodriguez
-     *
-     */
-    public static class ExecutionInfo {
-    	private static String logMessagesSeparator = "-----------------------------------------------------";
-    	private final String osNameAndVersion;
-    	private final String javaVersion;
-    	private final String cpuName;
-    	private final int logicalProcessors;
-    	private final String date;
-		private Long startNanos;
-    	/**
-         * The measured execution information.
-         */
-        protected Map<String, Duration> profiledStages = new HashMap<>();
-        protected Map<String, Duration> profiledRules = new HashMap<>();
-        protected Map<String, Long> started = new HashMap<>();
-		private Duration duration;
-    	
-		ExecutionInfo() {
-			osNameAndVersion = getOsNameAndVersion();
-			javaVersion = getJavaVersion();
-			cpuName = getCpuName();
-			logicalProcessors = getNumberOfHardwareThreads();
-			date = getTime();
-		}
-		
-		void logStart() {
-			startNanos = System.nanoTime();
-			logger.info(buildLines(
-					osNameAndVersion,
-					javaVersion,
-					cpuName,
-					"Logical processors: " + logicalProcessors,
-					"Starting execution at " + date,
-					logMessagesSeparator
-				));
-		}
-		
-		void logEnd() throws EpsilonExecutorException {
-			long endTimeNanos = System.nanoTime();
-			this.duration = Duration.ofNanos(endTimeNanos-startNanos);
-			logger.info(buildLines("",
-				"Profiled processes:",
-				profiledStages.entrySet().stream().map(e -> String.format("%s:%s", e.getKey(), e.getValue())),
-				"Finished execution at " + getTime(),
-				logMessagesSeparator
-			));
-			logger.info(buildLines("",
-					"Profiled rules:",
-					profiledRules.entrySet().stream().map(e -> String.format("%s:%s", e.getKey(), e.getValue())),
-					logMessagesSeparator
-				));
-			
-		}
-		
-		String buildLines(Object... lines) {
-			StringBuilder linesAsStr = new StringBuilder();
-			String nL = System.lineSeparator();
-			for (Object line : lines) {
-				linesAsStr.append(line).append(nL);
-			}
-			return linesAsStr.toString();
-		}
-		
-		void startStage(String name) {
-			started.put(name, System.nanoTime());
-		}
-		
-		void endStage(String name) {
-			long endTimeNanos = System.nanoTime();
-			Long startTime = started.getOrDefault(name, endTimeNanos);
-			profiledStages.put(name, Duration.ofNanos(endTimeNanos-startTime));
-		}
-		
-		void endModule(IEolModule module) {
-			if (module instanceof IErlModule) {
-				RuleProfiler ruleProfiler = ((IErlModule)module).getContext().getExecutorFactory().getRuleProfiler();
-				// Fixme Duplicate names?
-				for (Entry<NamedRule, Duration> entry : ruleProfiler.getExecutionTimes().entrySet()) {
-					Duration oldValue = profiledRules.put(entry.getKey().getName(), entry.getValue());
-					if (oldValue != null) {
-						System.err.println("Value for rule " + entry.getKey().getName() + " was replaced.");
-					}
-				}
-			}
-		}
-		
-		/**
-		 * Return the duration of the "prepareExecution" stage. A negative value indicates that the
-		 * stage was not signalled as finished.
-		 * @return
-		 */
-		public Optional<Duration> getPrepareExecutionDuration() {
-			return Optional.ofNullable(profiledStages.get("prepareExecution"));
-		}
-		
-		/**
-		 * Return the duration of the "preProcess" stage. A negative value indicates that the
-		 * stage was not signalled as finished.
-		 * @return
-		 */
-		public Optional<Duration> getPreProcessDuration() {
-			return Optional.ofNullable(profiledStages.get("preProcess"));
-		}
-		
-		/**
-		 * Return the duration of the "postProcess" stage. A negative value indicates that the
-		 * stage was not signalled as finished.
-		 * @return
-		 */
-		public Optional<Duration> getPostProcessDuration() {
-			return Optional.ofNullable(profiledStages.get("postProcess"));
-		}
-		
-		/**
-		 * Return the duration of the Epsilon module execution. A negative value indicates that the
-		 * stage was not signalled as finished.
-		 * @return
-		 */
-		public Optional<Duration> getScrpitExecutionDuration() {
-			return Optional.ofNullable(profiledStages.get("execute"));
-		}
-		
-		public Optional<Duration> getTotalDuration() {
-			return Optional.ofNullable(this.duration);
-		}
-		
-		public Optional<Duration> getRuleDuration(String name) {
-			return Optional.ofNullable(profiledRules.get(name));
-		}
-		
-		public Iterator<Entry<String, Duration>> getRulesDurations() {
-			return profiledRules.entrySet().iterator();
-		}
-		
-		
-    }
-    
-    protected void preProfile() {
-    	executionInfo = new ExecutionInfo();
-    	executionInfo.logStart();
-    }
-    
-    protected void prepareExecution() throws EpsilonExecutorException {
-    	if (profileExecution) {
-    		executionInfo.startStage("prepareExecution");
-        }
-    	try {
-            if (getScript() != null) {
-            	module.parse(getScript().toFile());
-            }
-            else if (getCode() != null) {
-        		module.parse(getCode());
-            }
-            else {
-                throw new EpsilonExecutorException("No script or code to execute");
-            }
-        }
-        catch (Exception e) {
-            logger.error("Failed to parse script: {}", getScript(), e);
-            throw new EpsilonExecutorException("Failed to parse script or code", e);
-        }
-
-        if (!module.getParseProblems().isEmpty()) {
-            logger.error("Parse errors occurred");
-			System.err.println("Parse errors occurred...");
-			for (ParseProblem problem : module.getParseProblems()) {
-				System.err.println(problem);
-			}
-            throw new EpsilonExecutorException("Parse errors occurred.");
-		}
-
-        logger.info("Adding models to context.");
-		for (IModel model : getModels()) {
-			module.getContext().getModelRepository().addModel(model);
-		}
-        logger.info("Adding parameters to context.");
-		module.getContext().getFrameStack().put(parameters, true);
-
-		logger.info("Adding Native Type Delegates");
-		module.getContext().getNativeTypeDelegates().addAll(nativeDelegates);
-		if (profileExecution) {
-    		executionInfo.endStage("prepareExecution");
-        }
-    }
-    
-    @Override
-    public final void run() throws RuntimeException {
-    	IEpsilonLanguageExecutor.super.run();
-    }
-    
-	@Override
-    public final void execute() throws EpsilonExecutorException {
-        logger.info("Executing engine.");
-        if (profileExecution) {
-        	preProfile();
-        }
-        prepareExecution();
-        
-        logger.info("Pre-process execution");
-        if (profileExecution) {
-    		executionInfo.startStage("preProcess");
-        }
-        preProcess();
-        if (profileExecution) {
-    		executionInfo.endStage("preProcess");
-        }
-        try {
-        	if (profileExecution) {
-        		executionInfo.startStage("execute");
-            }
-            result = executeInternal();
-        }
-        catch (EolRuntimeException e) {
-        	String msg = "Error executing the script";
-            logger.error(msg, e);
-            throw new EpsilonExecutorException(msg, e);
-        }
-        finally {
-        	if (profileExecution) {
-        		executionInfo.endStage("execute");
-            }
-        }
-        logger.info("Post-process execution.");
-        if (profileExecution) {
-    		executionInfo.startStage("postProcess");
-        }
-        postProcess();
-        if (profileExecution) {
-    		executionInfo.endStage("postProcess");
-        }
-        
-        if (profileExecution) {
-        	executionInfo.endModule(module);
-        	executionInfo.logEnd();
-        }
-	}
-	
-    /**
-     * Execute the module.
-     *
-     * @return the object
-     * @throws EolRuntimeException the eol runtime exception
-     */
-    abstract protected Object executeInternal() throws EolRuntimeException;
-    
-    
-    @Override
-    public void dispose() {
-        if (disposeModels) {
-            logger.info("Disposing models");
-            module.getContext().getModelRepository().dispose();
-        }
-        else {
-            logger.info("Removing models from context models");
-            module.getContext().getModelRepository().getModels().clear();
-        }
-        models.clear();
-        parameters.clear();
-        logger.info("Dispose context");
-        module.getContext().dispose();
-    }
-	
-	@Override
-    public Map<String, ?> getParameters() {
-		return Collections.unmodifiableMap(parameters);
-	}
-
-    @Override
-    public void addParameters(Map<String, Object> parameters) {
-        this.parameters.putAll(parameters);
-    }
-
-    @Override
-    public boolean addParameter(String name, Object value) {
-        return parameters.put(name, value) != null;
-    }
-
-    @Override
-    public boolean removeParameter(String name) {
-        return parameters.remove(name) != null;
-    }
-
-    @Override
-    public Set<IToolNativeTypeDelegate> getNativeDelegates() {
-        return Collections.unmodifiableSet(nativeDelegates);
-    }
-
-    @Override
-    public boolean addNativeDelegates(Collection<IToolNativeTypeDelegate> delegates) {
-        return this.nativeDelegates.addAll(delegates);
-    }
-
-    @Override
-    public boolean addNativeDelegate(IToolNativeTypeDelegate delegate) {
-        return nativeDelegates.add(delegate);
-
-    }
-
-    @Override
-    public boolean removeNativeDelegates(Collection<IToolNativeTypeDelegate> delegates) {
-        return this.nativeDelegates.removeAll(delegates);
-    }
-
-    @Override
-    public boolean removeNativeDelegate(IToolNativeTypeDelegate delegate) {
-        return nativeDelegates.remove(delegate);
-    }
-
-    @Override
-    public boolean isDisposeModels() {
-        return disposeModels;
-    }
-
-    @Override
-    public void setDisposeModels(boolean disposeModels) {
-        this.disposeModels = disposeModels;
-    }
-    
-    @Override
-    public boolean isProfilingEnabled() {
-    	return profileExecution;
-    }
-    
-    @Override
-    public void setProfilingEnabled(boolean profileExecution) {
-    	this.profileExecution = profileExecution;
-    }
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonEngineExecutorFactory.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonEngineExecutorFactory.java
index d211d43..fec9035 100644
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonEngineExecutorFactory.java
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonEngineExecutorFactory.java
@@ -9,12 +9,12 @@
 **********************************************************************/
 package org.eclipse.epsilon.executors;
 
-import org.eclipse.epsilon.executors.ecl.EclExecutor;
-import org.eclipse.epsilon.executors.egl.EglExecutor;
-import org.eclipse.epsilon.executors.egl.EgxExecutor;
-import org.eclipse.epsilon.executors.eol.EolExecutor;
-import org.eclipse.epsilon.executors.etl.EtlExecutor;
-import org.eclipse.epsilon.executors.evl.EvlExecutor;
+import org.eclipse.epsilon.executors.ecl.SimpleEclExecutor;
+import org.eclipse.epsilon.executors.egl.SimpleEglExecutor;
+import org.eclipse.epsilon.executors.egl.SimpleEgxExecutor;
+import org.eclipse.epsilon.executors.eol.SimpleEolExecutor;
+import org.eclipse.epsilon.executors.etl.SimpleEtlExecutor;
+import org.eclipse.epsilon.executors.evl.SimpleEvlExecutor;
 
 
 /**
@@ -22,24 +22,25 @@
  * 
  * @author Horacio Hoyos Rodriguez
  */
+@Deprecated
 public class EpsilonEngineExecutorFactory {
 
     @SuppressWarnings("unchecked")
-	public <E extends IEpsilonLanguageExecutor> E getExecutor(String engineName) {
+	public <E extends EpsilonLanguageExecutor> E getExecutor(String engineName) {
 
         switch (engineName.substring(0, 3).toUpperCase()) {
         	case "ECL":
-        		return (E) new EclExecutor();
+        		return (E) new SimpleEclExecutor();
             case "EGL":
-                return (E) new EglExecutor();
+                return (E) new SimpleEglExecutor();
             case "EGX":
-                return (E) new EgxExecutor();
+                return (E) new SimpleEgxExecutor();
             case "EOL":
-                return (E) new EolExecutor();
+                return (E) new SimpleEolExecutor();
             case "ETL":
-                return (E) new EtlExecutor();
+                return (E) new SimpleEtlExecutor();
             case "EVL":
-                return (E) new EvlExecutor();
+                return (E) new SimpleEvlExecutor();
             default:
             	return null;
         }
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonExecutor.java
new file mode 100644
index 0000000..49f6ddf
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonExecutor.java
@@ -0,0 +1,479 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors;
+
+import static org.eclipse.epsilon.common.util.OperatingSystem.getJavaVersion;
+import static org.eclipse.epsilon.common.util.OperatingSystem.getOsNameAndVersion;
+import static org.eclipse.epsilon.common.util.profiling.BenchmarkUtils.getCpuName;
+import static org.eclipse.epsilon.common.util.profiling.BenchmarkUtils.getNumberOfHardwareThreads;
+import static org.eclipse.epsilon.common.util.profiling.BenchmarkUtils.getTime;
+
+import java.nio.file.Path;
+import java.time.Duration;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.dom.NamedRule;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Epsilon Executor is used to run the different Language executors. 
+ * 
+ * @author Horacio Hoyos Rodriguez
+ *
+ */
+public class EpsilonExecutor {
+
+	public static final ExecutionTimeData NO_TIME_DATA = new ExecutionTimeData();
+
+    private static final Logger logger = LoggerFactory.getLogger(EpsilonExecutor.class);
+
+    /**
+     * The Epsilon Module that implements the specific language engine.
+     */
+    private final EpsilonLanguageExecutor<?> languageExecutor;
+    
+    /**
+     * The Script to be executed. Alternatively a block of code can be provided, see {@link #code}
+     */
+    private final Optional<Path> script;
+    
+    /**
+     * The Code to be executed. Alternatively a script file can be provided, see {@link #script}.
+     */
+    private final Optional<String> code;
+    
+    /**
+     * The runtime parameters.
+     */
+    private final Map<String, Object> parameters; // = new HashMap<>(4);
+    
+    /**
+     * The Models used during execution.
+     */
+    private final Set<IModel> models; // = new HashSet<>(4);
+    
+    /**
+     * The Result of the execution. Not all models provide a result.
+     */
+    //private Object result;
+    
+    /**
+     * The Native Type delegates used during execution.
+     */
+    private final Set<IToolNativeTypeDelegate> nativeDelegates; // = new HashSet<>(8);
+
+    /**
+     * The Dispose Models flag indicates if models will be disposed after execution.
+     */
+    private final boolean disposeModels; // = true;
+
+    /**
+     * The Profile Execution flag indicates if the execution should be measured.
+     */
+    private final boolean profileExecution; // = false;
+    
+    
+    private final Optional<ExecutionTimeData> timeData;
+    	
+     	
+	// Constructors with script
+    public EpsilonExecutor(
+        EpsilonLanguageExecutor<?> languageExecutor,
+        Path scriptPath) throws EpsilonExecutorException {
+        this(languageExecutor, scriptPath, Collections.emptySet(), Collections.emptyMap(), Collections.emptySet(), true, false);    
+    }
+    
+    public EpsilonExecutor(
+    	EpsilonLanguageExecutor<?> languageExecutor,
+        Path scriptPath,
+        Collection<IModel> models) throws EpsilonExecutorException {
+        this(languageExecutor, scriptPath, models, Collections.emptyMap(), Collections.emptySet(), true, false);    
+    }
+    
+        
+	public EpsilonExecutor(
+		EpsilonLanguageExecutor<?> languageExecutor,
+	    Path scriptPath,
+        Collection<IModel> models,
+    	Map<String, Object> parameters,
+		Collection<IToolNativeTypeDelegate> nativeDelegates) throws EpsilonExecutorException {
+        this(languageExecutor, scriptPath, models, parameters, nativeDelegates, true, false);    
+    }
+    
+    public EpsilonExecutor(
+    	EpsilonLanguageExecutor<?> languageExecutor,
+        Path scriptPath,
+        Collection<IModel> models,
+    	Map<String, Object> parameters,
+		Collection<IToolNativeTypeDelegate> nativeDelegates,
+        boolean disposeModels,
+        boolean profileExecution) throws EpsilonExecutorException {
+		super();
+		this.languageExecutor = languageExecutor;
+		this.script = Optional.of(scriptPath);
+		this.code = Optional.empty();
+		this.models = new HashSet<>(models);
+		this.parameters = parameters;
+		this.nativeDelegates = new HashSet<>(nativeDelegates);
+		this.disposeModels = disposeModels;
+		this.profileExecution = profileExecution;
+		this.timeData = profileExecution ? Optional.of(new ExecutionTimeData()) : Optional.empty();
+		parseSource();
+	}
+	
+	
+	// Constructors with code
+    public EpsilonExecutor(
+    	EpsilonLanguageExecutor<?> languageExecutor,
+        String code) throws EpsilonExecutorException {
+        this(languageExecutor, code, Collections.emptySet(), Collections.emptyMap(), Collections.emptySet(), true, false);    
+    }
+    
+    public EpsilonExecutor(
+    	EpsilonLanguageExecutor<?> languageExecutor,
+        String code,
+        Collection<IModel> models) throws EpsilonExecutorException {
+        this(languageExecutor, code, models, Collections.emptyMap(), Collections.emptySet(), true, false);    
+    }
+        
+    public EpsilonExecutor(
+    	EpsilonLanguageExecutor<?> languageExecutor,
+        String code,
+        Collection<IModel> models,
+    	Map<String, Object> parameters,
+		Collection<IToolNativeTypeDelegate> nativeDelegates) throws EpsilonExecutorException {
+        this(languageExecutor, code, models, parameters, nativeDelegates, true, false);
+    }
+	
+    public EpsilonExecutor(
+    	EpsilonLanguageExecutor<?> languageExecutor,
+		String code,
+        Collection<IModel> models,
+    	Map<String, Object> parameters,
+		Collection<IToolNativeTypeDelegate> nativeDelegates,
+		boolean disposeModels,
+		boolean profileExecution) throws EpsilonExecutorException {
+		super();
+		this.languageExecutor = languageExecutor;
+		this.script = Optional.empty();
+		this.code = Optional.of(code);
+		parseSource();
+		this.models = new HashSet<>(models);
+		this.parameters = parameters;
+		this.nativeDelegates = new HashSet<>(nativeDelegates);
+		this.disposeModels = disposeModels;
+		this.profileExecution = profileExecution;
+		this.timeData = profileExecution ? Optional.of(new ExecutionTimeData()) : Optional.empty();
+	}
+	   
+    /**
+     * A class that keeps track of the execution durations of the different stages of execution, and
+     * about the execution of the scripts and its rules (if rule based language).
+     * @author Horacio Hoyos Rodriguez
+     *
+     */
+    public static class ExecutionTimeData {
+    	private static String logMessagesSeparator = "-----------------------------------------------------";
+    	private final String osNameAndVersion;
+    	private final String javaVersion;
+    	private final String cpuName;
+    	private final int logicalProcessors;
+    	private final String date;
+		private Long startNanos;
+    	/**
+         * The measured execution information.
+         */
+        private Map<String, Duration> profiledStages = new HashMap<>();
+        private Map<String, Duration> profiledRules = new HashMap<>();
+        private Map<String, Long> started = new HashMap<>();
+		private Duration duration;
+    	
+		ExecutionTimeData() {
+			osNameAndVersion = getOsNameAndVersion();
+			javaVersion = getJavaVersion();
+			cpuName = getCpuName();
+			logicalProcessors = getNumberOfHardwareThreads();
+			date = getTime();
+		}
+		
+		void logStart() {
+			startNanos = System.nanoTime();
+			logger.info(buildLines(
+					osNameAndVersion,
+					javaVersion,
+					cpuName,
+					"Logical processors: " + logicalProcessors,
+					"Starting execution at " + date,
+					logMessagesSeparator
+				));
+		}
+		
+		void logEnd() {
+			long endTimeNanos = System.nanoTime();
+			this.duration = Duration.ofNanos(endTimeNanos-startNanos);
+			logger.info(buildLines("",
+				"Profiled processes:",
+				profiledStages.entrySet().stream().map(e -> String.format("%s:%s", e.getKey(), e.getValue())),
+				"Finished execution at " + getTime(),
+				logMessagesSeparator
+			));
+			logger.info(buildLines("",
+					"Profiled rules:",
+					profiledRules.entrySet().stream().map(e -> String.format("%s:%s", e.getKey(), e.getValue())),
+					logMessagesSeparator
+				));
+			
+		}
+		
+		String buildLines(Object... lines) {
+			StringBuilder linesAsStr = new StringBuilder();
+			String nL = System.lineSeparator();
+			for (Object line : lines) {
+				linesAsStr.append(line).append(nL);
+			}
+			return linesAsStr.toString();
+		}
+		
+		void startStage(String name) {
+			started.put(name, System.nanoTime());
+		}
+		
+		void endStage(String name) {
+			long endTimeNanos = System.nanoTime();
+			Long startTime = started.getOrDefault(name, endTimeNanos);
+			profiledStages.put(name, Duration.ofNanos(endTimeNanos-startTime));
+		}
+		
+		void endModule(EpsilonLanguageExecutor<?> languageExecutor) {
+			Optional<RuleProfiler> ruleProfiler = languageExecutor.getRuleProfiler();
+			if(ruleProfiler.isPresent()) {
+				for (Entry<NamedRule, Duration> entry : ruleProfiler.get().getExecutionTimes().entrySet()) {
+					Duration oldValue = profiledRules.put(entry.getKey().getName(), entry.getValue());
+					if (oldValue != null) {
+						System.err.println("Value for rule " + entry.getKey().getName() + " was replaced.");
+					}
+				}
+			}
+			
+		}
+		
+		/**
+		 * Return the duration of the "prepareExecution" stage. A negative value indicates that the
+		 * stage was not signalled as finished.
+		 * @return
+		 */
+		public Optional<Duration> getPrepareExecutionDuration() {
+			return Optional.ofNullable(profiledStages.get("prepareExecution"));
+		}
+		
+		/**
+		 * Return the duration of the "preProcess" stage. A negative value indicates that the
+		 * stage was not signalled as finished.
+		 * @return
+		 */
+		public Optional<Duration> getPreProcessDuration() {
+			return Optional.ofNullable(profiledStages.get("preProcess"));
+		}
+		
+		/**
+		 * Return the duration of the "postProcess" stage. A negative value indicates that the
+		 * stage was not signalled as finished.
+		 * @return
+		 */
+		public Optional<Duration> getPostProcessDuration() {
+			return Optional.ofNullable(profiledStages.get("postProcess"));
+		}
+		
+		/**
+		 * Return the duration of the Epsilon module execution. A negative value indicates that the
+		 * stage was not signalled as finished.
+		 * @return
+		 */
+		public Optional<Duration> getScrpitExecutionDuration() {
+			return Optional.ofNullable(profiledStages.get("execute"));
+		}
+		
+		public Optional<Duration> getTotalDuration() {
+			return Optional.ofNullable(this.duration);
+		}
+		
+		public Optional<Duration> getRuleDuration(String name) {
+			return Optional.ofNullable(profiledRules.get(name));
+		}
+		
+		public Iterator<Entry<String, Duration>> getRulesDurations() {
+			return profiledRules.entrySet().iterator();
+		}
+		
+		
+    }
+    
+    
+	public Optional<ExecutionTimeData> getExecutionTimeData() {
+		return timeData;
+	}
+ 
+    /**
+     * Create a Runnable so the executor can be executed in a thread. Internally the
+     * {@link #invoqueExecutor()} is called. Any exceptions will be wrapped inside a
+     * {@link RuntimeException}.
+     */
+    public <T> Runnable executeInThread() {
+    	class OneShotTask implements Runnable {
+    		private T result;
+            public void run() {
+            	try {
+					result = invoqueExecutor();
+				} catch (EpsilonExecutorException e) {
+					throw new RuntimeException(e);
+				}
+            }
+            @SuppressWarnings("unused")
+			public T getResult() { return result;}
+        }
+		return new OneShotTask();
+    }
+    
+    /**
+     * Execute the specific executor by executing all the execution stages.
+     * @param executor
+     * @return
+     * @throws EpsilonExecutorException
+     */
+    public <R> R invoqueExecutor() throws EpsilonExecutorException {
+        logger.info("Executing engine.");
+        preProfile();
+        prepareExecution();
+        logger.info("Pre-process execution");
+        timeData.ifPresent(td -> td.startStage("preProcess"));
+        languageExecutor.preProcess();
+        R result;
+        if (profileExecution) {
+    		timeData.ifPresent(td -> td.endStage("preProcess"));
+        }
+        try {
+        	if (profileExecution) {
+        		timeData.ifPresent(td -> td.startStage("execute"));
+            }
+            result = (R) languageExecutor.execute();
+        }
+        catch (EolRuntimeException e) {
+        	String msg = "Error executing the module.";
+            logger.error(msg, e);
+            throw new EpsilonExecutorException(msg, e);
+        }
+        finally {
+        	if (profileExecution) {
+        		timeData.ifPresent(td -> td.endStage("execute"));
+            }
+        }
+        logger.info("Post-process execution.");
+        if (profileExecution) {
+    		timeData.ifPresent(td -> td.startStage("postProcess"));
+        }
+        languageExecutor.postProcess();
+        if (profileExecution) {
+    		timeData.ifPresent(td -> td.endStage("postProcess"));
+        }
+        
+        if (profileExecution) {
+        	timeData.ifPresent(td -> td.endModule(languageExecutor));
+        	timeData.ifPresent(td -> td.logEnd());
+        }
+        return result;
+	}
+    
+    /**
+     * Disposes the executor. Implementing classes should perform any clean actions.
+     * This method should be invoked after execute.
+     * It is not invoked automatically because in some cases the user may need
+     * to access execution information that is still in the executor's context.
+     * The disposeModels flag determines if the models used by the module are also
+     * disposed (default true).
+     */
+    public void dispose() {
+        if (disposeModels) {
+            logger.info("Disposing models");
+            languageExecutor.disposeModelRepository();
+        }
+        else {
+            logger.info("Removing models from context models");
+            languageExecutor.clearModelRepository();
+        }
+        models.clear();
+        parameters.clear();
+        logger.info("Dispose context");
+        languageExecutor.dispose();
+    }
+    
+    private void preProfile() {
+    	timeData.ifPresent(ExecutionTimeData::logStart);
+    }
+    
+    private void prepareExecution() throws EpsilonExecutorException {
+    	if (!(script.isPresent() || code.isPresent())) {
+    		throw new EpsilonExecutorException("No script or code to execute");
+    	}
+    	timeData.ifPresent(ei -> ei.startStage("prepareExecution"));
+        logger.info("Adding models to executor");
+		languageExecutor.addModels(models);
+		logger.info("Adding parameters to context.");
+		languageExecutor.addParamters(parameters);
+
+		logger.info("Adding Native Type Delegates");
+		languageExecutor.addNativeTypeDelegates(nativeDelegates);
+		if (profileExecution) {
+    		timeData.ifPresent(td -> td.endStage("prepareExecution"));
+        }
+    }
+    
+	//  public Object getResult() {
+	//  return result;
+	//}
+	
+	private void parseSource() throws EpsilonExecutorException {
+		// Think this should be part of constructor, so object is correct at construction
+	  try {
+	  	if (script.isPresent()) {
+	  		languageExecutor.parse(script.get().toFile());
+	      }
+	      else {
+	      	languageExecutor.parse(code.get());
+	      }
+	  }
+	  catch (Exception e) {
+	  	String culprit = script.isPresent() ? "script" : "code";
+	      logger.error("Failed to parse provided {}", culprit, e);
+	      throw new EpsilonExecutorException("Failed to parse script or code", e);
+	  }
+	  if (!languageExecutor.getParseProblems().isEmpty()) {
+	      logger.error("Parse errors occurred");
+			System.err.println("Parse errors occurred...");
+			for (ParseProblem problem : languageExecutor.getParseProblems()) {
+				System.err.println(problem);
+			}
+	      throw new EpsilonExecutorException("Parse errors occurred.");
+		}
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonLanguageExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonLanguageExecutor.java
new file mode 100644
index 0000000..d03b2cd
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/EpsilonLanguageExecutor.java
@@ -0,0 +1,77 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+
+/**
+ * The IEpsilonLanguageExecutor defines a common executor API that the different Epsilon languages 
+ * can use to facilitate running Epsilon scripts in standalone applications.
+ * <p>
+ * The API provides 4 phases to the execution of an Epsilon Module: {@link #preProcess}, {@link #execute},
+ * {@link #postProcess}, and {@link #dispose}.
+ * The 4 phases should provide enough flexibility for specific executors to correctly prepare
+ * execution, execute, do any post execution processing and finally dispose the executor.
+ *
+ * @author Horacio Hoyos Rodriguez
+ *
+ */
+public interface EpsilonLanguageExecutor<R> {
+
+	// Methods to interact with the underlying module
+	boolean parse(File file) throws Exception;
+	
+	// boolean parse(URI uri) throws Exception;
+	
+	boolean parse(String code) throws Exception;
+	
+	List<ParseProblem> getParseProblems();
+	
+	void addModels(Collection<IModel> models);
+	
+	void addParamters(final Map<String, ?> parameters);
+	
+	void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates);
+	
+	Optional<RuleProfiler> getRuleProfiler();
+
+	void disposeModelRepository();
+
+	void clearModelRepository();
+
+	void dispose();
+
+    /**
+     * This method will be invoked before execution of the script
+     */
+    void preProcess();
+    
+    /**
+     * This method will be invoked after execution of the script
+     */
+    void postProcess();
+
+    /**
+     * Execute the provided script, against the list of models using the executor's module.
+     * @throws EpsilonExecutorException
+     */
+    R execute() throws EolRuntimeException;
+   
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ExecutorHelper.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ExecutorHelper.java
new file mode 100644
index 0000000..49838b1
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ExecutorHelper.java
@@ -0,0 +1,89 @@
+package org.eclipse.epsilon.executors;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.IEolModule;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.IErlModule;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+
+public class ExecutorHelper implements EpsilonLanguageExecutor<Object> {
+
+	final IEolModule module;
+	
+	public ExecutorHelper(IEolModule module) {
+		this.module = module;
+	}
+
+	@Override
+	public boolean parse(File file) throws Exception {
+		return module.parse(file);
+	}
+
+	@Override
+	public boolean parse(String code) throws Exception {
+		return module.parse(code);
+	}
+
+	@Override
+	public List<ParseProblem> getParseProblems() {
+		return module.getParseProblems();
+	}
+
+	@Override
+	public void addModels(Collection<IModel> models) {
+		this.module.getContext().getModelRepository().addModels(models.toArray(new IModel[0]));
+	}
+
+	@Override
+	public void addParamters(Map<String, ?> parameters) {
+		this.module.getContext().getFrameStack().put(parameters, true);
+	}
+
+	@Override
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		this.module.getContext().getNativeTypeDelegates().addAll(nativeDelegates);
+	}
+
+	@Override
+	public Optional<RuleProfiler> getRuleProfiler() {
+		if (module instanceof IErlModule) {
+			return Optional.of(((IErlModule)module).getContext().getExecutorFactory().getRuleProfiler());
+		}
+		return Optional.empty();
+	}
+
+	@Override
+	public void disposeModelRepository() {
+		module.getContext().getModelRepository().dispose();
+	}
+
+	@Override
+	public void clearModelRepository() {
+		module.getContext().getModelRepository().getModels().clear();
+	}
+
+	@Override
+	public void dispose() {
+		module.getContext().dispose();
+	}
+
+	@Override
+	public void preProcess() { }
+	
+	@Override
+	public void postProcess() { }
+
+	@Override
+	public Object execute() throws EolRuntimeException {
+		throw new RuntimeException("The ExecutorHelper does not support the execute method.");
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/IEpsilonLanguageExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/IEpsilonLanguageExecutor.java
deleted file mode 100644
index 7a99d28..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/IEpsilonLanguageExecutor.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors;
-
-import org.eclipse.epsilon.common.util.profiling.ProfileDiagnostic;
-import org.eclipse.epsilon.eol.IEolModule;
-import org.eclipse.epsilon.eol.models.IModel;
-import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor.ExecutionInfo;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * The IEpsilonLanguageExecutor defines a common executor API that the different Epsilon languages 
- * can use to facilitate running Epsilon script in standalone applications.
- * The API allows adding the source script/code, models used for execution, and any parameters and
- * native delegates that should be accessible during execution.
- * <p>
- * The API provides 4 phases to the execution of an Epsilon Module: preProcess, execute,
- * postProcess, and dispose.
- * The 4 phases should provide enough flexibility for specific executors to correctly prepare
- * execution, execute, do any post execution processing and finally dispose the executor.
- *
- * @author Horacio Hoyos Rodriguez
- *
- */
-public interface IEpsilonLanguageExecutor extends Runnable {
-
-    /**
-     * Get the Dispose Models Flag
-     * @return the value of the Dispose Models Flag
-     */
-    boolean isDisposeModels();
-
-    /**
-     * Set the value of the Dispose Models Flag
-     * @param disposeModels
-     */
-    void setDisposeModels(boolean disposeModels);
-
-    /**
-     * Whether profiling of execution times is enabled.
-     * @return The value of the flag.
-     */
-    boolean isProfilingEnabled();
-    
-    /**
-     * Enables or disables profiling of execution times based on the flag.
-     * @param profileExecution The value of the flag.
-     */
-    void setProfilingEnabled(boolean profileExecution);
-    
-    /**
-     * Get the ExecutionInfo for the current module.
-     * @return
-     */
-    ExecutionInfo getExecutionInfo();
-    
-    /**
-     * The module used by the executor
-     * @return
-     */
-    IEolModule getModule();
-
-    /**
-     * Get a human readable name of the executor
-     * @return The name of the executor
-     */
-    String getName();
-
-    /**
-     * Get the code being executed.
-     * @return
-     */
-    String getCode();
-
-    /**
-     * Provive the code to execute as a string
-     * @param code A String containing the code to execute
-     */
-    void setCode(String code);
-
-    /**
-     * Assign script to execute.
-     *
-     * @param script the path to the script
-     */
-    void setScript(Path script);
-    
-    default void setScript(String scriptPath) {
-    	setScript(Paths.get(scriptPath));
-    }
-
-    /**
-     * Get the script assigned to the executor
-     * @return
-     */
-    Path getScript();
-
-    /**
-     * Returns an unmodifiable view of the models used by the executor.
-     *
-     * @return a view of the list of models
-     */
-    Set<IModel> getModels();
-
-    /**
-     * Add a model to the executor. Models added to the executor should already
-     * be loaded (@link IModel.load())
-     *
-     * @param model the model.
-     * @return <code>true</code> if the model could be added.
-     */
-    boolean addModel(IModel model);
-
-    default boolean addModels(IModel... models) {
-    	boolean result = models != null;
-    	if (result) for (IModel model : models) {
-    		result &= addModel(model);
-    	}
-    	return result;
-    }
-    
-    /**
-     * Adds all of the models in the specified collection to this executor. Models
-     * added to the executor should already be loaded (@link IModel.load())
-     *
-     * @param models the models to add.
-     * @return
-     * @throws EpsilonExecutorException
-     */
-    default boolean addModels(Collection<IModel> models) {
-    	boolean result = models != null;
-    	if (result) for (IModel model : models) {
-    		result &= addModel(model);
-    	}
-    	return result;
-    }
-
-    /**
-     * Remove a model from the executor.
-     *
-     * @param model
-     * @return
-     */
-    boolean removeModel(IModel model);
-
-    default boolean removeModels(IModel... models) {
-    	boolean result = models != null;
-    	if (result) for (IModel model : models) {
-    		result &= removeModel(model);
-    	}
-    	return result;
-    }
-    
-    /**
-     * Removes from this executor all of its models that are contained in the specified
-     * collection.
-     * @param models
-     * @return
-     */
-    default boolean removeModels(Collection<IModel> models) {
-    	boolean result = models != null;
-    	if (result) for (IModel model : models) {
-    		result &= removeModel(model);
-    	}
-    	return result;
-    }
-
-    /**
-     * Get the result of the execution
-     * @return
-     */
-    Object getResult();
-
-    /**
-     * This method will be invoked before execution of the script
-     */
-    default void preProcess() {
-    	
-    }
-    
-    /**
-     * This method will be invoked after execution of the script
-     */
-    default void postProcess() {
-    	
-    }
-
-    /**
-     * Execute the provided script, against the list of models using the executor's module.
-     * @throws EpsilonExecutorException
-     */
-    void execute() throws EpsilonExecutorException;
-
-    /**
-     * Same as {@link #execute()} without checked exception. 
-     * @throws RuntimeException A wrapped {@linkplain EpsilonExecutorException}
-     */
-    @Override
-    default void run() throws RuntimeException {
-    	try {
-    		execute();
-    	}
-    	catch (EpsilonExecutorException ex) {
-    		throw new RuntimeException(ex);
-    	}
-    }
-    
-    /**
-     * Disposes the executor. Implementing classes should perform any clean actions.
-     * This method should be invoked after execute.
-     * It is not invoked automatically because in some cases the user may need
-     * to access execution information that is still in the executor's context.
-     * The disposeModels flag determines if the models used by the module are also
-     * disposed (default true).
-     */
-    void dispose();
-
-    /**
-     * Returns an unmodifiable view of the parameters used by the executor
-     * @return the parameters
-     */
-    Map<String, ?> getParameters();
-
-    /**
-     * Add a parameter to the executor. Parameters are used to provide additional
-     * information to the execution. In an Eclipse launch configuration these are
-     * defined in the parameters tab.
-     *
-     * The {@link org.eclipse.epsilon.executors.util.ParameterUtil} provides
-     * an API to facilitate creation of parameters.
-     * @param name the parameter name
-     * @param value the parameter value
-     */
-    boolean addParameter(String name, Object value);
-
-    /**
-     * Add a collection of parameters to the executor.
-     * @param parameters the parameters
-     * @see #addParameter(String, Object)
-     */
-    void addParameters(Map<String, Object> parameters);
-
-    /**
-     * Remove a parameter from the executor
-     * @param parameter the parameter name
-     * @see #addParameter(String, Object)
-     */
-    boolean removeParameter(String parameter);
-
-    /**
-     * Remove a collection of parameters from the executor.
-     * @param parameters the parameters
-     * @see #addParameter(String, Object)
-     */
-    default void removeParameters(Collection<String> parameters) {
-    	parameters.forEach(this::removeParameter);
-    }
-
-    /**
-     * Return an unmodifiable view of the Native Type Delegates used by the executor
-     * @return
-     */
-    Set<IToolNativeTypeDelegate> getNativeDelegates();
-
-    /**
-     * Add Native Type Delegates to the executor
-     * @param delegates A collection of IToolNativeTypeDelegate to add
-     * @return
-     */
-    boolean addNativeDelegates(Collection<IToolNativeTypeDelegate> delegates);
-
-    /**
-     * Add a Native Type Delegates to the executor
-     * @param delegate The IToolNativeTypeDelegate to add
-     * @return
-     */
-    boolean addNativeDelegate(IToolNativeTypeDelegate delegate);
-
-    /**
-     * Remove Native Type Delegates from the executor
-     * @param delegates  A collection of IToolNativeTypeDelegate to remove
-     * @return
-     */
-    boolean removeNativeDelegates(Collection<IToolNativeTypeDelegate> delegates);
-
-    /**
-     * Remove a Native Type Delegate from the executor
-     * @param delegate The IToolNativeTypeDelegate to remove
-     * @return
-     */
-    boolean removeNativeDelegate(IToolNativeTypeDelegate delegate);
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/EclExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/EclExecutor.java
deleted file mode 100644
index 199de60..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/EclExecutor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.ecl;
-
-import org.eclipse.epsilon.ecl.EclModule;
-import org.eclipse.epsilon.ecl.IEclModule;
-import org.eclipse.epsilon.ecl.trace.MatchTrace;
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 
- *
- * @author Sina Madani
- * @since 1.6
- */
-public class EclExecutor extends AbstractLanguageExecutor implements IEclExecutor {
-
-	static final Logger logger = LoggerFactory.getLogger(EclExecutor.class);
-	
-	public EclExecutor() {
-		this(new EclModule());
-	}
-	
-	public EclExecutor(IEclModule module) {
-		super(module);
-		 logger.info("Creating the EclStandaloneEngine");
-	}
-
-	@Override
-	protected MatchTrace executeInternal() throws EolRuntimeException {
-		logger.info("Executing ECL script.");
-        return getModule().execute();
-	}
-
-	@Override
-	public MatchTrace getResult() {
-		return (MatchTrace) result;
-	}
-	
-	@Override
-	public IEclModule getModule() {
-		return (IEclModule) module;
-	}
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/IEclExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/IEclExecutor.java
deleted file mode 100644
index 0bab31f..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/IEclExecutor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.ecl;
-
-import org.eclipse.epsilon.ecl.IEclModule;
-import org.eclipse.epsilon.ecl.trace.MatchTrace;
-import org.eclipse.epsilon.executors.IEpsilonLanguageExecutor;
-
-/**
- * 
- *
- * @author Sina Madani
- * @since 1.6
- */
-public interface IEclExecutor extends IEpsilonLanguageExecutor {
-
-	@Override
-	IEclModule getModule();
-	
-	@Override
-	MatchTrace getResult();
-	
-	default MatchTrace getMatchTrace() {
-		return getResult();
-	}
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/SimpleEclExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/SimpleEclExecutor.java
new file mode 100644
index 0000000..0e77742
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/ecl/SimpleEclExecutor.java
@@ -0,0 +1,106 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.ecl;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.ecl.EclModule;
+import org.eclipse.epsilon.ecl.IEclModule;
+import org.eclipse.epsilon.ecl.trace.MatchTrace;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The ECL executor
+ * @author Sina Madani
+ * @since 1.6
+ */
+public class SimpleEclExecutor implements EpsilonLanguageExecutor<MatchTrace> {
+
+	static final Logger logger = LoggerFactory.getLogger(SimpleEclExecutor.class);
+	private final IEclModule module;
+	private final ExecutorHelper helper;
+	
+	public SimpleEclExecutor() {
+		this(new EclModule());
+	}
+	
+	public SimpleEclExecutor(IEclModule mdl) {
+		logger.info("Creating the EclExecutor");
+		module = mdl;
+		helper = new ExecutorHelper(module);
+	}
+
+	@Override
+	public MatchTrace execute() throws EolRuntimeException {
+		logger.info("Executing ECL module.");
+        return module.execute();
+	}
+
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	public void dispose() {
+		helper.dispose();
+	}
+
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	public void postProcess() {
+		helper.postProcess();
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/EglExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/EglExecutor.java
deleted file mode 100644
index 769cff3..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/EglExecutor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.egl;
-
-import org.eclipse.epsilon.egl.EglTemplateFactory;
-import org.eclipse.epsilon.egl.EglTemplateFactoryModuleAdapter;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor;
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The EGL executor
- * @author Horacio Hoyos Rodriguez
- */
-public class EglExecutor extends AbstractLanguageExecutor {
-
-	private static final Logger logger = LoggerFactory.getLogger(EglExecutor.class);
-
-	public EglExecutor() {
-        super(new EglTemplateFactoryModuleAdapter(new EglTemplateFactory()));
-		logger.info("Creating the EglStandaloneEngine");
-    }
-
-	@Override
-	public void postProcess() {
-		System.out.println(result);
-	}
-
-	@Override
-	protected String executeInternal() throws EolRuntimeException {
-		logger.info("Executing EGL template.");
-		return (String) getModule().execute();
-	}
-
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/EgxExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/EgxExecutor.java
deleted file mode 100644
index 76e52ee..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/EgxExecutor.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.egl;
-
-import org.eclipse.epsilon.egl.EglTemplateFactory;
-import org.eclipse.epsilon.egl.EgxModule;
-import org.eclipse.epsilon.egl.IEgxModule;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor;
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The EGX executor
- * @author Horacio Hoyos Rodriguez
- */
-public class EgxExecutor extends AbstractLanguageExecutor implements IEgxExecutor {
-
-	private static final Logger logger = LoggerFactory.getLogger(EgxExecutor.class);
-
-	public EgxExecutor() {
-		this(new EgxModule(new EglTemplateFactory()));
-	}
-	
-	public EgxExecutor(IEgxModule module) {
-        super(module);
-		logger.info("Creating the EgxStandaloneEngine");
-    }
-
-	@Override
-	protected Object executeInternal() throws EolRuntimeException {
-		logger.info("Executing EGX Script.");
-		return module.execute();
-	}
-
-	@Override
-	public IEgxModule getModule() {
-		return (IEgxModule) super.getModule();
-	}
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/IEgxExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/IEgxExecutor.java
deleted file mode 100644
index 4fb0c79..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/IEgxExecutor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.egl;
-
-import org.eclipse.epsilon.egl.IEgxModule;
-import org.eclipse.epsilon.executors.IEpsilonLanguageExecutor;
-
-/**
- * 
- *
- * @author Sina Madani
- * @since 1.6
- */
-public interface IEgxExecutor extends IEpsilonLanguageExecutor {
-
-	@Override
-	IEgxModule getModule();
-	
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/SimpleEglExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/SimpleEglExecutor.java
new file mode 100644
index 0000000..66e12e2
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/SimpleEglExecutor.java
@@ -0,0 +1,121 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.egl;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.egl.EglTemplateFactory;
+import org.eclipse.epsilon.egl.EglTemplateFactoryModuleAdapter;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The EGL executor
+ * @author Horacio Hoyos Rodriguez
+ */
+public class SimpleEglExecutor implements EpsilonLanguageExecutor<Optional<String>> {
+
+	private static final Logger logger = LoggerFactory.getLogger(SimpleEglExecutor.class);
+	private EglTemplateFactoryModuleAdapter module;
+	private ExecutorHelper helper;
+
+	public SimpleEglExecutor() {
+		this(new EglTemplateFactoryModuleAdapter(new EglTemplateFactory()));
+    }
+
+	public SimpleEglExecutor(EglTemplateFactory templateFactory) {
+		this(new EglTemplateFactoryModuleAdapter(templateFactory));
+	}
+	
+	public SimpleEglExecutor(EglTemplateFactoryModuleAdapter mdl) {
+		logger.info("Creating the EglExecutor");
+		module = mdl;
+    	helper = new ExecutorHelper(module);
+	}
+	
+	@Override
+	public Optional<String> execute() throws EolRuntimeException {
+		logger.info("Executing current EGL template.");
+		String r = (String) ((EglTemplateFactoryModuleAdapter)module).execute();
+		return Optional.ofNullable(r);
+	}
+
+	@Override
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	@Override
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	@Override
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	@Override
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	@Override
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	@Override
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	@Override
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	@Override
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	@Override
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	@Override
+	public void dispose() {
+		helper.dispose();
+	}
+
+	@Override
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	@Override
+	public void postProcess() {
+		helper.postProcess();
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/SimpleEgxExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/SimpleEgxExecutor.java
new file mode 100644
index 0000000..94616cd
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/egl/SimpleEgxExecutor.java
@@ -0,0 +1,109 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.egl;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.egl.EglTemplateFactory;
+import org.eclipse.epsilon.egl.EgxModule;
+import org.eclipse.epsilon.egl.IEgxModule;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The EGX executor
+ * @author Horacio Hoyos Rodriguez
+ */
+public class SimpleEgxExecutor implements EpsilonLanguageExecutor<Object> {
+
+	private static final Logger logger = LoggerFactory.getLogger(SimpleEgxExecutor.class);
+	private IEgxModule module;
+	private ExecutorHelper helper;
+	
+	public SimpleEgxExecutor() {
+		this(new EgxModule());
+	}
+	
+	public SimpleEgxExecutor(EglTemplateFactory templateFactory) {
+		this(new EgxModule(templateFactory));
+	}
+	
+	public SimpleEgxExecutor(IEgxModule mdl) {
+		logger.info("Creating the EgxExecutor");
+		module = mdl;
+		helper = new ExecutorHelper(module);
+	}
+	
+	@Override
+	public Object execute() throws EolRuntimeException {
+		logger.info("Executing EGX Script.");
+		return module.execute();
+	}
+
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	public void dispose() {
+		helper.dispose();
+	}
+
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	public void postProcess() {
+		helper.postProcess();
+	}
+	
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eml/EmlTraces.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eml/EmlTraces.java
new file mode 100644
index 0000000..01026f3
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eml/EmlTraces.java
@@ -0,0 +1,38 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.eml;
+
+import org.eclipse.epsilon.ecl.trace.MatchTrace;
+import org.eclipse.epsilon.eml.trace.MergeTrace;
+
+/**
+ * A helper class to hold the EML results
+ * @author Horacio Hoyos
+ *
+ */
+public class EmlTraces {
+	
+	private final MatchTrace matchTrace;
+	private final MergeTrace mergeTrace;
+
+	public EmlTraces(MatchTrace matchTrace, MergeTrace mergeTrace) {
+		this.matchTrace = matchTrace;
+		this.mergeTrace = mergeTrace;
+	}
+
+	public MatchTrace getMatchTrace() {
+		return matchTrace;
+	}
+
+	public MergeTrace getMergeTrace() {
+		return mergeTrace;
+	}
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eml/SimpleEmlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eml/SimpleEmlExecutor.java
new file mode 100644
index 0000000..fe93484
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eml/SimpleEmlExecutor.java
@@ -0,0 +1,112 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.eml;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eml.execute.context.EmlContext;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.etl.EtlModule;
+import org.eclipse.epsilon.etl.IEtlModule;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The EML executor
+ *
+ * @author Horacio Hoyos Rodriguez
+ */
+public class SimpleEmlExecutor implements EpsilonLanguageExecutor<EmlTraces> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SimpleEmlExecutor.class);
+	private IEtlModule module;
+	private ExecutorHelper helper;
+	
+    public SimpleEmlExecutor() {
+    	this(new EtlModule());
+    }
+    
+    public SimpleEmlExecutor(IEtlModule mdl) {
+    	logger.info("Creating the EtlExecutor");
+    	module = mdl;
+    	helper = new ExecutorHelper(module);
+    }
+    
+	@Override
+	public EmlTraces execute() throws EolRuntimeException {
+		module.execute();
+		EmlContext c = (EmlContext) module.getContext();
+		return new EmlTraces(c.getMatchTrace(), c.getMergeTrace());
+	}
+
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	public void dispose() {
+		helper.dispose();
+	}
+
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	public void postProcess() {
+		helper.postProcess();
+	}
+
+	public boolean equals(Object obj) {
+		return helper.equals(obj);
+	}
+
+
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/EolExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/EolExecutor.java
index 2b0e171..73c0a5f 100644
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/EolExecutor.java
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/EolExecutor.java
@@ -9,80 +9,41 @@
 **********************************************************************/
 package org.eclipse.epsilon.executors.eol;
 
-import java.util.Collections;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
 import java.util.List;
-import org.eclipse.epsilon.eol.IEolModule;
-import org.eclipse.epsilon.eol.concurrent.EolModuleParallel;
-import org.eclipse.epsilon.eol.dom.Operation;
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
- * The EOL executor
- *
- * By default the complete EOL script is executed. Alternatively, a specific operation can be
- * invoked by setting the desired operationName name (see {@link #setOperationName(String)}).
- *
- * Additionally, the {@link #setOperationArguments(List)} method can be used to provide a list of
- * arguments to use for invocation of the operation. The arguments are considered to be in the same
- * order and of the correct type of the operation signature.
+ * The IEolExecutor API provides additional methods to invoke a single operation inside an EOL 
+ * script. The desired operation can be set using {@link #setOperationName(String)} and any 
+ * required parameters for the operation passed via {@link #setOperationArguments(List)}. Setting
+ * the operation name with a non-empty string will set the execution mode to {@link EolMode#OPERATION}.
+ * Executing in {@link EolMode#OPERATION} without previously setting the operation name
+ * (via {@link #setOperationName(String)} will result in an {@link EolRuntimeException}.
+ * 
+ * Setting the operation name to an empty string will result in the execution mode to change to 
+ * {@link EolMode#SCRIPT}. Alternatively the {@link #setMode(EolMode)} method can be used to
+ * change the execution mode.
  *
  * @author Horacio Hoyos Rodriguez
+ *
  */
-public class EolExecutor extends AbstractLanguageExecutor implements IEolExecutor  {
+public interface EolExecutor extends EpsilonLanguageExecutor<Object> {
 
-	private static final Logger logger = LoggerFactory.getLogger(EolExecutor.class);
-
-	private String operationName = "";
-	private List<Object> arguments = Collections.emptyList();
-	private EolMode mode = EolMode.COMPLETE;
-
-	public EolExecutor() {
-		this(new EolModuleParallel());
+	public static enum EolMode {
+		SCRIPT,
+		OPERATION
 	}
+
+    /**
+     * Set the operation name to invoke and any parameters to pass to the operation being invoked.
+     * @param arguments
+     */
+	SimpleEolExecutor changeOperation(String operationName, List<Object> arguments);
 	
-	public EolExecutor(IEolModule module) {
-		super(module);
-		logger.info("Creating the EolStandaloneEngine");
-	}
-	
-	@Override
-	protected Object executeInternal() throws EolRuntimeException {
-		switch(mode) {
-			case COMPLETE:
-				logger.info("Executing complete EOL script.");
-				return module.execute();	
-			case OPERATION:
-				if (operationName.length() == 0) {
-					throw new EolRuntimeException("Can not invoke executor in OPERATION mode without an operation name assigned.");
-				}
-				logger.info("Executing EOL operation {} with arguments: {}.", operationName, arguments);
-				Operation operation = module.getDeclaredOperations().getOperation(operationName);
-				return operation.execute(null, arguments, module.getContext());
-		}
-		return null;
-	}
-
-	@Override
-	public void setOperationName(String operationName) {
-		this.operationName = operationName;
-		if (operationName.length() > 0) {
-			this.mode = EolMode.OPERATION;
-		}
-		else {
-			this.mode = EolMode.COMPLETE;
-		}
-	}
-
-	@Override
-	public void setOperationArguments(List<Object> arguments) {
-		this.arguments = arguments;
-	}
-
-	@Override
-	public void setMode(EolMode mode) {
-		this.mode = mode;
-	}
+	/**
+     * Set the operation name to invoke. This method can be used for operations with no parameters.
+     * @param arguments
+     */
+	SimpleEolExecutor changeOperation(String operationName);
+    
 }
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/IEolExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/IEolExecutor.java
deleted file mode 100644
index 086e5f2..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/IEolExecutor.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.eol;
-
-import org.eclipse.epsilon.executors.IEpsilonLanguageExecutor;
-import java.util.List;
-
-/**
- * The IEolExecutor API provides additional methods to invoke a single operation inside an EOL 
- * script. The desired operation can be set using {@link #setOperationName(String)} and any 
- * required parameters for the operation passed via {@link #setOperationArguments(List)}. Setting
- * the operation name with a non-empty string will set the execution mode to {@link EolMode#OPERATION}.
- * Executing in {@link EolMode#OPERATION} without previously setting the operation name
- * (via {@link #setOperationName(String)} will result in an {@link EolRuntimeException}.
- * 
- * Setting the operation name to an empty string will result in the execution mode to change to 
- * {@link EolMode#COMPLETE}. Alternatively the {@link #setMode(EolMode)} method can be used to
- * change the execution mode.
- *
- * @author Horacio Hoyos Rodriguez
- *
- */
-public interface IEolExecutor extends IEpsilonLanguageExecutor {
-
-	public static enum EolMode {
-		COMPLETE,
-		OPERATION
-	}
-
-    /**
-     * Set the operation name to invoke. Arguments to invoke the operation
-     * can be provided via {@link #setOperationArguments(List)}
-     *
-     * @param operationName the operation name
-     */
-    void setOperationName(String operationName);
-
-    /**
-     * Set any parameters to pass to the operation being invoked. The operation
-     *
-     * @param arguments
-     */
-    void setOperationArguments(List<Object> arguments);
-    
-    /**
-     * Set the executor to "complete script mode", where the whole script as opposed to a single
-     * operation is run.
-     * <p>
-     * If the mode is set to {@link EolMode#OPERATION} and no operation name has been set
-     */
-    void setMode(EolMode mode);
-    
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/SimpleEolExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/SimpleEolExecutor.java
new file mode 100644
index 0000000..725d573
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/eol/SimpleEolExecutor.java
@@ -0,0 +1,153 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.eol;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.IEolModule;
+import org.eclipse.epsilon.eol.concurrent.EolModuleParallel;
+import org.eclipse.epsilon.eol.dom.Operation;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The EOL executor
+ *
+ * By default the complete EOL script is executed. Alternatively, a specific operation can be
+ * invoked by setting the desired operationName name (see {@link #setOperationName(String)}).
+ *
+ * Additionally, the {@link #setOperationArguments(List)} method can be used to provide a list of
+ * arguments to use for invocation of the operation. The arguments are considered to be in the same
+ * order and of the correct type of the operation signature.
+ *
+ * @author Horacio Hoyos Rodriguez
+ */
+public class SimpleEolExecutor implements EolExecutor  {
+
+	private static final Logger logger = LoggerFactory.getLogger(SimpleEolExecutor.class);
+
+	private final Optional<String> operationName;
+	private final List<Object> arguments;
+	private final EolMode mode;
+	private IEolModule module;
+	private ExecutorHelper helper;
+	
+	public SimpleEolExecutor() {
+		this(null, Collections.emptyList());
+	}
+	
+	public SimpleEolExecutor(IEolModule mdl) {
+		this(null, Collections.emptyList(), mdl);
+	}
+	
+	public SimpleEolExecutor(String oprtnNm, List<Object> arguments) {
+		this(oprtnNm, arguments, 1);
+	}
+	
+	public SimpleEolExecutor(String oprtnNm, List<Object> argmnts, int nmbrThrds) {
+		this(oprtnNm, argmnts, new EolModuleParallel(nmbrThrds));
+	}
+	
+	public SimpleEolExecutor(String oprtnNm, List<Object> argmnts, IEolModule mdl) {
+		operationName = Optional.ofNullable(oprtnNm);
+		mode = operationName.isPresent() ? EolMode.OPERATION : EolMode.SCRIPT;
+		arguments = argmnts;
+		module = mdl;
+		helper = new ExecutorHelper(module);
+	}
+
+	@Override
+	public Object execute() throws EolRuntimeException {
+		switch(mode) {
+			case SCRIPT:
+				logger.info("Executing complete EOL script.");
+				return module.execute();	
+			case OPERATION:
+				Operation operation = module
+						.getDeclaredOperations()
+						.getOperation(operationName.orElseThrow(() -> new EolRuntimeException("Can not invoke executor in OPERATION mode without an operation name assigned.")));
+				logger.info("Executing EOL operation {} with arguments: {}.", operationName, arguments);
+				return operation.execute(null, arguments, module.getContext());
+		}
+		return null;
+	}
+
+	@Override
+	public SimpleEolExecutor changeOperation(String operationName, List<Object> arguments) {
+		return new SimpleEolExecutor(operationName, arguments);
+	}
+	
+	@Override
+	public SimpleEolExecutor changeOperation(String operationName) {
+		return new SimpleEolExecutor(operationName, Collections.emptyList());
+	}
+
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	public void dispose() {
+		helper.dispose();
+	}
+
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	public void postProcess() {
+		helper.postProcess();
+	}
+	
+	
+
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/EtlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/EtlExecutor.java
deleted file mode 100644
index fd6db40..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/EtlExecutor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.etl;
-
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.eclipse.epsilon.etl.EtlModule;
-import org.eclipse.epsilon.etl.IEtlModule;
-import org.eclipse.epsilon.etl.trace.TransformationTrace;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The ETL executor
- *
- * @author Horacio Hoyos Rodriguez
- */
-public class EtlExecutor extends AbstractLanguageExecutor implements IEtlExecutor {
-
-    private static final Logger logger = LoggerFactory.getLogger(EtlExecutor.class);
-
-    public EtlExecutor() {
-    	this(new EtlModule());
-    }
-    
-    public EtlExecutor(IEtlModule module) {
-        super(module);
-        logger.info("Creating the EvlStandaloneEngine");
-    }
-
-    @Override
-	public IEtlModule getModule() {
-		return (IEtlModule) super.getModule();
-	}
-
-	@Override
-    protected TransformationTrace executeInternal() throws EolRuntimeException {
-        logger.info("Executing ETL script.");
-        return (TransformationTrace) getModule().execute();
-    }
-
-    @Override
-    public TransformationTrace getResult() {
-        return (TransformationTrace) super.getResult();
-    }
-
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/IEtlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/IEtlExecutor.java
deleted file mode 100644
index 3b9a916..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/IEtlExecutor.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.etl;
-
-import org.eclipse.epsilon.etl.IEtlModule;
-import org.eclipse.epsilon.etl.trace.TransformationTrace;
-import org.eclipse.epsilon.executors.IEpsilonLanguageExecutor;
-
-/**
- * The IEtlExecutor API provides additional methods to return the transformation trace and to store
- * the trace as a model.
- * 
- * @author Horacio Hoyos Rodriguez
- *
- * @param <M> the Module type
- */
-public interface IEtlExecutor extends IEpsilonLanguageExecutor {
-
-    /**
-     * Wrapper method to return the trace.
-     *
-     * @return the transformation trace
-     */
-    default TransformationTrace getTransformationTrace() {
-    	return (TransformationTrace) getResult();
-    }
-    
-    @Override
-    IEtlModule getModule();
-    
-//    /**
-//     * Save the transformation trace as an EMF model. The model conforms to the EtlSimpleTrace
-//     * metamodel defined as:
-//     * <pre>
-//	 * {@code
-//	 * @namespace(uri="http://www.eclipse.org/epsilon/etl/EtlSimpleTrace", prefix="etltr")
-//	 * package EtlSimpleTrace;
-//	 * 
-//	 *   class Trace {
-//   	 *     val TraceLink[*] links;
-//	 *   }
-//	 *
-//	 *   class TraceLink {
-//     *     ref EObject[*] sources;
-//     *     ref EObject[*] targets;
-//     *     attr String description;
-//     *   }
-//	 * }
-//	 * </pre>
-//	 * The metamodel can be retrieved via <code>IEtlExecutor.class.getResource("SimpleTrace.ecore")</code>.
-//	 *  
-//     * @param location				The path where the model will be stored
-//     */
-//	public void saveTransformationTraceAsEmfModel(Path location);
-
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/SimpleEtlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/SimpleEtlExecutor.java
new file mode 100644
index 0000000..1a7537c
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/etl/SimpleEtlExecutor.java
@@ -0,0 +1,107 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.etl;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.etl.EtlModule;
+import org.eclipse.epsilon.etl.IEtlModule;
+import org.eclipse.epsilon.etl.trace.TransformationTrace;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The ETL executor
+ *
+ * @author Horacio Hoyos Rodriguez
+ */
+public class SimpleEtlExecutor implements EpsilonLanguageExecutor<TransformationTrace> {
+
+    private static final Logger logger = LoggerFactory.getLogger(SimpleEtlExecutor.class);
+    private IEtlModule module;
+    private ExecutorHelper helper;
+
+    public SimpleEtlExecutor() {
+    	this(new EtlModule());
+    	
+    }
+    
+    public SimpleEtlExecutor(IEtlModule mdl) {
+    	logger.info("Creating the Etl Executor");
+    	module = mdl;
+    	helper = new ExecutorHelper(module);
+    }
+    
+
+	@Override
+	public TransformationTrace execute() throws EolRuntimeException {
+		return (TransformationTrace) module.execute();
+	}
+
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	public void dispose() {
+		helper.dispose();
+	}
+
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	public void postProcess() {
+		helper.postProcess();
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/EvlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/EvlExecutor.java
index 65e2904..bca0bfa 100644
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/EvlExecutor.java
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/EvlExecutor.java
@@ -10,87 +10,37 @@
 package org.eclipse.epsilon.executors.evl;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
-import org.eclipse.epsilon.executors.AbstractLanguageExecutor;
-import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
-import org.eclipse.epsilon.evl.IEvlModule;
-import org.eclipse.epsilon.evl.concurrent.EvlModuleParallelAnnotation;
+
+import org.eclipse.epsilon.evl.dom.Constraint;
+import org.eclipse.epsilon.evl.dom.ConstraintContext;
 import org.eclipse.epsilon.evl.execute.UnsatisfiedConstraint;
-import org.eclipse.epsilon.evl.execute.context.IEvlContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.eclipse.epsilon.executors.EpsilonLanguageExecutor;
 
 /**
- * The EVL executor
- * @author Horacio Hoyos Rodriguez
+ * The IEvlExecutor API provides additional methods to print the validation results.
+ *
  */
-public class EvlExecutor extends AbstractLanguageExecutor implements IEvlExecutor {
+public interface EvlExecutor extends EpsilonLanguageExecutor<Collection<UnsatisfiedConstraint>>  {
+    
 
-	private static final Logger logger = LoggerFactory.getLogger(EvlExecutor.class);
-
-	public EvlExecutor() {
-		this(new EvlModuleParallelAnnotation());
-	}
-	
-	public EvlExecutor(IEvlModule module) {
-        super(module);
-        logger.info("Creating the EvlStandaloneEngine");
-    }
-
-	@Override
-	public void postProcess() {
-        logger.info("Retrieving unsatisfied Constraints.");
-	}
-
-    @Override
-    protected Collection<UnsatisfiedConstraint> executeInternal() throws EolRuntimeException {
-        logger.info("Executing EVL script.");
-        return getModule().execute();
-    }
-
-	@Override
-	public void dispose() {
-		logger.info("Disposing engine.");
-		super.dispose();
-		getResult().clear();
-	}
-
-	@Override
-	public IEvlModule getModule() {
-		return (IEvlModule) module;
-	}
-	
-	@SuppressWarnings("unchecked")
-	@Override
-	public Collection<UnsatisfiedConstraint> getResult() {
-		return (Collection<UnsatisfiedConstraint>) result;
-	}
-	
     /**
-     * Prints the validation results.
+     * Send the unsatisfied constraints to the log
      */
-    // FIXME Make a nicer print method!, e.g. something like log entries that can be consumed by other APIs
-	@Override
-    public void printResult() {
-    	IEvlContext context = getModule().getContext();
-    	Set<UnsatisfiedConstraint> unsatisfiedConstraints = context.getUnsatisfiedConstraints();
-		int numUnsatisfied = unsatisfiedConstraints.size();
-    	if (numUnsatisfied > 0) {
-			logger.warn(String.format("There %s %s unsatisfied Constraint(s).",
-					numUnsatisfied > 1 ? "were" : "was",
-					numUnsatisfied));
-			for (UnsatisfiedConstraint uc : unsatisfiedConstraints) {
-				if (uc.getConstraint().isCritique()) {
-					logger.warn(uc.getMessage());
-				}
-				else {
-					logger.error(uc.getMessage());
-				}
-			}
-		}
-		else {
-			logger.info("All constraints have been satisfied.");
-		}
-    }
+    void logUnsatisfied(Collection<UnsatisfiedConstraint> unsatisfiedConstraints);
+    
+    /**
+     * Pretty print the unsatisfied constraints
+     */
+    void printUnsatisfied(Collection<UnsatisfiedConstraint> unsatisfiedConstraints);
 
+	List<Constraint> getConstraints();
+
+	List<ConstraintContext> getConstraintContexts();
+
+	ConstraintContext getConstraintContext(String name);
+
+	Set<UnsatisfiedConstraint> getUnsatisfiedConstraints();
+    
 }
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/IEvlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/IEvlExecutor.java
deleted file mode 100644
index 8fdcc4b..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/IEvlExecutor.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.evl;
-
-import java.util.Collection;
-
-import org.eclipse.epsilon.evl.IEvlModule;
-import org.eclipse.epsilon.evl.execute.UnsatisfiedConstraint;
-import org.eclipse.epsilon.executors.IEpsilonLanguageExecutor;
-
-/**
- * The IEvlExecutor API provides additional methods to get the validation results (a collection
- * of {@link UnsatisfiedConstraint}s) and to print the validation results.
- *
- */
-public interface IEvlExecutor extends IEpsilonLanguageExecutor {
-
-	@Override
-	Collection<UnsatisfiedConstraint> getResult();
-	
-    /**
-     * Gets the unsatisfied constraints.
-     *
-     * @return the unsatisfied constraints
-     */
-    default Collection<UnsatisfiedConstraint> getUnsatisfiedConstraints() {
-    	return (Collection<UnsatisfiedConstraint>) getResult();
-    }
-    
-    @Override
-    IEvlModule getModule();
-    
-    /**
-     * Prints the validation results.
-     */
-    void printResult();
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/ParallelEvlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/ParallelEvlExecutor.java
deleted file mode 100644
index fc84ec7..0000000
--- a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/ParallelEvlExecutor.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*********************************************************************
-* Copyright (c) 2019 The University of York.
-*
-* This program and the accompanying materials are made
-* available under the terms of the Eclipse Public License 2.0
-* which is available at https://www.eclipse.org/legal/epl-2.0/
-*
-* SPDX-License-Identifier: EPL-2.0
-**********************************************************************/
-package org.eclipse.epsilon.executors.evl;
-
-import org.eclipse.epsilon.evl.concurrent.EvlModuleParallel;
-import org.eclipse.epsilon.evl.concurrent.EvlModuleParallelElements;
-
-/**
- * Parallel EVL executor (parallelises everything by default).
- *
- * @author Sina Madani
- * @since 1.6
- */
-public class ParallelEvlExecutor extends EvlExecutor {
-
-	public ParallelEvlExecutor() {
-		this(new EvlModuleParallelElements());
-	}
-
-	public ParallelEvlExecutor(int parallelism) {
-		this(new EvlModuleParallelElements(parallelism));
-	}
-	
-	public ParallelEvlExecutor(EvlModuleParallel module) {
-		super(module);
-	}
-}
diff --git a/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/SimpleEvlExecutor.java b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/SimpleEvlExecutor.java
new file mode 100644
index 0000000..59f889a
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.executors/src/org/eclipse/epsilon/executors/evl/SimpleEvlExecutor.java
@@ -0,0 +1,220 @@
+/*********************************************************************
+* Copyright (c) 2019 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.executors.evl;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.eclipse.epsilon.common.parse.problem.ParseProblem;
+import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
+import org.eclipse.epsilon.eol.models.IModel;
+import org.eclipse.epsilon.eol.types.IToolNativeTypeDelegate;
+import org.eclipse.epsilon.erl.execute.RuleProfiler;
+import org.eclipse.epsilon.evl.EvlModule;
+import org.eclipse.epsilon.evl.IEvlFixer;
+import org.eclipse.epsilon.evl.IEvlModule;
+import org.eclipse.epsilon.evl.concurrent.EvlModuleParallelElements;
+import org.eclipse.epsilon.evl.dom.Constraint;
+import org.eclipse.epsilon.evl.dom.ConstraintContext;
+import org.eclipse.epsilon.evl.execute.CommandLineFixer;
+import org.eclipse.epsilon.evl.execute.UnsatisfiedConstraint;
+import org.eclipse.epsilon.executors.ExecutorHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The EVL executor
+ * @author Horacio Hoyos Rodriguez
+ */
+public class SimpleEvlExecutor implements EvlExecutor {
+
+	private static final Logger logger = LoggerFactory.getLogger(SimpleEvlExecutor.class);
+	private final IEvlModule module;
+	private ExecutorHelper helper;
+	
+	public SimpleEvlExecutor(IEvlModule mdl) {
+		logger.info("Creating the EvlExecutor");
+		module = mdl;
+		helper = new ExecutorHelper(module);
+	}
+	
+	public SimpleEvlExecutor() {
+		this(false, 0, null);
+    }
+	
+	public SimpleEvlExecutor(IEvlFixer evlFixer) {
+		this(false, 0, evlFixer);
+    }
+	
+	
+	public SimpleEvlExecutor(boolean useParallel) {
+		this(useParallel, 1, new CommandLineFixer());
+    }
+    
+	  
+	public SimpleEvlExecutor(boolean useParallel, int parallelism, IEvlFixer evlFixer) {
+		this(useParallel ? new EvlModuleParallelElements(parallelism) : new EvlModule());
+		module.setUnsatisfiedConstraintFixer(evlFixer);
+    }
+    
+	@Override
+	public Collection<UnsatisfiedConstraint> execute() throws EolRuntimeException {
+		return module.execute();
+	}
+	
+	@Override
+	public List<Constraint> getConstraints() {
+		return module.getConstraints();
+	}
+	
+	@Override
+	public List<ConstraintContext> getConstraintContexts() {
+		return module.getConstraintContexts();
+	}
+
+	@Override
+	public ConstraintContext getConstraintContext(String name) {
+		return module.getConstraintContext(name);
+	}
+	
+	@Override
+	public Set<UnsatisfiedConstraint> getUnsatisfiedConstraints() {
+		return module.getContext().getUnsatisfiedConstraints();
+	}
+
+	public boolean parse(File file) throws Exception {
+		return helper.parse(file);
+	}
+
+	public boolean parse(String code) throws Exception {
+		return helper.parse(code);
+	}
+
+	public List<ParseProblem> getParseProblems() {
+		return helper.getParseProblems();
+	}
+
+	public void addModels(Collection<IModel> models) {
+		helper.addModels(models);
+	}
+
+	public void addParamters(Map<String, ?> parameters) {
+		helper.addParamters(parameters);
+	}
+
+	public void addNativeTypeDelegates(Collection<IToolNativeTypeDelegate> nativeDelegates) {
+		helper.addNativeTypeDelegates(nativeDelegates);
+	}
+
+	public Optional<RuleProfiler> getRuleProfiler() {
+		return helper.getRuleProfiler();
+	}
+
+	public void disposeModelRepository() {
+		helper.disposeModelRepository();
+	}
+
+	public void clearModelRepository() {
+		helper.clearModelRepository();
+	}
+
+	public void dispose() {
+		helper.dispose();
+	}
+
+	public void preProcess() {
+		helper.preProcess();
+	}
+
+	public void postProcess() {
+		helper.postProcess();
+	}
+
+	@Override
+	public void logUnsatisfied(Collection<UnsatisfiedConstraint> unsatisfiedConstraints) {
+		int numUnsatisfied = unsatisfiedConstraints.size();
+    	if (numUnsatisfied > 0) {
+    		// Separate critiques from constraints
+    		List<UnsatisfiedConstraint> consraints = new ArrayList<>();
+    		List<UnsatisfiedConstraint> critiques = new ArrayList<>();
+    		unsatisfiedConstraints.stream()
+    				.forEach(uc -> {
+    					if (uc.getConstraint().isCritique()) {
+    						critiques.add(uc);
+    					} else {
+    						consraints.add(uc);}
+    					}
+    				);
+			logger.warn(String.format("There %s %s unsatisfied Constraint(s).",
+					numUnsatisfied > 1 ? "were" : "was",
+					numUnsatisfied));
+			for (UnsatisfiedConstraint uc : unsatisfiedConstraints) {
+				if (uc.getConstraint().isCritique()) {
+					logger.warn(uc.getMessage());
+				}
+				else {
+					logger.error(uc.getMessage());
+				}
+			}
+		}
+		else {
+			logger.info("All constraints have been satisfied.");
+		}
+	}
+
+	@Override
+	public void printUnsatisfied(Collection<UnsatisfiedConstraint> unsatisfiedConstraints) {
+		int numUnsatisfied = unsatisfiedConstraints.size();
+    	if (numUnsatisfied > 0) {
+    		// Separate critiques from constraints
+    		List<UnsatisfiedConstraint> consraints = new ArrayList<>();
+    		List<UnsatisfiedConstraint> critiques = new ArrayList<>();
+    		unsatisfiedConstraints.stream()
+    				.forEach(uc -> {
+    					if (uc.getConstraint().isCritique()) {
+    						critiques.add(uc);
+    					} else {
+    						consraints.add(uc);
+    					}
+    				});
+    		Optional<String> maxWidth = unsatisfiedConstraints.stream()
+    				.map(uc -> uc.getConstraint().getName())
+    				.max(Comparator.comparingInt(String::length));
+    		int tabDivision = maxWidth.orElse("        ").length();
+			String msg = "Unsatisfied Contraints";
+			String division = new String(new char[msg.length()]).replace("\0", "=");
+			System.out.println(msg);
+			System.out.println(division);
+			for (UnsatisfiedConstraint uc : consraints) {
+				System.out.format("\u16D6 %-"+tabDivision+"s %s%n", uc.getConstraint().getName(), uc.getMessage());
+			}
+			msg = "Unsatisfied Critiques";
+			division = new String(new char[msg.length()]).replace("\0", "=");
+			System.out.println(msg);
+			System.out.println(division);
+			for (UnsatisfiedConstraint uc : consraints) {
+				System.out.format("\u16B9 %-"+tabDivision+"s %s%n", uc.getConstraint().getName(), uc.getMessage());
+			}
+		}
+		else {
+			String msg = "All constraints have been satisfied";
+			String division = new String(new char[msg.length()]).replace("\0", "=");
+			System.out.println(msg);
+			System.out.println(division);
+		}
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.targetplatform/org.eclipse.epsilon.targetplatform.target b/plugins/org.eclipse.epsilon.targetplatform/org.eclipse.epsilon.targetplatform.target
index 2989e3f..7fe31ed 100644
--- a/plugins/org.eclipse.epsilon.targetplatform/org.eclipse.epsilon.targetplatform.target
+++ b/plugins/org.eclipse.epsilon.targetplatform/org.eclipse.epsilon.targetplatform.target
@@ -6,13 +6,15 @@
 </location>
 <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="false" type="InstallableUnit">
 <repository location="http://download.eclipse.org/releases/photon/"/>
-    <unit id="org.eclipse.emf.compare.ide.ui.source.feature.group" version="3.3.3.201805161152"/>
-    <unit id="org.eclipse.emf.compare.uml2.source.feature.group" version="3.3.3.201805161152"/>
-    <unit id="org.eclipse.ocl.all.sdk.feature.group" version="5.4.0.v20180611-1119"/>
-    <unit id="org.eclipse.sirius.runtime.feature.group" version="6.0.0.201806111309"/>
-    <unit id="org.eclipse.sirius.runtime.ide.ui.feature.group" version="6.0.0.201806111309"/>
-    <unit id="org.eclipse.xsd.sdk.feature.group" version="2.14.0.v20180131-0817"/>
-    <unit id="org.eclipse.xtext.sdk.feature.group" version="2.14.0.v20180523-0937"/>
+    <unit id="org.eclipse.emf.sdk.feature.group" version="2.14.0.v20180529-1157"/>
+    <unit id="org.eclipse.emf.validation.sdk.feature.group" version="1.12.0.201805030717"/>
+    <unit id="org.eclipse.equinox.sdk.feature.group" version="3.14.0.v20180518-2029"/>
+    <unit id="org.eclipse.gef.sdk.feature.group" version="3.11.0.201606061308"/>
+    <unit id="org.eclipse.gmf.feature.group" version="1.12.0.201806010809"/>
+    <unit id="org.eclipse.gmf.runtime.notation.sdk.feature.group" version="1.12.0.201805221301"/>
+    <unit id="org.eclipse.gmf.runtime.sdk.feature.group" version="1.12.0.201806010809"/>
+    <unit id="org.eclipse.jdt.feature.group" version="3.14.0.v20180611-0500"/>
+    <unit id="org.eclipse.modisco.sdk.feature.feature.group" version="1.2.0.201805182005"/>
 </location>
 <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="false" type="InstallableUnit">
 <unit id="org.eclipse.gmf.sdk.feature.group" version="3.2.1.201409171321"/>
@@ -23,15 +25,9 @@
 </location>
 <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
 <repository location="http://download.eclipse.org/releases/photon/"/>
-    <unit id="org.eclipse.emf.sdk.feature.group" version="2.14.0.v20180529-1157"/>
-    <unit id="org.eclipse.emf.validation.sdk.feature.group" version="1.12.0.201805030717"/>
-    <unit id="org.eclipse.equinox.sdk.feature.group" version="3.14.0.v20180518-2029"/>
-    <unit id="org.eclipse.gef.sdk.feature.group" version="3.11.0.201606061308"/>
-    <unit id="org.eclipse.gmf.feature.group" version="1.12.0.201806010809"/>
-    <unit id="org.eclipse.gmf.runtime.notation.sdk.feature.group" version="1.12.0.201805221301"/>
-    <unit id="org.eclipse.gmf.runtime.sdk.feature.group" version="1.12.0.201806010809"/>
-    <unit id="org.eclipse.jdt.feature.group" version="3.14.0.v20180611-0500"/>
-    <unit id="org.eclipse.modisco.sdk.feature.feature.group" version="1.2.0.201805182005"/>
+    <unit id="org.eclipse.ocl.all.sdk.feature.group" version="5.4.0.v20180611-1119"/>
+    <unit id="org.eclipse.xsd.sdk.feature.group" version="2.14.0.v20180131-0817"/>
+    <unit id="org.eclipse.xtext.sdk.feature.group" version="2.14.0.v20180523-0937"/>
 </location>
 <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="false" type="InstallableUnit">
 <unit id="org.eclipse.pde.feature.group" version="3.13.100.v20180611-0826"/>