private TiState Step(TiState state) { var headAddr = state.Stack.Peek(); var headNode = state.Heap[headAddr]; return(headNode switch { TiNode.Number number => StepNum(state, number), TiNode.Application application => StepAp(state, application), TiNode.Supercombinator supercombinator => StepSc(state, supercombinator), TiNode.Indirection indirection => StepInd(state, indirection), TiNode.Primitive primitive => StepPrim(state, primitive), TiNode.Data data => StepData(state, data), _ => throw new ArgumentOutOfRangeException(nameof(headNode)) });
private static (ImmutableDictionary <int, TiNode>, int) MarkFrom(ImmutableDictionary <int, TiNode> heap, int addr) { var node = heap[addr]; switch (node) { case TiNode.Application application: int function, argument; (heap, function) = MarkFrom(heap, application.Function); (heap, argument) = MarkFrom(heap, application.Argument); node = new TiNode.Application(function, argument); break; case TiNode.Data data: var components = new List <int>(); foreach (var component in data.Components) { int newComponent; (heap, newComponent) = MarkFrom(heap, component); components.Add(newComponent); } node = new TiNode.Data(data.Tag, components); break; case TiNode.Indirection indirection: return(MarkFrom(heap, indirection.Address)); case TiNode.Number _: break; case TiNode.Primitive _: break; case TiNode.Supercombinator _: break; case Marked _: return(heap, addr); default: throw new ArgumentOutOfRangeException(nameof(node)); } heap = heap.SetItem(addr, new Marked(node)); return(heap, addr); }