blob: 2dadb74da26df9b0edfc6a571adb531b779861f1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017, 2019 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 (inspired by Horacio Hoyos' prototype)
******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.analysis.AbstractPartialRegionsAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.analysis.PartialRegionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.analysis.PartialRegionClassAnalysis;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtschedule.ClassDatum;
import org.eclipse.qvtd.pivot.qvtschedule.Partition;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil;
import com.google.common.collect.Iterables;
/**
* PartitionedTransformationAnalysis<PRA> provides the mandatory default mangement of ClassDatum and PropertyDatum usage by partitions for a PartitionsAnalysis.
*/
public class PartitionedTransformationAnalysis extends AbstractPartialRegionsAnalysis<@NonNull PartitionsAnalysis>
{
protected final @NonNull TransformationPartitioner transformationPartitioner;
/**
* The PartitionAnalysis for each Partition.
*/
private final @NonNull Map<@NonNull Partition, @NonNull AbstractPartitionAnalysis<? extends @NonNull Partition>> partition2partitionAnalysis = new HashMap<>();
/**
* The FallibilityAnalysis for each Partition.
*/
private final @NonNull Map<@NonNull Partition, @NonNull AbstractFallibilityAnalysis> partition2fallibilityAnalysis = new HashMap<>();
private @Nullable RootPartitionAnalysis rootPartitionAnalysis = null;
public PartitionedTransformationAnalysis(@NonNull TransformationPartitioner transformationPartitioner) {
super(transformationPartitioner.getScheduleManager());
this.transformationPartitioner = transformationPartitioner;
}
public void addPartitionAnalysis(@NonNull AbstractPartitionAnalysis<? extends @NonNull Partition> partitionAnalysis) {
partition2partitionAnalysis.put(partitionAnalysis.getPartition(), partitionAnalysis);
}
public void analyzeFallibilities(@NonNull RootPartitionAnalysis rootPartitionAnalysis) {
for (@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis> nestedPartitionAnalysis : rootPartitionAnalysis.getPartitionAnalyses()) {
if (nestedPartitionAnalysis instanceof CyclicPartitionAnalysis) {
analyzeFallibilities((CyclicPartitionAnalysis)nestedPartitionAnalysis);
}
else if (nestedPartitionAnalysis instanceof LoadingPartitionAnalysis) {
;
}
else if (nestedPartitionAnalysis instanceof MappingPartitionAnalysis<?>) {
;
}
else {
throw new UnsupportedOperationException();
}
}
}
protected @NonNull AbstractFallibilityAnalysis analyzeFallibilities(@NonNull CyclicPartitionAnalysis partitionAnalysis) {
Iterable<@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis>> partitionAnalyses = partitionAnalysis.getPartitionAnalyses();
if (Iterables.size(partitionAnalyses) == 1) {
PartialRegionAnalysis<@NonNull PartitionsAnalysis> nestedPartitionAnalysis = partitionAnalyses.iterator().next();
if (nestedPartitionAnalysis instanceof CyclicPartitionAnalysis) {
return analyzeFallibilities((CyclicPartitionAnalysis)nestedPartitionAnalysis);
}
else {
assert nestedPartitionAnalysis instanceof MappingPartitionAnalysis<?>;
return getFallibilityAnalysis(nestedPartitionAnalysis.getPartition());
}
}
CyclicFallibilityAnalysis cyclicFallibilityAnalysis = new CyclicFallibilityAnalysis(partitionAnalysis);
for (@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis> nestedPartitionAnalysis : partitionAnalyses) {
if (nestedPartitionAnalysis instanceof CyclicPartitionAnalysis) {
AbstractFallibilityAnalysis nestedFallibilityAnalysis = analyzeFallibilities((CyclicPartitionAnalysis)nestedPartitionAnalysis);
cyclicFallibilityAnalysis.analyze(nestedFallibilityAnalysis);
}
else {
assert nestedPartitionAnalysis instanceof MappingPartitionAnalysis<?>;
Partition nestedPartition = nestedPartitionAnalysis.getPartition();
FallibilityAnalysis fallibilityAnalysis = partition2fallibilityAnalysis.get(nestedPartition);
assert fallibilityAnalysis == null;
cyclicFallibilityAnalysis.analyze((PartitionAnalysis) nestedPartitionAnalysis);
FallibilityAnalysis oldFallibilityAnalysis = partition2fallibilityAnalysis.put(nestedPartition, cyclicFallibilityAnalysis);
assert oldFallibilityAnalysis == null;
}
}
cyclicFallibilityAnalysis.analyze();
return cyclicFallibilityAnalysis;
}
public void analyzePartitions(@NonNull Iterable<@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis>> partitionAnalyses) {
for (@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis> partitionAnalysis : partitionAnalyses) {
((AbstractPartitionAnalysis<?>)partitionAnalysis).analyzePartition();
}
for (@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis> partitionAnalysis : partitionAnalyses) {
((AbstractPartitionAnalysis<?>)partitionAnalysis).analyzePartition2();
}
}
@Override
protected @NonNull PartialRegionClassAnalysis<@NonNull PartitionsAnalysis> createClassAnalysis(@NonNull ClassDatum classDatum) {
return new TraceClassPartitionAnalysis(transformationPartitioner.getTransformationAnalysis().getClassAnalysis(classDatum));
}
public @NonNull AbstractFallibilityAnalysis getFallibilityAnalysis(@NonNull Partition partition) {
AbstractFallibilityAnalysis fallibilityAnalysis = partition2fallibilityAnalysis.get(partition);
if (fallibilityAnalysis == null) {
PartitionAnalysis partitionAnalysis = getPartitionAnalysis(partition);
fallibilityAnalysis = new SelfCyclicFallibilityAnalysis((MappingPartitionAnalysis<?>) partitionAnalysis);
}
return fallibilityAnalysis;
}
@Override
public String getName() {
return transformationPartitioner.getName();
}
public @NonNull AbstractPartitionAnalysis<?> getPartitionAnalysis(@NonNull Partition partition) {
return ClassUtil.nonNullState(partition2partitionAnalysis.get(partition));
}
public @NonNull RootPartitionAnalysis getRootPartitionAnalysis() {
return ClassUtil.nonNullState(rootPartitionAnalysis);
}
public void setLoadingRegionAnalysis(@NonNull LoadingPartitionAnalysis loadingPartitionAnalysis) {
for (@NonNull ClassDatum classDatum : classDatum2classAnalysis.keySet()) {
TypedModel typedModel = QVTscheduleUtil.getReferredTypedModel(classDatum);
if (scheduleManager.isInput(typedModel)) {
PartialRegionClassAnalysis<@NonNull PartitionsAnalysis> classAnalysis = classDatum2classAnalysis.get(classDatum);
assert classAnalysis != null;
Iterable<@NonNull PartialRegionAnalysis<@NonNull PartitionsAnalysis>> producers = classAnalysis.getCompatibleProducers();
if (Iterables.isEmpty(producers)) {
classAnalysis.addProducer(loadingPartitionAnalysis);
}
}
}
partition2partitionAnalysis.put(loadingPartitionAnalysis.getPartition(), loadingPartitionAnalysis);
}
public void setRootPartitionAnalysis(@NonNull RootPartitionAnalysis rootPartitionAnalysis) {
this.rootPartitionAnalysis = rootPartitionAnalysis;
partition2partitionAnalysis.put(rootPartitionAnalysis.getPartition(), rootPartitionAnalysis);
}
}