public override string ToString(bool printReadably) { if (ast != null) { return("<fn " + Printer.pr_str(fparams, true) + " " + Printer.pr_str(ast, true) + ">"); } else { return("<builtin_function " + fn.ToString() + ">"); } }
static MalVal EVAL(MalVal ast, Dictionary <string, MalFunc> replEnv) { switch ((Object)ast) { case MalList mList: // Ast is a list. // TODO - should this also do vectors and hashmaps? if (mList.Count() <= 0) { // Empty list, return unchanged. Console.WriteLine("EVAL - empty list: " + Printer.pr_str(mList, true)); return(ast); } else { // ast is a non-empty list, so evaluate it. Console.WriteLine("EVAL - non-empty list: " + Printer.pr_str(mList, true)); // Evaluate the List. MalList evaledList = (MalList)eval_ast(ast, replEnv); MalVal listFirst = evaledList.First(); MalList listRest = evaledList.Rest(); switch ((Object)listFirst) { case MalFunc func: Console.WriteLine("EVAL - List head is: '" + Printer.pr_str(listFirst, true) + "'. Rest elements: "); // Take the first item of the evaluated list and call it as function using the rest of the evaluated list as its arguments return(func.Apply(listRest)); //return null; default: throw new MalEvalError("Can't use '" + listFirst.ToString(true) + "' as a function."); } } default: // If ast is not a list (e.g. a vector), return the result of calling eval_ast on it. return(eval_ast(ast, replEnv)); } }
String PRINT(MalVal exp) { return(Printer.pr_str(exp, true)); }
// Call the stored func, passing it a list containing args, if any. public MalVal Apply(MalList args) { Console.WriteLine("In Apply: " + Printer.pr_str(args, true)); return(fn(args)); }