/*
 * 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.cf.code;

import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.LocalItem;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.type.Prototype;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeBearer;
import java.util.ArrayList;

/**
 * Base implementation of {@link Machine}.
 *
 * <p><b>Note:</b> For the most part, the documentation for this class
 * ignores the distinction between {@link Type} and {@link
 * TypeBearer}.</p>
 */
public abstract class BaseMachine implements Machine {
    /* {@code non-null;} the prototype for the associated method */
    private final Prototype prototype;

    /** {@code non-null;} primary arguments */
    private TypeBearer[] args;

    /** {@code >= 0;} number of primary arguments */
    private int argCount;

    /** {@code null-ok;} type of the operation, if salient */
    private Type auxType;

    /** auxiliary {@code int} argument */
    private int auxInt;

    /** {@code null-ok;} auxiliary constant argument */
    private Constant auxCst;

    /** auxiliary branch target argument */
    private int auxTarget;

    /** {@code null-ok;} auxiliary switch cases argument */
    private SwitchList auxCases;

    /** {@code null-ok;} auxiliary initial value list for newarray */
    private ArrayList<Constant> auxInitValues;

    /** {@code >= -1;} last local accessed */
    private int localIndex;

    /** {@code null-ok;} local target spec, if salient and calculated */
    private RegisterSpec localTarget;

    /** {@code non-null;} results */
    private TypeBearer[] results;

    /**
     * {@code >= -1;} count of the results, or {@code -1} if no results
     * have been set
     */
    private int resultCount;

    /**
     * Constructs an instance.
     *
     * @param prototype {@code non-null;} the prototype for the associated method
     */
    public BaseMachine(Prototype prototype) {
        if (prototype == null) {
            throw new NullPointerException("prototype == null");
        }

        this.prototype = prototype;
        args = new TypeBearer[10];
        results = new TypeBearer[6];
        clearArgs();
    }

    /** {@inheritDoc} */
    public Prototype getPrototype() {
        return prototype;
    }

    /** {@inheritDoc} */
    public final void clearArgs() {
        argCount = 0;
        auxType = null;
        auxInt = 0;
        auxCst = null;
        auxTarget = 0;
        auxCases = null;
        auxInitValues = null;
        localIndex = -1;
        localTarget = null;
        resultCount = -1;
    }

    /** {@inheritDoc} */
    public final void popArgs(Frame frame, int count) {
        ExecutionStack stack = frame.getStack();

        clearArgs();

        if (count > args.length) {
            // Grow args, and add a little extra room to grow even more.
            args = new TypeBearer[count + 10];
        }

        for (int i = count - 1; i >= 0; i--) {
            args[i] = stack.pop();
        }

        argCount = count;
    }

    /** {@inheritDoc} */
    public void popArgs(Frame frame, Prototype prototype) {
        StdTypeList types = prototype.getParameterTypes();
        int size = types.size();

        // Use the above method to do the actual popping...
        popArgs(frame, size);

        // ...and then verify the popped types.

        for (int i = 0; i < size; i++) {
            if (! Merger.isPossiblyAssignableFrom(types.getType(i), args[i])) {
                throw new SimException("at stack depth " + (size - 1 - i) +
                        ", expected type " + types.getType(i).toHuman() +
                        " but found " + args[i].getType().toHuman());
            }
        }
    }

    public final void popArgs(Frame frame, Type type) {
        // Use the above method to do the actual popping...
        popArgs(frame, 1);

        // ...and then verify the popped type.
        if (! Merger.isPossiblyAssignableFrom(type, args[0])) {
            throw new SimException("expected type " + type.toHuman() +
                    " but found " + args[0].getType().toHuman());
        }
    }

    /** {@inheritDoc} */
    public final void popArgs(Frame frame, Type type1, Type type2) {
        // Use the above method to do the actual popping...
        popArgs(frame, 2);

        // ...and then verify the popped types.

        if (! Merger.isPossiblyAssignableFrom(type1, args[0])) {
            throw new SimException("expected type " + type1.toHuman() +
                    " but found " + args[0].getType().toHuman());
        }

        if (! Merger.isPossiblyAssignableFrom(type2, args[1])) {
            throw new SimException("expected type " + type2.toHuman() +
                    " but found " + args[1].getType().toHuman());
        }
    }

