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 Until(Evaluator eval, StackFrame frame) { switch (frame.state.value) { case "-eval-sexp-body-": // (Cond Body) (frame.temp1, frame.temp2) = (frame.args.atom, frame.args.next); frame.state = new Atom("-built-in-while-cond-"); break; case "-built-in-while-cond-": 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-while-body-"); } else { frame.state = new Atom("-eval-sexp-body-"); eval.Return(frame.temp3); } } else { eval.CreateFrame("-eval-", frame.temp1, frame.context); } break; case "-built-in-while-body-": if (eval.HaveReturn()) { frame.temp3 = eval.TakeReturn(); frame.state = new Atom("-built-in-while-cond-"); } else { eval.CreateFrame("-eval-block-", frame.temp2, frame.context); } break; } }
private static void Define(Evaluator eval, StackFrame frame) { var(sym, value, context) = StructureUtils.Split3(frame.args); if (sym.type != AtomType.Symbol) { throw new ArgumentException("Definition name must be symbol!"); } if (eval.HaveReturn()) { string name = (string)sym.value; Atom result = eval.TakeReturn(); Context ctx = context?.value as Context ?? frame.context.value as Context; if (result?.value is Closure function) { function.Name = name; } //Console.WriteLine($"DEFINE: '{name}' = '{result}' at -internal-state-{ctx}"); ContextUtils.Define(ctx, result, name); eval.Return(result); return; } eval.CreateFrame("-eval-", value, frame.context); frame.state = Atoms.INTERNAL_STATE; }
// TODO: Осознать, что тут происходит private static void TableEach(Evaluator eval, StackFrame frame) { var args = frame.args; var(dict, func) = StructureUtils.Split2(args); Context dictionary = GetDictionary(dict); Function proc = func?.value as Function; if (dictionary == null) { throw new ArgumentException("First argument must be table!"); } if (proc == null) { throw new ArgumentException("Second argument must be procedure!"); } switch (frame.state.value) { case "-eval-sexp-body-": var list = dictionary .Select(pair => StructureUtils.List(new Atom(AtomType.String, pair.Key), pair.Value)) .ToArray(); frame.temp1 = StructureUtils.List(list); frame.state = new Atom("-built-in-table-each-"); break; case "-built-in-table-each-": if (eval.HaveReturn()) { frame.temp2 = StructureUtils.BuildListContainer(frame.temp2, eval.TakeReturn()); } if (frame.temp1 != null) { var pair = frame.temp1.atom; frame.temp1 = frame.temp1.next; var newFrame = eval.CreateFrame( "-eval-sexp-args-", new Atom(func, pair), frame.context); newFrame.function = func; newFrame.args = frame.temp1.atom; } else { eval.SetReturn(null); frame.state = new Atom("-eval-sexp-body-"); } 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 Filter(Evaluator eval, StackFrame frame) { (var list, var proc, var skip) = StructureUtils.Split3(frame.args); bool skipNull = (bool?)skip?.value ?? false; switch (frame.state.value) { case "-eval-sexp-body-": frame.temp1 = list; frame.state = new Atom("-built-in-map-"); break; case "-built-in-map-": if (eval.HaveReturn()) { var pred = eval.TakeReturn(); bool add = (bool?)pred?.value ?? false; if (add) { frame.temp2 = StructureUtils.BuildListContainer(frame.temp2, frame.temp3); } } if (frame.temp1 != null) { while (skipNull && frame.temp1.atom == null) { frame.temp1 = frame.temp1.next; } var subExpression = frame.temp1.atom; frame.temp3 = subExpression; frame.temp1 = frame.temp1.next; subExpression = new Atom(subExpression, null); frame.temp1 = frame.temp1.next; var newFrame = eval.CreateFrame( "-eval-sexp-args-", new Atom(proc, subExpression), frame.context); newFrame.function = proc; newFrame.args = subExpression; } else { eval.SetReturn(frame.temp2.atom); frame.state = new Atom("-eval-sexp-body-"); } break; } }
private static void Each(Evaluator eval, StackFrame frame) { (var list, var proc, var skip) = StructureUtils.Split3(frame.args); bool skipNull = (bool?)skip?.value ?? false; switch (frame.state.value) { case "-eval-sexp-body-": frame.temp1 = list; frame.state = new Atom("-built-in-each-"); break; case "-built-in-each-": if (eval.HaveReturn()) { frame.temp2 = StructureUtils.BuildListContainer(frame.temp2, eval.TakeReturn()); } if (frame.temp1 != null) { while (skipNull && frame.temp1.atom == null) { frame.temp1 = frame.temp1.next; } var subExpression = new Atom(frame.temp1.atom, null); var newFrame = eval.CreateFrame( "-eval-sexp-body-", StructureUtils.List(proc, frame.temp1.atom), frame.context); newFrame.function = proc; newFrame.args = subExpression; frame.temp1 = frame.temp1.next; } else { eval.SetReturn(null); frame.state = new Atom("-eval-sexp-body-"); } break; } }
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 SetFirst(Evaluator eval, StackFrame frame) { var args = frame.args; Atom sym = (Atom)args?.value; if (sym.type != AtomType.Symbol) { throw new ArgumentException("Variable name must be symbol!"); } if (eval.HaveReturn()) { var result = eval.TakeReturn(); var ctx = frame.context.value as Context; ContextUtils.Set(ctx, result, (string)sym.value); eval.Return(result); return; } eval.CreateFrame("-eval-", args.next?.atom, frame.context); frame.state = Atoms.INTERNAL_STATE; }
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; } }