blob: cb7a8023cd2308132c269dc8f649750db8429530 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2022 CEA LIST 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(CEA LIST) - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.examples.codegen.analyzer;
import java.util.List;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.codegen.calling.OperationCallingConvention;
import org.eclipse.ocl.examples.codegen.calling.PropertyCallingConvention;
import org.eclipse.ocl.examples.codegen.cgmodel.CGAssertNonNullExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBoxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGBuiltInIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCachedOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCachedOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGCastExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGEcoreExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorType;
import org.eclipse.ocl.examples.codegen.cgmodel.CGGuardExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIfExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsEqual2Exp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIsEqualExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGIterator;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryIterateCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryIterationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGLibraryOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGModelFactory;
import org.eclipse.ocl.examples.codegen.cgmodel.CGNavigationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperation;
import org.eclipse.ocl.examples.codegen.cgmodel.CGOperationCallExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGParameter;
import org.eclipse.ocl.examples.codegen.cgmodel.CGProperty;
import org.eclipse.ocl.examples.codegen.cgmodel.CGShadowPart;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeId;
import org.eclipse.ocl.examples.codegen.cgmodel.CGUnboxExp;
import org.eclipse.ocl.examples.codegen.cgmodel.CGValuedElement;
import org.eclipse.ocl.examples.codegen.cgmodel.CGVariable;
import org.eclipse.ocl.examples.codegen.cgmodel.CGVariableExp;
import org.eclipse.ocl.examples.codegen.cgmodel.util.AbstractExtendingCGModelVisitor;
import org.eclipse.ocl.examples.codegen.generator.CodeGenerator;
import org.eclipse.ocl.examples.codegen.generator.TypeDescriptor;
import org.eclipse.ocl.examples.codegen.java.types.BoxedDescriptor;
import org.eclipse.ocl.examples.codegen.java.types.EcoreDescriptor;
import org.eclipse.ocl.examples.codegen.java.types.UnboxedDescriptor;
import org.eclipse.ocl.examples.codegen.utilities.CGUtil;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.ids.ElementId;
import org.eclipse.ocl.pivot.library.LibraryIteration;
import org.eclipse.ocl.pivot.library.iterator.IterateIteration;
/**
* A BoxingAnalyzer performs a bottom up tree-traversal inserting:
* <p>CGBoxExp or CGUnboxExp whereever a conversion from boxed to unboxed or vice-versa is required.
* <p>CGCastExp whereever the apparent type is not available (e.g. Parameters passed as Object).
* <p>CGGuardExp whereever a non-null value is required.
* <p>
* No attempt at optimisation is made, since this can be performed by Common SubExpression Elimination.
* <p>
* <h2>Simple (both boxed and unboxed)</h2>
* Boolean, String, null, EObject (except Types)
* <h2>Boxed/Unboxed</h2>
* IntegerValue/Number, RealValue/Number, TypeValue/EObject, InvalidValue/Exception, CollectionValue/List
* <h2>Boxed</h2>
* TupleValue
* <h2>Boxed Protocol</h2>
* Executor/Library Iteration/Operation/PropertyCall
* <h2>Unboxed Protocol</h2>
* Ecore Operation/PropertyCall
*/
public class BoxingAnalyzer extends AbstractExtendingCGModelVisitor<@Nullable Object, @NonNull CodeGenAnalyzer>
{
protected final @NonNull CodeGenerator codeGenerator;
public BoxingAnalyzer(@NonNull CodeGenAnalyzer analyzer) {
super(analyzer);
codeGenerator = analyzer.getCodeGenerator();
}
public @NonNull CodeGenAnalyzer getAnalyzer() {
return context;
}
public @NonNull CodeGenerator getCodeGenerator() {
return codeGenerator;
}
/**
* Return true if cgCallExp uses a safe navigation operator.
*/
public boolean isSafe(@NonNull CGCallExp cgCallExp) {
Element asElement = cgCallExp.getAst();
return (asElement instanceof CallExp) && ((CallExp)asElement).isIsSafe();
}
/**
* Insert a CGAssertNonNullExp around cgChild.
*/
public @Nullable CGValuedElement rewriteAsAssertNonNulled(@Nullable CGValuedElement cgChild) {
if ((cgChild == null) || cgChild.isNonNull() /*|| (cgParent instanceof CGGuardExp)*/) {
return cgChild;
}
CGAssertNonNullExp cgAssertExp = CGModelFactory.eINSTANCE.createCGAssertNonNullExp();
CGUtil.wrap(cgAssertExp, cgChild);
return cgAssertExp;
}
/**
* Insert a CGBoxExp around cgChild.
*/
public @Nullable CGValuedElement rewriteAsBoxed(@Nullable CGValuedElement cgChild) {
if ((cgChild == null) || cgChild.isBoxed()) {
return cgChild;
}
CGTypeId cgTypeId = cgChild.getTypeId();
ElementId elementId = cgTypeId.getElementId();
if (elementId != null) {
BoxedDescriptor boxedDescriptor = codeGenerator.getBoxedDescriptor(elementId);
if (cgChild.isEcore()) {
EClassifier eClassifier = cgChild.getEcoreClassifier();
Class<?> instanceClass = eClassifier != null ? eClassifier.getInstanceClass() : null;
EcoreDescriptor ecoreDescriptor = boxedDescriptor.getEcoreDescriptor(codeGenerator, instanceClass);
if (boxedDescriptor == ecoreDescriptor) {
return cgChild;
}
}
else {
UnboxedDescriptor unboxedDescriptor = boxedDescriptor.getUnboxedDescriptor(codeGenerator);
if (unboxedDescriptor == boxedDescriptor) {
return cgChild;
}
}
}
CGBoxExp cgBoxExp = CGModelFactory.eINSTANCE.createCGBoxExp();
// NameResolution unboxedNameResolution = codeGenerator.getNameResolution(cgChild);
// NameVariant boxedNameVariant = codeGenerator.getBOXED_NameVariant();
// NameResolution boxedNameResolution = unboxedNameResolution.addNameVariant(boxedNameVariant);
// boxedNameResolution.addCGElement(cgBoxExp);
CGUtil.wrap(cgBoxExp, cgChild);
return cgBoxExp;
}
/**
* Insert a CGEcoreExp around cgChild.
*/
public @Nullable CGValuedElement rewriteAsEcore(@Nullable CGValuedElement cgChild, /*@NonNull*/ EClassifier eClassifier) {
if ((cgChild == null) || cgChild.isEcore()) {
return cgChild;
}
CGTypeId cgTypeId = cgChild.getTypeId();
ElementId elementId = cgTypeId.getElementId();
if (elementId != null) {
BoxedDescriptor boxedDescriptor = codeGenerator.getBoxedDescriptor(elementId);
// EClassifier eClassifier = cgChild.getEcoreClassifier();
Class<?> instanceClass = eClassifier != null ? eClassifier.getInstanceClass() : null;
EcoreDescriptor ecoreDescriptor = boxedDescriptor.getEcoreDescriptor(codeGenerator, instanceClass);
if (cgChild.isUnboxed()) {
UnboxedDescriptor unboxedDescriptor = boxedDescriptor.getUnboxedDescriptor(codeGenerator);
if (ecoreDescriptor == unboxedDescriptor) {
return cgChild;
}
}
else {
if (ecoreDescriptor == boxedDescriptor) {
return cgChild;
}
}
}
CGEcoreExp cgEcoreExp = CGModelFactory.eINSTANCE.createCGEcoreExp();
cgEcoreExp.setEClassifier(eClassifier);
CGUtil.wrap(cgEcoreExp, cgChild);
return cgEcoreExp;
}
/**
* Insert a CGGuardExp around cgChild.
*/
public @Nullable CGValuedElement rewriteAsGuarded(@Nullable CGValuedElement cgChild, boolean isSafe, @NonNull String message) {
if ((cgChild == null) || cgChild.isNonNull() /*|| (cgParent instanceof CGGuardExp)*/) {
return cgChild;
}
CGGuardExp cgGuardExp = CGModelFactory.eINSTANCE.createCGGuardExp();
cgGuardExp.setMessage(message);
cgGuardExp.setSafe(isSafe);
// Guard is a prefix IF so new new variable name required; just a copyable resolution..
// NameResolution unguardedNameResolution = codeGenerator.getNameResolution(cgChild);
// NameResolution guardedNameResolution = unguardedNameResolution.addNameVariant(codeGenerator.getGUARDED_NameVariant());
// unguardedNameResolution.addCGElement(cgGuardExp); // XXX GUARD is a prefix throw - no new variable
CGUtil.wrap(cgGuardExp, cgChild);
return cgGuardExp;
}
/**
* Insert a CGCastExp around cgChild.
*/
protected CGValuedElement rewriteAsCast(@Nullable CGValuedElement/*CGVariableExp*/ cgChild) {
if (cgChild == null) {
return cgChild;
}
TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgChild);
if (typeDescriptor.getJavaClass() == Object.class) {
return cgChild;
}
TypedElement pivot = (TypedElement) cgChild.getAst();
Type asType = pivot.getType();
CGCastExp cgCastExp = CGModelFactory.eINSTANCE.createCGCastExp();
CGUtil.wrap(cgCastExp, cgChild);
cgCastExp.setAst(pivot);
if (asType != null) {
CGExecutorType cgExecutorType = context.createExecutorType(asType);
cgCastExp.setExecutorType(cgExecutorType);
}
cgCastExp.setTypeId(codeGenerator.getAnalyzer().getCGTypeId(pivot.getTypeId()));
return cgCastExp;
}
/**
* Insert a CGUnboxExp around cgChild.
*/
public @Nullable CGValuedElement rewriteAsUnboxed(@Nullable CGValuedElement cgChild) {
if ((cgChild == null) || cgChild.isUnboxed()) {
return cgChild;
}
CGTypeId cgTypeId = cgChild.getTypeId();
ElementId elementId = cgTypeId.getElementId();
if (elementId != null) {
// boolean maybePrimitive = codeGenerator.maybePrimitive(cgChild);
// TypeDescriptor boxedTypeDescriptor = codeGenerator.getTypeDescriptor(elementId, true, maybePrimitive);
// TypeDescriptor unboxedTypeDescriptor = codeGenerator.getTypeDescriptor(elementId, false, maybePrimitive);
TypeDescriptor boxedDescriptor = codeGenerator.getBoxedDescriptor(elementId);
TypeDescriptor unboxedDescriptor = boxedDescriptor.getUnboxedDescriptor(codeGenerator);
if (cgChild.isEcore()) {
EClassifier eClassifier = cgChild.getEcoreClassifier();
Class<?> instanceClass = eClassifier != null ? eClassifier.getInstanceClass() : null;
EcoreDescriptor ecoreDescriptor = boxedDescriptor.getEcoreDescriptor(codeGenerator, instanceClass);
if ((unboxedDescriptor == ecoreDescriptor) || (ecoreDescriptor instanceof UnboxedDescriptor)) {
return cgChild;
}
}
else {
if (unboxedDescriptor == boxedDescriptor) {
return cgChild;
}
}
}
CGUnboxExp cgUnboxExp = CGModelFactory.eINSTANCE.createCGUnboxExp();
CGUtil.wrap(cgUnboxExp, cgChild);
return cgUnboxExp;
}
@Override
@Nullable
public Object visiting(@NonNull CGElement visitable) {
throw new UnsupportedOperationException(getClass().getSimpleName() + ": " + visitable.getClass().getSimpleName());
}
@Override
public @Nullable Object visitCGBuiltInIterationCallExp(@NonNull CGBuiltInIterationCallExp cgElement) {
super.visitCGBuiltInIterationCallExp(cgElement);
rewriteAsBoxed(rewriteAsGuarded(cgElement.getSource(), isSafe(cgElement), "source for '" + cgElement.getAsIteration() + "'"));
CGValuedElement cgBody = cgElement.getBody();
if (cgBody.isRequired()) {
rewriteAsBoxed(rewriteAsGuarded(cgBody, false, "body for '" + cgElement.getAsIteration() + "'"));
}
else {
rewriteAsBoxed(cgBody);
}
return null;
}
@Override
public @Nullable Object visitCGCachedOperation(@NonNull CGCachedOperation cgCachedOperation) {
super.visitCGCachedOperation(cgCachedOperation);
rewriteAsBoxed(cgCachedOperation.getBody());
return null;
}
@Override
public @Nullable Object visitCGCachedOperationCallExp(@NonNull CGCachedOperationCallExp cgElement) {
super.visitCGCachedOperationCallExp(cgElement);
assert cgElement.getCgThis() == null;
List<CGValuedElement> cgArguments = cgElement.getArguments();
int iMax = cgArguments.size();
for (int i = 0; i < iMax; i++) { // Avoid CME from rewrite
CGValuedElement cgArgument = cgArguments.get(i);
if (i == 0) {
rewriteAsGuarded(cgArgument, isSafe(cgElement), "source for '" + cgElement.getAsOperation() + "'");
}
rewriteAsBoxed(cgArgument);
}
return null;
}
/* @Override
public @Nullable Object visitCGConstrainedProperty(@NonNull CGConstrainedProperty cgProperty) {
super.visitCGConstrainedProperty(cgProperty);
if (cgProperty.isRequired()) {
CGValuedElement body = cgProperty.getBody();
if (body != null) {
rewriteAsGuarded(body, false, "body for '" + cgProperty.getAst() + "'");
}
}
return null;
} */
/* @Override
public @Nullable Object visitCGEcoreOperation(@NonNull CGEcoreOperation cgElement) {
super.visitCGEcoreOperation(cgElement);
CGValuedElement body = cgElement.getBody();
if (body != null) {
rewriteAsEcore(body, cgElement.getEOperation().getEType());
}
return null;
} */
/* @Override
public @Nullable Object visitCGEcoreOppositePropertyCallExp(@NonNull CGEcoreOppositePropertyCallExp cgElement) {
super.visitCGEcoreOppositePropertyCallExp(cgElement);
rewriteAsEcore(cgElement.getSource(), cgElement.getEStructuralFeature().getEType());
if (cgElement.getEStructuralFeature().isMany()) {
rewriteAsAssertNonNulled(cgElement);
}
return null;
} */
/* @Override
public @Nullable Object visitCGEcorePropertyCallExp(@NonNull CGEcorePropertyCallExp cgElement) {
super.visitCGEcorePropertyCallExp(cgElement);
rewriteAsEcore(cgElement.getSource(), cgElement.getEStructuralFeature().getEContainingClass());
if (cgElement.getEStructuralFeature().isMany()) {
rewriteAsAssertNonNulled(cgElement);
}
return null;
} */
/* @Override
public @Nullable Object visitCGExecutorOppositePropertyCallExp(@NonNull CGExecutorOppositePropertyCallExp cgElement) {
super.visitCGExecutorOppositePropertyCallExp(cgElement);
rewriteAsUnboxed(cgElement.getSource());
CGTypedElement cgParent = (CGTypedElement) cgElement.getParent();
if (cgParent != null) {
rewriteAsBoxed(cgElement);
}
return null;
} */
/* @Override
public @Nullable Object visitCGExecutorPropertyCallExp(@NonNull CGExecutorPropertyCallExp cgElement) {
super.visitCGExecutorPropertyCallExp(cgElement);
rewriteAsUnboxed(cgElement.getSource());
CGTypedElement cgParent = (CGTypedElement) cgElement.getParent();
if (cgParent != null) {
rewriteAsBoxed(cgElement);
}
return null;
} */
@Override
public @Nullable Object visitCGElement(@NonNull CGElement cgElement) {
for (@NonNull CGElement cgChild : cgElement.getChildren()) {
cgChild.accept(this);
}
return null;
}
/* @Override
public @Nullable Object visitCGForeignProperty(@NonNull CGForeignProperty cgForeignProperty) {
super.visitCGForeignProperty(cgForeignProperty);
rewriteAsBoxed(cgForeignProperty.getBody());
if (cgForeignProperty.isRequired()) {
CGValuedElement body = cgForeignProperty.getBody();
if (body != null) {
rewriteAsGuarded(body, false, "body for '" + cgForeignProperty.getAst() + "'");
}
}
return null;
} */
/* @Override
public @Nullable Object visitCGForeignPropertyCallExp(@NonNull CGForeignPropertyCallExp cgElement) {
return null;
} */
@Override
public @Nullable Object visitCGIfExp(@NonNull CGIfExp cgElement) {
super.visitCGIfExp(cgElement);
rewriteAsGuarded(cgElement.getCondition(), false, "if condition");
CGValuedElement thenExpression = cgElement.getThenExpression();
CGValuedElement elseExpression = cgElement.getElseExpression();
if ((thenExpression != null) && (elseExpression != null)) {
boolean thenIsBoxed = thenExpression.isBoxed();
boolean elseIsBoxed = elseExpression.isBoxed();
if (thenIsBoxed != elseIsBoxed) {
if (thenIsBoxed) {
rewriteAsBoxed(cgElement.getElseExpression());
}
else {
rewriteAsBoxed(cgElement.getThenExpression());
}
}
}
return null;
}
// @Override
// public @Nullable Object visitCGIndexExp(@NonNull CGIndexExp cgIndexExp) {
// return null;
// }
@Override
public @Nullable Object visitCGIsEqualExp(@NonNull CGIsEqualExp cgElement) {
super.visitCGIsEqualExp(cgElement);
CGValuedElement cgSource = cgElement.getSource();
CGValuedElement cgArgument = cgElement.getArgument();
boolean sourceIsBoxed = cgSource.isBoxed();
boolean argumentIsBoxed = cgArgument.isBoxed();
if (sourceIsBoxed != argumentIsBoxed) { // FIXME also needs-boxing
if (!sourceIsBoxed) {
rewriteAsBoxed(cgSource);
}
if (!argumentIsBoxed) {
rewriteAsBoxed(cgArgument);
}
}
return null;
}
@Override
public @Nullable Object visitCGIsEqual2Exp(@NonNull CGIsEqual2Exp cgElement) {
super.visitCGIsEqual2Exp(cgElement);
CGValuedElement cgSource = cgElement.getSource();
CGValuedElement cgArgument = cgElement.getArgument();
boolean sourceIsBoxed = cgSource.isBoxed();
boolean argumentIsBoxed = cgArgument.isBoxed();
if (sourceIsBoxed != argumentIsBoxed) { // FIXME also needs-boxing
if (!sourceIsBoxed) {
rewriteAsBoxed(cgSource);
}
if (!argumentIsBoxed) {
rewriteAsBoxed(cgArgument);
}
}
return null;
}
@Override
public @Nullable Object visitCGLibraryIterateCallExp(@NonNull CGLibraryIterateCallExp cgElement) {
super.visitCGLibraryIterateCallExp(cgElement);
rewriteAsGuarded(cgElement.getSource(), isSafe(cgElement), "source for '" + cgElement.getAsIteration() + "'");
rewriteAsBoxed(cgElement.getSource());
LibraryIteration libraryIteration = cgElement.getLibraryIteration();
if (!(libraryIteration instanceof IterateIteration)) {
rewriteAsBoxed(cgElement.getBody());
}
return null;
}
@Override
public @Nullable Object visitCGLibraryIterationCallExp(@NonNull CGLibraryIterationCallExp cgElement) {
super.visitCGLibraryIterationCallExp(cgElement);
rewriteAsGuarded(cgElement.getSource(), isSafe(cgElement), "source for '" + cgElement.getAsIteration() + "'");
rewriteAsBoxed(cgElement.getSource());
LibraryIteration libraryIteration = cgElement.getLibraryIteration();
if (!(libraryIteration instanceof IterateIteration)) {
rewriteAsBoxed(cgElement.getBody());
}
return null;
}
/* @Override
public @Nullable Object visitCGLibraryOperation(@NonNull CGLibraryOperation cgLibraryOperation) {
super.visitCGLibraryOperation(cgLibraryOperation);
rewriteAsBoxed(cgLibraryOperation.getBody());
return null;
} */
/* @Override
public @Nullable Object visitCGNativeOperation(@NonNull CGNativeOperation cgNativeOperation) {
super.visitCGNativeOperation(cgNativeOperation);
rewriteAsUnboxed(cgNativeOperation.getBody());
return null;
} */
/* @Override
public @Nullable Object visitCGNativeProperty(@NonNull CGNativeProperty cgProperty) {
super.visitCGNativeProperty(cgProperty);
if (cgProperty.isRequired()) {
CGValuedElement body = cgProperty.getBody();
if (body != null) {
rewriteAsGuarded(body, false, "body for '" + cgProperty.getAst() + "'");
}
}
return null;
} */
/* @Override
public @Nullable Object visitCGNativePropertyCallExp(@NonNull CGNativePropertyCallExp cgElement) {
return super.visitCGNativePropertyCallExp(cgElement);
} */
@Override
public @Nullable Object visitCGNavigationCallExp(@NonNull CGNavigationCallExp cgNavigationCallExp) {
super.visitCGNavigationCallExp(cgNavigationCallExp);
PropertyCallingConvention callingConvention = cgNavigationCallExp.getReferredProperty().getCallingConvention();
callingConvention.rewriteWithBoxingAndGuards(this, cgNavigationCallExp);
return null;
}
@Override
public @Nullable Object visitCGOperation(@NonNull CGOperation cgOperation) {
super.visitCGOperation(cgOperation);
// if ("isAttribute".cgOperation(cgElement.getName())) { // XXX
// System.out.println("visitCGOperation for " + cgElement.getAst().toString());
// }
OperationCallingConvention callingConvention = cgOperation.getCallingConvention();
callingConvention.rewriteWithBoxingAndGuards(this, cgOperation);
return null;
}
@Override
public @Nullable Object visitCGOperationCallExp(@NonNull CGOperationCallExp cgElement) {
super.visitCGOperationCallExp(cgElement);;
CGOperation cgOperation = cgElement.getReferredOperation();
if ("specializeIn".equals(cgOperation.getName())) {
getClass(); // XXX
}
OperationCallingConvention callingConvention = cgOperation.getCallingConvention();
callingConvention.rewriteWithBoxingAndGuards(this, cgElement);
return null;
/* boolean isBoxed = callingConvention.isBoxed();
boolean isEcore = callingConvention.isEcore();
boolean isUnboxed = callingConvention.isUnboxed();
assert isBoxed == cgElement.isBoxed();
assert isEcore == cgElement.isEcore();
assert isUnboxed == cgElement.isUnboxed();
Operation referredOperation = cgElement.getReferredOperation();
CGValuedElement cgThis = cgElement.getCgThis();
// assert (cgThis == null) || cgThis.isEcore() || cgThis.isUnboxed();
EOperation eOperation = null;
//
// Guard / cast source
// XXX cgThis / cgSource
if (isBoxed) {
boolean isStatic = cgThis != null; // XXXcallingConvention.isStatic(cgOperation);
if (isStatic) {
assert cgThis != null;
boolean sourceMayBeNull = false;
if (referredOperation != null) { // XXX cgOperation is non-null
OperationId operationId = referredOperation.getOperationId();
sourceMayBeNull = context.hasOclVoidOperation(operationId); // FIXME redundant since LibraryOperationCallingConvention.createParaeters invokes hasOclVoidOperation
if (!sourceMayBeNull && cgThis.isNull()) {
// CGInvalid cgInvalid = context.getInvalid("null value1 for source parameter");
CGInvalid cgInvalid = context.getInvalid("''" + referredOperation.getOwningClass().getName() + "'' rather than ''OclVoid'' value required");
CGConstantExp cgLiteralExp = context.createCGConstantExp(CGUtil.getAST(cgElement), cgInvalid);
CGUtil.replace(cgElement, cgLiteralExp);
return null;
}
}
rewriteAsBoxed(cgThis);
if ((referredOperation != null) && !sourceMayBeNull && !cgThis.isNonNull()) {
// rewriteAsGuarded(cgThis, false, "value3 for source parameter");
rewriteAsGuarded(cgThis, false, "''" + referredOperation.getOwningClass().getName() + "'' rather than ''OclVoid'' value required");
}
}
}
else {
if (isEcore) {
eOperation = ((CGEcoreOperationCallExp)cgElement).getEOperation();
rewriteAsEcore(cgThis, eOperation.getEContainingClass());
if (eOperation.isMany()) {
rewriteAsAssertNonNulled(cgElement);
}
}
else {
rewriteAsUnboxed(cgThis);
}
if (!referredOperation.isIsStatic()) {
rewriteAsGuarded(cgElement.getCgThis(), isSafe(cgElement), "source for '" + referredOperation + "'");
}
// rewriteAsGuarded(cgSource, isSafe(cgElement), "source for '" + cgElement.getReferredOperation() + "'");
}
//
// Null check boxed arguments
//
// List<Parameter> ownedParameters = null;
List<CGParameter> cgParameters = cgOperation.getParameters();
if (referredOperation != null) { // Null if a Java method ?? could check Method parameters
// ownedParameters = referredOperation.getOwnedParameters();
if (isBoxed) {
List<CGValuedElement> cgArguments = cgElement.getCgArguments();
int iMax = cgArguments.size();
assert iMax == cgParameters.size();
if (!referredOperation.isIsValidating()) {
for (int i = 0; i < iMax; i++) { // Avoid CME from rewrite
CGValuedElement cgArgument = cgArguments.get(i);
// Parameter asParameter = ownedParameters.get(i);
CGParameter cgParameter = cgParameters.get(i);
// if (asParameter.isIsRequired()) {
if (cgParameter.isRequired()) {
if (cgArgument.isNull()) {
// CGInvalid cgInvalid = context.getInvalid("null value2 for " + asParameter.getName() + " parameter");
StringBuilder s= new StringBuilder();
s.append("''");
if (cgParameter.isIsSelf()) {
s.append(referredOperation.getOwningClass().getName());
}
else {
s.append(cgParameter.getTypeId());
}
s.append("'' rather than ''OclVoid'' value required");
CGInvalid cgInvalid = context.getInvalid(s.toString());
CGConstantExp cgLiteralExp = context.createCGConstantExp(CGUtil.getAST(cgElement), cgInvalid);
CGUtil.replace(cgElement, cgLiteralExp);
return null;
}
}
}
}
}
}
//
// Guard / cast arguments
//
List<EParameter> eParameters = null;
if (eOperation != null) {
eParameters = eOperation.getEParameters();
}
List<CGValuedElement> cgArguments = cgElement.getCgArguments();
int iMax = cgArguments.size();
for (int i = 0; i < iMax; i++) { // Avoid CME from rewrite
CGValuedElement cgArgument = cgArguments.get(i);
CGParameter cgParameter = cgParameters.get(i);
if (isBoxed) {
rewriteAsBoxed(cgArgument);
// if (cgParameters != null) {
// Parameter asParameter = ownedParameters.get(i);
if (cgParameter.isRequired() && !cgArgument.isNonNull()) {
// rewriteAsGuarded(cgArgument, false, "value4 for " + asParameter.getName() + " parameter");
rewriteAsGuarded(cgArgument, false, "''" + cgParameter.getTypeId() + "'' rather than ''OclVoid'' value required");
}
// }
}
else if ((eParameters != null) && !cgParameter.isIsSelf()) {
EParameter eParameter = eParameters.get(i-1);
rewriteAsEcore(cgArgument, eParameter.getEType());
}
else {
rewriteAsUnboxed(cgArgument);
}
}
return null; */
}
@Override
public @Nullable Object visitCGProperty(@NonNull CGProperty cgProperty) {
super.visitCGProperty(cgProperty);
// if ("isAttribute".cgOperation(cgElement.getName())) {
// System.out.println("visitCGOperation for " + cgElement.getAst().toString());
// }
PropertyCallingConvention callingConvention = cgProperty.getCallingConvention();
callingConvention.rewriteWithBoxingAndGuards(this, cgProperty);
return null;
}
@Override
public @Nullable Object visitCGShadowPart(@NonNull CGShadowPart cgShadowPart) {
rewriteAsUnboxed(cgShadowPart.getInit());
return super.visitCGShadowPart(cgShadowPart);
}
@Override
public @Nullable Object visitCGTypeExp(@NonNull CGTypeExp cgTypeExp) {
super.visitCGTypeExp(cgTypeExp);
TypeDescriptor typeDescriptor = codeGenerator.getTypeDescriptor(cgTypeExp);
if (typeDescriptor.getJavaClass() != org.eclipse.ocl.pivot.Class.class) {
rewriteAsCast(cgTypeExp); // XXX
}
return null;
}
@Override
public @Nullable Object visitCGVariableExp(@NonNull CGVariableExp cgElement) {
super.visitCGVariableExp(cgElement);
CGVariable referredVariable = cgElement.getReferredVariable();
if (referredVariable instanceof CGIterator) {
CGIterator cgIterator = (CGIterator)referredVariable;
EObject cgOperation = cgIterator.eContainer();
if ((cgOperation instanceof CGIterationCallExp) && !(cgOperation instanceof CGBuiltInIterationCallExp)) {
rewriteAsCast(cgElement);
}
}
else if (referredVariable instanceof CGParameter) {
CGParameter cgParameter = (CGParameter)referredVariable;
if (cgParameter.getAst() != null) { // Skip synthetic parameters such as executor
EObject cgOperation = cgParameter.eContainer();
if (cgOperation instanceof CGLibraryOperation) {
rewriteAsCast(cgElement);
}
}
}
return null;
}
}