| /******************************************************************************* |
| * 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;
|
| }
|
| }
|