diff options
author | dwagelaar | 2015-02-13 12:21:10 +0000 |
---|---|---|
committer | dwagelaar | 2015-02-13 12:21:10 +0000 |
commit | 2dab64d71d280c455351336d31ffe89650271d29 (patch) | |
tree | 11e3bb4c6be1230aa486a4a00db06a45ea08d15a /plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse | |
parent | 40023d506041524802ee376050b865f0393e67eb (diff) | |
download | org.eclipse.atl-2dab64d71d280c455351336d31ffe89650271d29.tar.gz org.eclipse.atl-2dab64d71d280c455351336d31ffe89650271d29.tar.xz org.eclipse.atl-2dab64d71d280c455351336d31ffe89650271d29.zip |
415863: Support (multiple) virtual dispatch for lazy rules
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=415863
Diffstat (limited to 'plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse')
3 files changed, 120 insertions, 4 deletions
diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/Rule.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/Rule.java index 239d362f..4942b3ab 100644 --- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/Rule.java +++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/Rule.java @@ -549,6 +549,19 @@ public interface Rule extends NamedElement { /** * <!-- begin-user-doc --> + * Matches this rule only (without suoer-rules) for <code>valuesMap</code>. + * Call {@link #compileState()} before calling this method. + * @param frame the stack frame in which to execute the matcher + * @param valuesMap the values to match against + * @return <code>true</code> iff the rule matches + * <!-- end-user-doc --> + * @model frameDataType="org.eclipse.m2m.atl.emftvm.StackFrame" + * @generated + */ + boolean matchOneOnly(StackFrame frame, Map<String, Object> valuesMap); + + /** + * <!-- begin-user-doc --> * Creates trace elements for the recorded matches for this rule. * Call {@link #compileState()} before calling this method. * @param frame the stack frame context @@ -612,6 +625,18 @@ public interface Rule extends NamedElement { boolean applyFirst(StackFrame frame); /** + * <!-- begin-user-doc --> + * Applies {@link #getRule()} to <code>trace</code> + * @param frame the stack frame in which to execute the applier and post-apply + * @param trace the source and target values to which to apply the rule + * @return the rule application result + * <!-- end-user-doc --> + * @model frameDataType="org.eclipse.m2m.atl.emftvm.StackFrame" + * @generated + */ + Object applyOne(StackFrame frame, TraceLink trace); + + /** * <!-- begin-user-doc --> * Applies this rule for the given <code>trace</code>. Call {@link #compileState()} before calling this method. * diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/EmftvmPackageImpl.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/EmftvmPackageImpl.java index bcff1330..fb63727a 100644 --- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/EmftvmPackageImpl.java +++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/EmftvmPackageImpl.java @@ -3745,6 +3745,15 @@ public class EmftvmPackageImpl extends EPackageImpl implements EmftvmPackage { g1.getETypeArguments().add(g2); addEParameter(op, g1, "valuesMap", 0, 1, IS_UNIQUE, IS_ORDERED); + op = addEOperation(ruleEClass, theEcorePackage.getEBoolean(), "matchOneOnly", 0, 1, IS_UNIQUE, IS_ORDERED); + addEParameter(op, this.getStackFrame(), "frame", 0, 1, IS_UNIQUE, IS_ORDERED); + g1 = createEGenericType(theEcorePackage.getEMap()); + g2 = createEGenericType(theEcorePackage.getEString()); + g1.getETypeArguments().add(g2); + g2 = createEGenericType(theEcorePackage.getEJavaObject()); + g1.getETypeArguments().add(g2); + addEParameter(op, g1, "valuesMap", 0, 1, IS_UNIQUE, IS_ORDERED); + op = addEOperation(ruleEClass, null, "createTraces", 0, 1, IS_UNIQUE, IS_ORDERED); addEParameter(op, this.getStackFrame(), "frame", 0, 1, IS_UNIQUE, IS_ORDERED); @@ -3761,6 +3770,10 @@ public class EmftvmPackageImpl extends EPackageImpl implements EmftvmPackage { op = addEOperation(ruleEClass, theEcorePackage.getEBoolean(), "applyFirst", 0, 1, IS_UNIQUE, IS_ORDERED); addEParameter(op, this.getStackFrame(), "frame", 0, 1, IS_UNIQUE, IS_ORDERED); + op = addEOperation(ruleEClass, theEcorePackage.getEJavaObject(), "applyOne", 0, 1, IS_UNIQUE, IS_ORDERED); + addEParameter(op, this.getStackFrame(), "frame", 0, 1, IS_UNIQUE, IS_ORDERED); + addEParameter(op, theTracePackage.getTraceLink(), "trace", 0, 1, IS_UNIQUE, IS_ORDERED); + op = addEOperation(ruleEClass, theEcorePackage.getEJavaObject(), "applyFor", 0, 1, IS_UNIQUE, IS_ORDERED); addEParameter(op, this.getStackFrame(), "frame", 0, 1, IS_UNIQUE, IS_ORDERED); addEParameter(op, theTracePackage.getTraceLink(), "trace", 0, 1, IS_UNIQUE, IS_ORDERED); diff --git a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/RuleImpl.java b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/RuleImpl.java index 0ce6078f..48679aab 100644 --- a/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/RuleImpl.java +++ b/plugins/org.eclipse.m2m.atl.emftvm/src/org/eclipse/m2m/atl/emftvm/impl/RuleImpl.java @@ -21,6 +21,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.NotificationChain; @@ -138,7 +139,7 @@ public class RuleImpl extends NamedElementImpl implements Rule { final Object[] values); /** - * + * Matches * @param frame * @param values * @return @@ -179,13 +180,47 @@ public class RuleImpl extends NamedElementImpl implements Rule { assert !isUnique(); final Map<String, Object> valuesMap = createValuesMap(values); if (matchOne(frame, valuesMap)) { - return applyTo(frame, createTrace(frame, valuesMap)); + final Set<Rule> matchedRules = matchManualSubRules(RuleImpl.this, frame, valuesMap); + final int size = matchedRules.size(); + switch (size) { + case 0: + //TODO should not work for abstract rules + return applyOne(frame, createTrace(frame, valuesMap)); + case 1: + return matchedRules.iterator().next().applyOne(frame, createTrace(frame, valuesMap)); + default: + throw new VMException(frame, String.format("More than one matching sub-rule found for %s: %s", + RuleImpl.this, matchedRules)); + } } else { return null; } } /** + * TODO + * @param rule + * @param frame + * @param valuesMap + * @return + */ + private Set<Rule> matchManualSubRules(final Rule rule, final StackFrame frame, final Map<String, Object> valuesMap) { + final Set<Rule> matchedRules = new HashSet<Rule>(); + for (Rule subRule : rule.getESubRules()) { + if (subRule.matchOneOnly(frame, valuesMap)) { + Set<Rule> matchedSubRules = matchManualSubRules(subRule, frame, valuesMap); + if (!matchedSubRules.isEmpty()) { + matchedRules.addAll(matchedSubRules); + } else { + //TODO not for abstract rules + matchedRules.add(subRule); + } + } + } + return matchedRules; + } + + /** * {@inheritDoc} */ @Override @@ -2086,13 +2121,23 @@ public class RuleImpl extends NamedElementImpl implements Rule { * <!-- end-user-doc --> * @generated NOT */ - public boolean matchOne(StackFrame frame, Map<String, Object> valuesMap) { + public boolean matchOne(final StackFrame frame, final Map<String, Object> valuesMap) { for (Rule superRule : getESuperRules()) { if (!superRule.matchOne(frame, valuesMap)) { return false; } } + return matchOneOnly(frame, valuesMap); + } + + /** + * <!-- begin-user-doc. --> + * {@inheritDoc} + * <!-- end-user-doc --> + * @generated NOT + */ + public boolean matchOneOnly(StackFrame frame, Map<String, Object> valuesMap) { // Check value types final ExecEnv env = frame.getEnv(); final Object[] values = createValuesArray(valuesMap); @@ -2124,7 +2169,7 @@ public class RuleImpl extends NamedElementImpl implements Rule { } // Check bound values - final CodeBlock binding = re.getBinding(); + CodeBlock binding = re.getBinding(); if (binding != null) { final Object bvalue = binding.execute(frame.getSubFrame(binding, values)); if (bvalue == null) { @@ -2239,6 +2284,39 @@ public class RuleImpl extends NamedElementImpl implements Rule { * <!-- end-user-doc --> * @generated NOT */ + public Object applyOne(final StackFrame frame, final TraceLink trace) { + Object result = null; + for (Rule rule : getAllESuperRules()) { + if (rule.getApplier() != null) { + result = rule.applyFor(frame, trace); + } else { + rule.applyFor(frame, trace); + } + if (rule.getPostApply() != null) { + result = rule.postApplyFor(frame, trace); + } else { + rule.postApplyFor(frame, trace); + } + } + if (getApplier() != null) { + result = applierCbState.applyFor(frame, trace); + } else { + applierCbState.applyFor(frame, trace); + } + if (getPostApply() != null) { + result = applierCbState.postApplyFor(frame, trace); + } else { + applierCbState.postApplyFor(frame, trace); + } + return result; + } + + /** + * <!-- begin-user-doc. --> + * {@inheritDoc} + * <!-- end-user-doc --> + * @generated NOT + */ public Object applyFor(final StackFrame frame, final TraceLink trace) { return applierCbState.applyFor(frame, trace); } |