package ovm.core;

import java.io.Serializable;

import ovm.core.domain.Oop;
import ovm.core.services.io.BasicIO;
import ovm.core.services.memory.VM_Address;
import ovm.util.OVMError;
import ovm.util.logging.Logger;

/**
 * Classes part of the image
 * usually extend this class. In previous versions of OVM, we used to
 * require that all classes in the image must extend OVMBase. This is no
 * longer the case.
 *
 * @author Vitek, Grothoff
 **/
public class OVMBase  implements Serializable {

    public static boolean dbg_mode_on = true; // This mode should be false
    // whenever this file is committed to CVS to avoid polluting output.

    public OVMBase() { }

    /* ******************* Debugging / assert support ********************** */
    /** Property controlling assertions  */
    private static final String ASSERTS_DISABLED = "ovm.OVMassert.disabled";

    /** Current state of assertions */
    private final static boolean noAsserts = Boolean.getBoolean(ASSERTS_DISABLED);

    public static final Oop asOop(Object o) {
	return VM_Address.fromObject(o).asOop();
    }

    /** Constant assertion flag to be used to exclude assertion calls from
        the compiled code
    */
    public static final boolean ASSERTS_ENABLED = false;

    /** Print the debugging string to the global logger terminated by a newline
     * @param s the debugging string to print
     **/
    public static void d(String s){  Logger.global.severe(s);  }

    /** Print the debugging string to the global logger
     * @param s the debugging string to print
     **/
    public static void p(String s){ Logger.global.severe(s);   }

    /**Print the debugging string to the global logger terminated by a newline
     * @param s the debugging string to print
     **/
    public static void pln(String s){ Logger.global.severe(s);   }

    /**Print directly using low level IO.
     */
    public static void bpln(String s) {
	BasicIO.bpln(s);
    }
    
    /**Value of the constant string indicating success.
     **/
    public static final String SUCCESS = "PASS";

    /**Fail if the given condition is false and assertions are
     * enabled.  By default, assertions are enabled unless the
     * property <code>ovm.OVMassert.disabled</code> is set.
     * @param condition the condition to be evaluated for failure; if
     *                  this is false, the assert fails and action
     *                  will be taken.
     * @param message the failure message to be used if this assertion fails */
    public static void OVMassert(boolean condition, String message)
     {
        if (noAsserts == true)  return;
        if (condition == false) {
            if (EXCEPT_ON_FAILURE)
                fail("ASSERTION FAILURE: " + message);
            else {
                // print the message because in some contexts throwing the
                // exception will cause an abort
                ovm.core.services.io.BasicIO.out.print("ASSERTION FAILURE: ");
                ovm.core.services.io.BasicIO.out.println(message);
                throw Executive.panic(message);
            }
        }
    }

    /**
     * Fail if the given condition is false and assertions are
     * enabled, printing a default &quot;assertion failed&quot;
     * message.  <p>By default, assertions are enabled unless the
     * property <code>ovm.OVMassert.disabled</code> is set.
     * @param condition the condition to be evaluated for failure; if
     *                  this is false, the assert fails and action
     *                  will be taken.  */
    public static void OVMassert(boolean condition) {
        OVMassert(condition, "Assertion failed.");
    }


    /**
     * Fail if the value of the message is not equal to value of the String
     * {@link #SUCCESS}.  The motivation for this method is to have a
     * way to avoid constructing the debugging String that is syntactically
     * cheap and readable.<p>
     *
     *Usage:<pre>
     *          OVMassert(condition ? OVMBase.SUCCESS : message);
     * </pre>
     * In the above <code>message</code> can be an expression which
     * constructs a string by concatenation (or performs any other
     * computationally intensive task). It will only be evaluated if
     * the condition evaluates to true.  The &quot;success&quot;
     * string should be a direct reference to the {@link #SUCCESS}
     * field or an interned string with the same value. By
     * default, assertions are enabled unless the property
     * <code>ovm.OVMassert.disabled</code> is set.
     * @param     message   the String to compare against */
    public static void OVMassert(String message)
     {
        if (noAsserts == true) return;
        if (SUCCESS != message) {
            if (EXCEPT_ON_FAILURE)
                fail("ASSERTION FAILURE: " + message);
            else {
                // print the message because in some contexts throwing the
                // exception will cause an abort
                ovm.core.services.io.BasicIO.out.print("ASSERTION FAILURE: ");
                ovm.core.services.io.BasicIO.out.println(message);
                throw Executive.panic(message);
            }
        }
    }

    static final boolean EXCEPT_ON_FAILURE = false;

    /**
     * Return a new {@link ovm.util.OVMError OVMError} given an error.
     **/
    public static OVMError failure(Throwable err) {return new OVMError(err); }

    /**
     * Return a new {@link ovm.util.OVMError OVMError} given an error
     * message.
     **/
    public static OVMError failure(String err) {return new OVMError(err); }

    /**
     * Throw a new {@link ovm.util.OVMError OVMError} given an error message.
     **/
    public static void fail(String message) { throw new OVMError(message); }

    /**
     * Throw an {@link ovm.util.OVMError OVMError} given some other
     * throwable that has caused the error.
     * @param t the <code>Throwable</code> related to this error
     **/
     public static void fail(Throwable err) { throw new OVMError(err); }

    /**
     * Throw an {@link ovm.util.OVMError.Unimplemented OVMError.Unimplemented}
     * with a message.
     * @param message error message to associated with the error
     **/
    public static void failUnimplemented(String message)
      { throw new OVMError.Unimplemented(message); }
} // end of OVMBase
