wip stalled needs BooleanValue
diff --git a/plugins/org.eclipse.ocl.pivot/.settings/.api_filters b/plugins/org.eclipse.ocl.pivot/.settings/.api_filters
index 8c45f42..e5d3ef0 100644
--- a/plugins/org.eclipse.ocl.pivot/.settings/.api_filters
+++ b/plugins/org.eclipse.ocl.pivot/.settings/.api_filters
@@ -731,6 +731,14 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/ocl/pivot/evaluation/EvaluationEnvironment.java" type="org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment">
+ <filter id="404000815">
+ <message_arguments>
+ <message_argument value="org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment"/>
+ <message_argument value="replaceInternal(VariableDeclaration, Object)"/>
+ </message_arguments>
+ </filter>
+ </resource>
<resource path="src/org/eclipse/ocl/pivot/evaluation/EvaluationVisitor.java" type="org.eclipse.ocl.pivot.evaluation.EvaluationVisitor">
<filter comment="Bug 512402 workaround" id="576725006">
<message_arguments>
@@ -739,6 +747,32 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/ocl/pivot/evaluation/Executor.java" type="org.eclipse.ocl.pivot.evaluation.Executor">
+ <filter id="404000815">
+ <message_arguments>
+ <message_argument value="org.eclipse.ocl.pivot.evaluation.Executor"/>
+ <message_argument value="popSymbolicEvaluationEnvironment()"/>
+ </message_arguments>
+ </filter>
+ <filter id="404000815">
+ <message_arguments>
+ <message_argument value="org.eclipse.ocl.pivot.evaluation.Executor"/>
+ <message_argument value="pushEvaluationEnvironment(NamedElement, Object)"/>
+ </message_arguments>
+ </filter>
+ <filter id="404000815">
+ <message_arguments>
+ <message_argument value="org.eclipse.ocl.pivot.evaluation.Executor"/>
+ <message_argument value="pushSymbolicEvaluationEnvironment(NamedElement, Object, Object)"/>
+ </message_arguments>
+ </filter>
+ <filter id="404000815">
+ <message_arguments>
+ <message_argument value="org.eclipse.ocl.pivot.evaluation.Executor"/>
+ <message_argument value="resetCaches()"/>
+ </message_arguments>
+ </filter>
+ </resource>
<resource path="src/org/eclipse/ocl/pivot/internal/context/AbstractParserContext.java" type="org.eclipse.ocl.pivot.internal.context.AbstractParserContext">
<filter comment="Bug 512402 workaround" id="576725006">
<message_arguments>
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/CompositeSymbolicConstraintImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/CompositeSymbolicConstraintImpl.java
new file mode 100644
index 0000000..d4d16e9
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/CompositeSymbolicConstraintImpl.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) 2010, 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ */
+package org.eclipse.ocl.pivot.internal.values;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicOperator;
+
+/**
+ * @since 1.12
+ */
+public class CompositeSymbolicConstraintImpl extends SymbolicUnknownValueImpl implements SymbolicConstraint
+{
+ protected final @NonNull List<@NonNull SymbolicConstraint> symbolicConstraints = new ArrayList<>();
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated NOT
+ */
+ public CompositeSymbolicConstraintImpl() {
+ super(TypeId.BOOLEAN, false, false); // FIXME inherited maBeInvalid/Null redundant
+ }
+
+ public void add(@NonNull SymbolicConstraint symbolicConstraint) {
+ assert symbolicConstraint.getTypeId2() == typeId;
+ assert symbolicConstraint instanceof SymbolicConstraintImpl;
+ assert !symbolicConstraints.contains(symbolicConstraint);
+ symbolicConstraints.add(symbolicConstraint);
+ }
+
+ @Override
+ public @Nullable SymbolicOperator getSymbolicOperator() {
+ return null;
+ }
+
+ @Override
+ public @Nullable Object getSymbolicValue() {
+ return null;
+ }
+
+ @Override
+ public boolean mayBeInvalid() {
+ for (@NonNull SymbolicConstraint symbolicConstraint : symbolicConstraints) {
+ if (symbolicConstraint.mayBeInvalid()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean mayBeNull() {
+ for (@NonNull SymbolicConstraint symbolicConstraint : symbolicConstraints) {
+ if (symbolicConstraint.mayBeNull()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public /*final*/ @NonNull String toString() {
+ StringBuilder s = new StringBuilder();
+ toString(s, 100);
+ return s.toString();
+ }
+
+ @Override
+ public void toString(@NonNull StringBuilder s, int lengthLimit) {
+ s.append("{");
+ boolean isFirst = true;
+ for (@NonNull SymbolicConstraint symbolicConstraint : symbolicConstraints) {
+ if (!isFirst) {
+ s.append(",");
+ }
+ s.append(symbolicConstraint);
+ isFirst = false;
+ }
+ s.append("}");
+ }
+}
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/NullValueImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/NullValueImpl.java
index b71f0c9..c446809 100644
--- a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/NullValueImpl.java
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/NullValueImpl.java
@@ -161,7 +161,7 @@
}
@Override
- public String toString() {
+ public @NonNull String toString() {
return "null";
}
} //NullValueImpl
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicConstraintImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicConstraintImpl.java
new file mode 100644
index 0000000..8d78c05
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicConstraintImpl.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2010, 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ */
+package org.eclipse.ocl.pivot.internal.values;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.utilities.ValueUtil;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicOperator;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Symbolic Value</b></em>'.
+ * @since 1.12
+ * <!-- end-user-doc -->
+ *
+ * @generated
+ */
+public class SymbolicConstraintImpl extends SymbolicUnknownValueImpl implements SymbolicConstraint
+{
+ protected final @NonNull SymbolicOperator symbolicOperator;
+ protected final @Nullable Object symbolicValue;
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated NOT
+ */
+ public SymbolicConstraintImpl(@NonNull TypeId typeId, boolean mayBeNull, boolean mayBeInvalid, @NonNull SymbolicOperator symbolicOperator, @Nullable Object symbolicValue) {
+ super(typeId, mayBeNull, mayBeInvalid);
+ this.symbolicOperator = symbolicOperator;
+ this.symbolicValue = symbolicValue;
+ }
+
+ @Override
+ public @NonNull SymbolicOperator getSymbolicOperator() {
+ return symbolicOperator;
+ }
+
+ @Override
+ public @Nullable Object getSymbolicValue() {
+ return symbolicValue;
+ }
+
+ @Override
+ public boolean mayBeInvalid() {
+ return ValueUtil.mayBeInvalid(symbolicValue);
+ }
+
+ @Override
+ public boolean mayBeNull() {
+ switch (symbolicOperator) {
+ case EQUALS: return ValueUtil.mayBeNull(symbolicValue);
+ case NOT_EQUALS: return !ValueUtil.mayBeNull(symbolicValue);
+ case COMPARE_TO: return false;
+ }
+ throw new UnsupportedOperationException(symbolicOperator.toString());
+ }
+
+ @Override
+ public /*final*/ @NonNull String toString() {
+ StringBuilder s = new StringBuilder();
+ toString(s, 100);
+ return s.toString();
+ }
+
+ @Override
+ public void toString(@NonNull StringBuilder s, int lengthLimit) {
+ s.append(symbolicOperator);
+ s.append("-");
+ s.append(symbolicValue);
+ }
+}
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicResultValueImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicResultValueImpl.java
new file mode 100644
index 0000000..161e84f
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicResultValueImpl.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2010, 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ */
+package org.eclipse.ocl.pivot.internal.values;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
+import org.eclipse.ocl.pivot.library.InvertibleLibraryOperation;
+import org.eclipse.ocl.pivot.library.LibraryOperation;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+
+/**
+ * <!-- begin-user-doc -->
+ * An implementation of the model object '<em><b>Symbolic Value</b></em>'.
+ * @since 1.12
+ * <!-- end-user-doc -->
+ *
+ * @generated
+ */
+public class SymbolicResultValueImpl extends SymbolicUnknownValueImpl {
+ private static final long serialVersionUID = 1L;
+
+ protected final @NonNull LibraryOperation operation;
+
+ protected final @Nullable Object sourceValue;
+ protected final @Nullable Object argumentValue;
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @generated NOT
+ */
+ public SymbolicResultValueImpl(@NonNull TypeId typeId, boolean mayBeNull, boolean mayBeInvalid,
+ @NonNull LibraryOperation operation, @Nullable Object sourceValue, @Nullable Object argumentValue) {
+ super(typeId, mayBeNull, mayBeInvalid);
+ this.operation = operation;
+ this.sourceValue = sourceValue;
+ this.argumentValue = argumentValue;
+ }
+
+ @Override
+ public void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicConstraint symbolicConstraint) {
+ if (operation instanceof InvertibleLibraryOperation) {
+ ((InvertibleLibraryOperation)operation).deduceFrom(symbolicExecutor, this, symbolicConstraint);
+ }
+ }
+
+ public @Nullable Object getArgumentValue() {
+ return argumentValue;
+ }
+
+ public @Nullable Object getSourceValue() {
+ return sourceValue;
+ }
+
+ @Override
+ public void toString(@NonNull StringBuilder s, int lengthLimit) {
+ s.append(operation.getClass().getSimpleName());
+ s.append("(");
+ s.append(sourceValue);
+ s.append(",");
+ s.append(argumentValue);
+ s.append(")");
+ s.append(":");
+ super.toString(s, lengthLimit);
+ }
+}
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicUnknownValueImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicUnknownValueImpl.java
index d05a896..674b967 100644
--- a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicUnknownValueImpl.java
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicUnknownValueImpl.java
@@ -20,11 +20,13 @@
import org.eclipse.ocl.pivot.ids.OclVoidTypeId;
import org.eclipse.ocl.pivot.ids.TupleTypeId;
import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
import org.eclipse.ocl.pivot.messages.PivotMessages;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.ocl.pivot.values.NullValue;
import org.eclipse.ocl.pivot.values.OCLValue;
import org.eclipse.ocl.pivot.values.RealValue;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
import org.eclipse.ocl.pivot.values.SymbolicValue;
/**
@@ -60,6 +62,9 @@
// }
@Override
+ public void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicConstraint symbolicConstraint) {}
+
+ @Override
public @NonNull NullValue divideReal(@NonNull RealValue right) {
if (right.asDouble() == 1.0) {
return this;
@@ -72,6 +77,12 @@
}
@Override
+ public boolean equals(Object obj) {
+ // TODO Auto-generated method stub
+ return super.equals(obj);
+ }
+
+ @Override
public @NonNull CollectionTypeId getCollectionTypeId() {
throw new InvalidValueException(PivotMessages.ConvertibleValueRequired, "Invalid");
}
@@ -112,10 +123,12 @@
@Override
public void toString(@NonNull StringBuilder s, int lengthLimit) {
s.append(typeId);
- s.append("-");
- s.append(mayBeNull);
- s.append("-");
- s.append(mayBeInvalid);
+ s.append("[");
+ s.append(mayBeNull ? "?" : "1");
+ if (mayBeInvalid) {
+ s.append("!");
+ }
+ s.append("]");
}
@Override
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicValueImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicValueImpl.java
index 6ef8ad2..8633f3d 100644
--- a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicValueImpl.java
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicValueImpl.java
@@ -13,6 +13,8 @@
import org.eclipse.emf.ecore.EClass;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
import org.eclipse.ocl.pivot.values.SymbolicValue;
import org.eclipse.ocl.pivot.values.ValuesPackage;
@@ -59,6 +61,9 @@
}
@Override
+ public void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicConstraint symbolicConstraint) {}
+
+ @Override
public @NonNull TypeId getTypeId() {
return getTypeId2();
}
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicVariableValueImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicVariableValueImpl.java
index 0398a4e..2d5721c 100644
--- a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicVariableValueImpl.java
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/SymbolicVariableValueImpl.java
@@ -13,6 +13,9 @@
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
/**
* <!-- begin-user-doc -->
@@ -25,14 +28,18 @@
public class SymbolicVariableValueImpl extends SymbolicValueImpl { //implements EObject {
protected final @NonNull VariableDeclaration variable;
+ protected final @NonNull SymbolicValue value;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param variable
+ * @param value
+ * @param object
* @generated NOT
*/
- public SymbolicVariableValueImpl(@NonNull VariableDeclaration variable) {
+ public SymbolicVariableValueImpl(@NonNull VariableDeclaration variable, @NonNull SymbolicValue value) {
this.variable = variable;
+ this.value = value;
}
// @Override
@@ -41,18 +48,36 @@
// }
@Override
- public @NonNull TypeId getTypeId() {
- return variable.getTypeId();
+ public void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicConstraint symbolicConstraint) {
+ symbolicExecutor.add(variable, symbolicConstraint);
}
@Override
+ public @NonNull TypeId getTypeId2() {
+ return variable.getTypeId();
+ }
+
+ public @NonNull SymbolicValue getValue() {
+ return value;
+ }
+
+// public @NonNull VariableDeclaration getVariable() {
+// return variable;
+// }
+
+ @Override
public boolean mayBeNull() {
- return !variable.isIsRequired();
+ boolean isRequired = variable.isIsRequired();
+ boolean mayBeNull = value.mayBeNull();
+ assert !isRequired || !mayBeNull;
+ return mayBeNull;
}
@Override
public void toString(@NonNull StringBuilder s, int lengthLimit) {
s.append(variable.getName());
+ s.append(":");
+ value.toString(s, lengthLimit);
}
/* @Override
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/UndefinedValueImpl.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/UndefinedValueImpl.java
index 98b114a..8e82939 100644
--- a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/UndefinedValueImpl.java
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/internal/values/UndefinedValueImpl.java
@@ -679,8 +679,15 @@
}
@Override
+ public /*final*/ @NonNull String toString() {
+ StringBuilder s = new StringBuilder();
+ toString(s, 100);
+ return s.toString();
+ }
+
+ @Override
public void toString(@NonNull StringBuilder s, int sizeLimit) {
- s.append(toString());
+ s.append(super.toString());
}
@Override
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicConstraint.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicConstraint.java
new file mode 100644
index 0000000..39ddc00
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicConstraint.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2018 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ocl.pivot.values;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * @since 1.12
+ */
+public interface SymbolicConstraint extends SymbolicValue
+{
+ @Nullable SymbolicOperator getSymbolicOperator();
+ @Nullable Object getSymbolicValue();
+}
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicOperator.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicOperator.java
new file mode 100644
index 0000000..964adcf
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicOperator.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2010, 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ */
+package org.eclipse.ocl.pivot.values;
+
+/**
+ * @since 1.12
+ */
+public enum SymbolicOperator
+{
+ EQUALS,
+ NOT_EQUALS,
+ COMPARE_TO
+} // SymbolicValue
diff --git a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicValue.java b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicValue.java
index f9e8da4..4bd080c 100644
--- a/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicValue.java
+++ b/plugins/org.eclipse.ocl.pivot/emf-gen/org/eclipse/ocl/pivot/values/SymbolicValue.java
@@ -10,6 +10,8 @@
*/
package org.eclipse.ocl.pivot.values;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
/**
* <!-- begin-user-doc -->
@@ -25,5 +27,10 @@
* @see org.eclipse.ocl.pivot.values.ValuesPackage#getSymbolicValue()
* @generated
*/
-public interface SymbolicValue extends Value {
+public interface SymbolicValue extends Value
+{
+ /**
+ * Update symbolicExecutor from any deductions that can be made from knowing that symbolicConstraint is observede.
+ */
+ void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicConstraint symbolicConstraint);
} // SymbolicValue
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/EvaluationEnvironment.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/EvaluationEnvironment.java
index 150a1bb..c0a93ec 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/EvaluationEnvironment.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/EvaluationEnvironment.java
@@ -16,6 +16,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.TypedElement;
+import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.internal.evaluation.ExecutorInternal;
import org.eclipse.ocl.pivot.utilities.Adaptable;
import org.eclipse.ocl.pivot.utilities.Customizable;
@@ -35,16 +36,16 @@
@NonNull ExecutorInternal getExecutor();
EvaluationEnvironment.@Nullable EvaluationEnvironmentExtension getParentEvaluationEnvironment();
}
-
+
/**
* Adds the supplied variable declaration and value binding to the
* environment. The variable declaration must not already be bound.
- *
+ *
* @param referredVariable
* the variable declaration to add
* @param value
* the associated binding
- *
+ *
* @see #replace(TypedElement, Object)
*/
void add(@NonNull TypedElement referredVariable, @Nullable Object value);
@@ -58,7 +59,7 @@
/**
* Returns the value associated with the supplied variable declaration
- *
+ *
* @param referredVariable
* the name whose value is to be returned
* @return the value associated with the name
@@ -73,7 +74,7 @@
/**
* Removes the supplied variable declaration and binding from the
* environment (if it exists) and returns it.
- *
+ *
* @param referredVariable
* the variable declaration to remove
* @return the value associated with the removed variable declaration
@@ -83,13 +84,19 @@
/**
* Replaces the current value of the supplied variable declaration with the
* supplied value.
- *
+ *
* @param referredVariable
* the variable declaration
* @param value
* the new value
*/
void replace(@NonNull TypedElement referredVariable, @Nullable Object value);
+ /**
+ * @since 1.12
+ */
+ default @Nullable Object replaceInternal(@NonNull VariableDeclaration referredVariable, @Nullable Object value) {
+ return null;
+ }
/** @deprecated moved to Evaluator */
@Deprecated
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/Executor.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/Executor.java
index acaa6fb..961560d 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/Executor.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/evaluation/Executor.java
@@ -31,10 +31,14 @@
{
/**
* @since 1.3
+ * @deprecated all methods moved to Executor with Java 8 defaults
*/
+ @Deprecated
public interface ExecutorExtension extends Executor
{
+ @Override
@NonNull EvaluationEnvironment pushEvaluationEnvironment(@NonNull NamedElement executableObject, @Nullable Object caller);
+ @Override
void resetCaches();
}
void add(@NonNull TypedElement referredVariable, @Nullable Object value);
@@ -78,7 +82,17 @@
*/
@Deprecated
@NonNull EvaluationEnvironment pushEvaluationEnvironment(@NonNull NamedElement executableObject, @Nullable OCLExpression callingObject);
+ /**
+ * @since 1.12
+ */
+ default @NonNull EvaluationEnvironment pushEvaluationEnvironment(@NonNull NamedElement executableObject, @Nullable Object caller) {
+ return pushEvaluationEnvironment(executableObject, caller instanceof OCLExpression ? (OCLExpression)caller : null);
+ }
void replace(@NonNull TypedElement referredVariable, @Nullable Object value);
+ /**
+ * @since 1.12
+ */
+ default void resetCaches() {}
@Override
void setLogger(@Nullable EvaluationLogger logger);
}
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/ecore/EObjectOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/ecore/EObjectOperation.java
index 73a35fd..72d43ee 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/ecore/EObjectOperation.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/ecore/EObjectOperation.java
@@ -23,7 +23,6 @@
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.Executor;
-import org.eclipse.ocl.pivot.evaluation.Executor.ExecutorExtension;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension;
import org.eclipse.ocl.pivot.library.AbstractOperation;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
@@ -61,7 +60,7 @@
}
}
ExpressionInOCL query = specification;
- EvaluationEnvironment nestedEvaluationEnvironment = ((ExecutorExtension)executor).pushEvaluationEnvironment(query, caller);
+ EvaluationEnvironment nestedEvaluationEnvironment = executor.pushEvaluationEnvironment(query, caller);
nestedEvaluationEnvironment.add(ClassUtil.nonNullModel(query.getOwnedContext()), boxedSourceAndArgumentValues[0]);
List<Variable> parameterVariables = query.getOwnedParameters();
int iMax = Math.min(parameterVariables.size(), boxedSourceAndArgumentValues.length-1);
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/AbstractExecutor.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/AbstractExecutor.java
index a351115..1647e24 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/AbstractExecutor.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/AbstractExecutor.java
@@ -35,7 +35,9 @@
import org.eclipse.ocl.pivot.TemplateParameter;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
+import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
+import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment.EvaluationEnvironmentExtension;
import org.eclipse.ocl.pivot.evaluation.EvaluationLogger;
import org.eclipse.ocl.pivot.evaluation.EvaluationVisitor;
import org.eclipse.ocl.pivot.evaluation.Evaluator;
@@ -542,11 +544,19 @@
public @NonNull EvaluationEnvironment pushEvaluationEnvironment(@NonNull NamedElement executableObject, @Nullable Object caller) {
EvaluationEnvironment.EvaluationEnvironmentExtension evaluationEnvironment2 = ClassUtil.nonNullState(evaluationEnvironment);
EvaluationEnvironment.EvaluationEnvironmentExtension nestedEvaluationEnvironment = createNestedEvaluationEnvironment(evaluationEnvironment2, executableObject, caller);
- evaluationEnvironment = nestedEvaluationEnvironment;
+ pushEvaluationEnvironment(nestedEvaluationEnvironment);
return nestedEvaluationEnvironment;
}
/**
+ * @since 1.12
+ */
+ protected EvaluationEnvironmentExtension pushEvaluationEnvironment(@NonNull EvaluationEnvironmentExtension nestedEvaluationEnvironment) {
+ assert nestedEvaluationEnvironment.getParentEvaluationEnvironment() == evaluationEnvironment;
+ return evaluationEnvironment = nestedEvaluationEnvironment;
+ }
+
+ /**
* @deprecated use TypedElement argument
*/
@Deprecated
@@ -561,6 +571,13 @@
}
/**
+ * @since 1.12
+ */
+ protected @Nullable Object replaceInternal(@NonNull VariableDeclaration referredVariable, @Nullable Object value) {
+ return evaluationEnvironment.replaceInternal(referredVariable, value);
+ }
+
+ /**
* @since 1.3
*/
@Override
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationEnvironment.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationEnvironment.java
index d56b93c..4ca6966 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationEnvironment.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationEnvironment.java
@@ -20,6 +20,7 @@
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.TypedElement;
+import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.ModelManager;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
@@ -128,7 +129,8 @@
throw new IllegalArgumentException(message);
}
}
- variableValues.put(referredVariable, value);
+ Object oldValue = variableValues.put(referredVariable, value);
+
}
/**
@@ -262,6 +264,10 @@
public void replace(@NonNull TypedElement referredVariable, @Nullable Object value) {
variableValues.put(referredVariable, value);
}
+ @Override
+ public @Nullable Object replaceInternal(@NonNull VariableDeclaration referredVariable, @Nullable Object value) {
+ return variableValues.put(referredVariable, value);
+ }
/**
* Returns a string representation of the bindings
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationVisitor.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationVisitor.java
index 6443904..f8dbd65 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationVisitor.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/BasicEvaluationVisitor.java
@@ -71,8 +71,11 @@
import org.eclipse.ocl.pivot.evaluation.IterationManager;
import org.eclipse.ocl.pivot.ids.CollectionTypeId;
import org.eclipse.ocl.pivot.ids.TuplePartId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
+import org.eclipse.ocl.pivot.internal.values.SymbolicUnknownValueImpl;
+import org.eclipse.ocl.pivot.internal.values.SymbolicVariableValueImpl;
import org.eclipse.ocl.pivot.labels.ILabelGenerator;
import org.eclipse.ocl.pivot.library.EvaluatorMultipleIterationManager;
import org.eclipse.ocl.pivot.library.EvaluatorMultipleMapIterationManager;
@@ -332,17 +335,51 @@
*/
@Override
public Object visitIfExp(@NonNull IfExp ifExp) {
- OCLExpression condition = ifExp.getOwnedCondition();
+ OCLExpression condition = PivotUtil.getOwnedCondition(ifExp);
Object conditionValue = condition.accept(undecoratedVisitor);
Object evaluatedCondition = ValueUtil.asBoolean(conditionValue);
- OCLExpression expression = null;
if (evaluatedCondition == ValueUtil.TRUE_VALUE) {
- expression = ifExp.getOwnedThen();
+ OCLExpression expression = PivotUtil.getOwnedThen(ifExp);
+ return expression.accept(undecoratedVisitor);
+ }
+ else if (evaluatedCondition == ValueUtil.FALSE_VALUE) {
+ OCLExpression expression = PivotUtil.getOwnedElse(ifExp);
+ return expression.accept(undecoratedVisitor);
}
else {
- expression = ifExp.getOwnedElse();
+ boolean mayBeInvalid = ValueUtil.mayBeInvalid(conditionValue);
+ boolean mayBeNull = ValueUtil.mayBeNull(conditionValue);
+ SymbolicExecutor symbolicExecutor = (SymbolicExecutor)context;
+ try {
+ OCLExpression expression = PivotUtil.getOwnedThen(ifExp);
+ symbolicExecutor.pushSymbolicEvaluationEnvironment(expression, conditionValue, Boolean.TRUE);
+ Object thenValue = expression.accept(undecoratedVisitor);
+ if (ValueUtil.mayBeInvalid(thenValue)) {
+ mayBeInvalid = true;
+ }
+ if (ValueUtil.mayBeNull(thenValue)) {
+ mayBeNull = true;
+ }
+ }
+ finally {
+ context.popEvaluationEnvironment();
+ }
+ try {
+ OCLExpression expression = PivotUtil.getOwnedElse(ifExp);
+ symbolicExecutor.pushSymbolicEvaluationEnvironment(expression, conditionValue, Boolean.FALSE);
+ Object elseValue = expression.accept(undecoratedVisitor);
+ if (ValueUtil.mayBeInvalid(elseValue)) {
+ mayBeInvalid = true;
+ }
+ if (ValueUtil.mayBeNull(elseValue)) {
+ mayBeNull = true;
+ }
+ }
+ finally {
+ context.popEvaluationEnvironment();
+ }
+ return new SymbolicUnknownValueImpl(ifExp.getTypeId(), mayBeNull, mayBeInvalid);
}
- return expression.accept(undecoratedVisitor);
}
/**
@@ -922,6 +959,9 @@
if (value instanceof InvalidValueException) {
throw (InvalidValueException)value;
}
+ else if (value instanceof SymbolicValue) { // FIXME obsolete wrt SymbolicConstraint
+ return new SymbolicVariableValueImpl(variableDeclaration, (SymbolicValue)value);
+ }
else {
return value;
}
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/SymbolicEvaluationVisitor.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/SymbolicEvaluationVisitor.java
index 1524b0d..556f007 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/SymbolicEvaluationVisitor.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/evaluation/SymbolicEvaluationVisitor.java
@@ -95,10 +95,20 @@
return !element2value.containsKey(element);
}
+ public boolean isFalse(@NonNull Element element) {
+ Object object = element2value.get(element);
+ return object == Boolean.FALSE;
+ }
+
+ public boolean isTrue(@NonNull Element element) {
+ Object object = element2value.get(element);
+ return object == Boolean.TRUE;
+ }
+
public boolean mayBeInvalid(@NonNull Element element) {
Object object = element2value.get(element);
if (object == null) {
- return true;
+ return !element2value.containsKey(element); // null may not be invalid
}
if (object instanceof Value) {
return ((Value)object).mayBeInvalid();
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedOperation.java
index 431998b..6dc176a 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedOperation.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedOperation.java
@@ -22,7 +22,6 @@
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.Executor;
-import org.eclipse.ocl.pivot.evaluation.Executor.ExecutorExtension;
import org.eclipse.ocl.pivot.library.AbstractOperation;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
@@ -45,7 +44,7 @@
@Override
public @Nullable Object basicEvaluate(@NonNull Executor executor, @NonNull TypedElement caller, @Nullable Object @NonNull [] boxedSourceAndArgumentValues) {
PivotUtil.checkExpression(expressionInOCL);
- EvaluationEnvironment nestedEvaluationEnvironment = ((ExecutorExtension)executor).pushEvaluationEnvironment(expressionInOCL, caller);
+ EvaluationEnvironment nestedEvaluationEnvironment = executor.pushEvaluationEnvironment(expressionInOCL, caller);
nestedEvaluationEnvironment.add(ClassUtil.nonNullModel(expressionInOCL.getOwnedContext()), boxedSourceAndArgumentValues[0]);
List<Variable> parameters = expressionInOCL.getOwnedParameters();
if (!parameters.isEmpty()) {
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedProperty.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedProperty.java
index 978968c..9da7a40 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedProperty.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/ConstrainedProperty.java
@@ -56,7 +56,7 @@
}
}
PivotUtil.checkExpression(expression2);
- EvaluationEnvironment nestedEvaluationEnvironment = ((Executor.ExecutorExtension)executor).pushEvaluationEnvironment(expression2, (Object)null);
+ EvaluationEnvironment nestedEvaluationEnvironment = executor.pushEvaluationEnvironment(expression2, (Object)null);
Variable contextVariable = expression2.getOwnedContext();
if (contextVariable != null) {
nestedEvaluationEnvironment.add(contextVariable, sourceValue);
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/executor/ExecutorManager.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/executor/ExecutorManager.java
index 52de7d7..0859b22 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/executor/ExecutorManager.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/library/executor/ExecutorManager.java
@@ -25,6 +25,7 @@
import org.eclipse.ocl.pivot.StandardLibrary;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
+import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
import org.eclipse.ocl.pivot.evaluation.EvaluationLogger;
import org.eclipse.ocl.pivot.evaluation.Evaluator;
@@ -140,6 +141,11 @@
public void replace(@NonNull TypedElement referredVariable, @Nullable Object value) {}
@Override
+ public @Nullable Object replaceInternal(@NonNull VariableDeclaration referredVariable, @Nullable Object value) {
+ return null;
+ }
+
+ @Override
public <T> void setOption(@NonNull Option<T> option, @Nullable T value) {
}
};
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/PivotMetamodelManager.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/PivotMetamodelManager.java
index 8895fa3..47f8f3a 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/PivotMetamodelManager.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/PivotMetamodelManager.java
@@ -64,7 +64,6 @@
import org.eclipse.ocl.pivot.MapType;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.Namespace;
-import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.NullLiteralExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Operation;
@@ -102,7 +101,6 @@
import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal;
import org.eclipse.ocl.pivot.internal.ecore.as2es.AS2Ecore;
import org.eclipse.ocl.pivot.internal.ecore.es2as.Ecore2AS;
-import org.eclipse.ocl.pivot.internal.evaluation.BasicOCLExecutor;
import org.eclipse.ocl.pivot.internal.evaluation.ExecutorInternal;
import org.eclipse.ocl.pivot.internal.evaluation.SymbolicEvaluationVisitor;
import org.eclipse.ocl.pivot.internal.library.ConstrainedOperation;
@@ -122,7 +120,6 @@
import org.eclipse.ocl.pivot.internal.utilities.OppositePropertyDetails;
import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
-import org.eclipse.ocl.pivot.internal.values.SymbolicNavigationCallValueImpl;
import org.eclipse.ocl.pivot.library.LibraryFeature;
import org.eclipse.ocl.pivot.library.LibraryProperty;
import org.eclipse.ocl.pivot.library.UnsupportedOperation;
@@ -640,6 +637,13 @@
return asString;
}
+ /**
+ * @since 1.12
+ */
+ protected SymbolicOCLExecutor createSymbolicExecutor(@NonNull ModelManager modelManager) {
+ return new SymbolicOCLExecutor((EnvironmentFactoryInternalExtension)environmentFactory, modelManager);
+ }
+
public @NonNull UnlimitedNaturalLiteralExp createUnlimitedNaturalLiteralExp(@NonNull Number unlimitedNaturalSymbol) { // FIXME move to PivotHelper
UnlimitedNaturalLiteralExp asUnlimitedNatural = PivotFactory.eINSTANCE.createUnlimitedNaturalLiteralExp();
asUnlimitedNatural.setUnlimitedNaturalSymbol(unlimitedNaturalSymbol);
@@ -1193,70 +1197,21 @@
*/
@Override
public @NonNull SymbolicEvaluationVisitor getSymbolicAnalysis(@NonNull ExpressionInOCL expressionInOCL, @Nullable Object context, @NonNull Object... parameters) {
- OCLExpression oclExpression = PivotUtil.getOwnedBody(expressionInOCL);
- OCLExpression contextExpression = FlowAnalysis.getControlExpression(oclExpression);
- // Map<@NonNull OCLExpression, @NonNull FlowAnalysis> oclExpression2flowAnalysis2 = oclExpression2flowAnalysis;
- // if (oclExpression2flowAnalysis2 == null) {
- // oclExpression2flowAnalysis2 = oclExpression2flowAnalysis = new HashMap<>();
- // }
-// ModelManager modelManager = environmentFactory.createModelManager(oclExpression);
- // Object context = null;
- ModelManager modelManager = null;
- // EvaluationVisitor evaluationVisitor = environmentFactory.createEvaluationVisitor(null, expressionInOCL, modelManager);
-
-
- // if (modelManager == null) {
- // let the evaluation environment create one
- modelManager = environmentFactory.createModelManager(context);
- // }
- // can determine a more appropriate context from the context
- // variable of the expression, to account for stereotype constraints
- // context = HelperUtil.getConstraintContext(rootEnvironment, context, expression);
- // ExecutorInternal executor = createExecutor(modelManager);
- ExecutorInternal executor = new BasicOCLExecutor((EnvironmentFactoryInternalExtension) environmentFactory, modelManager)
- {
- /* @Override
- protected @NonNull EvaluationEnvironmentExtension createRootEvaluationEnvironment(@NonNull NamedElement executableObject) {
- // return super.createRootEvaluationEnvironment(executableObject);
- return new BasicEvaluationEnvironment(this, executableObject)
- {
- @Override
- public void add(@NonNull TypedElement referredVariable, @Nullable Object value) {
- // TODO Auto-generated method stub
- super.add(referredVariable, value);
- }
- };
- } */
-
- @Override
- public @Nullable Object internalExecuteNavigationCallExp(@NonNull NavigationCallExp navigationCallExp, @NonNull Property referredProperty, @Nullable Object sourceValue) {
- return new SymbolicNavigationCallValueImpl(navigationCallExp, sourceValue);
- }
-
- @Override
- public Object internalExecuteOperationCallExp(@NonNull OperationCallExp operationCallExp, @Nullable Object @NonNull [] sourceAndArgumentValues) {
- return super.internalExecuteOperationCallExp(operationCallExp, sourceAndArgumentValues);
- }
-
- };
+ ModelManager modelManager = environmentFactory.createModelManager(context);
+ ExecutorInternal executor = createSymbolicExecutor(modelManager);
EvaluationEnvironment evaluationEnvironment = executor.initializeEvaluationEnvironment(expressionInOCL);
IdResolver idResolver = environmentFactory.getIdResolver();
Variable contextVariable = expressionInOCL.getOwnedContext();
if (contextVariable != null) {
- Object value = context; //new SymbolicVariableValueImpl(contextVariable); //idResolver.boxedValueOf(context);
- evaluationEnvironment.add(contextVariable, idResolver.boxedValueOf(value));
+ // Object value = new SymbolicVariableValueImpl(contextVariable, idResolver.boxedValueOf(context);
+ // Object value = new SymbolicVariableValueImpl(contextVariable, idResolver.boxedValueOf(context);
+ evaluationEnvironment.add(contextVariable, idResolver.boxedValueOf(context));
}
int i = 0;
for (Variable parameterVariable : PivotUtil.getOwnedParameters(expressionInOCL)) {
evaluationEnvironment.add(parameterVariable, idResolver.boxedValueOf(parameters[i++]));
}
EvaluationVisitor evaluationVisitor = executor.getEvaluationVisitor();
-
-
-
-
-// ExecutorInternal executor = ((EnvironmentFactoryExtension)environmentFactory).createExecutor(modelManager);
-// EvaluationVisitor evaluationVisitor = executor.getEvaluationVisitor();
SymbolicEvaluationVisitor symbolicEvaluationVisitor = new SymbolicEvaluationVisitor(evaluationVisitor);
try {
symbolicEvaluationVisitor.evaluate(expressionInOCL);
@@ -1264,11 +1219,6 @@
catch (InvalidValueException e) {
// Ok so some results are unarguably invalid.
}
- // FlowAnalysis flowAnalysis = oclExpression2flowAnalysis2.get(contextExpression);
- // if (flowAnalysis == null) {
- // flowAnalysis = environmentFactory.createFlowAnalysis(contextExpression);
- // oclExpression2flowAnalysis2.put(contextExpression, flowAnalysis);
- // }
return symbolicEvaluationVisitor;
}
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/SymbolicExecutor.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/SymbolicExecutor.java
new file mode 100644
index 0000000..93256a5
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/SymbolicExecutor.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ocl.pivot.internal.manager;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.NamedElement;
+import org.eclipse.ocl.pivot.VariableDeclaration;
+import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
+import org.eclipse.ocl.pivot.evaluation.Executor;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+
+/**
+ * @since 1.12
+ */
+public interface SymbolicExecutor extends Executor
+{
+ void add(@NonNull VariableDeclaration variable, @NonNull SymbolicConstraint symbolicConstraint);
+ @NonNull EvaluationEnvironment pushSymbolicEvaluationEnvironment(@NonNull NamedElement executableObject, @Nullable Object symbolicValue, @Nullable Object constantValue);
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/SymbolicOCLExecutor.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/SymbolicOCLExecutor.java
new file mode 100644
index 0000000..5e6c1be
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/manager/SymbolicOCLExecutor.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ocl.pivot.internal.manager;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.NamedElement;
+import org.eclipse.ocl.pivot.NavigationCallExp;
+import org.eclipse.ocl.pivot.OperationCallExp;
+import org.eclipse.ocl.pivot.Property;
+import org.eclipse.ocl.pivot.TypedElement;
+import org.eclipse.ocl.pivot.VariableDeclaration;
+import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment;
+import org.eclipse.ocl.pivot.evaluation.EvaluationEnvironment.EvaluationEnvironmentExtension;
+import org.eclipse.ocl.pivot.evaluation.ModelManager;
+import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.evaluation.BasicOCLExecutor;
+import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension;
+import org.eclipse.ocl.pivot.internal.values.CompositeSymbolicConstraintImpl;
+import org.eclipse.ocl.pivot.internal.values.SymbolicConstraintImpl;
+import org.eclipse.ocl.pivot.internal.values.SymbolicNavigationCallValueImpl;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicOperator;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
+
+/**
+ * @since 1.12
+ */
+public class SymbolicOCLExecutor extends BasicOCLExecutor implements SymbolicExecutor
+{
+ public SymbolicOCLExecutor( @NonNull EnvironmentFactoryInternalExtension environmentFactory, @NonNull ModelManager modelManager) {
+ super(environmentFactory, modelManager);
+ }
+
+ @Override
+ public void add(@NonNull VariableDeclaration variable, @NonNull SymbolicConstraint symbolicConstraint) {
+ Object oldConstraint = super.replaceInternal(variable, symbolicConstraint);
+ if (oldConstraint != null) {
+ CompositeSymbolicConstraintImpl compositeSymbolicConstraint;
+ if (oldConstraint instanceof CompositeSymbolicConstraintImpl) {
+ compositeSymbolicConstraint = (CompositeSymbolicConstraintImpl) oldConstraint;
+ }
+ else {
+ compositeSymbolicConstraint = new CompositeSymbolicConstraintImpl();
+ compositeSymbolicConstraint.add((SymbolicConstraint)oldConstraint);
+ super.replaceInternal(variable, compositeSymbolicConstraint);
+ }
+ compositeSymbolicConstraint.add(symbolicConstraint);
+ }
+
+ }
+
+ @Override
+ public @Nullable Object internalExecuteNavigationCallExp(@NonNull NavigationCallExp navigationCallExp, @NonNull Property referredProperty, @Nullable Object sourceValue) {
+ return new SymbolicNavigationCallValueImpl(navigationCallExp, sourceValue);
+ }
+
+ @Override
+ public Object internalExecuteOperationCallExp(@NonNull OperationCallExp operationCallExp, @Nullable Object @NonNull [] sourceAndArgumentValues) {
+ return super.internalExecuteOperationCallExp(operationCallExp, sourceAndArgumentValues);
+ }
+
+ @Override
+ public @NonNull EvaluationEnvironment pushSymbolicEvaluationEnvironment(@NonNull NamedElement executableObject, @Nullable Object symbolicValue, @Nullable Object constantValue) {
+ EvaluationEnvironment.EvaluationEnvironmentExtension evaluationEnvironment2 = (EvaluationEnvironmentExtension) getEvaluationEnvironment(); //ClassUtil.nonNullState(evaluationEnvironment);
+ EvaluationEnvironment.EvaluationEnvironmentExtension nestedEvaluationEnvironment = createNestedEvaluationEnvironment(evaluationEnvironment2, executableObject, (TypedElement)null);
+ pushEvaluationEnvironment(nestedEvaluationEnvironment);
+ if (symbolicValue instanceof SymbolicValue) {
+ ((SymbolicValue)symbolicValue).deduceFrom(this, new SymbolicConstraintImpl(TypeId.BOOLEAN, false, false, SymbolicOperator.EQUALS, constantValue));
+ }
+ return nestedEvaluationEnvironment;
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterableIterationManager.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterableIterationManager.java
index b2f51ed..6835ff4 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterableIterationManager.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterableIterationManager.java
@@ -127,7 +127,7 @@
if (accumulatorVariable != null) {
getEvaluationEnvironment().add(accumulatorVariable, accumulatorValue);
}
- ((Executor.ExecutorExtension)this.executor).pushEvaluationEnvironment(body, (Object)callExp);
+ this.executor.pushEvaluationEnvironment(body, (Object)callExp);
}
public AbstractEvaluatorIterableIterationManager(@NonNull AbstractEvaluatorIterableIterationManager<IV> iterationManager, @NonNull IV iterableValue) {
@@ -137,7 +137,7 @@
this.iterableValue = iterableValue;
this.accumulatorValue = iterationManager.accumulatorValue;
this.accumulatorVariable = iterationManager.accumulatorVariable;
- ((Executor.ExecutorExtension)this.executor).pushEvaluationEnvironment(body, (Object)callExp);
+ this.executor.pushEvaluationEnvironment(body, (Object)callExp);
}
@Override
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterationManager.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterationManager.java
index aa852ed..692c7e1 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterationManager.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/AbstractEvaluatorIterationManager.java
@@ -141,7 +141,7 @@
if (accumulatorVariable != null) {
getEvaluationEnvironment().add(accumulatorVariable, accumulatorValue);
}
- ((Executor.ExecutorExtension)this.executor).pushEvaluationEnvironment(body, (Object)callExp);
+ this.executor.pushEvaluationEnvironment(body, (Object)callExp);
}
public AbstractEvaluatorIterationManager(@NonNull AbstractEvaluatorIterationManager iterationManager, @NonNull CollectionValue collectionValue) {
@@ -151,7 +151,7 @@
this.collectionValue = collectionValue;
this.accumulatorValue = iterationManager.accumulatorValue;
this.accumulatorVariable = iterationManager.accumulatorVariable;
- ((Executor.ExecutorExtension)this.executor).pushEvaluationEnvironment(body, (Object)callExp);
+ this.executor.pushEvaluationEnvironment(body, (Object)callExp);
}
@Override
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/InvertibleLibraryOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/InvertibleLibraryOperation.java
new file mode 100644
index 0000000..b90da9d
--- /dev/null
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/InvertibleLibraryOperation.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Willink Transformations and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Contributors:
+ * E.D.Willink - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ocl.pivot.library;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
+
+/**
+ * An InvertibleLibraryOperation support deduction of operation input values from known output values.
+ *
+ * @since 1.12
+ */
+public interface InvertibleLibraryOperation
+{
+ /**
+ * Update symbolicExecutor from any deductions that can be made from knowing that resultValue satisfies resultConstraint.
+ */
+ void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicValue resultValue, @NonNull SymbolicConstraint resultConstraint);
+}
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/logical/BooleanImpliesOperation2.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/logical/BooleanImpliesOperation2.java
index 199d7b3..5f1805e 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/logical/BooleanImpliesOperation2.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/logical/BooleanImpliesOperation2.java
@@ -17,6 +17,7 @@
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.evaluation.Executor;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
import org.eclipse.ocl.pivot.library.AbstractSimpleBinaryOperation;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
@@ -44,10 +45,21 @@
if (sourceValue == Boolean.FALSE) {
return TRUE_VALUE;
}
- Object firstArgument = executor.evaluate(argument0);
- Boolean sourceBoolean = ValueUtil.asBoolean(sourceValue);
- Boolean argBoolean = ValueUtil.asBoolean(firstArgument);
- return evaluate(sourceBoolean, argBoolean);
+ else if (sourceValue == Boolean.TRUE) {
+ Object firstArgument = executor.evaluate(argument0);
+ Boolean argBoolean = ValueUtil.asBoolean(firstArgument);
+ return argBoolean;
+ }
+ try {
+ ((SymbolicExecutor)executor).pushSymbolicEvaluationEnvironment(callExp.getOwnedSource(), sourceValue, Boolean.TRUE);
+ Object firstArgument = executor.evaluate(argument0);
+ Boolean sourceBoolean = ValueUtil.asBoolean(sourceValue);
+ Boolean argBoolean = ValueUtil.asBoolean(firstArgument);
+ return evaluate(sourceBoolean, argBoolean);
+ }
+ finally {
+ executor.popEvaluationEnvironment();
+ }
}
@Override
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyEqualOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyEqualOperation.java
index 1f018af..995360b 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyEqualOperation.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyEqualOperation.java
@@ -13,19 +13,91 @@
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Type;
+import org.eclipse.ocl.pivot.evaluation.Executor;
+import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
+import org.eclipse.ocl.pivot.internal.values.SymbolicConstraintImpl;
+import org.eclipse.ocl.pivot.internal.values.SymbolicResultValueImpl;
import org.eclipse.ocl.pivot.library.AbstractSimpleBinaryOperation;
+import org.eclipse.ocl.pivot.library.InvertibleLibraryOperation;
+import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicOperator;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
/**
* OclAnyEqualOperation realises the OCLAny::=() library operation and
* regular derived implementations since the Value classes exhibit
* OCL value semantics.
*/
-public class OclAnyEqualOperation extends AbstractSimpleBinaryOperation
+public class OclAnyEqualOperation extends AbstractSimpleBinaryOperation implements InvertibleLibraryOperation
{
public static final @NonNull OclAnyEqualOperation INSTANCE = new OclAnyEqualOperation();
@Override
+ public void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicValue resultValue, @NonNull SymbolicConstraint resultConstraint) {
+ deduceFrom(symbolicExecutor, resultValue, resultConstraint, false);
+ }
+
+ /**
+ * @since 1.12
+ */
+ protected void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicValue resultValue, @NonNull SymbolicConstraint resultConstraint, boolean isInverted) {
+ SymbolicOperator thisSymbolicOperator = resultConstraint.getSymbolicOperator();
+ SymbolicOperator nestedSymbolicOperator = null;
+ if (thisSymbolicOperator == (isInverted ? SymbolicOperator.NOT_EQUALS : SymbolicOperator.EQUALS)) { // FIXME simplify, XOR
+ Object knownValue = resultConstraint.getSymbolicValue();
+ if (knownValue == Boolean.TRUE) {
+ nestedSymbolicOperator = SymbolicOperator.EQUALS;
+ }
+ else if (knownValue == Boolean.FALSE) {
+ nestedSymbolicOperator = SymbolicOperator.NOT_EQUALS;
+ }
+ }
+ else if (thisSymbolicOperator == (isInverted ? SymbolicOperator.EQUALS : SymbolicOperator.NOT_EQUALS)) {
+ Object knownValue = resultConstraint.getSymbolicValue();
+ if (knownValue == Boolean.TRUE) {
+ nestedSymbolicOperator = SymbolicOperator.NOT_EQUALS;
+ }
+ else if (knownValue == Boolean.FALSE) {
+ nestedSymbolicOperator = SymbolicOperator.EQUALS;
+ }
+ }
+ else {
+ throw new IllegalStateException(String.valueOf(thisSymbolicOperator));
+ }
+ if (nestedSymbolicOperator != null) {
+ Object sourceValue = ((SymbolicResultValueImpl)resultValue).getSourceValue();
+ Object argumentValue = ((SymbolicResultValueImpl)resultValue).getArgumentValue();
+ if (sourceValue instanceof SymbolicValue) {
+ ((SymbolicValue)sourceValue).deduceFrom(symbolicExecutor, new SymbolicConstraintImpl(TypeId.BOOLEAN, false, false, nestedSymbolicOperator, argumentValue));
+ }
+ if (argumentValue instanceof SymbolicValue) {
+ ((SymbolicValue)argumentValue).deduceFrom(symbolicExecutor, new SymbolicConstraintImpl(TypeId.BOOLEAN, false, false, nestedSymbolicOperator, sourceValue));
+ }
+ }
+ }
+
+ @Override
+ public @Nullable Object evaluate(@NonNull Executor executor, @NonNull TypeId returnTypeId,
+ @Nullable Object sourceValue, @Nullable Object argumentValue) {
+ if ((sourceValue instanceof SymbolicValue) || (argumentValue instanceof SymbolicValue)) {
+// boolean mayBeInvalid = ValueUtil.mayBeInvalid(sourceValue) || ValueUtil.mayBeInvalid(argumentValue);
+ if ((!ValueUtil.mayBeNull(sourceValue) && (argumentValue == null)) || ((sourceValue == null) && !ValueUtil.mayBeNull(argumentValue))) {
+ return evaluate(executor, sourceValue, argumentValue);
+// return new SymbolicBooleanValueImpl(returnTypeId, false, /*mayBeNull ||*/ mayBeInvalid, this, sourceValue, argumentValue);
+ }
+ else {
+ return new SymbolicResultValueImpl(returnTypeId, false, /*mayBeNull ||*/ false, this, sourceValue, argumentValue);
+ }
+ }
+ else {
+ return evaluate(executor, sourceValue, argumentValue);
+ }
+ }
+
+ @Override
public @NonNull Boolean evaluate(@Nullable Object left, @Nullable Object right) {
//
// A.2.2 is clear. 11.3.1 is vague.
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyNotEqualOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyNotEqualOperation.java
index be97855..c4d258c 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyNotEqualOperation.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclAnyNotEqualOperation.java
@@ -13,8 +13,11 @@
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.manager.SymbolicExecutor;
import org.eclipse.ocl.pivot.messages.PivotMessages;
import org.eclipse.ocl.pivot.values.InvalidValueException;
+import org.eclipse.ocl.pivot.values.SymbolicConstraint;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
/**
@@ -27,6 +30,11 @@
public static final @NonNull OclAnyNotEqualOperation INSTANCE = new OclAnyNotEqualOperation();
@Override
+ public void deduceFrom(@NonNull SymbolicExecutor symbolicExecutor, @NonNull SymbolicValue resultValue, @NonNull SymbolicConstraint resultConstraint) {
+ deduceFrom(symbolicExecutor, resultValue, resultConstraint, true);
+ }
+
+ @Override
public @NonNull Boolean evaluate(@Nullable Object left, @Nullable Object right) {
Object equals = super.evaluate(left, right);
if (equals == Boolean.FALSE) {
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableCompareToOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableCompareToOperation.java
index c6855cc..e92a286 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableCompareToOperation.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableCompareToOperation.java
@@ -12,9 +12,13 @@
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.values.SymbolicConstraintImpl;
import org.eclipse.ocl.pivot.library.AbstractSimpleBinaryOperation;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.IntegerValue;
+import org.eclipse.ocl.pivot.values.SymbolicOperator;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
/**
* OclComparableCompareToOperation realizes the abstract compareTo library operation using intrinsic Java functionality.
@@ -29,6 +33,11 @@
@SuppressWarnings("unchecked") int compareTo = ((Comparable<Object>)left).compareTo(right);
return integerValueOf(compareTo);
}
+ else if (left instanceof SymbolicValue) {
+ boolean mayBeInvalid = ValueUtil.mayBeInvalid(left) || ValueUtil.mayBeInvalid(right);
+ boolean mayBeNull = ValueUtil.mayBeNull(left) || ValueUtil.mayBeNull(right);
+ return new SymbolicConstraintImpl(TypeId.INTEGER, false, mayBeNull || mayBeInvalid, SymbolicOperator.COMPARE_TO, right);
+ }
else {
return integerValueOf(ValueUtil.throwUnsupportedCompareTo(left, right));
}
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableComparisonOperation.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableComparisonOperation.java
index eebce81..b776061 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableComparisonOperation.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/library/oclany/OclComparableComparisonOperation.java
@@ -19,29 +19,28 @@
import org.eclipse.ocl.pivot.evaluation.Executor;
import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.ids.TypeId;
+import org.eclipse.ocl.pivot.internal.values.SymbolicUnknownValueImpl;
import org.eclipse.ocl.pivot.library.AbstractUntypedBinaryOperation;
import org.eclipse.ocl.pivot.library.LibraryBinaryOperation;
import org.eclipse.ocl.pivot.library.LibraryConstants;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.InvalidValueException;
+import org.eclipse.ocl.pivot.values.SymbolicValue;
/**
* OclComparableComparisonOperation provides the abstract support for a comparison operation.
*/
public abstract class OclComparableComparisonOperation extends AbstractUntypedBinaryOperation
-{
+{
/** @deprecated use Executor */
@Deprecated
@Override
public @Nullable Boolean evaluate(@NonNull Evaluator evaluator, @Nullable Object left, @Nullable Object right) {
- return evaluate(getExecutor(evaluator), left, right);
+ return evaluate(getExecutor(evaluator), left, right);
}
- /**
- * @since 1.1
- */
@Override
- public @NonNull Boolean evaluate(@NonNull Executor executor, @Nullable Object left, @Nullable Object right) {
+ public @Nullable Object evaluate(@NonNull Executor executor, @NonNull TypeId returnTypeId, @Nullable Object left, @Nullable Object right) {
StandardLibrary standardLibrary = executor.getStandardLibrary();
IdResolver idResolver = executor.getIdResolver();
CompleteInheritance leftType = idResolver.getDynamicTypeOf(left).getInheritance(standardLibrary);
@@ -61,13 +60,29 @@
}
if (implementation != null) {
Object comparison = implementation.evaluate(executor, TypeId.INTEGER, left, right);
+ if (comparison instanceof SymbolicValue) {
+ boolean mayBeInvalid = ValueUtil.mayBeInvalid(left) || ValueUtil.mayBeInvalid(right);
+ boolean mayBeNull = ValueUtil.mayBeNull(left) || ValueUtil.mayBeNull(right);
+ return new SymbolicUnknownValueImpl(TypeId.BOOLEAN, false, mayBeNull || mayBeInvalid);
+ }
intComparison = ValueUtil.asInteger(comparison);
return getResultValue(intComparison) != false; // FIXME redundant test to suppress warning
}
else {
- throw new InvalidValueException("Unsupported compareTo for ''{0}''", left != null ? left.getClass().getName() : NULL_STRING); //$NON-NLS-1$
+ // throw new InvalidValueException("Unsupported compareTo for ''{0}''", left != null ? left.getClass().getName() : NULL_STRING); //$NON-NLS-1$
+ ValueUtil.throwUnsupportedCompareTo(left, right);
+ return false;
}
}
+ /**
+ * @since 1.1
+ */
+ @Override
+ public @NonNull Boolean evaluate(@NonNull Executor executor, @Nullable Object left, @Nullable Object right) {
+ // FIXME This reverse hierarchy call is necessary to preserve API but accommodate SymbolicValue
+ return (Boolean)evaluate(executor, TypeId.BOOLEAN, left, right);
+ }
+
protected abstract boolean getResultValue(Integer comparison);
}
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ValueUtil.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ValueUtil.java
index 3644087..4298adc 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ValueUtil.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/utilities/ValueUtil.java
@@ -1009,6 +1009,29 @@
}
/**
+ * @since 1.12
+ */
+ public static boolean mayBeInvalid(@Nullable Object value) {
+ if (value instanceof Value) {
+ return ((Value)value).mayBeInvalid();
+ }
+ return false;
+ }
+
+ /**
+ * @since 1.12
+ */
+ public static boolean mayBeNull(@Nullable Object value) {
+ if (value == null) {
+ return true;
+ }
+ else if (value instanceof Value) {
+ return ((Value)value).mayBeNull();
+ }
+ return false;
+ }
+
+ /**
* @since 1.1
*/
public static @NonNull NumberValue numberValueOf(@NonNull Number aNumber) {
diff --git a/tests/org.eclipse.ocl.examples.xtext.tests/src/org/eclipse/ocl/examples/test/xtext/FlowAnalysisTests.java b/tests/org.eclipse.ocl.examples.xtext.tests/src/org/eclipse/ocl/examples/test/xtext/FlowAnalysisTests.java
index c453f21..509db57 100644
--- a/tests/org.eclipse.ocl.examples.xtext.tests/src/org/eclipse/ocl/examples/test/xtext/FlowAnalysisTests.java
+++ b/tests/org.eclipse.ocl.examples.xtext.tests/src/org/eclipse/ocl/examples/test/xtext/FlowAnalysisTests.java
@@ -25,6 +25,7 @@
import org.eclipse.ocl.pivot.LetExp;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.NullLiteralExp;
+import org.eclipse.ocl.pivot.NumericLiteralExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
@@ -170,7 +171,7 @@
return ((MetamodelManagerInternal.MetamodelManagerInternalExtension2)metamodelManager).getFlowAnalysis(asExpression);
}
- protected @NonNull SymbolicEvaluationVisitor getSymbolicAnalysis(@NonNull ExpressionInOCL asExpressionInOCL, @Nullable Object context, @NonNull Object... parameters) {
+ protected @NonNull SymbolicEvaluationVisitor getSymbolicAnalysis(@NonNull ExpressionInOCL asExpressionInOCL, @Nullable Object context, @Nullable Object[] parameters) {
MetamodelManagerInternal metamodelManager = getMetamodelManager();
return ((MetamodelManagerInternal.MetamodelManagerInternalExtension2)metamodelManager).getSymbolicAnalysis(asExpressionInOCL, context, parameters);
}
@@ -259,14 +260,14 @@
// ocl.assertIsNonNull(asThenLiteralExp);
// ocl.assertIsNotKnown(asElseVariableExp);
- SymbolicEvaluationVisitor symbolicAnalysis1 = ocl.getSymbolicAnalysis(asExpressionInOCL, null);
+ SymbolicEvaluationVisitor symbolicAnalysis1 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[0]);
assert !symbolicAnalysis1.mayBeNull(asExpressionInOCL);
assert !symbolicAnalysis1.mayBeNull(asIf);
assert !symbolicAnalysis1.mayBeNull(asLetExp);
assert ocl.getIdResolver().oclEquals(symbolicAnalysis1.get(asIf), "null");
assert symbolicAnalysis1.isDead(asElseVariableExp);
- SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, new SymbolicUnknownValueImpl(TypeId.STRING, false, false));
+ SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, new SymbolicUnknownValueImpl(TypeId.STRING, false, false), new Object[0]);
assert !symbolicAnalysis2.mayBeNull(asExpressionInOCL);
assert !symbolicAnalysis2.mayBeNull(asIf);
assert !symbolicAnalysis2.mayBeNull(asLetExp);
@@ -278,13 +279,12 @@
public void testSymbolicAnalysis_BadDivide() throws Exception {
MyOCL ocl = new MyOCL();
ExpressionInOCL asExpressionInOCL = ocl.createQueryTestModel("BadDivide", "BadDivide(num : Real, den : Real) : Real",
- // "let num = 5.0 in den = 0.0 in num / den");
"num / den");
OperationCallExp asOperationCallExp = (OperationCallExp) asExpressionInOCL.getOwnedBody();
VariableExp asNumExp = (VariableExp) PivotUtil.getOwnedSource(asOperationCallExp);
VariableExp asDenExp = (VariableExp) PivotUtil.getOwnedArgument(asOperationCallExp, 0);
- SymbolicEvaluationVisitor symbolicAnalysis1 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, 5.0, 0.0);
+ SymbolicEvaluationVisitor symbolicAnalysis1 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{5.0, 0.0});
assert !symbolicAnalysis1.mayBeNull(asExpressionInOCL);
assert !symbolicAnalysis1.mayBeNull(asNumExp);
assert !symbolicAnalysis1.mayBeNull(asDenExp);
@@ -292,7 +292,109 @@
assert !symbolicAnalysis1.mayBeInvalid(asDenExp);
assert symbolicAnalysis1.mayBeInvalid(asOperationCallExp);
- SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, 5.0, 1.0);
+ SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{5.0, 1.0});
+ assert !symbolicAnalysis2.mayBeNull(asExpressionInOCL);
+ assert !symbolicAnalysis2.mayBeNull(asNumExp);
+ assert !symbolicAnalysis2.mayBeNull(asDenExp);
+ assert !symbolicAnalysis2.mayBeInvalid(asNumExp);
+ assert !symbolicAnalysis2.mayBeInvalid(asDenExp);
+ assert !symbolicAnalysis2.mayBeInvalid(asOperationCallExp);
+
+ SymbolicEvaluationVisitor symbolicAnalysis3 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{new SymbolicUnknownValueImpl(TypeId.REAL, false, false), 0.0});
+ assert !symbolicAnalysis3.mayBeNull(asExpressionInOCL);
+ assert !symbolicAnalysis3.mayBeNull(asNumExp);
+ assert !symbolicAnalysis3.mayBeNull(asDenExp);
+ assert !symbolicAnalysis3.mayBeInvalid(asNumExp);
+ assert !symbolicAnalysis3.mayBeInvalid(asDenExp);
+ assert symbolicAnalysis3.mayBeInvalid(asOperationCallExp);
+
+ SymbolicEvaluationVisitor symbolicAnalysis4 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{new SymbolicUnknownValueImpl(TypeId.REAL, false, false), 1.0});
+ assert !symbolicAnalysis4.mayBeNull(asExpressionInOCL);
+ assert !symbolicAnalysis4.mayBeNull(asNumExp);
+ assert !symbolicAnalysis4.mayBeNull(asDenExp);
+ assert !symbolicAnalysis4.mayBeInvalid(asNumExp);
+ assert !symbolicAnalysis4.mayBeInvalid(asDenExp);
+ assert !symbolicAnalysis4.mayBeInvalid(asOperationCallExp);
+
+ ocl.dispose();
+ }
+
+ public void testSymbolicAnalysis_ImpliesGuard() throws Exception {
+ MyOCL ocl = new MyOCL();
+ ExpressionInOCL asExpressionInOCL = ocl.createQueryTestModel("ImpliesGuard", "ImpliesGuard(x : Integer) : Boolean",
+ "x <> null implies2 x > 0");
+ OperationCallExp impliesExp = (OperationCallExp) asExpressionInOCL.getOwnedBody();
+ OperationCallExp notEqExp = (OperationCallExp) PivotUtil.getOwnedSource(impliesExp);
+ OperationCallExp gtExp = (OperationCallExp) PivotUtil.getOwnedArgument(impliesExp, 0);
+ VariableExp neSourceExp = (VariableExp) PivotUtil.getOwnedSource(notEqExp);
+ NullLiteralExp nullExp = (NullLiteralExp) PivotUtil.getOwnedArgument(notEqExp, 0);
+ VariableExp gtSourceExp = (VariableExp) PivotUtil.getOwnedSource(gtExp);
+ NumericLiteralExp zeroExp = (NumericLiteralExp) PivotUtil.getOwnedArgument(gtExp, 0);
+
+ assert nullExp.isNull();
+
+ /* SymbolicEvaluationVisitor symbolicAnalysis1 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{5});
+ assert !symbolicAnalysis1.mayBeNull(asExpressionInOCL);
+ assert !symbolicAnalysis1.mayBeNull(notEqExp);
+ assert !symbolicAnalysis1.mayBeNull(gtExp);
+
+ assert !symbolicAnalysis1.mayBeNull(neSourceExp);
+ assert symbolicAnalysis1.mayBeNull(nullExp);
+ assert !symbolicAnalysis1.mayBeNull(gtSourceExp);
+ assert !symbolicAnalysis1.mayBeNull(zeroExp);
+
+ assert !symbolicAnalysis1.mayBeInvalid(asExpressionInOCL);
+ assert !symbolicAnalysis1.mayBeInvalid(notEqExp);
+ assert !symbolicAnalysis1.mayBeInvalid(gtExp);
+
+ assert !symbolicAnalysis1.mayBeInvalid(neSourceExp);
+ assert !symbolicAnalysis1.mayBeInvalid(nullExp);
+ assert !symbolicAnalysis1.mayBeInvalid(gtSourceExp);
+ assert !symbolicAnalysis1.mayBeInvalid(zeroExp);
+
+ assert symbolicAnalysis1.isTrue(notEqExp);
+ assert symbolicAnalysis1.isTrue(gtExp);
+ assert symbolicAnalysis1.isTrue(asExpressionInOCL); */
+
+ /* SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{null});
+ assert !symbolicAnalysis2.mayBeNull(asExpressionInOCL);
+ assert !symbolicAnalysis2.mayBeNull(notEqExp);
+ assert symbolicAnalysis2.isDead(gtExp);
+
+ assert symbolicAnalysis2.mayBeNull(neSourceExp);
+ assert symbolicAnalysis2.mayBeNull(nullExp);
+ assert symbolicAnalysis2.isDead(gtSourceExp);
+ assert symbolicAnalysis2.isDead(zeroExp);
+
+ assert !symbolicAnalysis2.mayBeInvalid(asExpressionInOCL);
+ assert !symbolicAnalysis2.mayBeInvalid(notEqExp);
+
+ assert !symbolicAnalysis2.mayBeInvalid(neSourceExp);
+ assert !symbolicAnalysis2.mayBeInvalid(nullExp);
+
+ assert symbolicAnalysis2.isFalse(notEqExp);
+ assert symbolicAnalysis2.isTrue(asExpressionInOCL); */
+
+ SymbolicEvaluationVisitor symbolicAnalysis3 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, new Object[]{new SymbolicUnknownValueImpl(TypeId.INTEGER, true, false)});
+ assert !symbolicAnalysis3.mayBeNull(asExpressionInOCL);
+ assert !symbolicAnalysis3.mayBeNull(notEqExp);
+ assert !symbolicAnalysis3.mayBeNull(gtExp);
+
+ assert symbolicAnalysis3.mayBeNull(neSourceExp);
+ assert symbolicAnalysis3.mayBeNull(nullExp);
+ assert !symbolicAnalysis3.mayBeNull(gtSourceExp);
+ assert !symbolicAnalysis3.mayBeNull(zeroExp);
+
+ assert !symbolicAnalysis3.mayBeInvalid(asExpressionInOCL);
+ assert !symbolicAnalysis3.mayBeInvalid(notEqExp);
+
+ assert !symbolicAnalysis3.mayBeInvalid(neSourceExp);
+ assert !symbolicAnalysis3.mayBeInvalid(nullExp);
+
+ assert symbolicAnalysis3.isFalse(notEqExp);
+ assert symbolicAnalysis3.isTrue(asExpressionInOCL);
+
+/* SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, null, 5.0, 1.0);
assert !symbolicAnalysis2.mayBeNull(asExpressionInOCL);
assert !symbolicAnalysis2.mayBeNull(asNumExp);
assert !symbolicAnalysis2.mayBeNull(asDenExp);
@@ -314,16 +416,8 @@
assert !symbolicAnalysis4.mayBeNull(asDenExp);
assert !symbolicAnalysis4.mayBeInvalid(asNumExp);
assert !symbolicAnalysis4.mayBeInvalid(asDenExp);
- assert !symbolicAnalysis4.mayBeInvalid(asOperationCallExp);
-// assert ocl.getIdResolver().oclEquals(symbolicAnalysis1.get(asIf), "null");
-// assert symbolicAnalysis1.isDead(asElseVariableExp);
+ assert !symbolicAnalysis4.mayBeInvalid(asOperationCallExp); */
-// SymbolicEvaluationVisitor symbolicAnalysis2 = ocl.getSymbolicAnalysis(asExpressionInOCL, new SymbolicUnknownValueImpl(TypeId.STRING, false, false));
-// assert !symbolicAnalysis2.mayBeNull(asExpressionInOCL);
-// assert !symbolicAnalysis2.mayBeNull(asIf);
-// assert !symbolicAnalysis2.mayBeNull(asLetExp);
-// assert ocl.getIdResolver().oclEquals(symbolicAnalysis2.get(asIf), "null");
-// assert symbolicAnalysis2.isDead(asThenLiteralExp); */
ocl.dispose();
}