/******************************************************************************* * Copyright (c) 2013, 2015 CEA LIST and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * E.D.Willink(CEA LIST) - Initial API and implementation *******************************************************************************/ package org.eclipse.ocl.examples.codegen.analyzer; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.examples.codegen.cgmodel.CGCollectionExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGMapExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGShadowExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGElement; import org.eclipse.ocl.examples.codegen.cgmodel.CGExecutorType; import org.eclipse.ocl.examples.codegen.cgmodel.CGIfExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGInvalid; import org.eclipse.ocl.examples.codegen.cgmodel.CGIsEqual2Exp; import org.eclipse.ocl.examples.codegen.cgmodel.CGIsEqualExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGIsInvalidExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGIsKindOfExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGIsUndefinedExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGIterationCallExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGLetExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGOperation; import org.eclipse.ocl.examples.codegen.cgmodel.CGOperationCallExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGOppositePropertyCallExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGParameter; import org.eclipse.ocl.examples.codegen.cgmodel.CGPropertyCallExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGTupleExp; import org.eclipse.ocl.examples.codegen.cgmodel.CGTypeExp; 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.LocalContext; import org.eclipse.ocl.examples.codegen.utilities.CGUtil; import org.eclipse.ocl.pivot.Type; import org.eclipse.ocl.pivot.TypeExp; import org.eclipse.ocl.pivot.ids.ElementId; import org.eclipse.ocl.pivot.ids.TypeId; import org.eclipse.ocl.pivot.messages.PivotMessages; import org.eclipse.ocl.pivot.utilities.ValueUtil; /** * A CGElementVisitor handles the Pivot AST visits on behalf of a CodeGenAnalyzer. * Derived visitors may support an extended AST. */ public class AnalysisVisitor extends AbstractExtendingCGModelVisitor<Object, CodeGenAnalyzer> { public AnalysisVisitor(@NonNull CodeGenAnalyzer analyzer) { super(analyzer); } @Override public @Nullable Object visitCGCollectionExp(@NonNull CGCollectionExp cgCollectionExp) { super.visitCGCollectionExp(cgCollectionExp); CGInvalid cgInvalidValue = cgCollectionExp.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgCollectionExp, cgInvalidValue); } return null; } @Override public @Nullable Object visitCGElement(@NonNull CGElement cgElement) { for (CGElement cgChild : cgElement.getChildren()) { cgChild.accept(this); } return null; } /* @Override public void visitEnumLiteralExp(@NonNull EnumLiteralExp element) { CGElement thisAnalysis = context.getCurrentAnalysis(); thisAnalysis.initHashSource(ClassUtil.nonNullModel(element.getReferredEnumLiteral())); return thisAnalysis; }*/ @Override public @Nullable Object visitCGIfExp(@NonNull CGIfExp cgIfExp) { super.visitCGIfExp(cgIfExp); CGValuedElement cgCondition = context.getExpression(cgIfExp.getCondition()); CGInvalid cgInvalidValue = cgCondition.getInvalidValue(); if (cgInvalidValue != null) { CGUtil.replace(cgIfExp, cgInvalidValue); } else if (cgCondition.isNull()) { context.setConstant(cgIfExp, context.getInvalid("Null cgCondition")); } else if (cgCondition.isTrue()) { CGValuedElement cgThen = context.getExpression(cgIfExp.getThenExpression()); context.replace(cgIfExp, cgThen, "Null then-expression"); } else if (cgCondition.isFalse()) { CGValuedElement cgElse = context.getExpression(cgIfExp.getElseExpression()); context.replace(cgIfExp, cgElse, "Null else-expression"); } else if (cgCondition.isConstant()) { ElementId asTypeId = cgCondition.getTypeId().getElementId(); context.setConstant(cgIfExp, context.getInvalid(PivotMessages.TypedValueRequired, "Boolean", asTypeId)); } else { CGValuedElement cgThen = context.getExpression(cgIfExp.getThenExpression()); CGValuedElement cgElse = context.getExpression(cgIfExp.getElseExpression()); if (cgThen.isEquivalentTo(cgElse) == Boolean.TRUE) { context.replace(cgIfExp, cgThen, "Null then/else-expression"); } } return null; } @Override public @Nullable Object visitCGIsEqualExp(@NonNull CGIsEqualExp cgIsEqualExp) { super.visitCGIsEqualExp(cgIsEqualExp); CGValuedElement cgSource = cgIsEqualExp.getSource(); if (cgSource == null) { return null; } CGValuedElement cgArgument = cgIsEqualExp.getArgument(); if (cgArgument == null) { return null; } CGInvalid cgInvalidValue = cgSource.getInvalidValue(); if (cgInvalidValue == null) { cgInvalidValue = cgArgument.getInvalidValue(); } if (cgInvalidValue != null) { context.setConstant(cgIsEqualExp, cgInvalidValue); } else { CGValuedElement cgSourceValue = cgSource.getNamedValue(); CGValuedElement cgArgumentValue = cgArgument.getNamedValue(); Boolean isEqual = cgSourceValue.isEquivalentTo(cgArgumentValue); if (isEqual == Boolean.TRUE) { context.setConstant(cgIsEqualExp, context.getBoolean(!cgIsEqualExp.isNotEquals())); } else if (isEqual == Boolean.FALSE) { context.setConstant(cgIsEqualExp, context.getBoolean(cgIsEqualExp.isNotEquals())); } else if (cgSource.isTrue() && cgArgument.isNonNull() && (cgArgument.getASTypeId() == TypeId.BOOLEAN)) { context.replace(cgIsEqualExp, cgArgument, "Null term"); } else if (cgArgument.isTrue() && cgSource.isNonNull() && (cgSource.getASTypeId() == TypeId.BOOLEAN)) { context.replace(cgIsEqualExp, cgSource, "Null term"); } } return null; } @Override public @Nullable Object visitCGIsEqual2Exp(@NonNull CGIsEqual2Exp cgIsEqual2Exp) { super.visitCGIsEqual2Exp(cgIsEqual2Exp); CGValuedElement cgSource = cgIsEqual2Exp.getSource(); if (cgSource == null) { return null; } CGValuedElement cgArgument = cgIsEqual2Exp.getArgument(); if (cgArgument == null) { return null; } CGInvalid cgInvalidValue1 = cgSource.getInvalidValue(); CGInvalid cgInvalidValue2 = cgArgument.getInvalidValue(); if ((cgInvalidValue1 != null) && (cgInvalidValue2 != null)) { context.setConstant(cgIsEqual2Exp, context.getBoolean(true)); return null; } if ((cgInvalidValue1 != null) && cgArgument.isNonInvalid()) { context.setConstant(cgIsEqual2Exp, context.getBoolean(false)); return null; } if ((cgInvalidValue2 != null) && cgSource.isNonInvalid()) { context.setConstant(cgIsEqual2Exp, context.getBoolean(false)); return null; } boolean isNull1 = cgSource.isNull(); boolean isNull2 = cgArgument.isNull(); if (isNull1 && isNull2) { context.setConstant(cgIsEqual2Exp, context.getBoolean(true)); return null; } if (isNull1 && cgArgument.isNonNull()) { context.setConstant(cgIsEqual2Exp, context.getBoolean(false)); return null; } if (isNull2 && cgSource.isNonNull()) { context.setConstant(cgIsEqual2Exp, context.getBoolean(false)); return null; } CGValuedElement cgSourceValue = cgSource.getNamedValue(); CGValuedElement cgArgumentValue = cgArgument.getNamedValue(); Boolean isEqual = cgSourceValue.isEquivalentTo(cgArgumentValue); if (isEqual == Boolean.TRUE) { context.setConstant(cgIsEqual2Exp, context.getBoolean(true)); } else if (isEqual == Boolean.FALSE) { context.setConstant(cgIsEqual2Exp, context.getBoolean(false)); } else if (cgSource.isTrue() && cgArgument.isNonNull() && (cgArgument.getASTypeId() == TypeId.BOOLEAN)) { context.replace(cgIsEqual2Exp, cgArgument, "Null term"); } else if (cgArgument.isTrue() && cgSource.isNonNull() && (cgSource.getASTypeId() == TypeId.BOOLEAN)) { context.replace(cgIsEqual2Exp, cgSource, "Null term"); } return null; } @Override public @Nullable Object visitCGIsInvalidExp(@NonNull CGIsInvalidExp cgIsInvalidExp) { super.visitCGIsInvalidExp(cgIsInvalidExp); CGValuedElement cgSource = context.getExpression(cgIsInvalidExp.getSource()); if (cgSource.isInvalid()) { context.setConstant(cgIsInvalidExp, context.getBoolean(true)); } else if (cgSource.isNonInvalid()) { context.setConstant(cgIsInvalidExp, context.getBoolean(false)); } return null; } @Override public Object visitCGIsKindOfExp(@NonNull CGIsKindOfExp object) { super.visitCGIsKindOfExp(object); // FIXME constant type conformance return null; } @Override public @Nullable Object visitCGIsUndefinedExp(@NonNull CGIsUndefinedExp cgIsUndefinedExp) { super.visitCGIsUndefinedExp(cgIsUndefinedExp); CGValuedElement cgSource = context.getExpression(cgIsUndefinedExp.getSource()); if (cgSource.isInvalid() || cgSource.isNull()) { context.setConstant(cgIsUndefinedExp, context.getBoolean(true)); } else if (cgSource.isNonInvalid() && cgSource.isNonNull()) { context.setConstant(cgIsUndefinedExp, context.getBoolean(false)); } return null; } @Override public @Nullable Object visitCGLetExp(@NonNull CGLetExp cgLetExp) { super.visitCGLetExp(cgLetExp); CGValuedElement cgIn = context.getExpression(cgLetExp.getIn()); // if (cgLetExp.getInit().isGlobal()) { //Constant()) { // CGUtils.replace(cgLetExp, in); // } // else { if (cgIn.isConstant()) { context.replace(cgLetExp, cgIn.getNamedValue(), "Null let-expression"); } // } return null; } @Override public @Nullable Object visitCGIterationCallExp(@NonNull CGIterationCallExp cgIterationCallExp) { super.visitCGIterationCallExp(cgIterationCallExp); CGValuedElement cgSource = context.getExpression(cgIterationCallExp.getSource()); // if (!cgIterationCallExp.isValidating()) { CGInvalid cgInvalidValue = cgSource.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgIterationCallExp, cgInvalidValue); return null; } else if (cgSource.isNull()) { context.setConstant(cgIterationCallExp, context.getInvalid(PivotMessages.TypedValueRequired, TypeId.COLLECTION_NAME, ValueUtil.getTypeName(null))); return null; } // for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgIterationCallExp.getArguments()) { // CGConstant constantArgument = cgArgument.getConstantValue(); // if ((constantArgument != null) && constantArgument.isInvalid()) { // context.setConstant(cgIterationCallExp, constantArgument); // return null; // } // } // } return null; } @Override public @Nullable Object visitCGMapExp(@NonNull CGMapExp cgMapExp) { super.visitCGMapExp(cgMapExp); CGInvalid cgInvalidValue = cgMapExp.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgMapExp, cgInvalidValue); } return null; } @Override public @Nullable Object visitCGOperation(@NonNull CGOperation cgOperation) { super.visitCGOperation(cgOperation); CGValuedElement cgBody = context.getExpression(cgOperation.getBody()); for (@SuppressWarnings("null")@NonNull CGVariable cgParameter : cgOperation.getParameters()) { CGInvalid cgInvalidValue = cgParameter.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgBody, cgInvalidValue); return null; } } return null; } @Override public @Nullable Object visitCGOperationCallExp(@NonNull CGOperationCallExp cgOperationCallExp) { super.visitCGOperationCallExp(cgOperationCallExp); CGValuedElement cgSource = context.getExpression(cgOperationCallExp.getSource()); if (!cgOperationCallExp.isValidating()) { CGInvalid cgInvalidValue = cgSource.getInvalidValue(); if (cgInvalidValue == null) { for (@SuppressWarnings("null")@NonNull CGValuedElement cgArgument : cgOperationCallExp.getArguments()) { cgInvalidValue = cgArgument.getInvalidValue(); if (cgInvalidValue != null) { break; } } } if (cgInvalidValue != null) { context.setConstant(cgOperationCallExp, cgInvalidValue); return null; } } return null; } @Override public @Nullable Object visitCGOppositePropertyCallExp(@NonNull CGOppositePropertyCallExp cgPropertyCallExp) { super.visitCGOppositePropertyCallExp(cgPropertyCallExp); // Property referredProperty = ClassUtil.nonNullModel(element.getReferredProperty()); // thisAnalysis.initHashSource(referredProperty); // context.addNamedElement(referredProperty); CGValuedElement cgSource = context.getExpression(cgPropertyCallExp.getSource()); CGInvalid cgInvalidValue = cgSource.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgPropertyCallExp, cgInvalidValue); } else if (cgSource.isNull()) { context.setConstant(cgPropertyCallExp, context.getInvalid()); } return null; } @Override public @Nullable Object visitCGParameter(@NonNull CGParameter object) { return null; } @Override public @Nullable Object visitCGPropertyCallExp(@NonNull CGPropertyCallExp cgPropertyCallExp) { super.visitCGPropertyCallExp(cgPropertyCallExp); // Property referredProperty = ClassUtil.nonNullModel(element.getReferredProperty()); // thisAnalysis.initHashSource(referredProperty); // context.addNamedElement(referredProperty); CGValuedElement cgSource = context.getExpression(cgPropertyCallExp.getSource()); CGInvalid cgInvalidValue = cgSource.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgPropertyCallExp, cgInvalidValue); } else if (cgSource.isNull()) { context.setConstant(cgPropertyCallExp, context.getInvalid()); } return null; } @Override public @Nullable Object visitCGShadowExp(@NonNull CGShadowExp cgShadowExp) { // ShadowExp pShadowExp = (ShadowExp) cgShadowExp.getPivot(); // Type pType = pShadowExp.getType(); // if (pType != null) { // EObject eTarget = pType.getETarget(); // if (eTarget instanceof EClass) { // LocalContext localContext = context.getCodeGenerator().getGlobalContext().getLocalContext(cgShadowExp); // if (localContext != null) { // CGExecutorType cgExecutorType = localContext.getExecutorType(pType); // cgShadowExp.setReferredType(cgExecutorType); // cgShadowExp.getDependsOn().add(cgExecutorType); // } // } // } CGInvalid cgInvalidValue = cgShadowExp.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgShadowExp, cgInvalidValue); } return null; } @Override public @Nullable Object visitCGTupleExp(@NonNull CGTupleExp cgTupleExp) { CGInvalid cgInvalidValue = cgTupleExp.getInvalidValue(); if (cgInvalidValue != null) { context.setConstant(cgTupleExp, cgInvalidValue); } return null; } @Override public @Nullable Object visitCGTypeExp(@NonNull CGTypeExp cgTypeExp) { TypeExp pTypeExp = (TypeExp) cgTypeExp.getAst(); Type referredType = pTypeExp.getReferredType(); if (referredType != null) { LocalContext localContext = context.getCodeGenerator().getGlobalContext().getLocalContext(cgTypeExp); if (localContext != null) { CGExecutorType cgExecutorType = cgTypeExp.getExecutorType(); // cgTypeExp.setTypeId(cgExecutorType.getUnderlyingTypeId()); cgTypeExp.getDependsOn().add(cgExecutorType); } } return super.visitCGTypeExp(cgTypeExp); } @Override public @Nullable Object visitCGVariable(@NonNull CGVariable cgVariable) { CGValuedElement cgInit = cgVariable.getInit(); if (cgInit != null) { cgInit.accept(this); } return null; } @Override public @Nullable Object visitCGVariableExp(@NonNull CGVariableExp cgVariableExp) { super.visitCGVariableExp(cgVariableExp); if (cgVariableExp.isConstant() && !(cgVariableExp.getReferredVariable() instanceof CGParameter)) { context.setConstant(cgVariableExp, cgVariableExp.getNamedValue()); } // else if (cgVariableExp.isConstant()) { // context.replace(cgVariableExp, cgVariableExp.getReferredVariable().getInit()); // } return null; } @Override public @Nullable CGElement visiting(@NonNull CGElement visitable) { throw new UnsupportedOperationException(getClass().getSimpleName() + ": " + visitable.getClass().getSimpleName()); } }