private static void Cond(Evaluator eval, StackFrame frame) { switch (frame.state.value) { case "-eval-sexp-body-": frame.temp1 = frame.args; frame.state = new Atom("-built-in-cond-head-"); break; case "-built-in-cond-head-": if (eval.HaveReturn()) { var condition = eval.TakeReturn(); if (!condition.IsBool) { throw new ArgumentException($"Condition must return boolean atom, but found: {condition}!"); } if ((bool)condition.value) { frame.state = new Atom("-built-in-cond-body-"); break; } } if (frame.temp1 != null) { frame.temp2 = frame.temp1.atom; frame.temp1 = frame.temp1.next; if (!frame.temp2.IsPair) { throw new ArgumentException($"Condition element must be list, but found: {frame.temp2}!"); } eval.CreateFrame("-eval-", frame.temp2.atom, frame.context); } else { // Ни одно из условий не выполнилось frame.state = new Atom("-eval-sexp-body-"); eval.Return(Atoms.FALSE); } break; case "-built-in-cond-body-": if (eval.HaveReturn()) { eval.CloseFrame(); } else { eval.CreateFrame("-eval-block-", frame.temp2.next, frame.context); } break; } }
private static void Eval(Evaluator eval, StackFrame frame) { if (!eval.HaveReturn()) { var(expression, ctxAtom) = StructureUtils.Split2(frame.args); Context ctx = ctxAtom?.value as Context ?? frame.context.value as Context; eval.CreateFrame("-eval-", expression, ctx); return; } eval.CloseFrame(); }
private static void Apply(Evaluator eval, StackFrame frame) { if (eval.HaveReturn()) { var args = frame.args; Atom func = args.atom; Atom rest = StructureUtils.CloneList(args.next.atom); Function proc = func?.value as Function; if (proc == null) { throw new ArgumentException("First argument must be procedure!"); } eval.CreateFrame("-eval-", new Atom(func, rest), frame.context); return; } eval.CloseFrame(); }
private static void EvalEach(Evaluator eval, StackFrame frame) { if (!eval.HaveReturn()) { Atom expression = frame.args; Atom first = frame.args?.atom; if (first?.value is Context ctx) { expression = frame.args?.next; } else { ctx = frame.context.value as Context; } eval.CreateFrame("-eval-block-", expression, ctx); return; } eval.CloseFrame(); }
private static void If(Evaluator eval, StackFrame frame) { switch (frame.state.value) { case "-eval-sexp-body-": { // (cond BlockA BlockB) (frame.temp1, frame.temp2, frame.temp3) = StructureUtils.Split3(frame.args); frame.state = new Atom("-built-in-if-cond-"); } break; case "-built-in-if-cond-": { if (eval.HaveReturn()) { var condition = eval.TakeReturn(); if (!condition.IsBool) { throw new ArgumentException($"Condition must return boolean atom, but found: {condition}!"); } frame.state = new Atom((bool)condition.value ? "-built-in-if-then-" : "-built-in-if-else-"); } else { eval.CreateFrame("-eval-", frame.temp1, frame.context); } } break; case "-built-in-if-then-": { if (frame.temp2 == null) { throw new ArgumentException($"If statement must have at least one block of code!"); } if (eval.HaveReturn()) { eval.CloseFrame(); break; } eval.CreateFrame("-eval-", frame.temp2, frame.context); } break; case "-built-in-if-else-": frame.state = new Atom("-eval-sexp-body-"); if (eval.HaveReturn()) { eval.CloseFrame(); break; } if (frame.temp3 == null) { eval.Return(null); } else { eval.CreateFrame("-eval-", frame.temp3, frame.context); } break; } }