private void Execute(Continuation cont) { _current = cont; while (Next()) { if (!_break) { continue; } _break = false; _current = PopContext(); } }
public void Continue(Continuation continuation) { PushContext(continuation); while (true) { Execute(_current); _break = false; _current = PopContext(); if (_current == null) { break; } } }
private Continuation PopContext() { for (var n = ContextStack.Count - 1; n >= 0; --n) { var cont = ContextStack[n]; if (!cont.Active || !cont.Running) { continue; } ContextStack.RemoveAt(n); return(_current = cont.Start(this)); } return(null); }
/// <summary> /// Resume the continuation that spawned the current one /// </summary> private new void Resume() { if (!RPop(out var next)) { Break(); return; } switch (next) { case ICallable call: call.Invoke(_registry, DataStack); break; case IClassBase @class: Push(@class.NewInstance()); break; case MethodInfo mi: var numArgs = mi.GetParameters().Length; if (DataStack.Count < numArgs + 1) { var servant = DataStack.Count > 0 ? DataStack.Peek() : "null"; throw new NotEnoughArgumentsException($"{servant}.{mi.Name} expects {numArgs} args"); } var obj = Pop(); var args = new object[numArgs]; for (var n = 0; n < numArgs; ++n) { args[numArgs - n - 1] = Pop(); } var ret = mi.Invoke(obj, args); if (mi.ReturnType != typeof(void)) { Push(ret); } break; default: PushContext(next); _current = null; break; } Break(); }
/// <summary> /// Stop the current continuation and resume whatever is on the /// context stack. /// </summary> private void Break() { _break = true; _current = null; }
private void PushContext(Continuation continuation) { ContextStack.Add(continuation); _current = null; }