public List(params Object[] objs) { if (objs.Length == 0) throw new Exception ("this ctor can only be used with arrays of length >= 1"); Object tail = L.Qnil; for (int i = objs.Length - 1; i >= 1; i --) tail = new List (objs[i] ?? L.Qnil, tail); cdr = tail; car = objs[0] ?? L.Qnil; }
public static Shelisp.Object Fautoload(L l, Shelisp.Object function, [LispOptional] Shelisp.Object filename, Shelisp.Object docstring, Shelisp.Object interactive, Shelisp.Object type) { if (L.Qt.LispEq (Symbol.Ffboundp (l, function))) return L.Qnil; var autoload_function = new List (new Shelisp.Object[] { L.Qautoload, filename, docstring == null ? (Shelisp.Object)(Shelisp.String)"" : docstring, interactive == null ? L.Qnil : interactive, type == null ? L.Qnil : interactive }); Symbol.Ffset (l, function, autoload_function); //l.Environment = new List (new List(function, function), l.Environment); return autoload_function; }
public static Shelisp.Object Fmake_keymap(L l, [LispOptional] Shelisp.Object str) { Shelisp.Object tail; if (!L.NILP (str)) { Console.WriteLine ("str = {0}", str == null ? "null" : "not null"); tail = new List (str, L.Qnil); } else tail = L.Qnil; return new List (L.intern ("keymap"), new List (CharTable.Fmake_char_table (l, L.intern ("keymap"), L.Qnil), tail)); }
private static Shelisp.Object merge(L l, Shelisp.Object org_l1, Shelisp.Object org_l2, Shelisp.Object pred) { Shelisp.Object value; Shelisp.Object tail; Shelisp.Object tem; Shelisp.Object l1, l2; l1 = org_l1; l2 = org_l2; tail = L.Qnil; value = L.Qnil; while (true) { if (L.NILP (l1)) { if (L.NILP (tail)) return l2; Fsetcdr (l, tail, l2); return value; } if (L.NILP (l2)) { if (L.NILP (tail)) return l1; Fsetcdr (l, tail, l1); return value; } tem = new List (new Shelisp.Object[] { pred, Fcar (l, l2), Fcar (l, l1) }).Eval (l); if (L.NILP (tem)) { tem = l1; l1 = Fcdr (l, l1); org_l1 = l1; } else { tem = l2; l2 = Fcdr (l, l2); org_l2 = l2; } if (L.NILP (tail)) value = tem; else Fsetcdr (l, tail, tem); tail = tem; } }
public static Shelisp.Object ApplyLambda(L l, Shelisp.Object fun, Shelisp.Object args, [LispOptional] Shelisp.Object env, bool eval_args = true) { try { if (l.eval_depth ++ >= L.max_lisp_eval_depth) throw new Exception ("max eval depth exceeded"); // Console.WriteLine ("in ApplyLambda, fun = {0}, args = {1}, eval_args = {2}", fun, args, eval_args); // Console.WriteLine (Environment.StackTrace); if (env == null) env = l.Environment; if (!L.CONSP(fun)) Console.WriteLine ("{0} is not a cons cell! we're about to die!", fun); if (L.CAR(fun).LispEq (L.Qclosure)) { // this sets fun = ( environment args rest... ) where args rest... came from the original lambda. // so the cdr below meant to skip the lambda actually skips the environment. fun = L.CDR(fun); env = L.CAR(fun); } Shelisp.Object rest = L.CDR (fun); // get rid of the lambda Shelisp.Object arg_names = L.CAR(rest); Shelisp.Object body = L.CDR (rest); /* evaluate each of the arguments in the current environment, then add them to the environment and evaluate the body of the lambda */ Shelisp.Object lexenv = env; if (L.CONSP (arg_names)) { IEnumerator<Shelisp.Object> argname_enumerator = ((List)arg_names).GetEnumerator(); IEnumerator<Shelisp.Object> arg_enumerator = L.NILP (args) ? (new List<Shelisp.Object>()).GetEnumerator() : ((List)args).GetEnumerator(); bool optional_seen = false; bool rest_seen = false; while (argname_enumerator.MoveNext()) { if (((Symbol)argname_enumerator.Current).name == "&optional") { optional_seen = true; continue; } if (((Symbol)argname_enumerator.Current).name == "&rest") { rest_seen = true; continue; } if (rest_seen) { // gather up the rest of the args into a single list, add it to the lexenv using the current argname, // and break out of the loop List<Shelisp.Object> list = new List<Shelisp.Object>(); while (arg_enumerator.MoveNext()) list.Add (eval_args ? arg_enumerator.Current.Eval (l, env) : arg_enumerator.Current); Shelisp.Object rest_args = list.Count == 0 ? L.Qnil : new List(list.ToArray()); lexenv = new List (new List (argname_enumerator.Current, rest_args), lexenv); break; } else if (optional_seen) { // if there is nothing else in arg_enumerator, set parameters to nil if (!arg_enumerator.MoveNext()) { lexenv = new List (new List (argname_enumerator.Current, L.Qnil), lexenv); continue; } } else { if (!arg_enumerator.MoveNext()) throw new Exception ("not enough args"); } lexenv = new List (new List (argname_enumerator.Current, eval_args ? arg_enumerator.Current.Eval (l, env) : arg_enumerator.Current), lexenv); } } var old_env = l.Environment; l.Environment = lexenv; try { Shelisp.Object rv = L.Qnil; foreach (var form in (List)body) { L.EvalIndent(); rv = form.Eval (l, lexenv); L.EvalOutdent(); } return rv; } catch (Exception) { Debug.Print ("at lisp {0}", body); throw; } finally { l.Environment = old_env; } } finally { l.eval_depth --; } }
private static Shelisp.Vector ReadVector(StreamReader s) { Debug.Print ("ReadVector>"); // consume the [ s.Read(); List<Shelisp.Object> objs = new List<Shelisp.Object>(); Shelisp.Object obj; while ((obj = Read (s, ']')) != null) { Debug.Print ("+ {0}", obj); objs.Add (obj); } var rv = new Vector (objs.ToArray()); Debug.Print ("ReadList returning {0}", rv); return rv; }
private static Shelisp.Object ReadList(StreamReader s) { Debug.Print ("ReadList>"); // consume the ( s.Read(); List<Shelisp.Object> objs = new List<Shelisp.Object>(); Shelisp.Object obj; bool dot_seen = false; bool el_after_dot = false; while ((obj = Read (s, ')')) != null) { if (obj.LispEq (L.intern("."))) { if (dot_seen) throw new LispInvalidReadSyntaxException (". in wrong context"); dot_seen = true; continue; } else if (dot_seen) { if (el_after_dot) throw new LispInvalidReadSyntaxException (". in wrong context"); el_after_dot = true; } Debug.Print ("+ {0}", obj); objs.Add (obj); } Shelisp.Object rv; if (dot_seen) rv = L.make_list_atom_tail (objs.ToArray()); else rv = L.make_list (objs.ToArray()); Debug.Print ("ReadList returning {0}", rv); return rv; }