blob: 20d86fe961bb778730e4ff407c2beb484b779b82 [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.interpreter.term.rules;
import java.util.Vector;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.viatra2.core.IModelSpace;
import org.eclipse.viatra2.errors.VPMRuntimeException;
import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment;
import org.eclipse.viatra2.gtasm.interpreter.term.internal.TermInterpreterErrorString;
import org.eclipse.viatra2.gtasm.interpreter.term.internal.TermInterpreterException;
import org.eclipse.viatra2.gtasm.patternmatcher.patterns.IPatternMatcher;
import org.eclipse.viatra2.gtasm.patternmatcher.patterns.PatternMatcherProvider;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.MultiplicityKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ASMFunctionInvocation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Constant;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.NativeFunctionInvocation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.VariableReference;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Multiplicity;
import org.eclipse.viatra2.natives.ASMNativeFunction;
public class BasicTermEvaluator extends TermEvaluator {
private static BasicTermEvaluator _instance = new BasicTermEvaluator();
private BasicTermEvaluator() {
;
}
public static BasicTermEvaluator getInstance() {
return _instance;
}
/**
* This function evaluates the basic Terms. Constants,
* ASMFunctionInvocations, NativeFunctionInvocations, VeriableReferences.
*
* The Native function invocation works for some functions, like
* java.util.Random.nextInt(), but fails to work for example with
* java.lang.Double.parseDouble(String)
*
*/
@Override
public Object evaluate(IExecutionEnvironment executionEnvironment,
Term termToBeEvaluated) throws ViatraTransformationException {
if (termToBeEvaluated instanceof Constant) {
int kind = ((Constant) termToBeEvaluated).getKind().getValue();
switch (kind) {
case ValueKind.BOOLEAN:
return Boolean.valueOf(((Constant) termToBeEvaluated)
.getValue());
case ValueKind.DOUBLE:
return Double
.valueOf(((Constant) termToBeEvaluated).getValue());
case ValueKind.INTEGER:
return Integer.valueOf(((Constant) termToBeEvaluated)
.getValue());
case ValueKind.STRING:
return ((Constant) termToBeEvaluated).getValue();
case ValueKind.MULTIPLICITY:
if ("one_to_one".equals(((Constant) termToBeEvaluated)
.getValue())) {
return MultiplicityKind.ONE_TO_ONE_LITERAL;
} else if ("one_to_many".equals(((Constant) termToBeEvaluated)
.getValue())) {
return MultiplicityKind.ONE_TO_MANY_LITERAL;
} else if ("many_to_many".equals(((Constant) termToBeEvaluated)
.getValue())) {
return MultiplicityKind.MANY_TO_MANY_LITERAL;
} else if ("many_to_one".equals(((Constant) termToBeEvaluated)
.getValue())) {
return MultiplicityKind.MANY_TO_ONE_LITERAL;
}
case ValueKind.UNDEF:
return ValueKind.UNDEF_LITERAL;
case ValueKind.MODELELEMENT:
String fqn = ((Constant) termToBeEvaluated).getValue();
// result is definitely not null
if (fqn == null)
{String[] context = {"Fully Qualified Name"};
throw new TermInterpreterException(
TermInterpreterErrorString.REF_NOT_STRING_MODELELEMENTQUERY,
context,
termToBeEvaluated);
}
// get the IModelElement from the manager
IModelSpace _topmodel = executionEnvironment.getFramework()
.getTopmodel();
Object result = _topmodel.getModelManager().getElementByName(fqn);
if (result != null)
return result;
else
{
String[] context = {fqn};
throw new TermInterpreterException(
TermInterpreterErrorString.CONSTANT_MODELELEMENT_DOESNOTEXISTS
,context
,termToBeEvaluated);
}
default:
{String[] context = {termToBeEvaluated.getName()};
throw new TermInterpreterException(
TermInterpreterErrorString.UNIMP_TERM
,context
,termToBeEvaluated);
}
}
} else if (termToBeEvaluated instanceof ASMFunctionInvocation) {
EList<Object> evalParamList = new BasicEList<Object>();
for (Object term : ((ASMFunctionInvocation) termToBeEvaluated)
.getActualParameters()) {
evalParamList.add(TermEvaluator.getInstance()
.evaluate(executionEnvironment, (Term) term));
}
Object value = executionEnvironment.getValueOfASMFunction(
((ASMFunctionInvocation) termToBeEvaluated)
.getCalledFunction(), evalParamList);
return (value == null) ? ValueKind.UNDEF_LITERAL : value;
} else if (termToBeEvaluated instanceof NativeFunctionInvocation) {
// Name of the native function
String functionName = ((NativeFunctionInvocation) termToBeEvaluated)
.getFunctionName();
// array for the evaluated parameters
Object[] parameters = new Object[((NativeFunctionInvocation) termToBeEvaluated)
.getActualParameters().size()];
// Evaluating each parameter
int i = 0;
for (Object parameterToBeEvaluated : ((NativeFunctionInvocation) termToBeEvaluated)
.getActualParameters()) {
Object currparameter = TermEvaluator.getInstance()
.evaluate(executionEnvironment,
(Term) parameterToBeEvaluated);
// unbox java native values for native functions calls
if (currparameter instanceof JavaNativeValue)
parameters[i++] = ((JavaNativeValue) currparameter)
.getValue();
else
parameters[i++] = currparameter;
}
//try {
ASMNativeFunction _nativeFunction = executionEnvironment.getFramework()
.getNativeFunctionManager().getNativeFunctionForName(
functionName);
IModelSpace _topmodel = executionEnvironment.getFramework().getTopmodel();
Object o = null;
//Protects the Viatra runtime from any exception thrown from the native function invocation
try{
o = _nativeFunction.evaluate(
_topmodel, parameters);
}
catch (VPMRuntimeException e) {
String[] context = {e.getMessage()};
throw new TermInterpreterException(
TermInterpreterErrorString.VPM_CORE
,context
,termToBeEvaluated);
}// Any other exception that is not expected from the native ASM function
catch(Throwable t) {
String[] context = {functionName,t.getLocalizedMessage()};
throw new TermInterpreterException(
TermInterpreterErrorString.NATIVE_FUNCTION_EXCEPTION
,context
,termToBeEvaluated);
}
if (isASMNativeType(o))
return o;
else
return new JavaNativeValue(o);
} else if (termToBeEvaluated instanceof VariableReference) {
try {
return executionEnvironment
.getVariableValue(((VariableReference) termToBeEvaluated)
.getVariable());
} catch (ViatraTransformationException e) {
String[] context = {((VariableReference) termToBeEvaluated).getName()};
throw new TermInterpreterException(
TermInterpreterErrorString.EXECUTION_ENVIRONMENT_EXCEPTION
+ e.getMessage(), context, termToBeEvaluated);
}
} else if (termToBeEvaluated instanceof GTPatternCall) {
// Evaluates GTPatternCall for match. Boolean return value only.
// ((GTPatternBody)((GTPatternCall)termToBeEvaluated).getCalledPattern().getPatternBodies().get(0)).get
GTPattern gtPattern = ((GTPatternCall) termToBeEvaluated)
.getCalledPattern();
try {
IPatternMatcher patternMatcher = PatternMatcherProvider
.getInstance().getPatternMatcher(executionEnvironment,
gtPattern);
Vector<Object> patternParams = new Vector<Object>();
for (Object term : ((GTPatternCall) termToBeEvaluated)
.getActualParameters()) {
patternParams.add(TermEvaluator.getInstance()
.evaluate(executionEnvironment, (Term) term));
}
return patternMatcher.match(patternParams.toArray());
} catch (ViatraTransformationException e) {
throw e.addNewStackElement(termToBeEvaluated);
}
} else if (termToBeEvaluated instanceof Multiplicity) {
return termToBeEvaluated;
}
// the control gets here, if a non-implemented Term was evaluated.
String[] context = {termToBeEvaluated.getName()};
throw new TermInterpreterException(TermInterpreterErrorString.UNIMP_TERM, context, termToBeEvaluated);
}
}