Пример #1
0
        public bool TryGetVariable(String key, out Sexp s)
        {
            bool found = _variables.TryGetValue(key, out s);

            if (!found)
            {
                if (_parent != null)
                {
                    return(_parent.TryGetVariable(key, out s));
                }
            }
            return(found);
        }
Пример #2
0
 public Sexp Call(ref Environment e, MemoryStream ms, Sexp sexp)
 {
     if (sexp.Length == _parameterNames.Count)
     {
         int         i      = 0;
         Environment eClone = new Environment(e);
         // add the respective sexps to the parameter names
         foreach (String s in _parameterNames)
         {
             eClone.SetVariable(s, Evaluator.Evaluate(ref eClone, ms, sexp[i]));
             ++i;
         }
         // only return the last value so default to Void
         Sexp outSexp = Sexp.Void;
         foreach (Sexp s in Body)
         {
             outSexp = Evaluator.Evaluate(ref eClone, ms, s);
         }
         return(outSexp);
     }
     throw new CrispArgumentException(String.Format("'{0}' function expects {1} arguments, got {1}", _name, _parameterNames.Count, sexp.Length), sexp.Line);
 }
Пример #3
0
 /// <summary>
 /// Evaluates an Sexp using a provided environment returning it's value
 /// </summary>
 /// <param name="e">Supplied environment</param>
 /// <param name="ms">Stream that functions can output to</param>
 /// <param name="sexp">Sexp to be evaluated</param>
 /// <returns>Sexp</returns>
 public static Sexp Evaluate(ref Environment e, MemoryStream ms, Sexp sexp)
 {
     foreach (Sexp innerSexp in sexp)
     {
         // lists can be evaluated if it doesn't start with a ident
         if (innerSexp.Type == SexpType.LIST)
         {
             if (innerSexp[0].Type == SexpType.IDENT)
             {
                 Evaluate(ref e, ms, innerSexp);
             }
             else
             {
                 return(innerSexp);
             }
         }
         else if (innerSexp.Type == SexpType.IDENT) // has to be resolved
         {
             // collects all sexps
             List <Sexp> allSexps = new List <Sexp>(sexp);
             if (allSexps.Count > 1) // has been given arguments
             {
                 // check for builtin function, if found it executes it
                 Environment.CrispFunction cf;
                 if (e.TryGetBuiltinFunction(innerSexp.Value, out cf))
                 {
                     return(cf(ref e, ms, Sexp.FromList(allSexps.GetRange(1, allSexps.Count - 1))));
                 }
                 else
                 {
                     // check for a user defined function, if found executes it
                     CrispUserFunction cuf;
                     if (e.TryGetUserFunction(innerSexp.Value, out cuf))
                     {
                         return(cuf.Call(ref e, ms, Sexp.FromList(allSexps.GetRange(1, allSexps.Count - 1))));
                     }
                     else
                     {
                         // check for a varible, if found return it
                         Sexp s;
                         if (e.TryGetVariable(innerSexp.Value, out s))
                         {
                             return(s);
                         }
                         else
                         {
                             // not found
                             throw new CrispNotExistsException(String.Format("'{0}' does not exist in this namespace", innerSexp.Value), innerSexp.Line);
                         }
                     }
                 }
             }
             else // no args added
             {
                 // check for builtin function, if found it executes it
                 Environment.CrispFunction cf;
                 if (e.TryGetBuiltinFunction(innerSexp.Value, out cf))
                 {
                     return(cf(ref e, ms, Sexp.Void));
                 }
                 else
                 {
                     // check for a user defined function, if found executes it
                     CrispUserFunction cuf;
                     if (e.TryGetUserFunction(innerSexp.Value, out cuf))
                     {
                         return(cuf.Call(ref e, ms, Sexp.Void));
                     }
                     else
                     {
                         // check for a varible, if found return it
                         Sexp s;
                         if (e.TryGetVariable(innerSexp.Value, out s))
                         {
                             return(s);
                         }
                         else
                         {
                             // not found
                             throw new CrispNotExistsException(String.Format("'{0}' does not exist in this namespace", innerSexp.Value), innerSexp.Line);
                         }
                     }
                 }
             }
         }
         else
         {
             return(innerSexp);
         }
     }
     return(Sexp.Void);
 }
Пример #4
0
        /// <summary>
        /// This function turns a list of tokens into a list of Sexps. It recursively creates Sexps
        /// of type list, every top-level function call are actually stored in an Sexp
        /// </summary>
        /// <param name="tokens">The list of tokens to read</param>
        /// <param name="i">A shared index to keep track of next token throughout the recursive calls</param>
        /// <param name="numberOfParens">A shared interger that marks how many open parenthesises</param>
        /// <returns>A list of all Sexp values to be passed to the evaluator</returns>
        private Sexp Parse(List <Token> tokens, ref int i, ref int numberOfParens)
        {
            Sexp curr = new Sexp();

            for (; i < tokens.Count; ++i)
            {
                Token t = tokens[i];
                switch (t.Type)
                {
                case TokenType.OPEN_PAREN:
                    ++i;     // needs to be incremented here to stop an infinite recursion error
                    ++numberOfParens;
                    curr.Type = SexpType.LIST;
                    curr.Add(Parse(tokens, ref i, ref numberOfParens));
                    break;

                case TokenType.CLOSE_PAREN:
                    --numberOfParens;
                    // tests if there is a surplus ')' token
                    if (numberOfParens < 0)
                    {
                        throw new CrispParserExpcetion("Mismatched parenthesises", t.Line);
                    }
                    return(curr);

                case TokenType.INTEGER_LITERAL:
                    curr.Add(new Sexp(SexpType.INT, t.Value, t.Line));
                    break;

                case TokenType.FLOAT_LITERAL:
                    curr.Add(new Sexp(SexpType.FLOAT, t.Value, t.Line));
                    break;

                case TokenType.CHAR_LITERAL:
                    curr.Add(new Sexp(SexpType.CHAR, t.Value, t.Line));
                    break;

                case TokenType.IDENT:
                    curr.Add(new Sexp(SexpType.IDENT, t.Value, t.Line));
                    break;

                case TokenType.STRING_LITERAL:
                    curr.Add(new Sexp(SexpType.STRING, t.Value, t.Line));
                    break;

                case TokenType.BOOL_LITERAL:
                    curr.Add(new Sexp(SexpType.BOOL, t.Value, t.Line));
                    break;

                case TokenType.EOF:
                    // In a valid program there should be no unmatched '(' character
                    if (numberOfParens != 0)
                    {
                        throw new CrispParserExpcetion("Mismatched parenthesises", tokens[i - 1].Line);
                    }
                    break;

                default:
                    break;
                }
            }
            return(curr);
        }
Пример #5
0
 public void SetVariable(String key, Sexp value)
 {
     _variables[key] = value;
 }