Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Willink2019-12-03 09:54:46 +0000
committerEd Willink2019-12-03 11:21:29 +0000
commit04a0568279ee7f6dc9aefa7d132225029442df20 (patch)
tree2a6123df839de8578c774ab41b5cdd0087a4b50e
parent7f1f860364bea1eba6adf6edeb64310babd7ed23 (diff)
downloadorg.eclipse.qvtd-04a0568279ee7f6dc9aefa7d132225029442df20.tar.gz
org.eclipse.qvtd-04a0568279ee7f6dc9aefa7d132225029442df20.tar.xz
org.eclipse.qvtd-04a0568279ee7f6dc9aefa7d132225029442df20.zip
Accommodate non-null optional when heads
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RegionHelper.java47
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractInvocationAnalysis.java9
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractWhenInvocationAnalysis.java2
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/RelationAnalysis.java39
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/TopWhenInvocationAnalysis.java43
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtschedule/emf-gen/org/eclipse/qvtd/pivot/qvtschedule/impl/MappingNodeImpl.java12
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/InitUtility.java20
7 files changed, 147 insertions, 25 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RegionHelper.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RegionHelper.java
index 2723a5646..ea00bb27f 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RegionHelper.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RegionHelper.java
@@ -102,6 +102,7 @@ import org.eclipse.qvtd.pivot.qvtschedule.TuplePartEdge;
import org.eclipse.qvtd.pivot.qvtschedule.TypeLiteralNode;
import org.eclipse.qvtd.pivot.qvtschedule.UnknownNode;
import org.eclipse.qvtd.pivot.qvtschedule.VariableNode;
+import org.eclipse.qvtd.pivot.qvtschedule.impl.MappingNodeImpl;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.DomainUsage;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.InitUtility;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil;
@@ -154,6 +155,9 @@ public class RegionHelper<R extends Region> extends QVTscheduleUtil implements N
if (booleanLiteralExp != null) {
booleanLiteralNode.setOriginatingElement(booleanLiteralExp);
}
+ else if (utility.isNullable()) {
+ ((MappingNodeImpl)booleanLiteralNode).setRequiredOverride(false);
+ }
return booleanLiteralNode;
}
@@ -502,6 +506,32 @@ public class RegionHelper<R extends Region> extends QVTscheduleUtil implements N
return node;
}
+ @Deprecated /* @deprecated temporary ability to identify when isRequired is 'wrong' wrt variable,isRequired*/
+ public @NonNull VariableNode createOldNode2(@NonNull InitUtility utility, @NonNull VariableDeclaration variable) {
+ Role nodeRole;
+ boolean isThis = QVTbaseUtil.isThis(variable);
+ if (isThis) {
+ nodeRole = Role.LOADED;
+ }
+ else if (scheduleManager.isInput(scheduleManager.getDomainUsage(variable))) {
+ nodeRole = Role.LOADED;
+ }
+ else {
+ nodeRole = Role.PREDICATED;
+ }
+ ClassDatum classDatum = scheduleManager.getClassDatum(variable);
+ PatternVariableNode node = QVTscheduleFactory.eINSTANCE.createPatternVariableNode();
+ node.initialize(nodeRole, region, utility, getName(variable), classDatum);
+ ((MappingNodeImpl)node).setRequiredOverride(true);
+ node.initializeVariable(region, variable);
+ node.setMatched(QVTrelationUtil.isRequired(variable));
+ if (isThis) {
+ node.setThis();
+ node.setHead();
+ }
+ return node;
+ }
+
public @NonNull OperationCallNode createOperationCallNode(@NonNull InitUtility utility, @Nullable String nameHint, @NonNull Operation operation, @NonNull TypedElement callExpOrCollectionTemplateExp, @NonNull Node ... argNodes) {
String name = nameHint;
if (name == null) {
@@ -595,6 +625,15 @@ public class RegionHelper<R extends Region> extends QVTscheduleUtil implements N
return node;
}
+ @Deprecated /* @deprecated temporary ability to identify when isRequired is 'wrong' wrt variable,isRequired*/
+ public @NonNull Node createPredicatedNode2(@NonNull InitUtility utility, @NonNull String name, @NonNull ClassDatum classDatum, boolean isMatched, boolean isRequiredOverride) {
+ PatternTypedNode node = QVTscheduleFactory.eINSTANCE.createPatternTypedNode();
+ node.initialize(Role.PREDICATED, region, utility, name, classDatum);
+ ((MappingNodeImpl)node).setRequiredOverride(isRequiredOverride);
+ node.setMatched(isMatched);
+ return node;
+ }
+
public @NonNull Node createPredicatedStepNode(@NonNull InitUtility utility, @NonNull Node typedNode, boolean isMatched) {
String name = getName(typedNode);
ClassDatum classDatum = getClassDatum(typedNode);
@@ -645,6 +684,14 @@ public class RegionHelper<R extends Region> extends QVTscheduleUtil implements N
return node;
}
+ @Deprecated /* @deprecated temporary ability to identify when isRequired is 'wrong' wrt variable,isRequired*/
+ public @NonNull VariableNode createRealizedStepNode2(@NonNull InitUtility initUtility, @NonNull VariableDeclaration stepVariable) {
+ VariableNode node = createRealizedNode(initUtility, getName(stepVariable), scheduleManager.getClassDatum(stepVariable), true);
+ ((MappingNodeImpl)node).setRequiredOverride(true);
+ node.initializeVariable(region, stepVariable);
+ return node;
+ }
+
public @NonNull VariableNode createRealizedStepNode(@NonNull InitUtility initUtility, @NonNull VariableDeclaration stepVariable) {
VariableNode node = createRealizedNode(initUtility, getName(stepVariable), scheduleManager.getClassDatum(stepVariable), true);
node.initializeVariable(region, stepVariable);
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractInvocationAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractInvocationAnalysis.java
index c0b8d0eca..03162e1f0 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractInvocationAnalysis.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractInvocationAnalysis.java
@@ -165,7 +165,14 @@ public abstract class AbstractInvocationAnalysis implements InvocationAnalysis
* Return false since all where and many when matches are optional.
*/
@Override
- public boolean isMatched() {
+ public final boolean isMatched() {
+ boolean isMatched1 = !initUtility.isNullable();
+ boolean isMatched2 = isMatchedInternal();
+ assert isMatched1 == isMatched2;
+ return isMatched2;
+ }
+
+ protected boolean isMatchedInternal() {
return false;
}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractWhenInvocationAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractWhenInvocationAnalysis.java
index ee2e19e63..cbfe530a6 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractWhenInvocationAnalysis.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/AbstractWhenInvocationAnalysis.java
@@ -84,7 +84,7 @@ public abstract class AbstractWhenInvocationAnalysis extends AbstractInvocationA
* Return true since non-top and some top when matches are required.
*/
@Override
- public boolean isMatched() {
+ protected boolean isMatchedInternal() {
return true;
}
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/RelationAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/RelationAnalysis.java
index 875edae52..623c3fe94 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/RelationAnalysis.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/RelationAnalysis.java
@@ -689,10 +689,10 @@ public class RelationAnalysis extends RuleAnalysis
}
else {
if (hasWhenAndWhereInvocations) {
- invocationAnalysis = new NonTopWhereBeforeWhenInvocationAnalysis(this, invokedRelationAnalysis, initUtility, rootVariable2argumentNode);
+ invocationAnalysis = new NonTopWhereBeforeWhenInvocationAnalysis(this, invokedRelationAnalysis, initUtility.getNullableUtility(), rootVariable2argumentNode);
}
else {
- invocationAnalysis = new NonTopWhereOnlyInvocationAnalysis(this, invokedRelationAnalysis, initUtility, rootVariable2argumentNode);
+ invocationAnalysis = new NonTopWhereOnlyInvocationAnalysis(this, invokedRelationAnalysis, initUtility.getNullableUtility(), rootVariable2argumentNode);
}
}
}
@@ -1889,7 +1889,12 @@ public class RelationAnalysis extends RuleAnalysis
createOldNode(InitUtility.getRequiredInitUtility(variableDeclaration), variableDeclaration); // where 'output' is created by invoker
}
else if (getRealizedOutputVariables().contains(variableDeclaration)) {
- createRealizedStepNode(InitUtility.getRequiredInitUtility(variableDeclaration), variableDeclaration);
+ if (isOptionallyMatchedAtRoot(variableDeclaration)) {
+ createRealizedStepNode2(InitUtility.NON_NULL_MATCHED, variableDeclaration);
+ }
+ else {
+ createRealizedStepNode(InitUtility.getRequiredInitUtility(variableDeclaration), variableDeclaration);
+ }
}
else {
if (variableDeclaration instanceof TemplateVariable) {
@@ -1899,8 +1904,8 @@ public class RelationAnalysis extends RuleAnalysis
return; // CollectionTemplateExp variables would be bloat
// }
}
- if (Iterables.contains(QVTrelationUtil.getRootVariables(getRule()), variableDeclaration)) { // && isMatched(getRule())) {
- createOldNode(InitUtility.getRequiredInitUtility(variableDeclaration), variableDeclaration); // FIXME allow nullable
+ if (isOptionallyMatchedAtRoot(variableDeclaration)) {
+ createOldNode2(InitUtility.NON_NULL_MATCHED, variableDeclaration); // FIXME allow nullable
}
else {
createOldNode(InitUtility.getRequiredInitUtility(variableDeclaration), variableDeclaration);
@@ -1921,6 +1926,30 @@ public class RelationAnalysis extends RuleAnalysis
}
}
+ /**
+ * Return true unless a non-match is permitted for null input to null output. (See Bug 499432)
+ * @param variableDeclaration
+ */
+ public boolean isOptionallyMatchedAtRoot(@NonNull VariableDeclaration variableDeclaration) {
+ boolean anyRequired = false;
+ boolean isRootVariable = false;
+ for (@NonNull VariableDeclaration rootVariable : QVTrelationUtil.getRootVariables(getRule())) {
+ if (rootVariable == variableDeclaration) {
+ isRootVariable = true;
+ }
+ if (rootVariable.isIsRequired()) {
+ anyRequired = true;
+ }
+ }
+ if (!isRootVariable) { // Non-root is not
+ return false; // a root match
+ }
+ if (anyRequired) { // If any root cannot be null
+ return false; // a match is required
+ }
+ return true; // Match can be omitted
+ }
+
protected boolean synthesizeVariableEqualsPredicate(@NonNull VariableDeclaration variable, @NonNull OCLExpression valueExp) {
Node variableNode = region.getNode(variable);
if (variableNode == null) {
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/TopWhenInvocationAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/TopWhenInvocationAnalysis.java
index 901df48e2..438904bcf 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/TopWhenInvocationAnalysis.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/TopWhenInvocationAnalysis.java
@@ -24,22 +24,11 @@ import org.eclipse.qvtd.pivot.qvtschedule.utilities.InitUtility;
*/
public class TopWhenInvocationAnalysis extends AbstractWhenInvocationAnalysis
{
- public TopWhenInvocationAnalysis(@NonNull RelationAnalysis invokingRelationAnalysis, @NonNull RelationAnalysis invokedRelationAnalysis,
- @NonNull InitUtility initUtility, @NonNull Map<@NonNull VariableDeclaration, @NonNull Node> rootVariable2argumentNode) {
- super(invokingRelationAnalysis, invokedRelationAnalysis, initUtility, rootVariable2argumentNode);
- }
-
- @Override
- protected @NonNull Node createInvocationNode(@NonNull String name, @NonNull ClassDatum classDatum, boolean isMatched) {
- return invokingRelationAnalysis.createPredicatedNode(initUtility, name, classDatum, isMatched);
- }
-
-
/**
- * Return true unless a non-match is permitted for null input to null output. (See Bug 499432)
+ * Return true unless a non-match is permitted and used for null input to null output. (See Bug 499432)
*/
- @Override
- public boolean isMatched() {
+ // @Override
+ private static @NonNull InitUtility resolveInitUtility(@NonNull InitUtility initUtility, @NonNull Map<@NonNull VariableDeclaration, @NonNull Node> rootVariable2argumentNode) {
boolean anyRequired = false;
boolean anyOmitted = false;
for (@NonNull VariableDeclaration rootVariable : rootVariable2argumentNode.keySet()) {
@@ -53,12 +42,32 @@ public class TopWhenInvocationAnalysis extends AbstractWhenInvocationAnalysis
}
}
if (anyRequired) { // If any root cannot be null
- return true; // a match is required
+ return initUtility; // a match is required
}
if (!anyOmitted) { // If nothing omitted
- return true; // a match is required
+ return initUtility; // a match is required
}
- return false; // Match can be omitted
+ return initUtility.isConditional() ? InitUtility.NULLABLE_CONDITIONAL: InitUtility.NULLABLE_MATCHED; // Match can be omitted
+ }
+
+ public TopWhenInvocationAnalysis(@NonNull RelationAnalysis invokingRelationAnalysis, @NonNull RelationAnalysis invokedRelationAnalysis,
+ @NonNull InitUtility initUtility, @NonNull Map<@NonNull VariableDeclaration, @NonNull Node> rootVariable2argumentNode) {
+ super(invokingRelationAnalysis, invokedRelationAnalysis, resolveInitUtility(initUtility, rootVariable2argumentNode), rootVariable2argumentNode);
+ }
+
+ @Override
+ protected @NonNull Node createInvocationNode(@NonNull String name, @NonNull ClassDatum classDatum, boolean isMatched) {
+ if (initUtility.isNullable()) {
+ return invokingRelationAnalysis.createPredicatedNode2(initUtility, name, classDatum, isMatched, false);
+ }
+ else {
+ return invokingRelationAnalysis.createPredicatedNode(initUtility, name, classDatum, isMatched);
+ }
+ }
+
+ @Override
+ protected boolean isMatchedInternal() {
+ return !initUtility.isNullable();
}
@Override
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtschedule/emf-gen/org/eclipse/qvtd/pivot/qvtschedule/impl/MappingNodeImpl.java b/plugins/org.eclipse.qvtd.pivot.qvtschedule/emf-gen/org/eclipse/qvtd/pivot/qvtschedule/impl/MappingNodeImpl.java
index 8c50fec33..f56975fc0 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtschedule/emf-gen/org/eclipse/qvtd/pivot/qvtschedule/impl/MappingNodeImpl.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtschedule/emf-gen/org/eclipse/qvtd/pivot/qvtschedule/impl/MappingNodeImpl.java
@@ -249,6 +249,7 @@ public abstract class MappingNodeImpl extends NodeImpl implements MappingNode {
@Override
public boolean isRequired() {
boolean superIsRequired = super.isRequired();
+ boolean isRequired = isRequiredOverride != null ? isRequiredOverride : this.isRequired;
assert superIsRequired == isRequired;
return isRequired;
}
@@ -275,7 +276,7 @@ public abstract class MappingNodeImpl extends NodeImpl implements MappingNode {
else if (originatingElements.size() == 0) { // Normal initialization of variable
originatingVariable = variable;
originatingElements.add(variable);
- isRequired = variable.isIsRequired();
+ isRequired = isRequiredOverride != null ? isRequiredOverride : variable.isIsRequired();
assert isRequired == !getInitUtility().isNullable();
}
else { // Binding of a variable to its initializer
@@ -286,6 +287,15 @@ public abstract class MappingNodeImpl extends NodeImpl implements MappingNode {
}
}
+ @Deprecated /* @deprecated */
+ private @Nullable Boolean isRequiredOverride = null;
+
+ @Deprecated /* @deprecated temporary ability to identify when isRequired is 'wrong' wrt variable,isRequired*/
+ public void setRequiredOverride(boolean isRequired) {
+ isRequiredOverride = isRequired;
+ // this.isRequired = isRequired;
+ }
+
@Override
public @NonNull String toString() {
return super.toString();
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/InitUtility.java b/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/InitUtility.java
index cd67ffb0c..b57304144 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/InitUtility.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtschedule/src/org/eclipse/qvtd/pivot/qvtschedule/utilities/InitUtility.java
@@ -46,6 +46,26 @@ public enum InitUtility {
return (this == NON_NULL_CONDITIONAL) || (this == NULLABLE_CONDITIONAL);
}
+ public @NonNull InitUtility getConditionalUtility() {
+ switch(this) {
+ case NON_NULL_CONDITIONAL: return NON_NULL_CONDITIONAL;
+ case NON_NULL_MATCHED: return NON_NULL_CONDITIONAL;
+ case NULLABLE_CONDITIONAL: return NULLABLE_CONDITIONAL;
+ case NULLABLE_MATCHED: return NULLABLE_CONDITIONAL;
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ public @NonNull InitUtility getNullableUtility() {
+ switch(this) {
+ case NON_NULL_CONDITIONAL: return NULLABLE_CONDITIONAL;
+ case NON_NULL_MATCHED: return NULLABLE_MATCHED;
+ case NULLABLE_CONDITIONAL: return NULLABLE_CONDITIONAL;
+ case NULLABLE_MATCHED: return NULLABLE_MATCHED;
+ }
+ throw new UnsupportedOperationException();
+ }
+
public boolean isMatchedAsMatchedUtility() {
return (this == InitUtility.NON_NULL_MATCHED) || (this == InitUtility.NULLABLE_MATCHED) || (this == TRACE) || (this == DISPATCH);
}

Back to the top