/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.rop.code;

import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.Hex;

/**
 * Class that describes all the immutable parts of register-based operations.
 */
public final class Rop {
    /** minimum {@code BRANCH_*} value */
    public static final int BRANCH_MIN = 1;

    /** indicates a non-branching op */
    public static final int BRANCH_NONE = 1;

    /** indicates a function/method return */
    public static final int BRANCH_RETURN = 2;

    /** indicates an unconditional goto */
    public static final int BRANCH_GOTO = 3;

    /** indicates a two-way branch */
    public static final int BRANCH_IF = 4;

    /** indicates a switch-style branch */
    public static final int BRANCH_SWITCH = 5;

    /** indicates a throw-style branch (both always-throws and may-throw) */
    public static final int BRANCH_THROW = 6;

    /** maximum {@code BRANCH_*} value */
    public static final int BRANCH_MAX = 6;

    /** the opcode; one of the constants in {@link RegOps} */
    private final int opcode;

    /**
     * {@code non-null;} result type of this operation; {@link Type#VOID} for
     * no-result operations
     */
    private final Type result;

    /** {@code non-null;} types of all the sources of this operation */
    private final TypeList sources;

    /** {@code non-null;} list of possible types thrown by this operation */
    private final TypeList exceptions;

    /**
     * the branchingness of this op; one of the {@code BRANCH_*}
     * constants in this class
     */
    private final int branchingness;

    /** whether this is a function/method call op or similar */
    private final boolean isCallLike;

    /** {@code null-ok;} nickname, if specified (used for debugging) */
    private final String nickname;

    /**
     * Constructs an instance. This method is private. Use one of the
     * public constructors.
     *
     * @param opcode the opcode; one of the constants in {@link RegOps}
     * @param result {@code non-null;} result type of this operation; {@link
     * Type#VOID} for no-result operations
     * @param sources {@code non-null;} types of all the sources of this operation
     * @param exceptions {@code non-null;} list of possible types thrown by this
     * operation
     * @param branchingness the branchingness of this op; one of the
     * {@code BRANCH_*} constants
     * @param isCallLike whether the op is a function/method call or similar
     * @param nickname {@code null-ok;} optional nickname (used for debugging)
     */
    public Rop(int opcode, Type result, TypeList sources,
               TypeList exceptions, int branchingness, boolean isCallLike,
               String nickname) {
        if (result == null) {
            throw new NullPointerException("result == null");
        }

        if (sources == null) {
            throw new NullPointerException("sources == null");
        }

        if (exceptions == null) {
            throw new NullPointerException("exceptions == null");
        }

        if ((branchingness < BRANCH_MIN) || (branchingness > BRANCH_MAX)) {
            throw new IllegalArgumentException("bogus branchingness");
        }

        if ((exceptions.size() != 0) && (branchingness != BRANCH_THROW)) {
            throw new IllegalArgumentException("exceptions / branchingness " +
                                               "mismatch");
        }

        this.opcode = opcode;
        this.result = result;
        this.sources = sources;
        this.exceptions = exceptions;
        this.branchingness = branchingness;
        this.isCallLike = isCallLike;
        this.nickname = nickname;
    }

    /**
     * Constructs an instance. The constructed instance is never a
     * call-like op (see {@link #isCallLike}).
     *
     * @param opcode the opcode; one of the constants in {@link RegOps}
     * @param result {@code non-null;} result type of this operation; {@link
     * Type#VOID} for no-result operations
     * @param sources {@code non-null;} types of all the sources of this operation
     * @param exceptions {@code non-null;} list of possible types thrown by this
     * operation
     * @param branchingness the branchingness of this op; one of the
     * {@code BRANCH_*} constants
     * @param nickname {@code null-ok;} optional nickname (used for debugging)
     */
    public Rop(int opcode, Type result, TypeList sources,
               TypeList exceptions, int branchingness, String nickname) {
        this(opcode, result, sources, exceptions, branchingness, false,
             nickname);
    }

    /**
     * Constructs a no-exception instance. The constructed instance is never a
     * call-like op (see {@link #isCallLike}).
     *
     * @param opcode the opcode; one of the constants in {@link RegOps}
     * @param result {@code non-null;} result type of this operation; {@link
     * Type#VOID} for no-result operations
     * @param sources {@code non-null;} types of all the sources of this operation
     * @param branchingness the branchingness of this op; one of the
     * {@code BRANCH_*} constants
     * @param nickname {@code null-ok;} optional nickname (used for debugging)
     */
    public Rop(int opcode, Type result, TypeList sources, int branchingness,
               String nickname) {
        this(opcode, result, sources, StdTypeList.EMPTY, branchingness, false,
             nickname);
    }

    /**
     * Constructs a non-branching no-exception instance. The
     * {@code branchingness} is always {@code BRANCH_NONE},
     * and it is never a call-like op (see {@link #isCallLike}).
     *
     * @param opcode the opcode; one of the constants in {@link RegOps}
     * @param result {@code non-null;} result type of this operation; {@link
     * Type#VOID} for no-result operations
     * @param sources {@code non-null;} types of all the sources of this operation
     * @param nickname {@code null-ok;} optional nickname (used for debugging)
     */
    public Rop(int opcode, Type result, TypeList sources, String nickname) {
        this(opcode, result, sources, StdTypeList.EMPTY, Rop.BRANCH_NONE,
             false, nickname);
    }

