private static GmState StepPrim(GmInstruction.Prim instruction, GmState state) { if (!PrimHandlers.TryGetValue(instruction.Type, out var handler)) { throw new KeyNotFoundException(instruction.Type.ToString()); } return(handler(state)); }
private static PrettyPrinter.Node ShowStack(GmState state) => Append( Str("Stk ["), Indent(Interleave(new PrettyPrinter.Node.Newline(), state.Stack.Select(addr => Append( ShowAddr(addr), Str(": "), ShowNode(state, addr) )))), Str(" ]") );
public IEnumerable <GmState> Evaluate(GmState state) { yield return(state); while (!IsComplete(state)) { state = Step(state); yield return(state); } }
private static GmState StepUnwind(GmInstruction.Unwind _, GmState state) { var head = state.Stack.Peek(); var headNode = state.Heap[head]; return(headNode switch { GmNode.Number num => UnwindNum(num, state), GmNode.Application ap => UnwindAp(ap, state), GmNode.Global global => UnwindGlobal(global, state), GmNode.Indirection ind => UnwindInd(ind, state), _ => throw new ArgumentOutOfRangeException(nameof(headNode)) });
private static GmState Step(GmState state) { var(instruction, newState) = state.DequeueInstruction(); return(instruction switch { GmInstruction.PushGlobal pushGlobal => StepPushGlobal(pushGlobal, newState), GmInstruction.PushInt pushInt => StepPushInt(pushInt, newState), GmInstruction.MkAp mkAp => StepMkAp(mkAp, newState), GmInstruction.Push push => StepPush(push, newState), GmInstruction.Update update => StepUpdate(update, newState), GmInstruction.Pop pop => StepPop(pop, newState), GmInstruction.Slide slide => StepSlide(slide, newState), GmInstruction.Alloc alloc => StepAlloc(alloc, newState), GmInstruction.Unwind unwind => StepUnwind(unwind, newState), GmInstruction.Eval eval => StepEval(eval, newState), GmInstruction.Prim prim => StepPrim(prim, newState), GmInstruction.Cond cond => StepCond(cond, newState), _ => throw new ArgumentOutOfRangeException(nameof(instruction)) });
private static GmState BoxBool(bool value, GmState state) { return(state.AllocateAndPush(new GmNode.Number(value ? 1 : 0))); }
private static int UnboxNum(int addr, GmState state) { return(((GmNode.Number)state.Heap[addr]).Value); }
private static GmState BoxNum(int value, GmState state) { return(state.AllocateAndPush(new GmNode.Number(value))); }
public static string Print(GmState state) => PrettyPrinter.Display(ShowState(state));
private static PrettyPrinter.Node ShowNode(GmState state, int addr) => state.Heap[addr] switch {
private static PrettyPrinter.Node ShowState(GmState state) => Append(ShowStack(state), Newline());
private static bool IsComplete(GmState state) { return(state.Code.IsEmpty); }