    /** {@inheritDoc} */
    public final void popArgs(Frame frame, Type type1, Type type2,
            Type type3) {
        // Use the above method to do the actual popping...
        popArgs(frame, 3);

        // ...and then verify the popped types.

        if (! Merger.isPossiblyAssignableFrom(type1, args[0])) {
            throw new SimException("expected type " + type1.toHuman() +
                    " but found " + args[0].getType().toHuman());
        }

        if (! Merger.isPossiblyAssignableFrom(type2, args[1])) {
            throw new SimException("expected type " + type2.toHuman() +
                    " but found " + args[1].getType().toHuman());
        }

        if (! Merger.isPossiblyAssignableFrom(type3, args[2])) {
            throw new SimException("expected type " + type2.toHuman() +
                    " but found " + args[2].getType().toHuman());
        }
    }

    /** {@inheritDoc} */
    public final void localArg(Frame frame, int idx) {
        clearArgs();
        args[0] = frame.getLocals().get(idx);
        argCount = 1;
        localIndex = idx;
    }

    /** {@inheritDoc} */
    public final void auxType(Type type) {
        auxType = type;
    }

    /** {@inheritDoc} */
    public final void auxIntArg(int value) {
        auxInt = value;
    }

    /** {@inheritDoc} */
    public final void auxCstArg(Constant cst) {
        if (cst == null) {
            throw new NullPointerException("cst == null");
        }

        auxCst = cst;
    }

    /** {@inheritDoc} */
    public final void auxTargetArg(int target) {
        auxTarget = target;
    }

    /** {@inheritDoc} */
    public final void auxSwitchArg(SwitchList cases) {
        if (cases == null) {
            throw new NullPointerException("cases == null");
        }

        auxCases = cases;
    }

    /** {@inheritDoc} */
    public final void auxInitValues(ArrayList<Constant> initValues) {
        auxInitValues = initValues;
    }

    /** {@inheritDoc} */
    public final void localTarget(int idx, Type type, LocalItem local) {
        localTarget = RegisterSpec.makeLocalOptional(idx, type, local);
    }

    /**
     * Gets the number of primary arguments.
     *
     * @return {@code >= 0;} the number of primary arguments
     */
    protected final int argCount() {
        return argCount;
    }

    /**
     * Gets the width of the arguments (where a category-2 value counts as
     * two).
     *
     * @return {@code >= 0;} the argument width
     */
    protected final int argWidth() {
        int result = 0;

        for (int i = 0; i < argCount; i++) {
            result += args[i].getType().getCategory();
        }

        return result;
    }

    /**
     * Gets the {@code n}th primary argument.
     *
     * @param n {@code >= 0, < argCount();} which argument
     * @return {@code non-null;} the indicated argument
     */
    protected final TypeBearer arg(int n) {
        if (n >= argCount) {
            throw new IllegalArgumentException("n >= argCount");
        }

        try {
            return args[n];
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("n < 0");
        }
    }

    /**
     * Gets the type auxiliary argument.
     *
     * @return {@code null-ok;} the salient type
     */
    protected final Type getAuxType() {
        return auxType;
    }

    /**
     * Gets the {@code int} auxiliary argument.
     *
     * @return the argument value
     */
    protected final int getAuxInt() {
        return auxInt;
    }

    /**
     * Gets the constant auxiliary argument.
     *
     * @return {@code null-ok;} the argument value
     */
    protected final Constant getAuxCst() {
        return auxCst;
    }

    /**
     * Gets the branch target auxiliary argument.
     *
     * @return the argument value
     */
    protected final int getAuxTarget() {
        return auxTarget;
    }

    /**
     * Gets the switch cases auxiliary argument.
     *
     * @return {@code null-ok;} the argument value
     */
    protected final SwitchList getAuxCases() {
        return auxCases;
    }

    /**
     * Gets the init values auxiliary argument.
     *
     * @return {@code null-ok;} the argument value
     */
    protected final ArrayList<Constant> getInitValues() {
        return auxInitValues;
    }
    /**
     * Gets the last local index accessed.
     *
     * @return {@code >= -1;} the salient local index or {@code -1} if none
     * was set since the last time {@link #clearArgs} was called
     */
    protected final int getLocalIndex() {
        return localIndex;
    }

