| // 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); |
| } |