blob: 69d8796a4227b5b28e265b8922d4bffc0baa0195 [file] [log] [blame]
// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.structural;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.utils.structural.StructuralItem.CompareToAccept;
import com.android.tools.r8.utils.structural.StructuralItem.HashingAccept;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
public abstract class StructuralSpecification<T, V extends StructuralSpecification<T, V>> {
abstract V self();
/** Apply a structural mapping to the present specification. */
public final V withSpec(StructuralMapping<T> spec) {
spec.apply(this);
return self();
}
/**
* Base for accessing and visiting a sub-part on an item.
*
* <p>This specifies the getter for the sub-part as well as all of the methods that are required
* for visiting. The required methods coincide with the requirements of StructuralItem.
*
* <p>It is preferable to use withItem and make the item itself implement StructuralItem.
*/
@Deprecated
public final <S> V withCustomItem(
Function<T, S> getter, CompareToAccept<S> compare, HashingAccept<S> hasher) {
return withConditionalCustomItem(t -> true, getter, compare, hasher);
}
public final <S> V withCustomItem(Function<T, S> getter, StructuralAcceptor<S> acceptor) {
return withCustomItem(getter, acceptor, acceptor);
}
/** Base implementation for visiting an item. */
protected abstract <S> V withConditionalCustomItem(
Predicate<T> predicate,
Function<T, S> getter,
CompareToAccept<S> compare,
HashingAccept<S> hasher);
/** Base implementation for visiting an enumeration of items. */
protected abstract <S> V withCustomItemIterator(
Function<T, Iterator<S>> getter, CompareToAccept<S> compare, HashingAccept<S> hasher);
public final <S> V withCustomItemCollection(
Function<T, Collection<S>> getter, StructuralAcceptor<S> acceptor) {
return withCustomItemIterator(getter.andThen(Collection::iterator), acceptor, acceptor);
}
/**
* Specification for a "specified" item.
*
* <p>Using this the visiting methods are could based on the implementation of the Specified
* interface.
*/
public final <S extends StructuralItem<S>> V withItem(Function<T, S> getter) {
return withConditionalItem(t -> true, getter);
}
public final <S extends StructuralItem<S>> V withNullableItem(Function<T, S> getter) {
return withConditionalItem(s -> getter.apply(s) != null, getter);
}
public final <S extends StructuralItem<S>> V withConditionalItem(
Predicate<T> predicate, Function<T, S> getter) {
return withConditionalCustomItem(
predicate, getter, StructuralItem::acceptCompareTo, StructuralItem::acceptHashing);
}
public final <S extends StructuralItem<S>> V withItemIterator(Function<T, Iterator<S>> getter) {
return withCustomItemIterator(
getter, StructuralItem::acceptCompareTo, StructuralItem::acceptHashing);
}
public final <S extends StructuralItem<S>> V withItemCollection(
Function<T, Collection<S>> getter) {
return withItemIterator(getter.andThen(Collection::iterator));
}
public final <S extends StructuralItem<S>> V withItemArray(Function<T, S[]> getter) {
return withItemIterator(getter.andThen(a -> Arrays.asList(a).iterator()));
}
public final <S extends StructuralItem<S>> V withItemArrayAllowingNullMembers(
Function<T, S[]> getter) {
return withCustomItemIterator(
getter.andThen(a -> Arrays.asList(a).iterator()),
(a, b, visitor) -> {
if (a == null || b == null) {
return visitor.visitBool(a != null, b != null);
}
return a.acceptCompareTo(b, visitor);
},
(a, visitor) -> {
if (a == null) {
visitor.visitInt(0);
} else {
a.acceptHashing(visitor);
}
});
}
/**
* Helper to declare an assert on the item.
*
* <p>Only run if running with -ea. Must be run on any item being visited (ie, both in the case of
* comparisons and equality).
*/
public abstract V withAssert(Predicate<T> predicate);
// Primitive Java types. These will need overriding to avoid boxing.
public abstract V withBool(Predicate<T> getter);
public abstract V withInt(ToIntFunction<T> getter);
public abstract V withLong(ToLongFunction<T> getter);
public abstract V withDouble(ToDoubleFunction<T> getter);
public abstract V withIntArray(Function<T, int[]> getter);
public abstract V withShortArray(Function<T, short[]> getter);
public abstract V withDexReference(Function<T, DexReference> getter);
}