| /******************************************************************************* |
| * Copyright (c) 2013, 2018 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 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.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.CGMapExp; |
| 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.CGShadowExp; |
| import org.eclipse.ocl.examples.codegen.cgmodel.CGTemplateParameterExp; |
| 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<@Nullable Object, @NonNull 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 (@NonNull 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, context.createCGConstantExp(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, "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.ITERABLE_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 visitCGTemplateParameterExp(@NonNull CGTemplateParameterExp cgTemplateParameterExp) { |
| TypeExp pTypeExp = (TypeExp) cgTemplateParameterExp.getAst(); |
| Type referredType = pTypeExp.getReferredType(); |
| if (referredType != null) { |
| LocalContext localContext = context.getCodeGenerator().getGlobalContext().getLocalContext(cgTemplateParameterExp); |
| if (localContext != null) { |
| CGValuedElement cgTemplateableElement = cgTemplateParameterExp.getTemplateableElement(); |
| // cgTypeExp.setTypeId(cgExecutorType.getUnderlyingTypeId()); |
| cgTemplateParameterExp.getDependsOn().add(cgTemplateableElement); |
| } |
| } |
| return super.visitCGTemplateParameterExp(cgTemplateParameterExp); |
| } |
| |
| @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()); |
| } |
| } |