package edu.neu.ccs.demeterf;

/** Represents a Value that can be tossed out of a traversal.  Includes
 *    static methods to hide how we actually deal with values and
 *    cutting traversals short.  See {@link edu.neu.ccs.demeterf.examples Examples}
 *    for more details.
 *
 *    <p>This class basically allows a program to cut off traversal by jumping 
 *    out with a value (considered <i>tossing</i>). e.g., We might stop traversal
 *    after finding a metching element in a list. Usually you would <tt>toss</tt>
 *    a value within an <tt>update</tt> method, as these are called on the way down
 *    while traversing ("pre-order"). 
 */
public class ValueThrow extends RuntimeException{
    Object val;
    private ValueThrow(Object v){ val = v; }
    
    /** Get the inner Thrown Value */
    public <T> T value(){ return (T)val; }
    
    /** Toss a Value out of the traversal */
    public static void toss(Object o) throws ValueThrow{
        throw new ValueThrow(o);
    }
    /** Handles traversing when a thrown value is expected (No traversal Argument) */
    public static <T> T traverse(Traversal t, Object o){
        try{
            return t.<T>traverse(o);
        }catch(ValueThrow v){ return v.<T>value(); }
    }
    /** Handles traversing when a thrown value is expected (With traversal Argument) */
    public static <T> T traverse(Traversal t, Object o, Object a){
        try{
            return t.<T>traverse(o,a);
        }catch(ValueThrow v){ return v.<T>value(); }
    }
}