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."); } }
/// <summary> /// (gui-inspect OBJECT) /// shows a Form with data on the item OBJECT /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static object GuiInspect(Cons args, Environment environment) { // TODO : Fix //string sname = (string) Functions.SymbolName(new Cons(args.First()), environment); InspectorForm i = new InspectorForm(args.Car(), environment); i.ShowDialog(); return args.First(); }
/// <summary> /// Process the arguments passed to a closure, and add them to the given enviroment. /// </summary> /// <param name="argumentNameList">The list of names and kewords the closure was created with.</param> /// <param name="argumentList">The arguments passed to the closure.</param> /// <param name="localEnvironment">The closure's local variables.</param> /// <returns>Nothing.</returns> public static void ProcessArguments(Cons argumentNameList, Cons argumentList, Environment localEnvironment) { while (argumentNameList != null) { // Get the name for the closure's parameter. Then check to see if it's a keyword, if it is then // process the keyword. Otherwise set up that parameter in the closure's enviroment with the // caller specified value. Symbol argumentName = (Symbol)argumentNameList.Car(); switch (argumentName.ToString()) { case "&rest": argumentName = (Symbol)argumentNameList.Cadr(); localEnvironment.AssignLocal(argumentName, argumentList); argumentNameList = null; argumentList = null; break; case "&optional": ProcessOptionalArguments((Cons)argumentNameList.Cdr(), argumentList, localEnvironment); argumentNameList = null; argumentList = null; break; case "&key": ProcessKeyArguments((Cons)argumentNameList.Cdr(), argumentList, localEnvironment); argumentNameList = null; argumentList = null; break; default: if (argumentList == null) { throw new LSharpException("Not enough parameters given."); } localEnvironment.AssignLocal(argumentName, argumentList.Car()); argumentList = (Cons)argumentList.Cdr(); argumentNameList = (Cons)argumentNameList.Cdr(); break; } } // 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 Length(Cons args, Environment environment) { object o = args.Car(); if (o == null) { return(0); } else { return(Runtime.Call("length", args)); } }
public override bool Equals(object obj) { if (obj is Cons) { Cons that = (Cons)obj; bool carsEqual = Primitives.Eql(this.Car(), that.Car()); bool cdrsEqual = Primitives.Eql(this.Cdr(), that.Cdr()); return(carsEqual && cdrsEqual); } else { return(false); } }
/// <summary> /// (length expression) /// Returns the length of expression. If expression is null, length returns 0, /// otherwise the length is calculated by calling the length method on the object, /// ensuring that length works for strings, lists and most collection-like objects. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Length(Cons args, Environment environment) { object o = args.Car(); if (o == null) return 0; else return Runtime.Call("length", args); }
public static string WriteToString(Object x) { if (x == null) { return("null"); } if (x == Reader.EOFVALUE) { return("EOF"); } Type type = x.GetType(); if (x is string) { return(string.Format("\"{0}\"", (string)x)); } if (x is bool) { return(x.ToString().ToLower()); } if (x is char) { return(string.Format("#\\{0}", x)); } if (x is Symbol) { return(string.Format("{0}", x)); } if (x is Cons) { bool wasquote = true; Cons cons = (Cons)x; StringBuilder stringBuilder = new StringBuilder(); Symbol car = cons.Car() as Symbol; if (car == Symbol.QUOTE) { stringBuilder.Append("'"); } else if (car == Symbol.BACKQUOTE) { stringBuilder.Append("`"); } else if (car == Symbol.SPLICE) { stringBuilder.Append(",@"); } else if (car == Symbol.UNQUOTE) { stringBuilder.Append(","); } else { wasquote = false; stringBuilder.Append("("); stringBuilder.Append(WriteToString(cons.Car())); stringBuilder.Append(" "); } Object o; o = cons.Cdr(); while (o != null) { if (o is Cons) { cons = (Cons)o; stringBuilder.Append(WriteToString(cons.Car())); o = cons.Cdr(); if (o != null) { stringBuilder.Append(" "); } } else { stringBuilder.Append(". "); stringBuilder.Append(WriteToString(o)); o = null; } } string op = stringBuilder.ToString().Trim(); if (wasquote) { return(op); } else { return(op + ")"); } } return(x.ToString().Trim()); }
/// <summary> /// (play-sound filename) /// Plays the sound from filename /// </summary> /// <param name="args"></param> /// <param name="e"></param> /// <returns></returns> public static object PlaySound(Cons args, Environment e) { return Sound.Play((string) args.Car()); }
/// <summary> /// (call method object argument*) /// Calls a .NET method on a given object with given arguments. /// This is useful if the method name clashes with a variable which is already /// bound in the current L Sharp lexical environment. /// </summary> /// <param name="args"></param> /// <param name="environment"></param> /// <returns></returns> public static Object Call(Cons args, Environment environment) { return Runtime.Call(args.Car().ToString(), (Cons)Runtime.EvalList(args.Rest(),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(); } }
public static Object Call(Cons args, Environment environment) { return(Runtime.Call(args.Car().ToString(), (Cons)Runtime.EvalList(args.Rest(), environment))); }
public static object Item(Cons args, Environment environment) { int index = (int)args.Car(); Array array = (Array) args.Cadr(); return array.GetValue(index); }
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().GetType() == typeof(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."); } }
/// <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 + @"); } "; }
public static string GenerateCons(Cons args, LSharp.Environment environment) { // ananlysi cons if (args == null) { return @"//retval = null; // dont null mite need retval "; } else { Symbol sym = args.Car() as Symbol; object e = Runtime.Eval(sym, environment); if (e is Function) { Function f = e as Function; string v = "{" + NewLine; Cons rest = args.Rest() as Cons; v += GenerateFuncCall(f.Method.DeclaringType.ToString(), f.Method.Name, rest, environment); return v + "}" + NewLine; } else if (e is SpecialForm) { SpecialForm f = e as SpecialForm; Cons rest = args.Rest() as Cons; string r = Printer.ConsToString(rest); string lFName = f.Method.Name.ToLower(); if (lFName == "while") return While(rest, environment) as string; if (lFName == "for") return For(rest, environment) as string; if (lFName == "and") return And(rest, environment) as string; if (lFName == "call") return Call(rest, environment) as string; if (lFName == "cond") return Cond(rest, environment) as string; if (lFName == "do") return Do(rest, environment) as string; if (lFName == "foreach") return ForEach(rest, environment) as string; if (lFName == "if") return If(rest, environment) as string; if (lFName == "let") return Let(rest, environment) as string; if (lFName == "or") return Or(rest, environment) as string; if (lFName == "quote") return Quote(rest, environment) as string; if (lFName == "setq") return Setq(rest, environment) as string; if (lFName == "the") return The(rest, environment) as string; if (lFName == "to") return To(rest, environment) as string; if (lFName == "try") return Try(rest, environment) as string; if (lFName == "when") return When(rest, environment) as string; if (lFName == "with") return With(rest, environment) as string; return Runtime.EvalString("(" + f.Method.Name + " " + r + ")", environment) as string; } else if (e is Macro) { Macro m = e as Macro; Cons rest = args.Rest() as Cons; Cons em = m.Expand(rest) as Cons; return Generate(em, environment); } else if (e is Closure) { extracode += Closure(new Cons(sym), environment) as string; string v = "{" + NewLine; Cons rest = args.Rest() as Cons; v += GenerateFuncCall(null, environment.GetValue(sym) as string, rest, environment); return v + "}" + NewLine; } else if (currsymbols.ContainsKey(sym)) { string v = "{" + NewLine; Cons rest = args.Rest() as Cons; v += GenerateFuncCall(null, environment.GetValue(sym) as string, rest, environment); return v + "}" + NewLine; } else { // not good, lets not support this for now: .NET method call try { // try: LSharp.Runtime.Appy(<args>); Cons rest = args.Rest() as Cons; string ret = GenerateList(rest, environment, "temporarytableforspecialfunctioncall"); ret += "\nLSharp.Runtime.Apply(retval, LSharp.Cons.FromList(temporarytableforspecialfunctioncall), environment);"; //return ret; //"// call not supported";// Call(args, environment).ToString(); return Call(args, environment) as string; } catch { string margs = GetArgs(); string v = GenerateList(args.Rest() as Cons, environment, margs); return string.Format("retval = LSharp.Cons.FromList({0});{1}", margs, NewLine); } } } }
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(); } }