blob: 88c4d80d0416d7318076e7d376421dedd8db4124 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 Peter Pasztor, Akos Horvath, Gergely Varro, Istvan Rath and Daniel Varro
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Peter Pasztor, Akos Horvath, Gergely Varro, Istvan Rath - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.trigger.engine;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
import org.eclipse.emf.common.util.EList;
import org.eclipse.viatra2.framework.IFramework;
import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.ASMFunctionContent;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.ASMFunction;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ASMFunctionInvocation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.FunctionInvocation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.VariableReference;
public class TriggerExecutionEnvironment implements IExecutionEnvironment {
/**
* This class is used to handle the execution environment when running an
* ASM
*
* If the TermEvaluator creates a sub-execution environment (stack) for its
* operation for example at a function call, the values may change, the
* variables and everything that changed needs to be refreshed
*
* @author Peter Pasztor
*
*/
protected IExecutionEnvironment parentExecutionEnvironment;
protected IFramework framework;
/*
* protected TermHandler termHandler; protected PatternBuilder
* patternBuilder;
*/
// protected SimpleModelSpace modelSpace;
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#getFramework()
*/
public IFramework getFramework() {
return framework;
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#onBegin(java.util.Map)
*/
public void onBegin(Map<Variable, Object> variables) {
;
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#onTerminate()
*/
public Map<Variable, Object> onTerminate() {
return null;
}
// protected Hashtable<Variable, Object> variableValues;
protected Map<Variable, Object> variableValues;
protected ASMFunctionContent ASMFunctionValues;
public TriggerExecutionEnvironment(IFramework framework) {
parentExecutionEnvironment = null;
// variableValues = new Hashtable<Variable, Object>();
variableValues = new TreeMap<Variable, Object>(
new Comparator<Variable>() {
/*
* XXX Istvan: is it valid to compare variables in an
* executionenvironment by their name?
*/
public int compare(Variable o1, Variable o2) {
// if (o1 instanceof PatternVariable || o2 instanceof
// PatternVariable)
// return o1.getName().compareTo(o2.getName());
// else
{
int h_o1 = o1.hashCode();
int h_o2 = o2.hashCode();
if (h_o1 == h_o2)
return 0;
else if (h_o1 > h_o2)
return 1;
else
return -1;
}
}
});
ASMFunctionValues = ASMFunctionContent.getInstance();
this.framework = framework;
}
public TriggerExecutionEnvironment(IExecutionEnvironment parent) {
parentExecutionEnvironment = parent;
variableValues = new Hashtable<Variable, Object>(parent
.getVariableValues());
ASMFunctionValues = ASMFunctionContent.getInstance();
framework = parent.getFramework();
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#getValueOfASMFunction(org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.ASMFunction,
* org.eclipse.emf.common.util.EList)
*/
public Object getValueOfASMFunction(ASMFunction asmFunction, EList<Object> location) {
HashMap<EList<Object>, Object> af = ASMFunctionContent.getInstance().get(
asmFunction);
if (af == null)
return null;
return af.get(location);
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#updateASMFunction(org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.ASMFunction,
* org.eclipse.emf.common.util.EList, java.lang.Object)
*/
public void updateASMFunction(ASMFunction asmFunction, EList<Object> location,
Object value) throws ViatraTransformationException {
if (ASMFunctionValues.get(asmFunction) != null) {
ASMFunctionValues.get(asmFunction).put(location, value);
// notify value listeners
ASMFunctionValues.notifyListeners(asmFunction, location, value);
} else {
// ASMFunctionValues.(asmFunction).put(location, value);
// TODO: What to do???
// throw new ASMInterpreterException(
// ErrorStrings.UPDATE_NONEXISTENT_ASMFUNCTION
// + asmFunction.getName(), asmFunction);
}
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#addVariable(org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable,
* java.lang.Object)
*/
public void addVariable(Variable key, Object value)
throws ViatraTransformationException {
if (variableValues.containsKey(key)) {
// throw new ASMInterpreterException(ErrorStrings.ADD_EXISTING_VAR
// + key.getName() + "\"!", key);
} else {
variableValues.put(key, value);
}
}
// This is necessary when returning from another ExecutionEnvironment
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#updateVariables(java.util.Map)
*/
public void updateVariables(Map<Variable, Object> changedVariables) {
variableValues.putAll(changedVariables);
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#getVariableValue(org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable)
*/
public Object getVariableValue(Variable variable)
throws ViatraTransformationException {
// The local variables are more likely to be accessed, and are not so
// many as the global ones
if (variableValues.containsKey(variable))
return variableValues.get(variable);
else {
// This line has temporarily added
return null;
// throw new ASMInterpreterException(
// ErrorStrings.VALUE_OF_NOT_EXISTING_VAR + variable.getName(),
// variable);
}
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#setVariableValue(org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable,
* java.lang.Object)
*/
public void setVariableValue(Variable variable, Object value)
throws ViatraTransformationException { // The Variable itself doesn't
// change, just the value
if (variableValues.containsKey(variable)) {
// This is the easy case, just modify the value
variableValues.put(variable, value);
} else {
// throw new ASMInterpreterException(
// ErrorStrings.SET_VALUE_NOT_EXISTING_VAR
// + variable.getName(), variable);
}
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#getVariableValues()
*/
public Map<Variable, Object> getVariableValues() {
return variableValues;
}
/*
* (non-Javadoc)
*
* @see executionEnvironment.IExecutionEnvironment#fetchVariableVariations(java.util.HashMap,
* org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term)
*/
public void fetchVariableVariations(
HashMap<Variable, Vector<Object>> possibleVariableValues,
Term termToBeEvaluated) {
Integer index;
Set<EList<Object>> keys;
Set<Variable> variables = possibleVariableValues.keySet();
if (termToBeEvaluated instanceof FunctionInvocation) {
// Get into the parameters only
if (termToBeEvaluated instanceof ASMFunctionInvocation) {
// Here happens the real fetching of possibly good variable
// values
((ASMFunctionInvocation) termToBeEvaluated)
.getActualParameters();
for (Object parameter : ((ASMFunctionInvocation) termToBeEvaluated)
.getActualParameters()) {
// For every parameter, we check whether it's a variable
// from the list, or not.
if (parameter instanceof VariableReference) {
if (variables.contains(((VariableReference) parameter)
.getVariable())) {
// We found one. Now we must get the possible
// values.
// (parameter is now an instance of type Variable!)
index = ((ASMFunctionInvocation) termToBeEvaluated)
.getActualParameters().indexOf(parameter);
keys = this.ASMFunctionValues.get(
((ASMFunctionInvocation) termToBeEvaluated)
.getCalledFunction()).keySet();
for (EList<Object> key : keys) {
// Now we get a possible value (parameter holds
// the Variable!)
// Only one appearance allowed, hence the check
// It wastes time, but
// wastes much less time than having to
// re-evaluate the term again
// and again for the same parameters
if (!possibleVariableValues.get(
((VariableReference) parameter)
.getVariable()).contains(
key.get(index)))
possibleVariableValues.get(
((VariableReference) parameter)
.getVariable()).add(
key.get(index));
}
}
} else if (parameter instanceof FunctionInvocation) {
// It might be nested. Further investigation required.
fetchVariableVariations(possibleVariableValues,
((Term) parameter));
}
}
} // end of ASMFunctionInvocation
else {
// Other function invocations -- like operations etc.
// We must look at the operands, the operation itself is not
// important,
// the term evaluator will take care of that. It might be
// necessary to
// recursively process them, to be able to process not trivial
// conditions.
for (Object parameter : ((FunctionInvocation) termToBeEvaluated)
.getActualParameters()) {
this.fetchVariableVariations(possibleVariableValues,
((Term) parameter));
}
}
} else {
// There is a problem here, since only FunctionInvocations are
// allowed...
}
}
}