/// <summary> /// (= { symbol value}*) /// Setq (Set Quote) is the variable assignment operator. /// Sets each variable symbol to value in the current environment. /// The abbreviation = is more commonly used in L Sharp. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> 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; }
/// <summary> /// (to variable limit expression) /// Starting at 0, assigns variable to succesive integers upto and /// including limit. Executes expression on each iteration. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> 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; }
/// <summary> /// (each symbol IEnumerable expression) /// Iterates over any object which impelements IEnumerablewith succesive /// elements being assigned to a variable named symbol; exceutes expression /// on each iteration. Cons (LSharp lists), as well as many .NET collections /// are IEnumerable. Foreach is a synonym for each. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> 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; }
/// <summary> /// (let symbol value expression*) /// Binds a new local variable symbol to value in a new local lexical environment, /// before evaluating expressions. Similar to with, but often more convenient for /// decalring a single local variable. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> 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; }
/// <summary> /// (= { symbol value}*) /// </summary> public static Object Setq(Cons args, LSharp.Environment environment) { string v = "";//"//(setq " + Printer.ConsToString(args) + ")" + NewLine; while (args != null) { Symbol s = (Symbol)args.First(); Cons sec = args.Second() as Cons; if (sec != null) { Symbol ss = sec.First() as Symbol; if (ss == Symbol.FromName("fn")) { Closure c = Runtime.Eval(sec, environment) as Closure; environment.Assign(s, c); extracode += Closure( new Cons(s), environment); args = (Cons)args.Cddr(); continue; } if (ss == Symbol.FromName("macro")) { Macro m = Runtime.Eval(sec, environment) as Macro; environment.Assign(s, m); args = (Cons)args.Cddr(); continue; } } v += GenerateAssign(s,Generate(args.Second(),environment), environment); args = (Cons)args.Cddr(); } return v; }
/// <summary> /// (to variable limit expression) /// </summary> public static Object To(Cons args, LSharp.Environment environment) { string v = //"//(to " + Printer.ConsToString(args) + ")" + NewLine + "{" + NewLine; LSharp.Environment localEnvironment = new LSharp.Environment(environment); v += GenerateAssignLocal(args.First() as Symbol, 0, localEnvironment); v += Generate(args.Second(),environment); string lbl = MakeUnique("endstop"); v += string.Format(@" int {1} = (int)retval; while ({0} < {1}) {{ ", localEnvironment.GetValue(args.First() as Symbol), lbl); foreach (object item in (Cons)args.Cddr()) { v += Generate(item, localEnvironment); } v += localEnvironment.GetValue(args.First() as Symbol) + "++;"; v += "}" + NewLine; v += string.Format(@" retval = null; "); return v + "}" + NewLine; }
/// <summary> /// (let symbol value expression*) /// </summary> public static Object Let(Cons args, LSharp.Environment environment) { string v = //"//(let " + Printer.ConsToString(args) + ")" + NewLine + "{" + NewLine; LSharp.Environment localEnvironment = new LSharp.Environment(environment); v += GenerateAssignLocal((Symbol) args.First(), Generate(args.Second(),environment), localEnvironment); foreach (object item in (Cons)args.Cddr()) { v += Generate(item, localEnvironment); } return v + "}" + NewLine; }
/// <summary> /// (each symbol IEnumerable expression) /// </summary> public static Object ForEach(Cons args, LSharp.Environment environment) { //string v = "//(each " + Printer.ConsToString(args) + ")" + NewLine; string v = ""; LSharp.Environment localEnvironment = new LSharp.Environment(environment); Symbol variable = (Symbol) args.First(); string vn = localEnvironment.AssignLocal(variable, MakeUnique(variable.Name)) as string; v += Generate(args.Second(),environment) + string.Format(@" foreach (object {0} in (System.Collections.IEnumerable)retval) {{", vn); foreach (object item in (Cons)args.Cddr()) { v += Generate(item, localEnvironment); } v += "}" + NewLine; return v; }
/// <summary> /// (call method object argument*) /// </summary> public static Object Call(Cons args, LSharp.Environment environment) { string v = //"//(call " + Printer.ConsToString(args) + ")" + NewLine + "{" + NewLine; ArrayList argtypes = new ArrayList(); ArrayList argz = new ArrayList(); if (args.Length() > 2) { foreach (object arg in (args.Cddr() as Cons)) { if (Primitives.IsAtom(arg)) { argz.Add(Printer.WriteToString(arg)); } else { string argn = MakeUnique("arg"); string sv = Generate(arg, environment); sv += string.Format(@"{0} {1} = ({0}) retval; ", typeof(object) , argn); argz.Add(argn); v += sv; } argtypes.Add(typeof(object)); } } string typemethname = args.Car().ToString(); string methname = typemethname; string typename = string.Empty; Type type = typeof(object); int i = methname.LastIndexOf("."); if (i >= 0) { methname = methname.Substring(i + 1); typename = typemethname.Substring(0, i); type = TypeCache.FindType(typename); } MethodInfo mi = null; mi = type.GetMethod(methname, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance, binder, argtypes.ToArray(typeof(Type)) as Type[], null); string objn = string.Empty; if (mi == null) { type = TypeCache.FindType(args.Second().ToString()); mi = type.GetMethod(methname, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Static, binder, argtypes.ToArray(typeof(Type)) as Type[], null); if (mi == null) { // use reflection v += Generate(args.Second(), environment); v += string.Format(@"retval = retval.GetType().InvokeMember(""{0}"", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance, null, retval, new object[]{{", methname) + string.Join(", ", argz.ToArray(typeof(string)) as string[]) + @"}); } "; return v; } else { objn = type.ToString(); } } else { objn = MakeUnique("obj"); v += Generate(args.Second(), environment); v += string.Format(@"{0} {1} = ({0}) retval; ", type, objn); } v += "retval = " + (mi.ReturnType == typeof(void) ? @"null; " : "") + objn + "." + mi.Name + "(" + string.Join(", ", argz.ToArray(typeof(string)) as string[]); return v + @"); } "; }
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().GetType() == typeof(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(); } }
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(); } }