private static void Syntax(Evaluator eval, StackFrame frame) { var args = frame.args; // [tag before after] var(tag, before, after) = StructureUtils.Split3(args.atom); if (!tag.IsSymbol && !tag.IsString) { throw new ArgumentException("Tag must be string or symbol!"); } if (!before.IsBool) { throw new ArgumentException("Eval args flag must be boolean!"); } if (!after.IsBool) { throw new ArgumentException("Eval result flag must be boolean!"); } Atom vars = StructureUtils.CloneTree(args?.next?.atom); Atom body = StructureUtils.CloneTree(args?.next?.next); if (vars.type != AtomType.Pair && vars.type != AtomType.Symbol) { throw new ArgumentException("Args must be list or symbol!"); } var ctx = frame.context.value as Context; var closure = new Closure(ctx, vars, body, (string)tag.value); closure.EvalArgs = (bool)before.value; closure.EvalResult = (bool)after.value; eval.Return(new Atom(AtomType.Function, closure)); }
private static void PredNotNull(Evaluator eval, StackFrame frame) { eval.Return(frame.args.value == null ? Atoms.FALSE : Atoms.TRUE); }
private static void GetContext(Evaluator eval, StackFrame frame) { eval.Return(frame.context); }
private static void Nope(Evaluator eval, StackFrame frame) { eval.Return(null); }
private static void Write(Evaluator eval, StackFrame frame) { var(stream, value) = StructureUtils.Split2(frame.args); if (stream.type != AtomType.Native) { throw new ArgumentException("Argument must be stream!"); } StreamWriter writer = stream?.value as StreamWriter; if (writer == null) { throw new ArgumentException("Argument must be stream!"); } if (value == null) { throw new ArgumentException("Second argument can't be null!"); } switch (value.type) { case AtomType.Number: var type = UNumber.NumberType(value?.value); switch (type) { case UNumber.UINT_8: writer.Write(Convert.ToByte(value.value)); break; case UNumber.SINT_8: writer.Write(Convert.ToSByte(value.value)); break; case UNumber.UINT16: writer.Write(Convert.ToUInt16(value.value)); break; case UNumber.SINT16: writer.Write(Convert.ToInt16(value.value)); break; case UNumber._CHAR_: writer.Write(Convert.ToChar(value.value)); break; case UNumber.UINT32: writer.Write(Convert.ToUInt32(value.value)); break; case UNumber.SINT32: writer.Write(Convert.ToInt32(value.value)); break; case UNumber.UINT64: writer.Write(Convert.ToUInt64(value.value)); break; case UNumber.SINT64: writer.Write(Convert.ToInt64(value.value)); break; case UNumber.FLO32: writer.Write(Convert.ToSingle(value.value)); break; case UNumber.FLO64: writer.Write(Convert.ToDouble(value.value)); break; default: writer.Write(value.value); break; } break; default: writer.Write(value.value); break; } eval.Return(null); }
private static void ReadLine(Evaluator eval, StackFrame frame) { string line = Console.ReadLine(); eval.Return(new Atom(AtomType.String, line)); }
private static void Quote(Evaluator eval, StackFrame frame) { eval.Return(frame.args.atom); }
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; } }