public IShellReturnable Execute(ShellBaseVisitor <IShellReturnable> visitor) { return(visitor.VisitStatement_block(statement_block)); }
/// <summary> /// Sets up, executes, and then cleans up function calls. /// </summary> /// <remark> /// Set name to "" if the function is namespaced. /// </remark> public static Shell.Types.IShellReturnable ExecuteFunction( ShellBaseVisitor <Shell.Types.IShellReturnable> visitor, State state, Shell.Types.Function function, List <Tuple <int, Shell.Types.IShellData> > unnamedArgs ) { Shell.Types.IShellReturnable returnValue; if (unnamedArgs == null) { unnamedArgs = new List <Tuple <int, Types.IShellData> >(); } var lambda = function.SelectLambda(unnamedArgs); if (lambda == null) { throw new Shell.Problems.InvalidFunctionCall(function, unnamedArgs); } var args = lambda.NameArguments(unnamedArgs); string argString = ""; if (args.Count > 0) { var sb = new StringBuilder(" "); for (int i = 0; i < args.Count; i++) { sb.Append($"{args[i].Item2}:{args[i].Item3}"); if (i + 1 != args.Count) { sb.Append(" "); } } argString = sb.ToString(); } // pre-setup for state state.ENTER_CONTEXT($"{function.name}{argString}"); // allow the function to call itself through its own identifier state.Functions.Set(function.name, function); // set up state with arguments in context foreach (var arg in args) { if (arg.Item3 is Shell.Types.Property prop) { if (lambda is Shell.Types.BuiltinLambda) { state.Variables.Set(arg.Item2, prop); } else { state.Variables.Set(arg.Item2, prop.Value); } } else { state.Variables.Set(arg.Item2, arg.Item3); } } if (lambda is Shell.Types.UserDefinedLambda udLambda) { returnValue = udLambda.Execute(visitor); } else { returnValue = ((Shell.Types.BuiltinLambda)lambda).Execute(state, args); } //cleanup if (state.HasReturned()) { logger.Debug($"{function.name} returned {returnValue}"); state.EndReturn(); } state.EXIT_CONTEXT(); return(returnValue); }