package water.rapids.ast; import water.rapids.Env; import water.rapids.Val; import water.rapids.vals.ValFun; import water.util.StringUtils; /** * A primitive operation. Execution just returns the function. *Application* (not execution) applies the function * to the arguments. */ public abstract class AstPrimitive<T extends AstPrimitive<T>> extends AstRoot<T> { private transient ValFun _v; /** * Number of function's arguments + 1. Thus, a binary operator like '+' * should be declared with 3 nargs: ["+", lhs, rhs]. * For variable-argument functions this method should return -1. */ public abstract int nargs(); /** * List of argument names. The length of the returned array should be equal * to `nargs() - 1` (unless `nargs()` returns -1, in which case this function * may return {"..."} or something similar). */ public abstract String[] args(); /** * <p>Primary method to invoke this function, passing all the parameters * as the `asts` list.</p> * * @param env Current execution environment. Variables are looked up here. * @param stk TODO need clarification * @param asts List of AstRoot expressions that are arguments to the * function. First element in this list is the function itself. * @return value resulting from calling the function with the provided list * of arguments. */ public abstract Val apply(Env env, Env.StackHelp stk, AstRoot[] asts); @Override public ValFun exec(Env env) { if (_v == null) _v = new ValFun(this); return _v; } @Override public String example() { int nargs = nargs(); return nargs == 1? "(" + str() + ")" : nargs >= 2? "(" + str() + " " + StringUtils.join(" ", args()) + ")" : nargs == -1? "(" + str() + " ...)" : null; // shouldn't be possible, but who knows? } @Override public String description() { return ""; } }