示例#1
0
        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();
            }
        }
示例#2
0
        public ILispNode Clone()
        {
            var result = new LispList();

            ForEach(x => result.Add(x.Clone()));

            return(result);
        }
示例#3
0
        public LispList(LispList parent)
        {
            Parent = parent;

            if (Parent != null)
            {
                Parent.Add(this);
            }
        }
示例#4
0
        public LispAtom(LispList parent, string tokenValue, Token token)
        {
            Parent     = parent;
            TokenValue = tokenValue;
            Token      = token;

            SetValue(tokenValue as object);

            if (Parent != null)
            {
                Parent.Add(this);
            }
        }
示例#5
0
        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);
            }
        }
示例#6
0
 public LispList(LispList parent, IEnumerable <ILispNode> value) : base(value)
 {
     Parent = parent;
 }
示例#7
0
 public LispAtom(LispList parent, object value) : this(parent, String.Empty, Token.MAX)
 {
     SetValue(value);
 }
示例#8
0
 public Defun(string functionName, LispList formalParameters, IList <ILispNode> body) : base(formalParameters, body)
 {
     FunctionName = functionName;
 }
示例#9
0
 public Lambda(LispList formalParameters, IList <ILispNode> body)
 {
     FormalParameters = formalParameters;
     Body             = body;
 }
示例#10
0
        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));
        }