public override object Do(KObject args, KEnvironment env, Continuation <KObject> cont) { CPara(args, 2); KObject expr = First(args); KEnvironment envir = Second(args) as KEnvironment; Check(envir, "not an enviroment"); return(CPS.PassTo <KObject>(() => Evaluator.rceval(expr, envir, cont))); }
public override object Do(KObject args, KEnvironment env, Continuation <KObject> cont) { CPara(args, 2); KPair p = args as KPair; Continuation <KObject> c = null; c = new Continuation <KObject>((x) => { return(CPS.PassTo(() => Evaluator.rceval( new KPair(p.Car, new KPair(new KString(c.Context.ToString()), new KNil())), env, cont))); }, cont, "error-handler"); c.isHandler = true; return(CPS.PassTo(() => Evaluator.rceval(Second(p), env, c))); }
public override object Do(KObject args, KEnvironment env, Continuation <KObject> cont) { CPara(args, 2); KObject definand = First(args), expr = Second(args); var cc = new Continuation <KObject>((e) => { try { Evaluator.BindFormalTree(definand, e, env); } catch (Exception ex) { return(CPS.Error <KObject>(ex.Message, cont)); } return(CPS.Return <KObject>(new KInert(), cont)); }, cont, "define"); return(CPS.PassTo(() => Evaluator.rceval(expr, env, cc))); }
private static RecursionResult <KObject> combineOp(KOperative op, KObject operands, KEnvironment env, Continuation <KObject> cont) { if (null == op.Expr) { if (op is ICombinable) { return((op as ICombinable).Combine(operands, env, cont)); } return(CPS.Error <KObject>("Primitive without implementation!" + op.Write(), cont)); } KEnvironment local = new KEnvironment(op.staticenv); if (!(op.EFormal is KIgnore)) { local.Bind(((KSymbol)op.EFormal).Value, env); } BindFormalTree(op.Formals, operands, local); return(CPS.PassTo <KObject>(() => Evaluator.rceval(op.Expr, local, cont))); }
public override object Do(KObject args, KEnvironment env, Continuation <KObject> cont) { CPara(args, 3); KObject pred = First(args), tr = Second(args), fl = Third(args); var cc = new Continuation <KObject>((p) => { if (!(p is KBoolean)) { return(CPS.Error <KObject>("$if: predicate not boolean", cont)); } else { if (((KBoolean)p).Value) { return(CPS.PassTo <KObject>(() => Evaluator.rceval(tr, env, cont))); } else { return(CPS.PassTo <KObject>(() => Evaluator.rceval(fl, env, cont))); } } }, cont, "if"); return(CPS.PassTo(() => Evaluator.rceval(pred, env, cc))); }
public static RecursionResult <KObject> rceval(KObject datum, KEnvironment env, Continuation <KObject> cont) { // useful for debugging //Console.WriteLine(datum.Display()); if (datum is KPair) { KPair p = datum as KPair; // this function get called when the operator is evaluated to f var childCont = new Continuation <KObject>((f) => { if (f is KOperative) { return(combineOp(f as KOperative, p.Cdr, env, cont)); } else if (f is KApplicative && (p.Cdr is KPair || p.Cdr is KNil)) { if (p.Cdr is KNil) { return(combineApp(f as KApplicative, p.Cdr, env, cont)); } KPair ops = p.Cdr as KPair; LinkedList <KObject> input = new LinkedList <KObject>(); KPair.Foreach(x => { input.AddLast(x); }, ops); LinkedList <KObject> pairs = new LinkedList <KObject>(); Func <KObject, RecursionResult <KObject> > recursion = null; bool firstRun = true; // this continuation is called with the next argument evaled to x. Place next value recursion = (x) => { if (CPS.getContext() is int && !firstRun) { // restore elements when reentering continuation int oldInputCount = (int)CPS.getContext() + 1; input = new LinkedList <KObject>(); KPair.Foreach(e => { input.AddLast(e); }, ops); int leaveOutputs = input.Count - oldInputCount; while (input.Count > oldInputCount) { input.RemoveFirst(); } while (pairs.Count >= leaveOutputs) { pairs.RemoveFirst(); } firstRun = true; } pairs.AddFirst(x); if (input.Count == 0) { // we are finished KObject output = new KNil(); foreach (var el in pairs) { output = new KPair(el, output); } firstRun = false; return(combineApp(f as KApplicative, output, env, cont)); } else { // do something with the next Head argument KObject next = input.First.Value; input.RemoveFirst(); var cc2 = new Continuation <KObject>(recursion, cont, input.Count); return(CPS.PassTo(() => rceval(next, env, cc2))); } }; KObject next2 = input.First.Value; input.RemoveFirst(); var cc = new Continuation <KObject>(recursion, cont, input.Count); return(CPS.PassTo(() => rceval(next2, env, cc))); } return(CPS.Error <KObject>("Unsuitable operation of " + f.Write(), cont)); }, cont, "eval op/app"); return(CPS.PassTo(() => rceval(p.Car, env, childCont))); } else if (datum is KSymbol) { KObject val = env.Lookup(((KSymbol)datum).Value); if (null == val) { return(CPS.Error <KObject>("Unbound variable " + ((KSymbol)datum).Value, cont)); } return(CPS.Return(val, cont)); } else { return(CPS.Return(datum, cont)); } }