package water.rapids.ast; import water.rapids.*; import water.rapids.ast.params.AstId; import water.rapids.vals.ValFun; import water.util.SB; import java.util.ArrayList; /** * Apply A Function. Basic function execution. */ public class AstExec extends AstRoot { public final AstRoot[] _asts; public AstExec() { this((AstRoot[])null); } public AstExec(AstRoot[] asts) { _asts = asts; } public AstExec(ArrayList<AstRoot> asts) { _asts = asts.toArray(new AstRoot[asts.size()]); } @Override public String str() { SB sb = new SB().p('('); for (AstRoot ast : _asts) sb.p(ast.toString()).p(' '); return sb.p(')').toString(); } @Override public String example() { return "(func ...args)"; } @Override public String description() { return "List of whitespace-separated tokens within parenthesis is interpreted as a function application. The " + "first argument must be a function name (or an expression returning a function), all other tokens are passed " + "to the function as arguments. For example: `(sqrt 16)`, `(+ 2 3)`, `(getTimeZone)`, etc."; } // Function application. Execute the first AstRoot and verify that it is a // function. Then call that function's apply method. Do not evaluate other // arguments; e.g. short-circuit logicals' apply calls may choose to not ever // evalute some arguments. @Override public Val exec(Env env) { Val fun = _asts[0].exec(env); if (!fun.isFun()) throw new IllegalArgumentException("Expected a function but found " + fun.getClass()); AstPrimitive ast = fun.getFun(); int nargs = ast.nargs(); if (nargs != -1 && nargs != _asts.length) throw new IllegalArgumentException( "Incorrect number of arguments; '" + ast + "' expects " + (nargs - 1) + " but was passed " + (_asts.length - 1)); try (Env.StackHelp stk = env.stk()) { return env.returning(ast.apply(env, stk, _asts)); } } public String[] getArgs() { return ((ValFun) _asts[0].exec(new Env(null))).getArgs(); } }