public static Object Try(Cons args, Environment environment) { try { return(Runtime.Eval(args.First(), environment)); } catch (Exception e) { environment.AssignLocal(Symbol.IT, e); // If a catch form is specified then evaluate it if (args.Second() as Symbol == Symbol.NULL) { throw; } return(Runtime.Eval(args.Second(), environment)); } finally { // If a finally form was specified then evaluate it if (args.Length() > 2) { Runtime.Eval(args.Third(), environment); } } }
public static Object Cond(Cons args, Environment environment) { Cons clauses = args; while (clauses.Length() > 0) { if (clauses.Length() == 1) { // This is a default (else) clause, so just execute it return(Runtime.Eval(clauses.First(), environment)); } if (clauses.Length() >= 2) { if (Conversions.ObjectToBoolean(Runtime.Eval(clauses.First(), environment))) { return(Runtime.Eval(clauses.Second(), environment)); } else { clauses = (Cons)clauses.Cddr(); } } } return(null); }
public static object EvalString(string expression, Environment environment) { object input = ReadString(expression, environment); object output = Runtime.Eval(input, environment); return(output); }
public static Object And(Cons args, Environment environment) { foreach (Object item in args) { if (Conversions.ObjectToBoolean(Runtime.Eval(item, environment)) == false) { return(false); } } return(true); }
private static void ProcessOptionalArguments(Cons argumentNameList, Cons argumentList, Environment localEnvironment) { // We need to add all the arguments to the closure's environment. while (argumentNameList != null) { Symbol argumentName = null; object argumentValue = null; // We need to get the name of the argument, it can either be just the name or, it can be // it's own Cons with the name and an expression for the default value. if (argumentNameList.Car() is Cons) { // It is a Cons, so extract the name and the default value. argumentName = (Symbol)argumentNameList.Caar(); argumentValue = argumentNameList.Cadar(); } else { argumentName = (Symbol)argumentNameList.Car(); } // Now, if the caller has specified a value for this argument, get it now. if (argumentList != null) { argumentValue = argumentList.Car(); argumentList = (Cons)argumentList.Cdr(); } // Finally add the parameter to the closure's list and then move onto the next argument. // Because the default can be any expression, we need to evaluate the value every time the // function is called. localEnvironment.AssignLocal(argumentName, Runtime.Eval(argumentValue, localEnvironment)); argumentNameList = (Cons)argumentNameList.Cdr(); } // Looks like the caller has supplied more parameters than the closure can use. if (argumentList != null) { throw new LSharpException("Too many parameters given."); } }
public static Object While(Cons args, Environment environment) { object test; while ((Conversions.ObjectToBoolean(test = Runtime.Eval(args.First(), environment)))) { foreach (object item in (Cons)args.Rest()) { Runtime.Eval(item, environment); } } return(test); }
public static Object Do(Cons args, Environment environment) { object result = null; if (args != null) { foreach (object item in args) { result = Runtime.Eval(item, environment); } } return(result); }
public static Object Setq(Cons args, Environment environment) { object v = null; while (args != null) { Symbol s = (Symbol)args.First(); v = Runtime.Eval(args.Second(), environment); environment.Assign(s, v); args = (Cons)args.Cddr(); } return(v); }
public static Object Let(Cons args, Environment environment) { Environment localEnvironment = new Environment(environment); localEnvironment.AssignLocal((Symbol)args.First(), Runtime.Eval(args.Second(), environment)); object result = null; foreach (object item in (Cons)args.Cddr()) { result = Runtime.Eval(item, localEnvironment); } //return Runtime.Eval(args.Third(),localEnvironment); return(result); }
public static Object For(Cons args, Environment environment) { Environment localEnvironment = new Environment(environment); Runtime.Eval(args.First(), localEnvironment); object test; while ((Conversions.ObjectToBoolean(test = Runtime.Eval(args.Second(), localEnvironment)))) { foreach (object item in (Cons)args.Cdddr()) { Runtime.Eval(item, localEnvironment); } Runtime.Eval(args.Third(), localEnvironment); } return(test); }
public static Object To(Cons args, Environment environment) { Environment localEnvironment = new Environment(environment); localEnvironment.AssignLocal((Symbol)args.First(), 0); int endStop = int.Parse(Runtime.Eval(args.Second(), localEnvironment).ToString()); while ((int)localEnvironment.GetValue((Symbol)args.First()) < endStop) { foreach (object item in (Cons)args.Cddr()) { Runtime.Eval(item, localEnvironment); } localEnvironment.AssignLocal((Symbol)args.First(), ((int)Runtime.Eval(args.First(), localEnvironment)) + 1); } return(null); }
public static object BackQuoteExpand(Object form, Environment environment) { if (!(form is Cons)) { return(form); } Cons expression = (Cons)form; Cons result = null; foreach (object item in expression) { if (item is Cons) { Cons list = (Cons)item; Symbol sym = list.First() as Symbol; if (sym == Symbol.BACKQUOTE) { result = new Cons(BackQuoteExpand(list.Second(), environment), result); } else if (sym == Symbol.UNQUOTE) { result = new Cons(Runtime.Eval(BackQuoteExpand(list.Second(), environment), environment), result); } else if (sym == Symbol.SPLICE) { Cons l = (Cons)Runtime.Eval(BackQuoteExpand(list.Second(), environment), environment); foreach (object o in l) { result = new Cons(o, result); } } else { result = new Cons(BackQuoteExpand(item, environment), result); } } else { result = new Cons(item, result); } } return(result.Reverse()); }
public Object Expand(Cons arguments) { // Create a new lexical environment Environment localEnvironment = new Environment(environment); Primitives.ProcessArguments(argumentNames, arguments, localEnvironment); object result = null; if (body != null) { foreach (object o in body) { result = Runtime.Eval(o, localEnvironment); } } return(result); }
public static Object If(Cons args, Environment environment) { if (Conversions.ObjectToBoolean(Runtime.Eval(args.First(), environment))) { // Evaluate the then part return(Runtime.Eval(args.Second(), environment)); } else if (args.Length() > 2) { // Evaluate the optional else part return(Runtime.Eval(args.Third(), environment)); } else { return(null); } }
/// <summary> /// Invokes the closure with arguments bound to the values specified in the /// argument list /// </summary> /// <param name="arguments"></param> /// <returns></returns> public Object Invoke(Cons arguments) { // Create a new lexical environment Environment localEnvironment = new Environment(environment); Primitives.ProcessArguments(argumentNames, arguments, localEnvironment); // Evaluate the body within this lexixal environment object result = null; if (body != null) { foreach (object o in body) { result = Runtime.Eval(o, localEnvironment); } } return(result); }
public static Object ForEach(Cons args, Environment environment) { Environment localEnvironment = new Environment(environment); Symbol variable = (Symbol)args.First(); Object list = Runtime.Eval(args.Second(), localEnvironment); foreach (object o in (System.Collections.IEnumerable)list) { localEnvironment.AssignLocal(variable, o); //Runtime.Eval(args.Third(),localEnvironment); foreach (object item in (Cons)args.Cddr()) { Runtime.Eval(item, localEnvironment); } } return(null); }
public static Object With(Cons args, Environment environment) { Environment localEnvironment = new Environment(environment); Cons bindings = (Cons)args.First(); while ((bindings != null) && (bindings.Length() > 1)) { localEnvironment.AssignLocal((Symbol)bindings.First(), Runtime.Eval(bindings.Second(), environment)); bindings = (Cons)bindings.Cddr(); } object result = null; foreach (object item in (Cons)args.Cdr()) { result = Runtime.Eval(item, localEnvironment); } return(result); }
public static Object Load(Cons args, Environment environment) { object filename = args.First(); if (filename is string) { TextReader textReader = new StreamReader((string)filename); string buffer = textReader.ReadToEnd(); textReader.Close(); // We want to evaluate the whole file, so there is an implicit do // which we now make explicit string expression = string.Format("(do {0})", buffer); object input = Reader.Read(new StringReader(expression), ReadTable.DefaultReadTable()); object output = Runtime.Eval(input, environment); return(output); } throw new LSharpException(String.Format("Using: {0} is not a string", filename)); }
public static Object Trace(Cons args, Environment environment) { string filename = (String)Runtime.Eval(args.First(), environment); try { Runtime.Profiler = new XmlTracer(filename); object result = null;; foreach (object item in (Cons)args.Rest()) { result = Runtime.Eval(item, environment); } return(result); } finally { Runtime.Profiler.Close(); Runtime.Profiler = new DefaultProfiler(); } }
/// <summary> /// Evaluates an expression in a given lexical environment /// </summary> /// <param name="form"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Eval(Object expression, Environment environment) { profiler.TraceCall(expression); if (expression == Reader.EOFVALUE) { return(profiler.TraceReturn(expression)); } if (expression == null) { return(profiler.TraceReturn(null)); } // The expression is either an atom or a list if (Primitives.IsAtom(expression)) { // Number if (expression is double) { return(profiler.TraceReturn(expression)); } if (expression is int) { return(profiler.TraceReturn(expression)); } // Character if (expression is char) { return(profiler.TraceReturn(expression)); } // String if (expression is string) { return(profiler.TraceReturn(expression)); } Symbol sym = expression as Symbol; if (sym == Symbol.TRUE) { return(profiler.TraceReturn(true)); } if (sym == Symbol.FALSE) { return(profiler.TraceReturn(false)); } if (sym == Symbol.NULL) { return(profiler.TraceReturn(null)); } // If the symbol is bound to a value in this lexical environment if (environment.Contains(sym)) { // Then it's a variable so return it's value return(profiler.TraceReturn(environment.GetValue(sym))); } else { // Otherwise symbols evaluate to themselves return(profiler.TraceReturn(expression)); } } else { // The expression must be a list Cons cons = (Cons)expression; // Lists are assumed to be of the form (function arguments) // See if there is a binding to a function, clsoure, macro or special form // in this lexical environment object function = environment.GetValue((Symbol)cons.First()); // If there is no binding, then use the function name directly - it's probably // the name of a .NET method if (function == null) { function = cons.First(); } // If it's a special form if (function is SpecialForm) { return(profiler.TraceReturn(((SpecialForm)function)((Cons)cons.Cdr(), environment))); } // If its a macro application if (function is Macro) { object expansion = ((Macro)function).Expand((Cons)cons.Cdr()); return(profiler.TraceReturn(Runtime.Eval(expansion, environment))); } // It must be a function, closure or method invocation, // so call apply Object arguments = EvalList((Cons)cons.Cdr(), environment); return(profiler.TraceReturn(Runtime.Apply(function, arguments, environment))); } }
public static Object Eval(Cons args, Environment environment) { return(Runtime.Eval(args.First(), environment)); }
public static Object The(Cons args, Environment environment) { Type o = TypeCache.FindType(args.First().ToString()); return(Conversions.The(o, Runtime.Eval(args.Second(), environment))); }
private static void ProcessKeyArguments(Cons argumentNameList, Cons argumentList, Environment localEnvironment) { // Make sure that all of the defined key arguments are inserted to the local enviroment with their // defaults. while (argumentNameList != null) { Symbol argumentName = null; object argumentValue = null; // We need to get the name of the argument, it can either be just the name or, it can be // it's own Cons with the name and an expression for the default value. if (argumentNameList.Car() is Cons) { // It is a Cons, so extract the name and the default value. Because the default can be // any expression, we need to evaluate the value every time the function is called. argumentName = (Symbol)argumentNameList.Caar(); argumentValue = Runtime.Eval(argumentNameList.Cadar(), localEnvironment); } else { argumentName = (Symbol)argumentNameList.Car(); } // Add this variable to the closure's environment, then advance to the next parameter. localEnvironment.AssignLocal(argumentName, argumentValue); argumentNameList = (Cons)argumentNameList.Cdr(); } // Now that the parameters and their defaults have been added to the environment we can now // process the supplied arguments. while (argumentList != null) { // Because these are keyed parameters, the caller needs to specify the name of each // parameter. if (argumentList.Car().GetType() != typeof(Symbol)) { throw new LSharpException("Key parameters must be specified by name."); } // Grab the current parameter and the value associated with it. Then make sure that this // is a keyword. Symbol keywordName = (Symbol)argumentList.Car(); object argumentValue = argumentList.Cadr(); if (keywordName.Name[0] != ':') { throw new LSharpException(keywordName + " is not a valid keyword."); } // Now that we know they supplied a keyword, create a symbol out of it and make sure that // it exists. //keywordName = new Symbol(keywordName.Name.Substring(1)); keywordName = Symbol.FromName(keywordName.Name.Substring(1)); if (localEnvironment.Contains(keywordName) == false) { throw new LSharpException(keywordName + " is not a recognised keyword."); } // Update the parameter with the value that the user specified and then move onto the next // argument in the list. localEnvironment.AssignLocal(keywordName, argumentValue); argumentList = (Cons)argumentList.Cddr(); } }