public LispList(List <LispDataType> list) : base(false, true)
            {
                Data = list;

                // Handle dotted list input.
                LispSymbolicAtom dot = new LispSymbolicAtom(".");
                int dotCount         = Data.Count(sym => sym is LispSymbolicAtom && (LispSymbolicAtom)sym == dot);

                if (dotCount > 1)
                {
                    throw new LispException(string.Format(ERR_INVALID_LIST_ENDING, Data.Last()));
                }
                else if (dotCount == 1)
                {
                    if (Data.FindIndex(sym => sym is LispSymbolicAtom && (LispSymbolicAtom)sym == dot) != Data.Count - 2)
                    {
                        throw new LispException(string.Format(ERR_INVALID_LIST_ENDING, Data.Last()));
                    }
                    else
                    {
                        Data.RemoveAt(Data.Count - 2);
                        IsDotted = true;
                    }
                }

                if (list.Count == 0)
                {
                    IsAtom    = true;
                    IsLiteral = true;
                }
            }
            public LispList(string input) : base(false, true)
            {
                // Omit the beginning and the ending parenthesis, we just want the items inside the list.
                input = input.Substring(1, input.Length - 2).ToUpper();

                Data = ProcessInputBuffer(ref input);

                // Handle dotted list input.
                LispSymbolicAtom dot = new LispSymbolicAtom(".");
                int dotCount         = Data.Count(sym => sym is LispSymbolicAtom && (LispSymbolicAtom)sym == dot);

                if (dotCount > 1)
                {
                    throw new LispException(string.Format(ERR_INVALID_LIST_ENDING, Data.Last()));
                }
                else if (dotCount == 1)
                {
                    if (Data.FindIndex(sym => sym is LispSymbolicAtom && (LispSymbolicAtom)sym == dot) != Data.Count - 2)
                    {
                        throw new LispException(string.Format(ERR_INVALID_LIST_ENDING, Data.Last()));
                    }
                    else
                    {
                        Data.RemoveAt(Data.Count - 2);
                        IsDotted = true;
                    }
                }

                // List is both an atom and a list when empty (nil).
                if (Data.Count == 0)
                {
                    IsAtom = true;
                }
            }
        private LispDataType dotimes(LispList args, LispDataType body)
        {
            if (args.Count != 2 && args.Count != 3)
            {
                throw new LispException(string.Format(ERR_INVALID_NUMBER_OF_ARGUMENTS, "DOTIMES"));
            }
            if (!(args[0] is LispSymbolicAtom))
            {
                throw new LispException(string.Format(ERR_NOT_A_SYMBOL, args[0]));
            }
            LispSymbolicAtom counterVar = (LispSymbolicAtom)args[0];

            LispSymbolicAtom[] symbolArray = new LispSymbolicAtom[] { counterVar };
            setq(symbolArray, new LispNumericAtom[] { new LispNumericAtom((LispNumericAtom)args[1].Evaluate(this)) - 1 });

            while ((LispNumericAtom)counterVar.Evaluate(this) >= 0)
            {
                body.Evaluate(this);
                setq(symbolArray, new LispNumericAtom[] { new LispNumericAtom((LispNumericAtom)counterVar.Evaluate(this)) - 1 });
            }

            if (args.Count == 3)
            {
                return(args[2].Evaluate(this));
            }
            return(new LispList());
        }
        private LispDataType eql(LispDataType d1, LispDataType d2)
        {
            LispSymbolicAtom t   = new LispSymbolicAtom("T");
            LispList         nil = new LispList();;

            d1 = d1.Evaluate(this);
            d2 = d2.Evaluate(this);

            if (d1 is LispList && d2 is LispList)
            {
                if (((LispList)d1).Count == 0 && ((LispList)d2).Count == 0)
                {
                    return(t);
                }
                else
                {
                    return(nil);
                }
            }
            else if (d1.ToString() == d2.ToString())
            {
                return(t);
            }
            else
            {
                return(nil);
            }
        }
 private LispDataType boundp(LispSymbolicAtom a)
 {
     if (LispGlobals.ContainsKey(((LispSymbolicAtom)a.Evaluate(this)).Value))
     {
         return(new LispSymbolicAtom("T"));
     }
     else
     {
         return(new LispList());
     }
 }
        private LispSymbolicAtom defun(LispSymbolicAtom name, LispList arguments, LispDataType function, LispInterpreter context)
        {
            List <LispSymbolicAtom> argList = new List <LispSymbolicAtom>();

            foreach (LispDataType arg in arguments)
            {
                if (arg is LispSymbolicAtom)
                {
                    argList.Add((LispSymbolicAtom)arg);
                }
                else
                {
                    throw new LispException(string.Format(ERR_NOT_A_SYMBOL, arg.ToString()));
                }
            }
            LispUserFunctions[name.Value] = new LispUserFunction(name.Value, argList, function);
            LispSymbolicAtom result = new LispSymbolicAtom(name);

            result.SetLiteral(true);
            return(result);
        }
        // Definitions of all the C# implementations of built-in Lisp functions.
        private LispDataType load(LispSymbolicAtom sPath)
        {
            string path          = sPath.Evaluate(this).ToString();
            int    fileExtension = path.LastIndexOf('.');

            if (fileExtension == -1)
            {
                path += ".lsp";
            }

            if (File.Exists(path))
            {
                StreamReader fin = new StreamReader(path);
                string       line;
                while ((line = fin.ReadLine()) != null)
                {
                    int comment = line.IndexOf(';');

                    // No comment found, push onto the command buffer.
                    if (comment == -1)
                    {
                        Read(' ' + line + ' ');
                    }

                    // Ignore the comment by pushing everything before onto the command buffer.
                    else
                    {
                        Read(' ' + line.Substring(0, comment) + ' ');
                    }
                }
                fin.Close();
                Eval();
                return(new LispSymbolicAtom("T"));
            }
            else
            {
                return(new LispList());
            }
        }
 private LispSymbolicAtom makunbound(LispSymbolicAtom a)
 {
     LispGlobals.Remove(((LispSymbolicAtom)a.Evaluate(this)).Value);
     return(a);
 }
 private LispDataType set(LispSymbolicAtom symbol, LispDataType value)
 {
     LispGlobals[symbol.Value] = value.Evaluate(this);
     return(value);
 }