// (c) Tuomas J. Lukka package org.fenfire.lava; import org.fenfire.util.*; import java.lang.reflect.*; /** An API for caching and evaluating * functional expressions. */ public abstract class Functional { /** Hints about a Function class. * Created using HintsMaker. * An empty interface in order to be unmodifiable. */ public interface Hints { } protected class DefaultHints implements Hints { public DefaultHints(HintsMaker maker) { this.bgGroup = maker.bgGroup; this.isSlow = maker.isSlow; this.placeholder = maker.placeholder; } public final Object bgGroup; public final boolean isSlow; public final Object placeholder; } /** An interface for creating Hints objects. */ public class HintsMaker { private Object bgGroup = null; private boolean isSlow = false; private Object placeholder = null; /** This function must be run in a background object * of the given group if it's not run directly. * This is useful for using Libvob OpenGL, since * OpenGL objects should only be handled in one thread. * Default: null. */ void setBackgroundGroup(Object id) { this.bgGroup = id; } /** Whether this function usually consumes considerable time * to generate its output, given all its inputs. * Evaluations of functions given as parameters to this function * are not counted. * Default: not slow. */ void setSlow(boolean isSlow) { this.isSlow = isSlow; } /** Set the placeholder object to be returned if the function value * is not ready yet. * Default: null. */ void setPlaceholder(Object o) { this.placeholder = o; } /** Create the Hints object. */ Hints make() { return new DefaultHints(this); } } /** A node in the functional calculation DAG. */ public interface Node { /** Get a function entry point for this node. */ Function getCallableFunction(); } /** Create a new node in the DAG. * @param id An identifier for the node. Used for determining caching &c. * Should be stable between invocations. * @param functionClass The class of which the Function (or NodeFunction) * object should * be created. * @param parameters The parameters for the constructor of the class. * These may contain Node objects, which will be converted * to functions or nodefunctions as appropriate. */ public abstract Node createNode( Object id, Class functionClass, Object[] parameters ); /** Helper function: Select a suitable constructor. * Useful for createNode. * Goes through the constructors of functionClass and * selects one to call given the parameter objects. * Instead of the Node objects in parameters, * gives the Function interface. * XXX PROBLEM: NODEFUNCTIONS!! *

* Chooses the first matching one, which may be too general sometimes. *

* Throws an error if no suitable constructor found. */ protected Constructor selectConstructor(Class functionClass, Object[] parameters) { Constructor[] constructors = functionClass.getConstructors(); CONSTRUCTORS: for(int i=0; i