public IEnumerable <Position> Execute(QuipuEnv qee) { // Empty program: exit immediately if (qee.ThreadValues.Count == 0) { yield break; } while (true) { var instr = Threads[qee.CurrentThread].Knots[qee.CurrentKnot]; yield return(instr.Position); var result = instr.Instruction(qee); if (result != null) { if (result.Value == -1) { yield break; } if (result.Value < -1 || result.Value >= Threads.Length) { throw new InvalidOperationException(@"Jump to invalid thread {0}.".Fmt(result)); } qee.ThreadValues[qee.CurrentThread] = qee.Stack.Pop(); qee.CurrentThread = result.Value; qee.CurrentKnot = 0; qee.Stack.Clear(); qee.Stack.Push(qee.ThreadValues[result.Value]); } else { qee.CurrentKnot++; if (qee.CurrentKnot >= Threads[qee.CurrentThread].Knots.Count) { qee.ThreadValues[qee.CurrentThread] = qee.Stack.Pop(); qee.CurrentThread++; if (qee.CurrentThread >= Threads.Length) { break; } qee.CurrentKnot = 0; qee.Stack.Clear(); qee.Stack.Push(qee.ThreadValues[qee.CurrentThread]); } } } yield return(new Position(SourceLength, 0)); }
public IEnumerable<Position> Execute(QuipuEnv qee) { // Empty program: exit immediately if (qee.ThreadValues.Count == 0) yield break; while (true) { var instr = Threads[qee.CurrentThread].Knots[qee.CurrentKnot]; yield return instr.Position; var result = instr.Instruction(qee); if (result != null) { if (result.Value == -1) yield break; if (result.Value < -1 || result.Value >= Threads.Length) throw new InvalidOperationException(@"Jump to invalid thread {0}.".Fmt(result)); qee.ThreadValues[qee.CurrentThread] = qee.Stack.Pop(); qee.CurrentThread = result.Value; qee.CurrentKnot = 0; qee.Stack.Clear(); qee.Stack.Push(qee.ThreadValues[result.Value]); } else { qee.CurrentKnot++; if (qee.CurrentKnot >= Threads[qee.CurrentThread].Knots.Count) { qee.ThreadValues[qee.CurrentThread] = qee.Stack.Pop(); qee.CurrentThread++; if (qee.CurrentThread >= Threads.Length) break; qee.CurrentKnot = 0; qee.Stack.Clear(); qee.Stack.Push(qee.ThreadValues[qee.CurrentThread]); } } } yield return new Position(SourceLength, 0); }