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 DefClass(Cons args, Environment environment) { string className = args.First().ToString(); Cons superClasses = args.Cadr() as Cons; string superClass = null; string interfaces = null; if (superClasses != null) { superClass = superClasses.First().ToString(); if (superClasses.Length() >= 2) { StringBuilder b = new StringBuilder(); b.Append(superClasses.Second()); foreach (object item in (Cons)superClasses.Cddr()) { b.Append(", " + item); } interfaces = b.ToString(); } } return(ClassBuilder.CreateClass(className, superClass, interfaces)); }
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 Nconc(Cons args, Environment environment) { // With no argument, returns null if (args == null) { return(null); } // With one argument, returns that argument if (args.Length() < 2) { return(args.First()); } for (int i = 0; i < args.Length() - 1; i++) { Cons cons = (Cons)args.Nth(i); cons = (Cons)cons.Last(); cons.Rplacd(args.Nth(i + 1)); } return(args.First()); }
public static Object Cons(Cons args, Environment environment) { int l = args.Length(); if (l == 0) { return(null); } if (l == 1) { return(args.First()); } return(new Cons(args.First(), Cons((Cons)args.Rest(), environment))); }
public static Object Read(Cons args, Environment environment) { ReadTable readTable = (ReadTable)environment.GetValue(Symbol.FromName("*readtable*")); TextReader textReader = args.First() as TextReader; object eofValue = Reader.EOFVALUE; if (args.Length() > 1) { eofValue = args.Second(); } return(Reader.Read(textReader, readTable, eofValue)); }
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); } }
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); }
/// <summary> /// Creates a fresh cons, the car of which is object-1 and the cdr of which is object-2. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Cons(Cons args, Environment environment) { if (args.Length() == 1) return args.First(); if (args.Length() == 2) return new Cons(args.First(),Cons((Cons)args.Rest(), environment)); throw new LSharpException("Too many arguments given to cons"); }
/// <summary> /// Calls a .NET method. /// The first argument is the object to which the method is attached. /// Passes the rest of the arguments to the appropriate constructor /// </summary> /// <param name="method"></param> /// <param name="arguments"></param> /// <returns></returns> public static object Call(String method, Cons arguments) { BindingFlags bindingFlags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic; // Is it a method on a static type or an object instance ? Type type; if (arguments.First().GetType() == typeof(LSharp.Symbol)) { bindingFlags = bindingFlags | BindingFlags.Static | BindingFlags.FlattenHierarchy; // Find the type object from its name type = TypeCache.Instance().FindType(arguments.First().ToString()); } else { bindingFlags = bindingFlags | BindingFlags.Instance; type = arguments.First().GetType(); } Type[] types = new Type[arguments.Length() -1]; object[] parameters = new object[arguments.Length() -1]; int loop = 0; if (arguments.Rest() != null) foreach (object argument in (Cons)arguments.Rest()) { types[loop] = argument.GetType(); parameters[loop] = argument; loop++; } // Start by looking for a method call MethodInfo m = type.GetMethod(method.ToString(), bindingFlags | BindingFlags.InvokeMethod ,null,types,null); if (m != null) return m.Invoke(arguments.First(),parameters); // Now loook for a property get PropertyInfo p = type.GetProperty(method.ToString(),bindingFlags | BindingFlags.GetProperty, null,null, types,null); if (p != null) return p.GetGetMethod().Invoke(arguments.First(),parameters); // Now look for a field get FieldInfo f = type.GetField(method.ToString(),bindingFlags | BindingFlags.GetField); if (f != null) return f.GetValue(arguments.First()); // FIXME: or an event ? EventInfo e = type.GetEvent(method.ToString(), bindingFlags); // | BindingFlags.Event) if (e != null) // attempt to call the click event return e.GetRaiseMethod().Invoke(arguments.First(), parameters); throw new LSharpException(string.Format("Call: No such method, property, field, or event '{0}' on '{1}'", method.ToString(),type)); }
/// <summary> /// (read TextReader [eof]) /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Read(Cons args, Environment environment) { ReadTable readTable = (ReadTable)environment.GetValue(Symbol.FromName("*readtable*")); TextReader textReader = (TextReader)args.First(); object eofValue = null; if (args.Length() > 1) eofValue = args.Second(); return Reader.Read(textReader, readTable, eofValue); }
/// <summary> /// (spawn expression) is like eval except that the expression /// is evaluated on a new thread. Returns immediately with /// the new thread object, but execution of expressions /// continues synchronously. Experimental. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Spawn(Cons args, Environment environment) { if (args.Length() == 1) return ThreadAdapter.Fork(args.First(), environment, System.Threading.ApartmentState.MTA); else if (args.Length() == 2) return ThreadAdapter.Fork(args.First(), environment, (System.Threading.ApartmentState) Runtime.Eval(args.Second(), environment)); else throw new LSharpException("Incorrect arguments given to spawn"); }
/// <summary> /// (try expression catch [finally]) /// The try special form corresponds to the try-catch-finally construct found /// in C#. If catch is null then there is deemed to be no catch block /// at all. If an exception occurs, the variable "it" is bound to the Exception /// object in the local environment. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> 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() == 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); } }
/// <summary> /// (defmethod name "arg1 arg2" "(expression1)" "(expression 2)" [...]) /// Created methods used for DefClass <br /> /// </summary> /// <param name="args"></param> /// <param name="e"></param> /// <returns></returns> public static object DefMethod(Cons args, Environment e) { string name; string[] _args; string commands = ""; name = args.First().ToString(); _args = args.Second().ToString().Split(new string[] {" "}, StringSplitOptions.None);; for (int i = 2; i < args.Length(); i++) commands += args.Nth(i) + " "; commands = commands.Replace("\\", "\\\\"); commands = commands.Replace("\"", "\\\""); //FIXME: //code = code.Replace("\n", "\\n"); DefinedMethod ret = new DefinedMethod(commands, name, _args); e.AssignLocal(Symbol.FromName(name), ret); Console.WriteLine("Assigned '" + ret.Name + "' as a DefinedMethod"); return ret; }
/// <summary> /// (if test then [else]) /// The if special form corresponds to the if-then-else construct found in /// most algebraic programming languages. First the form test is evauated, /// if true then the form then is evaluated.Otherwise, optionally the form /// else is evaluated. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> 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> /// Calls a .NET method. /// The first argument is the object to which the method is attached. /// Passes the rest of the arguments to the appropriate constructor /// </summary> /// <param name="method"></param> /// <param name="arguments"></param> /// <returns></returns> public static object Call(String method, Cons arguments) { BindingFlags bindingFlags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic; string methname = method; string typename = string.Empty; Type type = null; int i = methname.LastIndexOf("."); if (i >= 0) { methname = methname.Substring(i + 1); typename = method.Substring(0, i); type = TypeCache.FindType(typename); } // Is it a method on a static type or an object instance ? if (type == null) { if (arguments.First() is Symbol) { bindingFlags = bindingFlags | BindingFlags.Static | BindingFlags.FlattenHierarchy; // Find the type object from its name type = TypeCache.FindType(arguments.First().ToString()); } else { bindingFlags = bindingFlags | BindingFlags.Instance; type = arguments.First().GetType(); } } else { bindingFlags = bindingFlags | BindingFlags.Instance; } if (type == null) { throw new LSharpException(string.Format("Call: No such type '{0}'. Did you forget a 'using'?", arguments.First())); } Type[] types = new Type[arguments.Length() - 1]; object[] parameters = new object[arguments.Length() - 1]; int loop = 0; if (arguments.Rest() != null) { foreach (object argument in (Cons)arguments.Rest()) { types[loop] = argument.GetType(); parameters[loop] = argument; loop++; } } // Start by looking for a method call MethodInfo m = type.GetMethod(methname, bindingFlags | BindingFlags.InvokeMethod , null, types, null); if (m != null) { return(m.Invoke(arguments.First(), parameters)); } // Now loook for a property get PropertyInfo p = type.GetProperty(methname, bindingFlags | BindingFlags.GetProperty, null, null, types, null); if (p != null) { return(p.GetGetMethod().Invoke(arguments.First(), parameters)); } // Now look for a field get FieldInfo f = type.GetField(methname, bindingFlags | BindingFlags.GetField); if (f != null) { return(f.GetValue(arguments.First())); } // or an event ? throw new LSharpException(string.Format("Call: No such method, property or field '{1}.{0}({2})'", method.ToString(), type, TypeString(types, parameters))); }
/// <summary> /// Creates a dynamic class /// (defclass "classname" "inheritsfrom" [defmethod]) /// e.g. (defclass "class1" "Object" DefinedMethods*) /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object DefClass(Cons args, Environment environment) { string className = args.First().ToString(); string superClass = args.Second().ToString(); DefinedMethod[] methods = new DefinedMethod[args.Length() - 2]; for (int i = 2; i < args.Length(); i++) { try { Symbol toFind = (Symbol) args.Nth(i); object foundMethod = environment.GetValue(toFind); methods[i - 2] = (DefinedMethod) foundMethod; } catch (Exception e ) { Console.WriteLine("DEFCLASS ERROR: " + e.Message + " " + e.StackTrace); } } return ClassBuilder.CreateClass(className, superClass, "", methods); }
public static string GenerateList(Cons rest, LSharp.Environment environment, string margs) { string v = string.Format(@"System.Collections.ArrayList {0} = new System.Collections.ArrayList({1}); ", margs, rest.Length()); // load args foreach (object argo in rest) { if (argo is Symbol) { Symbol sarg = (Symbol)argo; if (environment.Contains(sarg)) { v += string.Format(@"{1}.Add({0}); ", environment.GetValue(sarg), margs); } else { v += Generate(argo, environment); v += margs + @".Add(retval); "; } } else if (argo is Cons) { v += Generate(argo, environment); v += margs + @".Add(retval); "; } else { // load primitive v += string.Format(@"{1}.Add({0}); ", Printer.WriteToString(argo), margs); } } return v; }
/// <summary> /// Evaluates an LSharp expression in a given environment /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Eval(Cons args, Environment environment) { if (args.Length() == 1) return Runtime.Eval(args.First(), environment); else throw new LSharpException("Incorrect arguments given to eval"); }
public static string GenerateFuncCall(string type, string method, Cons rest, LSharp.Environment environment) { string v = string.Empty; string typemeth = method; if (type != null) { typemeth = type + "." + method; } if (rest == null) { return v + "retval = " + typemeth + string.Format(@"(null, environment); "); } else { if (rest.Length() == 1) { object argo = rest.First(); string argn = "retval"; if (argo is Symbol) { Symbol sarg = (Symbol)argo; if (environment.Contains(sarg)) { argn = environment.GetValue(sarg) as string; } else { v += Generate(argo, environment); } } else if (argo is Cons) { v += Generate(argo, environment); } else { // load primitive argn = Printer.WriteToString(argo); } return v + "retval = " + typemeth + string.Format(@"(new LSharp.Cons({0}), environment); ", argn); } else { string margs = GetArgs(); v += GenerateList(rest, environment, margs); return v + "retval = " + typemeth + string.Format(@"(LSharp.Cons.FromList({0}), environment); ", margs); } } }
/// <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 + @"); } "; }
/// <summary> /// (if test then [else]) /// </summary> public static Object If(Cons args, LSharp.Environment environment) { string v = //"//(if " + Printer.ConsToString(args) + ")" + NewLine + Generate(args.First(),environment) + string.Format(@" if (LSharp.Conversions.ObjectToBoolean(retval)) {{ // Evaluate the then part {0} }} ", Generate(args.Second(),environment)); if (args.Length() > 2) { // Evaluate the optional else part v += string.Format(@" else {{ {0} }} ", Generate(args.Third(),environment)); } return v; }
/// <summary> /// (nconc list*) /// Returns a list whose elements are the elements of each list in /// order. Destructively modifies all but the last list, such that /// the cdr of the last cons in each list is the next list. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Nconc(Cons args, Environment environment) { // With no argument, returns null if (args == null) return null; // With one argument, returns that argument if (args.Length() < 2) return args.First(); for (int i = 0; i < args.Length() -1; i ++) { Cons cons = (Cons)args.Nth(i); cons = (Cons)cons.Last(); cons.Rplacd(args.Nth(i+1)); } return args.First(); }
/// <summary> /// (try expression catch [finally]) /// </summary> public static Object Try(Cons args, LSharp.Environment environment) { string v = "";//"//(try " + Printer.ConsToString(args) + ")" + NewLine + string.Format(@" try {{ {0} }} catch (Exception e) {{ {1} }}", Generate(args.First(), environment) ,(args.Second() as Symbol == Symbol.NULL) ? "throw" : Generate(args.Second(),environment)); if (args.Length() > 2) { v += string.Format(@" finally {{ {0} }} ", Generate(args.Third(),environment)); } return v; }