public static ILispNode ApplyDynamicFunction(Lambda lambda, LispList arguments, CallStack callStack, params object [] args) { try { callStack.PushFrame(); var functionBodyStatements = lambda.Body; var fOptional = false; for (var iParam = 0; iParam < lambda.FormalParameters.Count; iParam++) { var param = lambda.FormalParameters[iParam]; Debug.Assert(param is LispAtom, "Formal Parameter should be an Atom"); var paramName = (param as LispAtom).ValueAsString; Debug.Assert(paramName != String.Empty, "Formal Parameter name cannot be a null string"); fOptional |= paramName.EndsWith("?"); paramName = paramName.TrimEnd('?'); ILispNode paramValue = null; try { paramValue = arguments[iParam].Eval(callStack, true); if (paramValue is LispMissing) { throw new Exception("Value to be bound cannot be evaluated"); } } catch { if (!fOptional) { throw new Exception(String.Format("Cannot find value to bind to {0}", paramName)); } paramValue = new LispNil(); } finally { Debug.Assert(paramValue != null, paramName + " is bound to null"); var invocationParamName = String.Format("{0}_{1}", paramName, callStack.NumberOfFrames); callStack[invocationParamName] = paramValue; functionBodyStatements = functionBodyStatements.Select(x => ReplaceParamName(x, paramName, invocationParamName)).ToList(); } } ILispNode result = new LispNil(); foreach (var statement in functionBodyStatements) { result = statement.Eval(callStack); } return(result); } finally { callStack.PopFrame(); } }
public ILispNode Clone() { var result = new LispList(); ForEach(x => result.Add(x.Clone())); return(result); }
public LispList(LispList parent) { Parent = parent; if (Parent != null) { Parent.Add(this); } }
public LispAtom(LispList parent, string tokenValue, Token token) { Parent = parent; TokenValue = tokenValue; Token = token; SetValue(tokenValue as object); if (Parent != null) { Parent.Add(this); } }
public ILispNode Eval(CallStack callStack, params object [] args) { try { // () if (Count == 0) { return(_nil); } var functor = this[0].Eval(callStack, false); // ( =>nil ) if (functor is LispNil) { return(_nil); } // ( =>missing ) if (functor is LispMissing) { return(functor); } var arguments = new LispList(); do { if (IsImproperList) { arguments.Add(this[1] as LispAtom); continue; } arguments = new LispList(null, this.Skip(1)); }while (false); // ( =>(lambda) ) and ( =>'funcname' ) return(Functor.Apply(functor, arguments, callStack, args)); } catch (LispException) { throw; } catch (Exception ex) { throw new LispException(this, "Exception while applying functor to arguments", ex); } }
public LispList(LispList parent, IEnumerable <ILispNode> value) : base(value) { Parent = parent; }
public LispAtom(LispList parent, object value) : this(parent, String.Empty, Token.MAX) { SetValue(value); }
public Defun(string functionName, LispList formalParameters, IList <ILispNode> body) : base(formalParameters, body) { FunctionName = functionName; }
public Lambda(LispList formalParameters, IList <ILispNode> body) { FormalParameters = formalParameters; Body = body; }
public static ILispNode Apply(ILispNode functor, LispList arguments, CallStack callStack, params object [] args) { if (functor is LispNil) { return(new LispNil()); } if (functor is LispMissing) { throw new Exception("Cannot apply a Functor of type Missing!"); } Lambda lambda = null; do { if (functor is LispAtom) { var functionName = (functor as LispAtom).ValueAsString; if (functionName == String.Empty) { throw new Exception("functor's ValueAsString is Empty!"); } var resolvedFunctor = ResolveFunctor(functionName, callStack, args); if (resolvedFunctor.DynamicFunction != null) { lambda = resolvedFunctor.DynamicFunction; break; } foreach (var nativeFunction in resolvedFunctor.NativeFunctions) { try { #if TRACE_FLOW var strTrace = String.Format("{0}({1} {2})", new String(' ', callStack.NumberOfFrames), functionName, arguments.ToString().Unlist()); _calls.Push(strTrace); #endif var result = nativeFunction.Invoke(functor, arguments, callStack, args); #if TRACE_FLOW #if TRACE_FLOW_VERBOSE Console.WriteLine("{0} => {1}\n{2}", Calls.Pop(), result.ToString(), callStack.ToString()); #else Console.WriteLine("{0} => {1}", _calls.Pop(), result); #endif #endif return(result); } #if TRACE_FLOW catch (Exception ex) { Console.WriteLine( "({0} {1}) throws: {2}", nativeFunction.GetType().FullName + "." + nativeFunction.Method.Name, arguments.ToLispArgString(), ex.Message); Console.WriteLine("Stack:\n{0}", _calls.ToList().Aggregate(String.Empty, (r, x) => r + ("\n" + x))); continue; } #else catch { continue; } #endif } } if (functor is LispList) { var lambdaExpression = (functor as LispList); lambda = new Lambda(lambdaExpression.Car as LispList, lambdaExpression.Cdr as IList <ILispNode>); } }while (false); try { return(ApplyDynamicFunction(lambda, arguments, callStack, args)); } catch (Exception ex) { Console.WriteLine("({0} {1}) throws: {2}", lambda, arguments.ToLispArgString(), ex.Message); } throw new LispException(functor, String.Format("{0} : All known implementations have failed: ", functor)); }