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); }
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); }
/// <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); }
/// <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); }
public void SetVariable(String key, Sexp value) { _variables[key] = value; }