    /**
     * Constructs a non-empty exceptions instance. Its
     * {@code branchingness} is always {@code BRANCH_THROW},
     * but it is never a call-like op (see {@link #isCallLike}).
     *
     * @param opcode the opcode; one of the constants in {@link RegOps}
     * @param result {@code non-null;} result type of this operation; {@link
     * Type#VOID} for no-result operations
     * @param sources {@code non-null;} types of all the sources of this operation
     * @param exceptions {@code non-null;} list of possible types thrown by this
     * operation
     * @param nickname {@code null-ok;} optional nickname (used for debugging)
     */
    public Rop(int opcode, Type result, TypeList sources, TypeList exceptions,
               String nickname) {
        this(opcode, result, sources, exceptions, Rop.BRANCH_THROW, false,
             nickname);
    }

    /**
     * Constructs a non-nicknamed instance with non-empty exceptions, which
     * is always a call-like op (see {@link #isCallLike}). Its
     * {@code branchingness} is always {@code BRANCH_THROW}.
     *
     * @param opcode the opcode; one of the constants in {@link RegOps}
     * @param sources {@code non-null;} types of all the sources of this operation
     * @param exceptions {@code non-null;} list of possible types thrown by this
     * operation
     */
    public Rop(int opcode, TypeList sources, TypeList exceptions) {
        this(opcode, Type.VOID, sources, exceptions, Rop.BRANCH_THROW, true,
             null);
    }

    /** {@inheritDoc} */
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            // Easy out.
            return true;
        }

        if (!(other instanceof Rop)) {
            return false;
        }

        Rop rop = (Rop) other;

        return (opcode == rop.opcode) &&
            (branchingness == rop.branchingness) &&
            (result == rop.result) &&
            sources.equals(rop.sources) &&
            exceptions.equals(rop.exceptions);
    }

    /** {@inheritDoc} */
    @Override
    public int hashCode() {
        int h = (opcode * 31) + branchingness;
        h = (h * 31) + result.hashCode();
        h = (h * 31) + sources.hashCode();
        h = (h * 31) + exceptions.hashCode();

        return h;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer(40);

        sb.append("Rop{");

        sb.append(RegOps.opName(opcode));

        if (result != Type.VOID) {
            sb.append(" ");
            sb.append(result);
        } else {
            sb.append(" .");
        }

        sb.append(" <-");

        int sz = sources.size();
        if (sz == 0) {
            sb.append(" .");
        } else {
            for (int i = 0; i < sz; i++) {
                sb.append(' ');
                sb.append(sources.getType(i));
            }
        }

        if (isCallLike) {
            sb.append(" call");
        }

        sz = exceptions.size();
        if (sz != 0) {
            sb.append(" throws");
            for (int i = 0; i < sz; i++) {
                sb.append(' ');
                Type one = exceptions.getType(i);
                if (one == Type.THROWABLE) {
                    sb.append("<any>");
                } else {
                    sb.append(exceptions.getType(i));
                }
            }
        } else {
            switch (branchingness) {
                case BRANCH_NONE:   sb.append(" flows"); break;
                case BRANCH_RETURN: sb.append(" returns"); break;
                case BRANCH_GOTO:   sb.append(" gotos"); break;
                case BRANCH_IF:     sb.append(" ifs"); break;
                case BRANCH_SWITCH: sb.append(" switches"); break;
                default: sb.append(" " + Hex.u1(branchingness)); break;
            }
        }

        sb.append('}');

        return sb.toString();
    }

    /**
     * Gets the opcode.
     *
     * @return the opcode
     */
    public int getOpcode() {
        return opcode;
    }

    /**
     * Gets the result type. A return value of {@link Type#VOID}
     * means this operation returns nothing.
     *
     * @return {@code null-ok;} the result spec
     */
    public Type getResult() {
        return result;
    }

    /**
     * Gets the source types.
     *
     * @return {@code non-null;} the source types
     */
    public TypeList getSources() {
        return sources;
    }

    /**
     * Gets the list of exception types that might be thrown.
     *
     * @return {@code non-null;} the list of exception types
     */
    public TypeList getExceptions() {
        return exceptions;
    }

    /**
     * Gets the branchingness of this instance.
     *
     * @return the branchingness
     */
    public int getBranchingness() {
        return branchingness;
    }

    /**
     * Gets whether this opcode is a function/method call or similar.
     *
     * @return {@code true} iff this opcode is call-like
     */
    public boolean isCallLike() {
        return isCallLike;
    }


    /**
     * Gets whether this opcode is commutative (the order of its sources are
     * unimportant) or not. All commutative Rops have exactly two sources and
     * have no branchiness.
     *
     * @return true if rop is commutative
     */
    public boolean isCommutative() {
        switch (opcode) {
            case RegOps.AND:
            case RegOps.OR:
            case RegOps.XOR:
            case RegOps.ADD:
            case RegOps.MUL:
                return true;
            default:
                return false;
        }
    }

    /**
     * Gets the nickname. If this instance has no nickname, this returns
     * the result of calling {@link #toString}.
     *
     * @return {@code non-null;} the nickname
     */
    public String getNickname() {
        if (nickname != null) {
            return nickname;
        }

        return toString();
    }

    /**
     * Gets whether this operation can possibly throw an exception. This
     * is just a convenient wrapper for
     * {@code getExceptions().size() != 0}.
     *
     * @return {@code true} iff this operation can possibly throw
     */
    public final boolean canThrow() {
        return (exceptions.size() != 0);
    }
}
