blob: 665a715008cf27cb6b9b7930afa1cce13b476df9 [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.impl.rules;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import org.eclipse.viatra2.gtasm.interpreter.exception.ASMInterpreterErrorStrings;
import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.IExecutionEnvironment;
import org.eclipse.viatra2.gtasm.interpreter.impl.executionEnvironment.BlockRuleExecutionEnvironment;
import org.eclipse.viatra2.gtasm.interpreter.impl.machine.ASMInterpreterException;
import org.eclipse.viatra2.gtasm.interpreter.term.rules.TermEvaluator;
import org.eclipse.viatra2.gtasm.patternmatcher.IMatching;
import org.eclipse.viatra2.gtasm.patternmatcher.ParameterMode;
import org.eclipse.viatra2.gtasm.patternmatcher.PatternMatcherParameters;
import org.eclipse.viatra2.gtasm.patternmatcher.Scope;
import org.eclipse.viatra2.gtasm.patternmatcher.patterns.IGTRuleMatcher;
import org.eclipse.viatra2.gtasm.patternmatcher.patterns.IPatternMatcher;
import org.eclipse.viatra2.gtasm.patternmatcher.patterns.PatternMatcherProvider;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.BlockRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.ChooseRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.ForallRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.compoundRules.LetRule;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.core.RuntimeAnnotation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.VariableDefinition;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.ASMRuleInvocation;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall;
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.gt.GTRule;
import org.eclipse.viatra2.interpreters.IProgressReport;
/** Interprets the block rules of the GTASM language
* @author Peter Pasztor, Akos Horvath and Istvan Rath
*
*/
public class BlockRuleInterpreter extends RuleInterpreter {
private static BlockRuleInterpreter _instance = new BlockRuleInterpreter();
private BlockRuleInterpreter()
{
;
}
public static BlockRuleInterpreter getInstance() {
return _instance;
}
@Override
public Boolean interpretRule(IExecutionEnvironment executionEnvironment, ASMRuleInvocation ruleToBeInterpreted, IProgressReport pr)
throws ViatraTransformationException
{
BlockRule blockRule=(BlockRule)ruleToBeInterpreted;
if(blockRule instanceof LetRule)
{
LetRule letBlockRule = (LetRule)ruleToBeInterpreted;
return interpretLetRule(executionEnvironment,letBlockRule,pr);
}
else if(blockRule instanceof ForallRule)
{
ForallRule forallBlockRule = (ForallRule) blockRule;
if (forallBlockRule.getGtrule()==null)
{
if(forallBlockRule.getCondition() instanceof GTPatternCall)
{
//FORALL with GTPATTERN
// GTPatternCall patternCall = (GTPatternCall)forallBlockRule.getCondition();
// //boolean isParallel = false;
// //int threadPoolSize = 0;
// for (Object _ra : patternCall.getCalledPattern().getRuntimeAnnotations())
// {
// RuntimeAnnotation ra = (RuntimeAnnotation) _ra;
// if (ra.getAnnotationName().equalsIgnoreCase("@parallelforall"))
// {
// isParallel = true;
// for(Object _p : ra.getElements())
// {
// RuntimeAnnotationElement p = (RuntimeAnnotationElement) _p;
// if (p.getKey().equalsIgnoreCase("threadpoolsize"))
// {
// threadPoolSize = Integer.parseInt(p.getValue());
// }
// }
// break;
// }
// }
// if (isParallel)
// return interpretForallRulewithGTPattern_Parallel(executionEnvironment, forallBlockRule, pr, threadPoolSize);
// else
return interpretForallRulewithGTPattern(executionEnvironment, forallBlockRule,pr);
}
else
{
//FORALL with ASMFUNCTION
return interpretForallRulewithASMFunction(executionEnvironment, forallBlockRule,pr);
}
}
else
{
//FORALL with GTRULE
return interpretForallRulewithGTRule(executionEnvironment, forallBlockRule,pr);
}
}
else if(blockRule instanceof ChooseRule)
{
ChooseRule chooseBlockRule = ((ChooseRule)blockRule);
if (chooseBlockRule.getGtrule()==null) {
if(chooseBlockRule.getCondition() instanceof GTPatternCall)
{
//CHOOSE with GTPATTERN
return interpretChooseRulewithGTPattern(executionEnvironment, chooseBlockRule,pr);
}
else
{
//CHOOSE with ASMFUNCTION
return interpretChooseRulewithASMFunction(executionEnvironment, chooseBlockRule,pr);
}
}
else
{
//CHOOSE with GTRULE
return interpretChooseRulewithGTRule(executionEnvironment, chooseBlockRule,pr);
}
}
return Boolean.FALSE;
}
private Boolean interpretLetRule(IExecutionEnvironment executionEnvironment, LetRule letBlockRule, IProgressReport pr)
throws ViatraTransformationException
{
BlockRuleExecutionEnvironment letRuleExecutionEnvironment =
new BlockRuleExecutionEnvironment(executionEnvironment.getFramework(),letBlockRule.getBody());
Hashtable<Variable, Object> childExecutionEnvironmentVariables=new Hashtable<Variable, Object>();
childExecutionEnvironmentVariables.putAll(executionEnvironment.getVariableValues());
//evaluate the variable definitions' values.
for (Object variableDefinition : letBlockRule.getDefinitions()) {
// This long line puts the variable's values into the execution environment. If the parser gave a null value,
// a ValueKind.UNDEF_LITERAL value is substituted.
VariableDefinition varDef = (VariableDefinition)variableDefinition;
childExecutionEnvironmentVariables.put(varDef.getVariable(),(varDef.getValue())==null?
ValueKind.UNDEF_LITERAL:TermEvaluator.getInstance().evaluate(executionEnvironment, varDef.getValue()));
}
letRuleExecutionEnvironment.onBegin(childExecutionEnvironmentVariables);
Boolean result= RuleInterpreter.getInstance().interpretRule(letRuleExecutionEnvironment,letBlockRule.getBody(),pr);
childExecutionEnvironmentVariables=(Hashtable<Variable, Object>)letRuleExecutionEnvironment.onTerminate();
for (Variable variable : executionEnvironment.getVariableValues().keySet()) {
try {
executionEnvironment.setVariableValue(variable, childExecutionEnvironmentVariables.get(variable));
} catch (ViatraTransformationException e) {
String[] context = {variable.getName(),e.getMessage()};
throw new ASMInterpreterException(
ASMInterpreterErrorStrings.SET_VAR_VALUE_AFTER_NATIVE_CALL
,context
,letBlockRule);
}
}
return result;
}
private Boolean interpretForallRulewithGTRule(IExecutionEnvironment executionEnvironment, ForallRule forallBlockRule, IProgressReport pr)
throws ViatraTransformationException{
HashMap<Variable, Scope> parameterParameterScopes = new HashMap<Variable, Scope>();
GTRule gtRule = forallBlockRule.getGtrule().getRule();
Collection<IMatching> lHSmatches;
//Needs a new Exec.env. for the ***DO*** part of the rule
BlockRuleExecutionEnvironment forallRuleExecutionEnvironment =
BlockRuleInterpreterHelper.getNewExecutionEnvironment(executionEnvironment, forallBlockRule);
//New GTEXEC. env. for the action part of the gtRule
IExecutionEnvironment gtEnvironment= new BlockRuleExecutionEnvironment(executionEnvironment.getFramework());
// get scopes for the gtRule
parameterParameterScopes =
BlockRuleInterpreterHelper.getScopesFromContainmentConstraints(forallRuleExecutionEnvironment
, forallBlockRule);
// get matcher parameters
PatternMatcherParameters mp=
BlockRuleInterpreterHelper.getGTRuleMatchParameters(forallRuleExecutionEnvironment
,forallBlockRule
, parameterParameterScopes
, gtRule
, forallBlockRule.getGtrule());
// Get patternMatcher
IGTRuleMatcher gtMatcher;
//evaluate the matches of the LHS for the gtRule
try{
gtMatcher = PatternMatcherProvider.getInstance().getGtRuleMatcher(gtEnvironment,gtRule,mp);
lHSmatches =gtMatcher.initMatchAll(mp.getCallSignature(), mp.getInputMapping(), mp.getQuantificationOrder());
} catch (ViatraTransformationException e1) {
throw e1.addNewStackElement(forallBlockRule);
}
if(lHSmatches != null && lHSmatches.size() != 0)
{
// reorder if neccessary
lHSmatches = BlockRuleInterpreterHelper.
reorder(gtRule.getPrecondition().getCalledPattern(), lHSmatches);
// the RHS\LHS and action part of the rule are evaluated by the matchAll method
for(IMatching lHSMatch: lHSmatches)
{ //get matches
Object[] match;
try {
match = gtMatcher.matchAll(lHSMatch, mp.getCallSignature(),mp.getInputMapping());
} catch (ViatraTransformationException e1) {
throw e1.addNewStackElement(forallBlockRule);
}
//Bind the variables for the 'DO' part of the rule
BlockRuleInterpreterHelper.
evaulateDoPartofGTRuleInvocation(gtRule
,match
,forallBlockRule
,forallRuleExecutionEnvironment
,forallBlockRule.getGtrule()
,pr);
}// end of for cycle for the matches of the GTRULE
}
/*************************************************/
// write the changed values back
forallRuleExecutionEnvironment.onTerminate();
for(Variable var :executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var, forallRuleExecutionEnvironment.getVariableValue(var));
/*************************************************/
return Boolean.TRUE;
}
private Boolean interpretForallRulewithASMFunction(IExecutionEnvironment executionEnvironment, ForallRule forallBlockRule, IProgressReport pr)
throws ViatraTransformationException{
// This will list all the values a symbolic variable might hold.
HashMap<Variable, Vector<Object>> valueList = new HashMap<Variable, Vector<Object>>();
Map<Variable, Object> variables = new Hashtable<Variable, Object>(executionEnvironment.getVariableValues());
for (Object variable : forallBlockRule.getLocalVariables()) {
valueList.put(((Variable) variable), new Vector<Object>());
variables.put((Variable)variable, ValueKind.UNDEF_LITERAL);
}
executionEnvironment.fetchVariableVariations(valueList,forallBlockRule.getCondition());
// We have a list of possible values for the variables.
// Now we must get each configuration (just as a Cartesian multiplication
// would, but being a lot more efficient), and evaluate them using brute force.
Object[] keys = valueList.keySet().toArray();
// Needs a new Exec.env. the new Variables will be added later.
BlockRuleExecutionEnvironment forallRuleExecutionEnvironment =
new BlockRuleExecutionEnvironment(executionEnvironment.getFramework()
,forallBlockRule.getBody());
forallRuleExecutionEnvironment.onBegin(variables);
// We need a divider vector to be able to iterate through all the variations.
Vector<Integer> divVect = new Vector<Integer>();
divVect.add(new Integer(valueList.get(keys[0]).size()));
Integer maxCount = new Integer(valueList.get(keys[0]).size());
for (int iter = 1; iter < valueList.size(); iter++) {
maxCount*=valueList.get(keys[iter]).size();
divVect.add(valueList.get(keys[iter]).size());
// Don't bother, if the function doesn't have any values. In such cases, this speeds up a lot.
if(valueList.get(keys[iter]).size()==0) {
//return Boolean.FALSE; //Istvan: this causes incorrect behaviour, see #335
return Boolean.TRUE;
}
}
// To speed up things a bit.
//Integer maxCount = divVect.lastElement();
Integer size = divVect.size();
//Evaluate all configurations
for (Integer iter_config = 0; iter_config < maxCount; iter_config++) {
Integer config_no = new Integer(iter_config);
// bind the variables
for (int iter_var = 0; iter_var < size; iter_var++) {
//Integer num=config_no-config_no%(iter_var==0?1:divVect.get(iter_var-1))/divVect.get(iter_var);
Variable variable = (Variable) (valueList.keySet().toArray()[iter_var]);
try {
forallRuleExecutionEnvironment.setVariableValue(
variable,
valueList.get(valueList.keySet().toArray()[iter_var]).get(config_no % divVect.get(iter_var)));
} catch (ViatraTransformationException e) {
String[] context = {variable.getName(),e.getMessage()};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.RULE_INIT_VAR_ASMFUNCTION
,context
,forallBlockRule);
}
config_no = (config_no - config_no % divVect.get(iter_var))/divVect.get(iter_var);
}
// Now for the last variable
//evaluate it in a sandbox-like execution environment.
if (Boolean.TRUE.equals(
TermEvaluator.getInstance().evaluate(forallRuleExecutionEnvironment,forallBlockRule.getCondition())))
{
// The condition evaluated to true --> this is a good configuration to interpret
// the actual rule
//TODO: if it fails, what to do?
RuleInterpreter.getInstance().interpretRule(forallRuleExecutionEnvironment,forallBlockRule.getBody(),pr);
}
}
// all runs are done now
// write the changed values back
forallRuleExecutionEnvironment.onTerminate();
for(Variable var :executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var, forallRuleExecutionEnvironment.getVariableValue(var));
return Boolean.TRUE;
}
/*
private Boolean interpretForallRulewithGTPattern_Parallel(IExecutionEnvironment executionEnvironment, final ForallRule forallBlockRule, final IProgressReport pr, final int threadPoolSize)
throws ViatraTransformationException
{
int i=0;
GTPatternCall forallGTPatternCall = (GTPatternCall)forallBlockRule.getCondition();
PatternMatcherParameters mp;
Collection<IMatching> matches;
// make new execution environment
final BlockRuleExecutionEnvironment forallRuleExecutionEnvironment = getNewExecutionEnvironment(executionEnvironment, forallBlockRule);
//Get scopes from containmentConstraints
HashMap<Variable, Scope> parameterParameterScopes =getScopesFromContainmentConstraints(forallRuleExecutionEnvironment,forallBlockRule);
//Get patternMatcher
IPatternMatcher patternMatcher;
try
{
patternMatcher = PatternMatcherProvider.getInstance().getPatternMatcher(forallRuleExecutionEnvironment,
forallGTPatternCall.getCalledPattern());
// get matcher parameters
mp=getMatchParameters(forallRuleExecutionEnvironment,forallBlockRule, parameterParameterScopes);
// get matches
matches =patternMatcher.matchAll(mp.getInputMapping(), mp.getCallSignature(),mp.getQuantificationOrder() );
} catch (ViatraTransformationException e1) {
throw e1.addNewStackElement(forallBlockRule);
}
// create threadpool for execution
ThreadPool pool = new ThreadPool(threadPoolSize);
// reorder if neccessary
matches = reorder(forallGTPatternCall.getCalledPattern(), matches);
// Assign the parameters to the new exec.environment
for (IMatching match : matches) {
// make a copy of the execution environment
final IExecutionEnvironment _forallRuleExecutionEnvironment = new ExecutionEnvironment(forallRuleExecutionEnvironment);
// bind the variables
// Update variables values from the matching
for (i=0;i< forallGTPatternCall.getActualParameters().size();i++) {
// OUTPUT checking
if(mp.getCallSignature()[i].getParameterMode().equals(ParameterMode.OUTPUT))
{ Variable variable = ((VariableReference)forallGTPatternCall.getActualParameters().get(i)).getVariable();
try {
_forallRuleExecutionEnvironment.setVariableValue(
variable,
match.lookup(i));
} catch (ViatraTransformationException e) {
String[] context = {variable.getName(),e.getMessage()};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.RULE_INIT_VAR_PARALLEL_FORALL
,context
,forallBlockRule);
}
}
}
pool.assign(new Runnable(){
public void run() {
try {
RuleInterpreter.getInstance().interpretRule(_forallRuleExecutionEnvironment,forallBlockRule.getBody(),null);
} catch (ViatraTransformationException e) {
e.printStackTrace();
}
}
});
//TODO: what if fail???
}
pool.complete();
// write the changed values back -- TODO NO INFORMATION PROPAGATION SUPPORT FOR NOW
//forallRuleExecutionEnvironment.onTerminate();
//for(Variable var :org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.getVariableValues().keySet())
// org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.setVariableValue(var, forallRuleExecutionEnvironment.getVariableValue(var));
return Boolean.TRUE;
}
*/
private Boolean interpretForallRulewithGTPattern(IExecutionEnvironment executionEnvironment, ForallRule forallBlockRule, IProgressReport pr)
throws ViatraTransformationException {
int i=0;
GTPatternCall forallGTPatternCall = (GTPatternCall)forallBlockRule.getCondition();
PatternMatcherParameters mp;
Collection<IMatching> matches;
// make new execution environment
BlockRuleExecutionEnvironment forallRuleExecutionEnvironment =
BlockRuleInterpreterHelper.getNewExecutionEnvironment(executionEnvironment, forallBlockRule);
//Get scopes from containmentConstraints
HashMap<Variable, Scope> parameterParameterScopes =
BlockRuleInterpreterHelper.getScopesFromContainmentConstraints(forallRuleExecutionEnvironment,forallBlockRule);
//Get patternMatcher
IPatternMatcher patternMatcher;
try{
patternMatcher = PatternMatcherProvider.getInstance().getPatternMatcher(forallRuleExecutionEnvironment,
forallGTPatternCall.getCalledPattern());
// get matcher parameters
mp=
BlockRuleInterpreterHelper.getMatchParameters(
forallRuleExecutionEnvironment,forallBlockRule, parameterParameterScopes);
// get matches
matches =patternMatcher.matchAll(mp.getInputMapping(), mp.getCallSignature(),mp.getQuantificationOrder() );
} catch (ViatraTransformationException e1) {
throw e1.addNewStackElement(forallBlockRule);
}
// reorder if neccessary
matches = BlockRuleInterpreterHelper.
reorder(forallGTPatternCall.getCalledPattern(), matches);
// Assign the parameters to the new exec.environment
for (IMatching match : matches) {
// bind the variables
// Update variables values from the matching
for (i=0;i< forallGTPatternCall.getActualParameters().size();i++) {
// OUTPUT checking
if(mp.getCallSignature()[i].getParameterMode().equals(ParameterMode.OUTPUT))
{ Variable variable = ((VariableReference)forallGTPatternCall.getActualParameters().get(i)).getVariable();
try {
forallRuleExecutionEnvironment.setVariableValue(
variable,
match.lookup(i));
} catch (ViatraTransformationException e) {
String[] context = {variable.getName(),e.getMessage()};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.RULE_INIT_VAR_FORALL
,context
,forallBlockRule );
}
}
}
RuleInterpreter.getInstance().interpretRule(forallRuleExecutionEnvironment,forallBlockRule.getBody(),pr);
//TODO: what if fail???
}
/*************************************************/
// write the changed values back
forallRuleExecutionEnvironment.onTerminate();
for(Variable var :executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var, forallRuleExecutionEnvironment.getVariableValue(var));
/*************************************************/
return Boolean.TRUE;
}
private Boolean interpretChooseRulewithGTPattern(
IExecutionEnvironment executionEnvironment,
ChooseRule chooseBlockRule, IProgressReport pr) throws ViatraTransformationException {
int i= 0;
GTPatternCall chooseGTPatternCall = (GTPatternCall) chooseBlockRule.getCondition();
PatternMatcherParameters mp;
IMatching match;
HashMap<Variable, Scope> parameterParameterScopes = new HashMap<Variable, Scope>();
// Needs a new Exec.env. the new Variables will be added also.
BlockRuleExecutionEnvironment chooseRuleExecutionEnvironment =
BlockRuleInterpreterHelper.getNewExecutionEnvironment(executionEnvironment, chooseBlockRule);
// get scopes
parameterParameterScopes =
BlockRuleInterpreterHelper.getScopesFromContainmentConstraints(chooseRuleExecutionEnvironment, chooseBlockRule);
// is true pseudorandom required?
GTPattern gtPattern = chooseGTPatternCall.getCalledPattern();
boolean isRandom = false;
for (Object annot : gtPattern.getRuntimeAnnotations()) {
if ("@random".equals(((RuntimeAnnotation) annot).getAnnotationName().toLowerCase())) {
isRandom = true; break;
}
}
// Get patternMatcher
IPatternMatcher patternMatcher;
try{
patternMatcher = PatternMatcherProvider.getInstance().getPatternMatcher(chooseRuleExecutionEnvironment, gtPattern);
// get matcher parameters
mp =
BlockRuleInterpreterHelper.getMatchParameters(chooseRuleExecutionEnvironment, chooseBlockRule,
parameterParameterScopes);
// get matches
if (!isRandom) match = patternMatcher.match(mp.getInputMapping(), mp.getCallSignature());
else match = patternMatcher.matchRandomly(mp.getInputMapping(), mp.getCallSignature());
} catch (ViatraTransformationException e1) {
throw e1.addNewStackElement(chooseBlockRule);
}
// no match found
if (match == null)
return Boolean.FALSE;
// Update variables values from the matching
for (i = 0; i < chooseGTPatternCall.getActualParameters().size(); i++) {
if (mp.getCallSignature()[i].getParameterMode().equals(
ParameterMode.OUTPUT)) {
Variable variable = ((VariableReference) chooseGTPatternCall.getActualParameters().get(i)).getVariable();
try {
chooseRuleExecutionEnvironment.setVariableValue(
variable , match.lookup(i));
} catch (ViatraTransformationException e) {
String[] context = {variable.getName(), e.getMessage()};
throw new ASMInterpreterException(
ASMInterpreterErrorStrings.RULE_INIT_VAR_CHOOSE
,context
,chooseBlockRule);
}
}
}
Boolean result = RuleInterpreter.getInstance().interpretRule(chooseRuleExecutionEnvironment
,chooseBlockRule.getBody(),pr);
/** ********************************************** */
// write the changed values back
chooseRuleExecutionEnvironment.onTerminate();
for (Variable var : executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var,
chooseRuleExecutionEnvironment.getVariableValue(var));
/** ********************************************** */
return result;
}
private Boolean interpretChooseRulewithASMFunction(IExecutionEnvironment executionEnvironment, ChooseRule chooseBlockRule, IProgressReport pr)
throws ViatraTransformationException{
// This will list all the values a symbolic variable might hold.
HashMap<Variable, Vector<Object>> valueList = new HashMap<Variable, Vector<Object>>();
Map<Variable, Object> variables = new Hashtable<Variable, Object>(executionEnvironment.getVariableValues());
for (Object variable : chooseBlockRule.getLocalVariables()) {
valueList.put(((Variable) variable), new Vector<Object>());
variables.put((Variable)variable, ValueKind.UNDEF_LITERAL);
}
executionEnvironment.fetchVariableVariations(valueList,chooseBlockRule.getCondition());
// We have a list of possible values for the variables.
// Now we must get each configuration (just as a Cartesian multiplication
// would, but being a lot more efficient), and evaluate them using brute force.
Object[] keys = valueList.keySet().toArray();
// Needs a new Exec.env. the new Variables will be added later.
BlockRuleExecutionEnvironment chooseRuleExecutionEnvironment =
new BlockRuleExecutionEnvironment(executionEnvironment.getFramework(),
chooseBlockRule.getBody());
chooseRuleExecutionEnvironment.onBegin(variables);
// We need a divider vector to be able to iterate through all the variations.
Vector<Integer> divVect = new Vector<Integer>();
divVect.add(new Integer(valueList.get(keys[0]).size()));
Integer maxCount = new Integer(valueList.get(keys[0]).size());
for (int iter = 1; iter < valueList.size(); iter++) {
//divVect.add(valueList.get(keys[iter]).size()
// * divVect.get(iter - 1));
maxCount*=valueList.get(keys[iter]).size();
divVect.add(valueList.get(keys[iter]).size());
// Don't bother, if the function doesn't have any values. In such cases, this speeds up a lot.
if(valueList.get(keys[iter]).size()==0) return Boolean.FALSE;
}
// To speed up things a bit.
//Integer maxCount = divVect.lastElement();
Integer size = divVect.size();
//Evaluate all configurations
for (Integer iter_config = 0; iter_config < maxCount; iter_config++) {
Integer config_no = new Integer(iter_config);
// bind the variables
for (int iter_var = 0; iter_var < size; iter_var++) {
//Integer num=config_no-config_no%(iter_var==0?1:divVect.get(iter_var-1))/divVect.get(iter_var);
Variable variable = (Variable) (valueList.keySet().toArray()[iter_var]);
try {
chooseRuleExecutionEnvironment.setVariableValue(
variable,
valueList.get(valueList.keySet().toArray()[iter_var]).get(config_no % divVect.get(iter_var)));
} catch (ViatraTransformationException e) {
String[] context = {variable.getName(),e.getMessage()};
throw new ASMInterpreterException(ASMInterpreterErrorStrings.RULE_INIT_VAR_ASMFUNCTION
,context
,chooseBlockRule);
}
config_no = (config_no - config_no % divVect.get(iter_var))/divVect.get(iter_var);
}
//evaluate it in a sandbox-like execution environment.
if (Boolean.TRUE.equals(TermEvaluator.getInstance().evaluate(
chooseRuleExecutionEnvironment,
chooseBlockRule.getCondition()))) {
// The condition evaluated to true --> this is a good configuration to interpret
// the actual rule
//TODO: if it fails, what to do?
boolean result = RuleInterpreter.getInstance()
.interpretRule(chooseRuleExecutionEnvironment,
chooseBlockRule.getBody(),pr);
// write the changed values back
chooseRuleExecutionEnvironment.onTerminate();
for(Variable var :executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var, chooseRuleExecutionEnvironment.getVariableValue(var));
return result;
/* ***********************************************************
* The only difference to ForAllRule!!!!!!!!!!!!!!!!!!!!!!!!!
*
* THIS RETURNS ON THE FIRST MATCH!
/* ***********************************************************/
}
//TODO: Akos Horvath check that this changed value back rewriter is required!
chooseRuleExecutionEnvironment.onTerminate();
for(Variable var :executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var, chooseRuleExecutionEnvironment.getVariableValue(var));
}
return Boolean.FALSE;
}
private Boolean interpretChooseRulewithGTRule(IExecutionEnvironment executionEnvironment, ChooseRule chooseBlockRule, IProgressReport pr)
throws ViatraTransformationException{
//CHOOSE with GTRULE
HashMap<Variable, Scope> parameterParameterScopes = new HashMap<Variable, Scope>();
GTRule gtRule = (chooseBlockRule.getGtrule()).getRule();
//Collection<IMatching> lHSmatches;
// Needs a new Exec.env. for the ***DO*** part of the rule
BlockRuleExecutionEnvironment chooseRuleExecutionEnvironment =
BlockRuleInterpreterHelper.getNewExecutionEnvironment(executionEnvironment, chooseBlockRule);
// New GTEXEC. env. for the action part of the gtRule
IExecutionEnvironment gtEnvironment= new BlockRuleExecutionEnvironment(executionEnvironment.getFramework());
// get scopes for the gtRule
parameterParameterScopes = BlockRuleInterpreterHelper.getScopesFromContainmentConstraints(chooseRuleExecutionEnvironment
, chooseBlockRule);
// get matcher parameters
PatternMatcherParameters mp=BlockRuleInterpreterHelper.getGTRuleMatchParameters(chooseRuleExecutionEnvironment
,chooseBlockRule
, parameterParameterScopes
, gtRule
, chooseBlockRule.getGtrule());
// Get patternMatcher
IGTRuleMatcher gtMatcher;
// get matches
Object[] match;
try {
gtMatcher = PatternMatcherProvider.getInstance().getGtRuleMatcher(gtEnvironment,gtRule,mp);
match = gtMatcher.match(mp.getCallSignature(), mp.getInputMapping());
} catch (ViatraTransformationException e1) {
throw e1.addNewStackElement(chooseBlockRule);
}
//Bind the variable for the Do part of the rule
if(match != null)
{
Boolean result= BlockRuleInterpreterHelper.evaulateDoPartofGTRuleInvocation(gtRule
, match
, chooseBlockRule
, chooseRuleExecutionEnvironment
,chooseBlockRule.getGtrule(),pr);
//*************************************************/
// writes the changed values back
chooseRuleExecutionEnvironment.onTerminate();
for(Variable var :executionEnvironment.getVariableValues().keySet())
executionEnvironment.setVariableValue(var, chooseRuleExecutionEnvironment.getVariableValue(var));
//*************************************************/
return result;
}
else // there is no match found, choose rule fails
return Boolean.FALSE;
}
}