| /******************************************************************************* |
| * 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.interpreter.impl.executionEnvironment; |
| |
| 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.ASMInterpreterErrorStrings; |
| 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.gtasm.interpreter.impl.machine.ASMInterpreterException; |
| 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 ExecutionEnvironment 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 org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment#getFramework() |
| */ |
| public IFramework getFramework() { |
| return framework; |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment#onBegin(java.util.Map) |
| */ |
| public void onBegin(Map<Variable, Object> variables) { |
| ; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment#onTerminate() |
| */ |
| public Map<Variable, Object> onTerminate() { |
| return null; |
| } |
| |
| // protected Hashtable<Variable, Object> variableValues; |
| protected Map<Variable, Object> variableValues; |
| |
| protected ASMFunctionContent ASMFunctionValues; |
| |
| public ExecutionEnvironment(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 ExecutionEnvironment(IExecutionEnvironment parent) { |
| parentExecutionEnvironment = parent; |
| |
| variableValues = new Hashtable<Variable, Object>(parent |
| .getVariableValues()); |
| ASMFunctionValues = ASMFunctionContent.getInstance(); |
| framework = parent.getFramework(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.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 org.eclipse.viatra2.gtasm.interpreter.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 { |
| String[] context = {asmFunction.getName()}; |
| throw new ASMInterpreterException( |
| ASMInterpreterErrorStrings.UPDATE_NONEXISTENT_ASMFUNCTION |
| , context |
| , asmFunction); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.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)) |
| { |
| String[] context = {key.getName()}; |
| throw new ASMInterpreterException(ASMInterpreterErrorStrings.ADD_EXISTING_VAR |
| , context |
| , key); |
| } |
| else |
| variableValues.put(key, value); |
| } |
| |
| // This is necessary when returning from another ExecutionEnvironment |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment#updateVariables(java.util.Map) |
| */ |
| public void updateVariables(Map<Variable, Object> changedVariables) { |
| variableValues.putAll(changedVariables); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.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 |
| { |
| String[] context = {variable.getName()}; |
| throw new ASMInterpreterException( |
| ASMInterpreterErrorStrings.VALUE_OF_NOT_EXISTING_VAR |
| ,context |
| ,null); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.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 |
| { |
| String context[] = {variable.getName()}; |
| throw new ASMInterpreterException( |
| ASMInterpreterErrorStrings.SET_VALUE_NOT_EXISTING_VAR |
| , context |
| , null); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment#getVariableValues() |
| */ |
| public Map<Variable, Object> getVariableValues() { |
| return variableValues; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.viatra2.gtasm.interpreter.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... |
| |
| } |
| } |
| } |