    /**
     * Gets the target local register spec of the current operation, if any.
     * The local target spec is the combination of the values indicated
     * by a previous call to {@link #localTarget} with the type of what
     * should be the sole result set by a call to {@link #setResult} (or
     * the combination {@link #clearResult} then {@link #addResult}.
     *
     * @return {@code null-ok;} the salient register spec or {@code null} if no
     * local target was set since the last time {@link #clearArgs} was
     * called
     */
    protected final RegisterSpec getLocalTarget() {
        if (localTarget == null) {
            return null;
        }

        if (resultCount != 1) {
            throw new SimException("local target with " +
                    ((resultCount == 0) ? "no" : "multiple") + " results");
        }

        TypeBearer result = results[0];
        Type resultType = result.getType();
        Type localType = localTarget.getType();

        if (resultType == localType) {
            return localTarget;
        }

        if (! Merger.isPossiblyAssignableFrom(localType, resultType)) {
            // The result and local types are inconsistent. Complain!
            throwLocalMismatch(resultType, localType);
            return null;
        }

        if (localType == Type.OBJECT) {
            /*
             * The result type is more specific than the local type,
             * so use that instead.
             */
            localTarget = localTarget.withType(result);
        }

        return localTarget;
    }

    /**
     * Clears the results.
     */
    protected final void clearResult() {
        resultCount = 0;
    }

    /**
     * Sets the results list to be the given single value.
     *
     * <p><b>Note:</b> If there is more than one result value, the
     * others may be added by using {@link #addResult}.</p>
     *
     * @param result {@code non-null;} result value
     */
    protected final void setResult(TypeBearer result) {
        if (result == null) {
            throw new NullPointerException("result == null");
        }

        results[0] = result;
        resultCount = 1;
    }

    /**
     * Adds an additional element to the list of results.
     *
     * @see #setResult
     *
     * @param result {@code non-null;} result value
     */
    protected final void addResult(TypeBearer result) {
        if (result == null) {
            throw new NullPointerException("result == null");
        }

        results[resultCount] = result;
        resultCount++;
    }

    /**
     * Gets the count of results. This throws an exception if results were
     * never set. (Explicitly clearing the results counts as setting them.)
     *
     * @return {@code >= 0;} the count
     */
    protected final int resultCount() {
        if (resultCount < 0) {
            throw new SimException("results never set");
        }

        return resultCount;
    }

    /**
     * Gets the width of the results (where a category-2 value counts as
     * two).
     *
     * @return {@code >= 0;} the result width
     */
    protected final int resultWidth() {
        int width = 0;

        for (int i = 0; i < resultCount; i++) {
            width += results[i].getType().getCategory();
        }

        return width;
    }

    /**
     * Gets the {@code n}th result value.
     *
     * @param n {@code >= 0, < resultCount();} which result
     * @return {@code non-null;} the indicated result value
     */
    protected final TypeBearer result(int n) {
        if (n >= resultCount) {
            throw new IllegalArgumentException("n >= resultCount");
        }

        try {
            return results[n];
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("n < 0");
        }
    }

    /**
     * Stores the results of the latest operation into the given frame. If
     * there is a local target (see {@link #localTarget}), then the sole
     * result is stored to that target; otherwise any results are pushed
     * onto the stack.
     *
     * @param frame {@code non-null;} frame to operate on
     */
    protected final void storeResults(Frame frame) {
        if (resultCount < 0) {
            throw new SimException("results never set");
        }

        if (resultCount == 0) {
            // Nothing to do.
            return;
        }

        if (localTarget != null) {
            /*
             * Note: getLocalTarget() doesn't necessarily return
             * localTarget directly.
             */
            frame.getLocals().set(getLocalTarget());
        } else {
            ExecutionStack stack = frame.getStack();
            for (int i = 0; i < resultCount; i++) {
                stack.push(results[i]);
            }
        }
    }

    /**
     * Throws an exception that indicates a mismatch in local variable
     * types.
     *
     * @param found {@code non-null;} the encountered type
     * @param local {@code non-null;} the local variable's claimed type
     */
    public static void throwLocalMismatch(TypeBearer found,
            TypeBearer local) {
        throw new SimException("local variable type mismatch: " +
                "attempt to set or access a value of type " +
                found.toHuman() +
                " using a local variable of type " +
                local.toHuman() +
                ". This is symptomatic of .class transformation tools " +
                "that ignore local variable information.");
    }
}
