Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Willink2016-10-24 17:59:14 +0000
committerEd Willink2016-10-30 11:38:52 +0000
commita0df6f39f412658c038f7fc0b52f8a4880f4d993 (patch)
tree29f5ea8e799060f2fd024b484c9b41dd7b0551e4 /plugins
parent27b3353ed9790a71864591a30e59eeb688cd3a0c (diff)
downloadorg.eclipse.qvtd-a0df6f39f412658c038f7fc0b52f8a4880f4d993.tar.gz
org.eclipse.qvtd-a0df6f39f412658c038f7fc0b52f8a4880f4d993.tar.xz
org.eclipse.qvtd-a0df6f39f412658c038f7fc0b52f8a4880f4d993.zip
[500962] Test AbstractInvocationConstructor and its Binders
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/RootRegion2Mapping.java36
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/AbstractInterpretedInvocation.java44
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java27
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java271
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiExecutor.java2
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java8
-rw-r--r--plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java4
-rw-r--r--plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java327
8 files changed, 524 insertions, 195 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/RootRegion2Mapping.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/RootRegion2Mapping.java
index 5d161847a..5296de421 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/RootRegion2Mapping.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvts2qvti/RootRegion2Mapping.java
@@ -21,15 +21,12 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.AnyType;
-import org.eclipse.ocl.pivot.CollectionKind;
-import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.DataType;
import org.eclipse.ocl.pivot.InvalidType;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Operation;
-import org.eclipse.ocl.pivot.PivotFactory;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
@@ -40,7 +37,6 @@ import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
-import org.eclipse.ocl.pivot.utilities.TypeUtil;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.ClassDatumAnalysis;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.Edge;
import org.eclipse.qvtd.compiler.internal.qvtp2qvts.NavigableEdge;
@@ -56,6 +52,7 @@ import org.eclipse.qvtd.pivot.qvtimperative.ConnectionVariable;
import org.eclipse.qvtd.pivot.qvtimperative.DeclareStatement;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTypedModel;
import org.eclipse.qvtd.pivot.qvtimperative.MappingParameter;
+import org.eclipse.qvtd.pivot.qvtimperative.Statement;
public class RootRegion2Mapping extends AbstractScheduledRegion2Mapping
{
@@ -155,19 +152,11 @@ public class RootRegion2Mapping extends AbstractScheduledRegion2Mapping
connection2variable.put(rootConnection, createRootConnectionVariable(name, commonType, initExpression));
}
else if (commonType instanceof CollectionType) {
- CollectionLiteralExp initExpression = PivotFactory.eINSTANCE.createCollectionLiteralExp();
- initExpression.setType(commonType);
- initExpression.setKind(TypeUtil.getCollectionKind((CollectionType) commonType));
- initExpression.setIsRequired(true);
- connection2variable.put(rootConnection, createRootConnectionVariable(name, commonType, initExpression));
+ connection2variable.put(rootConnection, createRootConnectionVariable(name, commonType, null));
}
else {
- CollectionLiteralExp initExpression = PivotFactory.eINSTANCE.createCollectionLiteralExp();
CollectionType setType = visitor.getEnvironmentFactory().getCompleteEnvironment().getSetType(commonType, true, null, null);
- initExpression.setType(setType);
- initExpression.setKind(CollectionKind.SET);
- initExpression.setIsRequired(true);
- connection2variable.put(rootConnection, createRootConnectionVariable(name, setType, initExpression));
+ connection2variable.put(rootConnection, createRootConnectionVariable(name, setType, null));
}
}
}
@@ -253,8 +242,14 @@ public class RootRegion2Mapping extends AbstractScheduledRegion2Mapping
}
}
} */
+ List<Statement> ownedStatements = mapping.getOwnedStatements();
for (@NonNull Region callableRegion : region.getCallableChildren()) {
- mapping.getOwnedStatements().add(createCall(callableRegion, null));
+ if (isInstall(callableRegion)) {
+ ownedStatements.add(createInstall(callableRegion));
+ }
+ else {
+ ownedStatements.add(createCall(callableRegion, null));
+ }
}
}
@@ -326,4 +321,15 @@ public class RootRegion2Mapping extends AbstractScheduledRegion2Mapping
}
return commonType;
}
+
+ protected boolean isInstall(@NonNull Region calledRegion) {
+ AbstractRegion2Mapping calledRegion2Mapping = visitor.getRegion2Mapping(calledRegion);
+ for (@NonNull Node calledGuardNode : calledRegion2Mapping.getGuardNodes()) {
+ NodeConnection callingConnection = calledGuardNode.getIncomingPassedConnection();
+ if (callingConnection == null) {
+ return false;
+ }
+ }
+ return true;
+ }
} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/AbstractInterpretedInvocation.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/AbstractInterpretedInvocation.java
new file mode 100644
index 000000000..3b90fc3cb
--- /dev/null
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/AbstractInterpretedInvocation.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Willink Transformations and others.
+ * 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:
+ * E.D.Willink - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.qvtd.pivot.qvtimperative.evaluation;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.ids.IdResolver;
+import org.eclipse.qvtd.runtime.evaluation.AbstractInvocation;
+import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor;
+
+public abstract class AbstractInterpretedInvocation extends AbstractInvocation
+{
+ protected final @NonNull Object @NonNull [] values;
+
+ public AbstractInterpretedInvocation(@NonNull InvocationConstructor constructor, @NonNull Object @NonNull [] theseValues) {
+ super(constructor);
+ int iMax = theseValues.length;
+ this.values = new @NonNull Object[iMax];
+ for (int i = 0; i < iMax; i++) {
+ this.values[i] = theseValues[i];
+ }
+ }
+
+ @Override
+ public boolean isEqual(@NonNull IdResolver idResolver, @NonNull Object @NonNull [] thoseValues) {
+ int iMax = thoseValues.length;
+ if (iMax != values.length) {
+ return false;
+ }
+ for (int i = 0; i < iMax; i++) {
+ if (!idResolver.oclEquals(values[i], thoseValues[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java
index f393ed0f3..f3dd6689a 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/BasicQVTiExecutor.java
@@ -12,6 +12,7 @@ package org.eclipse.qvtd.pivot.qvtimperative.evaluation;
import java.io.IOException;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -48,7 +49,6 @@ import org.eclipse.qvtd.pivot.qvtbase.Function;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseUtil;
import org.eclipse.qvtd.pivot.qvtimperative.AppendParameterBinding;
-import org.eclipse.qvtd.pivot.qvtimperative.ConnectionVariable;
import org.eclipse.qvtd.pivot.qvtimperative.GuardParameterBinding;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTransformation;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTypedModel;
@@ -63,6 +63,7 @@ import org.eclipse.qvtd.pivot.qvtimperative.SimpleParameterBinding;
import org.eclipse.qvtd.pivot.qvtimperative.Statement;
import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil;
import org.eclipse.qvtd.runtime.evaluation.AbstractTransformer;
+import org.eclipse.qvtd.runtime.evaluation.Interval;
import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException;
public abstract class BasicQVTiExecutor extends AbstractExecutor implements QVTiExecutor
@@ -72,6 +73,7 @@ public abstract class BasicQVTiExecutor extends AbstractExecutor implements QVTi
private @Nullable QVTiModelManager modelManager = null;
protected final boolean debugExceptions = AbstractTransformer.EXCEPTIONS.isActive();
protected final boolean debugInvocations = AbstractTransformer.INVOCATIONS.isActive();
+ private final @NonNull Map<@NonNull Mapping, @NonNull Interval> mapping2interval = new HashMap<>();;
public BasicQVTiExecutor(@NonNull QVTiEnvironmentFactory environmentFactory, @NonNull ImperativeTransformation transformation) {
super(environmentFactory);
@@ -164,6 +166,12 @@ public abstract class BasicQVTiExecutor extends AbstractExecutor implements QVTi
return (QVTiEvaluationEnvironment) super.getEvaluationEnvironment();
}
+ @Override
+ public @NonNull Interval getInterval(@NonNull Mapping asMapping) {
+ Interval interval = mapping2interval.get(asMapping);
+ return ClassUtil.nonNullState(interval);
+ }
+
/**
* Gets the named TypedModel.
*/
@@ -248,17 +256,21 @@ public abstract class BasicQVTiExecutor extends AbstractExecutor implements QVTi
int index = 0;
for (MappingParameterBinding binding : mappingCall.getBinding()) {
MappingParameter boundVariable = ClassUtil.nonNullState(binding.getBoundVariable());
+ Object boundValue = boundValues[index++];
if (binding instanceof AppendParameterBinding) { // FIXME visit the bindings
- replace(boundVariable, boundValues[index++], !(boundVariable instanceof ConnectionVariable)); // FIXME static type conformance test
+ replace(boundVariable, boundValue, false);
}
else if (binding instanceof GuardParameterBinding) {
- replace(boundVariable, boundValues[index++], !(boundVariable instanceof ConnectionVariable)); // FIXME static type conformance test
+ // if (boundValue instanceof Connection) {
+ // boundValue = ((Connection)boundValue).
+ // }
+ replace(boundVariable, boundValue, ((GuardParameterBinding)binding).isIsCheck());
}
else if (binding instanceof LoopParameterBinding) {
- replace(boundVariable, boundValues[index++], !(boundVariable instanceof ConnectionVariable)); // FIXME static type conformance test
+ replace(boundVariable, boundValue, ((LoopParameterBinding)binding).isIsCheck());
}
else if (binding instanceof SimpleParameterBinding) {
- replace(boundVariable, boundValues[index++], !(boundVariable instanceof ConnectionVariable)); // FIXME static type conformance test
+ replace(boundVariable, boundValue, ((SimpleParameterBinding)binding).isIsCheck());
}
else {
assert false;
@@ -354,10 +366,13 @@ public abstract class BasicQVTiExecutor extends AbstractExecutor implements QVTi
@Override
public @Nullable Object internalExecuteTransformation(@NonNull ImperativeTransformation transformation, @NonNull EvaluationVisitor undecoratedVisitor) {
Mapping rule = QVTimperativeUtil.getOwnedMapping(transformation, QVTimperativeUtil.ROOT_MAPPING_NAME);
+ // assert rule == transformation.getRule().get(0);
CallExp callExp = PivotFactory.eINSTANCE.createOperationCallExp(); // FIXME TransformationCallExp
pushEvaluationEnvironment(rule, (TypedElement)callExp);
try {
- rule.accept(undecoratedVisitor);
+ Interval rootInterval = getInvocationManager().getRootInterval();
+ mapping2interval.put(rule, rootInterval);
+ rule.accept(undecoratedVisitor); // Use an outer InvocationConstructor?
getInvocationManager().flush();
}
finally {
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java
index 6135003de..691a5fe23 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiEvaluationVisitor.java
@@ -28,7 +28,6 @@ import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.CollectionValue;
-import org.eclipse.ocl.pivot.values.CollectionValue.Accumulator;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.qvtd.pivot.qvtbase.BaseModel;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
@@ -67,6 +66,9 @@ import org.eclipse.qvtd.pivot.qvtimperative.SimpleParameterBinding;
import org.eclipse.qvtd.pivot.qvtimperative.Statement;
import org.eclipse.qvtd.pivot.qvtimperative.VariableStatement;
import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil;
+import org.eclipse.qvtd.runtime.evaluation.Connection;
+import org.eclipse.qvtd.runtime.evaluation.Interval;
+import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor;
import org.eclipse.qvtd.runtime.evaluation.InvocationFailedException;
/**
@@ -86,18 +88,18 @@ public class QVTiEvaluationVisitor extends BasicEvaluationVisitor implements IQV
private @Nullable Object doConnectionAccumulation(@NonNull ConnectionVariable targetVariable, @NonNull OCLExpression valueExpression) {
try {
- Object connection = executor.getValueOf(targetVariable);
- CollectionValue.Accumulator connectionCollection = (Accumulator) ValueUtil.asCollectionValue(connection);
+ Object targetValue = ClassUtil.nonNullState(executor.getValueOf(targetVariable));
+ Connection connectionCollection = (Connection) targetValue;
Object values = valueExpression.accept(undecoratedVisitor);
- if (values instanceof Iterable<?>) {
- CollectionValue valuesCollection = ValueUtil.asCollectionValue(values);
- for (Object value : valuesCollection) {
- connectionCollection.add(value);
- }
- }
- else {
- connectionCollection.add(values);
- }
+ // if (values instanceof Iterable<?>) {
+ // CollectionValue valuesCollection = ValueUtil.asCollectionValue(values);
+ // for (Object value : valuesCollection) {
+ // connectionCollection.append(value);
+ // }
+ // }
+ // else {
+ connectionCollection.append(values);
+ // }
return connectionCollection;
}
catch (RuntimeException e) {
@@ -106,6 +108,133 @@ public class QVTiEvaluationVisitor extends BasicEvaluationVisitor implements IQV
}
}
+ private @Nullable Object doMappingCall(@NonNull MappingCall mappingCall) {
+ Mapping referredMapping = mappingCall.getReferredMapping();
+ if (referredMapping == null) {
+ return null;
+ }
+ @NonNull Object @NonNull [] boundValues = new @NonNull Object[mappingCall.getBinding().size()];
+ int index = 0;
+ for (MappingParameterBinding binding : mappingCall.getBinding()) {
+ VariableDeclaration boundVariable = binding.getBoundVariable();
+ if (boundVariable == null) {
+ return null;
+ }
+ if (binding instanceof AppendParameterBinding) { // FIXME visit the bindings
+ AppendParameterBinding appendParameterBinding = (AppendParameterBinding)binding;
+ ConnectionVariable value = appendParameterBinding.getValue();
+ if (value == null) {
+ return null;
+ }
+ Object valueOrValues = executor.getValueOf(value);
+ if (valueOrValues == null) {
+ return null;
+ }
+ boundValues[index++] = valueOrValues;
+ }
+ else if (binding instanceof GuardParameterBinding) {
+ Type varType = boundVariable.getType();
+ if (varType == null) {
+ return null;
+ }
+ GuardParameterBinding guardParameterBinding = (GuardParameterBinding)binding;
+ ConnectionVariable value = guardParameterBinding.getValue();
+ if (value == null) {
+ return null;
+ }
+ Object valueOrValues = executor.getValueOf(value);
+ if (valueOrValues == null) {
+ return null;
+ }
+ Type valueType = idResolver.getDynamicTypeOf(valueOrValues);
+ if (!guardParameterBinding.isIsCheck() || valueType.conformsTo(environmentFactory.getStandardLibrary(), varType)) {
+ boundValues[index++] = valueOrValues;
+ }
+ else {
+ return null;
+ }
+ }
+ else if (binding instanceof LoopParameterBinding) {
+ Type varType = boundVariable.getType();
+ if (varType == null) {
+ return null;
+ }
+ LoopParameterBinding guardParameterBinding = (LoopParameterBinding)binding;
+ LoopVariable value = guardParameterBinding.getValue();
+ if (value == null) {
+ return null;
+ }
+ Object valueOrValues = executor.getValueOf(value);
+ if (valueOrValues == null) {
+ return null;
+ }
+ Type valueType = idResolver.getDynamicTypeOf(valueOrValues);
+ if (!guardParameterBinding.isIsCheck() || valueType.conformsTo(environmentFactory.getStandardLibrary(), varType)) {
+ boundValues[index++] = valueOrValues;
+ }
+ else {
+ return null;
+ }
+ }
+ else if (binding instanceof SimpleParameterBinding) {
+ Type varType = boundVariable.getType();
+ if (varType == null) {
+ return null;
+ }
+ SimpleParameterBinding simpleParameterBinding = (SimpleParameterBinding)binding;
+ OCLExpression value = simpleParameterBinding.getValue();
+ if (value == null) {
+ return null;
+ }
+ Object valueOrValues = value.accept(undecoratedVisitor);
+ if (valueOrValues == null) {
+ return null;
+ }
+ assert !(boundVariable instanceof ConnectionVariable);
+ // boundValues[index++] = valueOrValues;
+
+ // }
+ // else {
+ Type valueType = idResolver.getDynamicTypeOf(valueOrValues);
+ if (!simpleParameterBinding.isIsCheck() || valueType.conformsTo(environmentFactory.getStandardLibrary(), varType)) {
+ boundValues[index++] = valueOrValues;
+ }
+ else {
+ return null;
+ }
+ // }
+ }
+ }
+ return executor.internalExecuteMappingCall(mappingCall, boundValues, undecoratedVisitor);
+ }
+
+ private @Nullable Object doMappingInstall(@NonNull MappingCall mappingCall) {
+ Mapping referredMapping = mappingCall.getReferredMapping();
+ if (referredMapping == null) {
+ return null;
+ }
+ InvocationConstructor invocationConstructor = executor.getInvocationConstructor(mappingCall, undecoratedVisitor);
+ List<MappingParameterBinding> mappingBindings = mappingCall.getBinding();
+ assert mappingBindings != null;
+ for (MappingParameterBinding asMappingCallBinding : mappingBindings) {
+ if (asMappingCallBinding instanceof GuardParameterBinding) {
+ ConnectionVariable connectionVariable = ((GuardParameterBinding)asMappingCallBinding).getValue();
+ assert connectionVariable != null;
+ Object value = executor.getValueOf(connectionVariable);
+ assert value != null;
+ invocationConstructor.addConsumedConnection((Connection) value);
+ }
+ else if (asMappingCallBinding instanceof AppendParameterBinding) {
+ ConnectionVariable connectionVariable = ((AppendParameterBinding)asMappingCallBinding).getValue();
+ assert connectionVariable != null;
+ Object value = executor.getValueOf(connectionVariable);
+ assert value != null;
+ invocationConstructor.addAppendedConnection((Connection) value);
+ }
+ }
+ return Boolean.TRUE;
+ }
+
@Override
public @Nullable Object visitAddStatement(@NonNull AddStatement connectionStatement) {
ConnectionVariable targetVariable = connectionStatement.getTargetVariable() ;
@@ -160,21 +289,27 @@ public class QVTiEvaluationVisitor extends BasicEvaluationVisitor implements IQV
@Override
public Object visitBufferStatement(@NonNull BufferStatement object) {
- CollectionValue.Accumulator accumulator;
+ Mapping asMapping = QVTimperativeUtil.getContainingMapping(object);
+ assert asMapping != null;
+ Interval interval = executor.getInterval(asMapping);
+ Connection connection = null;
OCLExpression ownedExpression = object.getOwnedExpression();
+ String name = object.getName();
+ assert name != null;
if (ownedExpression != null) {
Object initValue = ownedExpression.accept(undecoratedVisitor);
- accumulator = ValueUtil.createCollectionAccumulatorValue((CollectionTypeId) ownedExpression.getTypeId());
+ connection = interval.createConnection(name, (CollectionTypeId) ownedExpression.getTypeId(), object.isIsStrict());
if (initValue != null) {
for (Object value : (Iterable<?>)initValue) {
- accumulator.add(value);
+ assert value != null;
+ connection.append(value);
}
}
}
else {
- accumulator = ValueUtil.createCollectionAccumulatorValue((CollectionTypeId) object.getTypeId());
+ connection = interval.createConnection(name, (CollectionTypeId) object.getTypeId(), object.isIsStrict());
}
- executor.replace(object, accumulator, false);
+ executor.replace(object, connection, false);
return true;
}
@@ -279,108 +414,20 @@ public class QVTiEvaluationVisitor extends BasicEvaluationVisitor implements IQV
@Override
public @Nullable Object visitMappingCall(@NonNull MappingCall mappingCall) {
- Mapping referredMapping = mappingCall.getReferredMapping();
- if (referredMapping == null) {
- return null;
+ if (mappingCall.isIsInstall()) {
+ return doMappingInstall(mappingCall);
}
- @NonNull Object @NonNull [] boundValues = new @NonNull Object[mappingCall.getBinding().size()];
- int index = 0;
- for (MappingParameterBinding binding : mappingCall.getBinding()) {
- VariableDeclaration boundVariable = binding.getBoundVariable();
- if (boundVariable == null) {
- return null;
- }
- if (binding instanceof AppendParameterBinding) { // FIXME visit the bindings
- AppendParameterBinding appendParameterBinding = (AppendParameterBinding)binding;
- ConnectionVariable value = appendParameterBinding.getValue();
- if (value == null) {
- return null;
- }
- Object valueOrValues = executor.getValueOf(value);
- if (valueOrValues == null) {
- return null;
- }
- boundValues[index++] = valueOrValues;
- }
- else if (binding instanceof GuardParameterBinding) {
- Type varType = boundVariable.getType();
- if (varType == null) {
- return null;
- }
- GuardParameterBinding guardParameterBinding = (GuardParameterBinding)binding;
- ConnectionVariable value = guardParameterBinding.getValue();
- if (value == null) {
- return null;
- }
- Object valueOrValues = executor.getValueOf(value);
- if (valueOrValues == null) {
- return null;
- }
- Type valueType = idResolver.getDynamicTypeOf(valueOrValues);
- if (!guardParameterBinding.isIsCheck() || valueType.conformsTo(environmentFactory.getStandardLibrary(), varType)) {
- boundValues[index++] = valueOrValues;
- }
- else {
- return null;
- }
- }
- else if (binding instanceof LoopParameterBinding) {
- Type varType = boundVariable.getType();
- if (varType == null) {
- return null;
- }
- LoopParameterBinding guardParameterBinding = (LoopParameterBinding)binding;
- LoopVariable value = guardParameterBinding.getValue();
- if (value == null) {
- return null;
- }
- Object valueOrValues = executor.getValueOf(value);
- if (valueOrValues == null) {
- return null;
- }
- Type valueType = idResolver.getDynamicTypeOf(valueOrValues);
- if (!guardParameterBinding.isIsCheck() || valueType.conformsTo(environmentFactory.getStandardLibrary(), varType)) {
- boundValues[index++] = valueOrValues;
- }
- else {
- return null;
- }
- }
- else if (binding instanceof SimpleParameterBinding) {
- Type varType = boundVariable.getType();
- if (varType == null) {
- return null;
- }
- SimpleParameterBinding simpleParameterBinding = (SimpleParameterBinding)binding;
- OCLExpression value = simpleParameterBinding.getValue();
- if (value == null) {
- return null;
- }
- Object valueOrValues = value.accept(undecoratedVisitor);
- if (valueOrValues == null) {
- return null;
- }
- assert !(boundVariable instanceof ConnectionVariable);
- // boundValues[index++] = valueOrValues;
-
- // }
- // else {
- Type valueType = idResolver.getDynamicTypeOf(valueOrValues);
- if (!simpleParameterBinding.isIsCheck() || valueType.conformsTo(environmentFactory.getStandardLibrary(), varType)) {
- boundValues[index++] = valueOrValues;
- }
- else {
- return null;
- }
- // }
- }
+ else {
+ return doMappingCall(mappingCall);
}
- return executor.internalExecuteMappingCall(mappingCall, boundValues, undecoratedVisitor);
}
@Override
public @Nullable Object visitMappingLoop(@NonNull MappingLoop mappingLoop) {
Object inValues = mappingLoop.getOwnedExpression().accept(undecoratedVisitor);
+ if (inValues instanceof Connection) {
+ inValues = ((Connection)inValues).typedIterable(Object.class);
+ }
if (inValues instanceof Iterable<?>) {
List<LoopVariable> iterators = mappingLoop.getOwnedIterators();
if (iterators.size() > 0) {
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiExecutor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiExecutor.java
index 3a817700b..de3fb94c2 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiExecutor.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiExecutor.java
@@ -22,6 +22,7 @@ import org.eclipse.qvtd.pivot.qvtimperative.Mapping;
import org.eclipse.qvtd.pivot.qvtimperative.MappingCall;
import org.eclipse.qvtd.pivot.qvtimperative.NewStatement;
import org.eclipse.qvtd.pivot.qvtimperative.SetStatement;
+import org.eclipse.qvtd.runtime.evaluation.Interval;
import org.eclipse.qvtd.runtime.evaluation.InvocationConstructor;
import org.eclipse.qvtd.runtime.evaluation.InvocationManager;
@@ -31,6 +32,7 @@ public interface QVTiExecutor extends ExecutorInternal
Boolean execute();
@Override
@NonNull QVTiEvaluationEnvironment getEvaluationEnvironment();
+ @NonNull Interval getInterval(@NonNull Mapping asMapping);
@NonNull InvocationConstructor getInvocationConstructor(@NonNull MappingCall mappingCall, @NonNull EvaluationVisitor undecoratedVisitor);
@NonNull InvocationManager getInvocationManager();
@Nullable Resource getModel(@NonNull String name);
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java
index cab29c4bf..9a1b2701b 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtimperative/src/org/eclipse/qvtd/pivot/qvtimperative/evaluation/QVTiIncrementalExecutor.java
@@ -69,11 +69,11 @@ public class QVTiIncrementalExecutor extends BasicQVTiExecutor
*/
public static int RUN_TIME_EVALUATOR_API_VERSION = Transformer.RUN_TIME_EVALUATOR_API_VERSION_1_1_0_2;
- public static final class InterpretedInvocationConstructor extends AbstractInvocationConstructor.Incremental
+ public static class InterpretedInvocationConstructor extends AbstractInvocationConstructor.Incremental
{
protected final @NonNull QVTiIncrementalExecutor executor;
- private final @NonNull MappingCall mappingCall;
- private final @NonNull EvaluationVisitor undecoratedVisitor;
+ protected final @NonNull MappingCall mappingCall;
+ protected final @NonNull EvaluationVisitor undecoratedVisitor;
public InterpretedInvocationConstructor(@NonNull QVTiIncrementalExecutor executor, @NonNull Mapping asMapping,
@NonNull MappingCall mappingCall, @NonNull EvaluationVisitor undecoratedVisitor) {
@@ -93,7 +93,7 @@ public class QVTiIncrementalExecutor extends BasicQVTiExecutor
}
}
- public final static class InterpretedInvocation extends AbstractInvocation.Incremental
+ public static class InterpretedInvocation extends AbstractInvocation.Incremental
{
protected final @NonNull Object @NonNull [] theseValues;
diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java
index 2cc6fadc0..411abc355 100644
--- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java
+++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/evaluation/AbstractInvocation.java
@@ -81,9 +81,11 @@ public abstract class AbstractInvocation extends AbstractInvocationInternal
return createdObjects != null ? createdObjects : EMPTY_OBJECT_LIST;
}
+ @SuppressWarnings("null")
@Override
public @NonNull String getName() {
- return constructor.getName() + "-" + sequence;
+ InvocationConstructor constructor2 = constructor; // May be invoked from toString() during constructor debugging
+ return (constructor2 != null ? constructor2.getName() : "null") + "-" + sequence;
}
@Override
diff --git a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java
index 9db92d72b..9a490c431 100644
--- a/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java
+++ b/plugins/org.eclipse.qvtd.runtime/src/org/eclipse/qvtd/runtime/internal/evaluation/AbstractInvocationConstructor.java
@@ -42,6 +42,195 @@ public abstract class AbstractInvocationConstructor implements InvocationConstru
}
}
+ private static abstract class Binder
+ {
+ /**
+ * The Mapping.ownedParameter index that consumes or appends to the connection.
+ */
+ protected final int valueIndex;
+
+ /**
+ * The Connection that provides the values to be consumed.
+ */
+ protected final @NonNull Connection connection;
+
+ protected Binder(int valueIndex, @NonNull Connection connection) {
+ this.valueIndex = valueIndex;
+ this.connection = connection;
+ }
+ }
+
+ private static class Appender extends Binder
+ {
+ /**
+ * Next Appender in linked list of all appenders.
+ */
+ private @Nullable Appender nextAppender = null;
+
+ protected Appender(int valueIndex, @NonNull Connection connection) {
+ super(valueIndex, connection);
+ }
+
+ public void appendAppender(int valueIndex, @NonNull Connection connection) {
+ if (nextAppender != null) {
+ nextAppender.appendAppender(valueIndex, connection);
+ }
+ else {
+ nextAppender = new Appender(valueIndex, connection);
+ }
+ }
+
+ public void propagate(@NonNull Object @NonNull [] values) {
+ values[valueIndex] = connection;
+ if (nextAppender != null) {
+ nextAppender.propagate(values);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "?/" + valueIndex;
+ }
+ }
+
+ /**
+ * A Consumer manages the provision of values to be consumed from a Connection
+ * at a Mapping guard parameter.
+ */
+ private static class Consumer extends Binder
+ {
+ protected final @NonNull AbstractInvocationConstructor invocationConstructor;
+
+ /**
+ * The logical AbstractInvocationConstructor.consumers index of this Consumer.
+ */
+ protected final int consumerIndex;
+
+ /**
+ * The index of the last value consumed by a previous propagate.
+ */
+ private int previouslyConsumedIndex = 0;
+
+ /**
+ * The index of the last value to be consumed by the current propagate.
+ */
+ private int targetConsumedIndex = 0;
+
+ /**
+ * The index of the value used by the current invocation of the current propagate.
+ */
+ private int currentConsumedIndex = 0;
+
+ /**
+ * Next Consumer in linked list of all consumers.
+ */
+ private @Nullable Consumer nextConsumer = null;
+
+ protected Consumer(@NonNull AbstractInvocationConstructor invocationConstructor, int valueIndex, int consumerIndex, @NonNull Connection connection) {
+ super(valueIndex, connection);
+ this.invocationConstructor = invocationConstructor;
+ assert 0 <= consumerIndex;
+ assert consumerIndex <= valueIndex;
+ this.consumerIndex = consumerIndex;
+ }
+
+ public void appendConsumer(int valueIndex, @NonNull Connection connection) {
+ assert targetConsumedIndex == 0;
+ if (nextConsumer != null) {
+ nextConsumer.appendConsumer(valueIndex, connection);
+ }
+ else {
+ nextConsumer = new Consumer(invocationConstructor, valueIndex, consumerIndex+1, connection);
+ }
+ }
+
+ public boolean computeWork() {
+ targetConsumedIndex = connection.getCapacity();
+ boolean hasWork = previouslyConsumedIndex < targetConsumedIndex;
+ if ((nextConsumer != null) && nextConsumer.computeWork()) {
+ hasWork = true;
+ }
+ return hasWork;
+ }
+
+ public void didWork() {
+ previouslyConsumedIndex = targetConsumedIndex;
+ if (nextConsumer != null) {
+ nextConsumer.didWork();
+ }
+ }
+
+ public void invoked(@NonNull Invocation invocation) {
+ if (connection instanceof Connection.Incremental) {
+ ((Connection.Incremental)connection).consume(currentConsumedIndex, invocation);
+ }
+ if (nextConsumer != null) {
+ nextConsumer.invoked(invocation);
+ }
+ }
+
+ /**
+ * Propagate all new values of this and downstream consumers, updating values with prevailing state.
+ * Returns true if one or more invocations were invoked.
+ */
+ public boolean propagateHere(int partialConsumerIndex, @NonNull Object @NonNull [] values) {
+ boolean didInvoke = false;
+ if (partialConsumerIndex < consumerIndex) {
+ for (currentConsumedIndex = 0; currentConsumedIndex < targetConsumedIndex; currentConsumedIndex++) {
+ didInvoke |= propagateNext(partialConsumerIndex, values);
+ }
+ }
+ else if (partialConsumerIndex == consumerIndex) {
+ if (nextConsumer != null) {
+ // Offer each old index to downstream new indexes
+ for (currentConsumedIndex = 0; currentConsumedIndex < previouslyConsumedIndex; currentConsumedIndex++) {
+ Boolean didDownstreamInvoke = propagateNext(partialConsumerIndex+1, values);
+ if (didDownstreamInvoke != null) {
+ if (!didDownstreamInvoke) {
+ break; // If no downstream new index interested, terminate
+ }
+ didInvoke = true;
+ }
+ }
+ }
+ for (currentConsumedIndex = previouslyConsumedIndex; currentConsumedIndex < targetConsumedIndex; currentConsumedIndex++) {
+ didInvoke |= propagateNext(partialConsumerIndex, values);
+ }
+ }
+ else {
+ assert false;
+ }
+ return didInvoke;
+ }
+
+ /**
+ * Propagate all new values of downstream consumers, updating values with prevailing state.
+ * Returns true if one or more invocations were invoked.
+ * Returns null if no value to pass downstream.
+ * Returns false if no invocations could be invoked.
+ */
+ private @Nullable Boolean propagateNext(int partialConsumerIndex, @NonNull Object @NonNull [] values) {
+ Object value = connection.getValue(currentConsumedIndex);
+ if (value == null) { // May be null for incrementally revoked value
+ return null; // doesn't constitute a downstream failure
+ }
+ values[valueIndex] = value;
+ if (nextConsumer != null) {
+ return nextConsumer.propagateHere(partialConsumerIndex, values);
+ }
+ else {
+ Invocation invocation = invocationConstructor.invoke(values);
+ invocationConstructor.invoked(invocation);
+ return true;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return consumerIndex + "/" + valueIndex + " " + previouslyConsumedIndex + "/" + currentConsumedIndex + "/" + targetConsumedIndex;
+ }
+ }
+
protected final @NonNull Interval interval;
protected final IdResolver.@NonNull IdResolverExtension idResolver;
protected final @NonNull String name;
@@ -60,14 +249,40 @@ public abstract class AbstractInvocationConstructor implements InvocationConstru
*/
private /*@LazyNonNull*/ List<@NonNull Invocation> allInvocations = null;
- private final @NonNull List<@NonNull Connection> consumedConnections = new ArrayList<>();
- private final @NonNull List<@NonNull Connection> appendedConnections = new ArrayList<>();
- private int /*@LazyNonNull*/ [] oldConsumedIndexes = null;
+ /**
+ * The number of values required to match the Mapping.ownedParameters.
+ */
+ private int valuesCount = 0;
+
+ /**
+ * Linked list of the Consumers to manage each guard parameter.
+ */
+ private /*@LazyNonNull*/ Consumer firstConsumer = null;
+
+ /**
+ * Linked list of the Appenders to manage each append parameter.
+ */
+ private /*@LazyNonNull*/ Appender firstAppender = null;
+
+ /**
+ * The values passed to the current invocation, one per Mapping.ownedParameter in that order.
+ */
+ private @NonNull Object /*@LazyNonNull*/ values[] = null;
+
+ /**
+ * Set true while propagation in progress.
+ */
+ private boolean propagating = false;
+
+ /**
+ * Set true if re-entrant propgation inhibited.
+ */
+ private boolean repropagate = false;
protected AbstractInvocationConstructor(@NonNull InvocationManager invocationManager, @NonNull String name, boolean isStrict) {
this.interval = invocationManager.createInterval();
Executor executor = invocationManager.getExecutor();
- this.idResolver = (IdResolver.IdResolverExtension)executor.getIdResolver(); // FIXME null Transformer
+ this.idResolver = (IdResolver.IdResolverExtension)executor.getIdResolver();
this.name = name;
this.isStrict = isStrict;
invocationManager.addInvoker(this);
@@ -79,18 +294,34 @@ public abstract class AbstractInvocationConstructor implements InvocationConstru
}
@Override
- public void addAppendedConnection(@NonNull Connection connection) {
- assert oldConsumedIndexes == null;
- assert !appendedConnections.contains(connection);
- appendedConnections.add(connection);
+ public synchronized void addAppendedConnection(@NonNull Connection connection) {
+ assert values == null;
+ // assert oldConsumedIndexes == null;
+ // assert !appendedConnections.contains(connection);
+ // appendedConnections.add(connection);
connection.addAppender(this);
+ if (firstAppender != null) {
+ firstAppender.appendAppender(valuesCount, connection);
+ }
+ else {
+ firstAppender = new Appender(valuesCount, connection);
+ }
+ valuesCount++;
}
@Override
- public void addConsumedConnection(@NonNull Connection connection) {
- assert !consumedConnections.contains(connection);
- consumedConnections.add(connection);
+ public synchronized void addConsumedConnection(@NonNull Connection connection) {
+ assert values == null;
+ // assert !consumedConnections.contains(connection);
+ // consumedConnections.add(connection);
connection.addConsumer(this);
+ if (firstConsumer != null) {
+ firstConsumer.appendConsumer(valuesCount, connection);
+ }
+ else {
+ firstConsumer = new Consumer(this, valuesCount, 0, connection);
+ }
+ valuesCount++;
}
@Override
@@ -178,6 +409,12 @@ public abstract class AbstractInvocationConstructor implements InvocationConstru
return theInvocation;
}
+ protected void invoked(@NonNull Invocation invocation) {
+ if (firstConsumer != null) {
+ firstConsumer.invoked(invocation);
+ }
+ }
+
@Override
public boolean isStrict() {
return isStrict;
@@ -190,57 +427,33 @@ public abstract class AbstractInvocationConstructor implements InvocationConstru
@Override
public void propagate() {
- int consumedConnectionsSize = consumedConnections.size();
- if (oldConsumedIndexes == null) {
- oldConsumedIndexes = new int[consumedConnectionsSize];
- for (int i = 0; i < consumedConnectionsSize; i++) {
- oldConsumedIndexes[i] = 0;
- }
- }
- int @NonNull [] newConsumedIndexes = new int[consumedConnectionsSize];
- boolean hasWork = false;
- for (int i = 0; i < consumedConnectionsSize; i++) {
- Connection consumedConnection = consumedConnections.get(i);
- newConsumedIndexes[i] = consumedConnection.getCapacity();
- if (newConsumedIndexes[i] > oldConsumedIndexes[i]) {
- hasWork = true;
- }
- }
- if (hasWork) {
- int appendedConnectionsSize = appendedConnections.size();
- @NonNull Object @NonNull [] boundValues = new @NonNull Object[consumedConnectionsSize + appendedConnectionsSize];
- for (int i = 0; i < appendedConnectionsSize; i++) {
- boundValues[consumedConnectionsSize+i] = appendedConnections.get(i);
- }
- int @NonNull [] consumeIndexes = new int[consumedConnectionsSize];
- propagate(0, newConsumedIndexes, consumeIndexes, boundValues);
- for (int i = 0; i < consumedConnectionsSize; i++) {
- oldConsumedIndexes[i] = newConsumedIndexes[i];
- }
- }
- }
- private void propagate(int depth, int @NonNull [] newConsumedIndexes, int @NonNull [] consumeIndexes, @NonNull Object @NonNull [] boundValues) {
- int consumedConnectionsSize = consumedConnections.size();
- if (depth < consumedConnectionsSize) {
- Connection consumedConnection = consumedConnections.get(depth);
- for (int i = oldConsumedIndexes[depth]; i < newConsumedIndexes[depth]; i++) {
- consumeIndexes[depth] = i;
- Object value = consumedConnection.getValue(i);
- if (value != null) { // Revoked value may be null.
- boundValues[depth] = value;
- propagate(depth+1, newConsumedIndexes, consumeIndexes, boundValues);
+ @NonNull Object[] values2 = values;
+ if (values2 == null) {
+ synchronized (this) {
+ values2 = values;
+ if (values2 == null) {
+ values2 = values = new @NonNull Object[valuesCount];
+ if (firstAppender != null) {
+ firstAppender.propagate(values2);
+ }
}
}
}
- else {
- Invocation mappingInstance = invoke(boundValues);
- for (int i = 0; i < consumedConnectionsSize; i++) {
- Connection consumedConnection = consumedConnections.get(i);
- if (consumedConnection instanceof Connection.Incremental) {
- ((Connection.Incremental)consumedConnection).consume(consumeIndexes[i], mappingInstance);
- }
+ synchronized (this) {
+ if (propagating) {
+ repropagate = true;
+ return;
}
+ propagating = true;
}
+ do {
+ repropagate = false;
+ if (firstConsumer.computeWork()) {
+ firstConsumer.propagateHere(0, values2);
+ firstConsumer.didWork();
+ }
+ } while (repropagate);
+ propagating = false;
}
@Override

Back to the top