private Symbol(PrimitiveSymbol prim) { switch (prim) { case PrimitiveSymbol.Unbound: this.name = "unbound"; this.value = this.function = this; break; default: throw new NotSupportedException(); } }
public Hash(L l, Shelisp.Object test, Shelisp.Object weakness, Shelisp.Object size, Shelisp.Object rehash_size, Shelisp.Object rehash_threshold) { this.l = l; this.test = test; this.weakness = weakness; this.size = size; this.rehash_size = size; this.rehash_threshold = rehash_threshold; this.count = 0; // map weakness to our enum if (L.NILP (weakness)) { weakness_ = Weakness.None; } else if (weakness.LispEq (L.Qt)) { weakness_ = Weakness.KeyAndValue; } else if (weakness.LispEq (L.Qkey)) { weakness_ = Weakness.Key; } else if (weakness.LispEq (L.Qvalue)) { weakness_ = Weakness.Value; } else if (weakness.LispEq (L.Qkey_or_value)) { weakness_ = Weakness.KeyOrValue; } else if (weakness.LispEq (L.Qkey_and_value)) { weakness_ = Weakness.KeyAndValue; } else throw new Exception (string.Format ("invalid weakness {0}", weakness)); compare = null; // use a builtin comparison function for the builtin test types if (test.LispEq (L.intern ("eq"))) { compare = compare_eq; } else if (test.LispEq (L.intern ("eql"))) { compare = compare_eql; } else if (test.LispEqual (L.intern ("equal"))) { compare = compare_equal; } table = new Tuple<Shelisp.Object,Shelisp.Object>[(int)((Number)size).boxed]; }
public override Shelisp.Object Eval(L l, Shelisp.Object env = null) { try { if (l.eval_depth ++ >= L.max_lisp_eval_depth) throw new Exception ("max eval depth exceeded"); env = env ?? l.Environment; Debug.Print (this); // function evaluation gets stuffed in here unfortunately Object first = L.CAR(this); Object rest = L.CDR(this); Shelisp.Object fun = first; retry: #if my_stupid_way if (first is Symbol) { Debug.Print ("first is {0}", first); Shelisp.Object lex_binding = List.Fassq (l, first, env); if (!L.NILP (lex_binding)) { var binding = L.CDR (lex_binding); if (binding is Symbol && !(L.Qunbound.LispEq (((Symbol)binding).Function))) fun = ((Symbol)binding).Function; } if (fun is Symbol) { fun = L.Findirect_function (l, fun); Debug.Print ("first was a symbol, function = {0}", fun); } } #else fun = first; if ((fun is Symbol) && !fun.LispEq (L.Qunbound)) { fun = ((Symbol)fun).Function; if (fun is Symbol) fun = L.Findirect_function (l, fun, L.Qnil); } #endif if (fun is Subr) { Subr subr = (Subr)fun; Shelisp.Object[] args; L.EvalSpew ("evaluating subr application, {0}", fun); if (!L.LISTP(rest)) throw new WrongTypeArgumentException ("listp", rest); if (L.NILP (rest)) { args = new Shelisp.Object[0]; } else { Shelisp.List rest_list = L.CONS(rest); args = new Shelisp.Object[rest_list.Length]; int argnum = 0; if (subr.unevalled) { Debug.Print (" unevalled args"); } else { Debug.Print (" evalled args"); } L.EvalIndent(1); foreach (var o in rest_list) { L.EvalSpew ("arg: {0}", o); if (subr.unevalled) { args[argnum++] = o; } else { var evalled = o.Eval (l, env); if (L.Qunbound.LispEq (evalled)) throw new Exception (string.Format ("form {0} evaluated to unbound. this is NOT what you want", o)); args[argnum++] = evalled; } } L.EvalOutdent(1); } try { L.EvalIndent(); Shelisp.Object rv = ((Subr)fun).Call (l, args); L.EvalOutdent(); L.EvalSpew ("evaluating of {0} resulted in {1}", fun, rv); return rv; } catch { Debug.Print ("at lisp {0}", fun); throw; } } else { if (L.NILP (fun) || fun.LispEq(L.Qunbound)) { Console.WriteLine ("entire application is {0}", this); throw new LispVoidFunctionException (first); } if (!L.LISTP (fun)) throw new LispInvalidFunctionException (first); Shelisp.Object funcar = L.CAR (fun); if (!(funcar is Symbol)) { throw new LispInvalidFunctionException (first); } if (funcar.LispEq (L.Qautoload)) { FileIO.DoAutoload (l, fun, first); goto retry; } #if notyet if (EQ (funcar, Qmacro)) val = eval_sub (apply1 (Fcdr (fun), original_args)); else if (EQ (funcar, Qlambda) || EQ (funcar, Qclosure)) val = apply_lambda (fun, original_args); else xsignal1 (Qinvalid_function, original_fun); #else if (funcar.LispEq (L.Qmacro)) { L.EvalSpew ("evaluating macro application, {0} = {1}, ", first, L.CDR(fun)); L.EvalIndent(1); foreach (var r in (List)rest) L.EvalSpew ("arg: {0}", r); L.EvalOutdent(1); L.EvalIndent(); var expanded = List.ApplyLambda (l, L.CDR(fun), rest, env, false); L.EvalOutdent(); L.EvalSpew ("macro {0} expanded to {1}", first, expanded); var expanded_evalled = expanded.Eval (l, env); L.EvalSpew ("evaluating of {0} resulted in {1}", first, expanded_evalled); return expanded_evalled; } if (funcar.LispEq (L.Qlambda) || funcar.LispEq (L.Qclosure)) { L.EvalSpew ("evaluating function application, {0} = {1}, ", first, L.CDR(fun)); if (L.CONSP(rest)) { L.EvalIndent (1); foreach (var r in (List)rest) L.EvalSpew ("arg: {0}", r); L.EvalOutdent (1); } L.EvalIndent(); var rv = List.ApplyLambda (l, fun, rest, env); L.EvalOutdent(); L.EvalSpew ("evaluating of {0} resulted in {1}", first, rv); return rv; } else { throw new LispInvalidFunctionException (first); } #endif } } finally { l.eval_depth --; } }
public Symbol(string name) { this.name = name; this.value = Unbound; this.function = Unbound; }
public static Shelisp.Object Fmake_hash_table(L l, params Shelisp.Object[] keyword_args) { Shelisp.Object test = L.intern ("eql"); // this is wrong, it's not just numbers, right? Shelisp.Object weakness = L.Qnil; Shelisp.Object size = new Number (65); Shelisp.Object rehash_size = new Number (1.5); Shelisp.Object rehash_threshold = new Number (0.8); for (int i = 0; i < keyword_args.Length; i += 2) { var keyword = keyword_args[i]; Console.WriteLine (keyword); if (i == keyword_args.Length - 1) throw new Exception (string.Format ("keyword {0} has no value", keyword)); var value = keyword_args[i+1]; if (keyword.LispEq (L.Qtest)) test = value; else if (keyword.LispEq (L.Qweakness)) weakness = value; else if (keyword.LispEq (L.Qsize)) size = value; else if (keyword.LispEq (L.Qrehash_size)) rehash_size = value; else if (keyword.LispEq (L.Qrehash_threshold)) rehash_threshold = value; } return new Hash (l, test, weakness, size, rehash_size, rehash_threshold); }