All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.yawk.valda.ir.code.Slot Maven / Gradle / Ivy

The newest version!
package at.yawk.valda.ir.code;

import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
 * @author yawkat
 */
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class Slot {
    @Getter private final Arity arity;
    @Getter private final String name;

    static  Slot single(
            String name,
            Function get,
            BiConsumer set
    ) {
        return optional(Arity.SINGLE, name, get, set);
    }

    static  Slot optional(
            String name,
            Function get,
            BiConsumer set
    ) {
        return optional(Arity.OPTIONAL, name, get, set);
    }

    @SuppressWarnings("unchecked")
    private static  Slot optional(
            Arity arity,
            String name,
            Function get,
            BiConsumer set
    ) {
        return new Slot(arity, name) {
            @Override
            public LocalVariable getVariable(Instruction instruction) {
                return get.apply((I) instruction);
            }

            @Override
            public void setVariable(Instruction instruction, LocalVariable variable) {
                set.accept((I) instruction, variable);
            }

            @Override
            public List getVariables(Instruction instruction) {
                LocalVariable v = getVariable(instruction);
                return v == null ? Collections.emptyList() : Collections.singletonList(v);
            }

            @Override
            public void setVariables(Instruction instruction, List variable) {
                if (arity == Arity.OPTIONAL && variable.isEmpty()) {
                    setVariable(instruction, null);
                } else {
                    setVariable(instruction, Iterables.getOnlyElement(variable));
                }
            }
        };
    }

    @SuppressWarnings("unchecked")
    static  Slot variadic(
            String name,
            Function> get,
            BiConsumer> set
    ) {
        return new Slot(Arity.VARIADIC, name) {
            @Override
            public List getVariables(Instruction instruction) {
                return get.apply((I) instruction);
            }

            @Override
            public void setVariables(Instruction instruction, List variable) {
                set.accept((I) instruction, variable);
            }
        };
    }

    public LocalVariable getVariable(Instruction instruction) {
        if (arity == Arity.VARIADIC) { throw new UnsupportedOperationException(); }
        return Iterables.getOnlyElement(getVariables(instruction));
    }

    public abstract List getVariables(Instruction instruction);

    public void setVariable(Instruction instruction, LocalVariable variable) {
        if (arity == Arity.VARIADIC) { throw new UnsupportedOperationException(); }
        setVariables(instruction, Collections.singletonList(variable));
    }

    public abstract void setVariables(Instruction instruction, List variables);

    public void setVariable(Instruction instruction, int index, LocalVariable variable) {
        List variables = new ArrayList<>(getVariables(instruction));
        variables.set(index, variable);
        setVariables(instruction, variables);
    }

    public enum Arity {
        OPTIONAL,
        SINGLE,
        VARIADIC
    }
}