public object Apply(ProcedureNode procedure, IList<object> arguments, Environment environment) { if (arguments.Count != procedure.Parameters.Count() && !procedure.Parameters.Select(x => x.Name).Contains("&")) { throw new ArgumentException("Wrong number of arguments given to procedure! Expected: " + procedure.Parameters.Count()); } var localEnv = procedure.Environment.CreateChildEnvironment(); for (int i = 0; i < procedure.Parameters.Count(); ++i) { object evaluatedArgument; bool finished = false; var parameterSymbol = procedure.Parameters.ElementAt(i); if (parameterSymbol.Name == "&") { parameterSymbol = procedure.Parameters.ElementAt(i + 1); evaluatedArgument = procedure.IsMacro ? arguments.Skip(i).ToList() : arguments.Skip(i).Select(arg => evaluator.Evaluate(arg, environment)).ToList(); localEnv.DefineSymbol(parameterSymbol, evaluatedArgument); finished = true; } else { evaluatedArgument = procedure.IsMacro ? arguments.ElementAt(i) : evaluator.Evaluate(arguments.ElementAt(i), environment); } localEnv.DefineSymbol(parameterSymbol, evaluatedArgument); if (finished) { break; } } var res = evaluator.Evaluate(procedure.Body, localEnv); if (procedure.IsMacro) { return evaluator.Evaluate(res, environment); } return res; }
private void PrettyPrintSub(ProcedureNode node) { stringWriter.Write("<procedure: " + node.Symbol + ">"); }
public object ApplyDefMacro(IList<object> arguments, Environment environment) { if (arguments.Count != 3) { throw new ArgumentException("Wrong number of arguments given to defmacro! Expected: " + 3); } var symbol = arguments.ElementAt(0) as SymbolNode; if (symbol == null) { throw new ArgumentException("First argument to defmacro not a symbol!"); } var parameterList = arguments.ElementAt(1) as IList<object>; if (parameterList == null) { throw new ArgumentException("Second argument to defmacro not a parameterlist!"); } var body = arguments.ElementAt(2); var macro = new ProcedureNode(parameterList.Cast<SymbolNode>(), new[] { body }, environment.CreateChildEnvironment(), true); environment.DefineSymbol(symbol, macro); return symbol; }