internal static T DynamicCall <T>(dynamic routine, params object[] args) { var context = new StackContext(routine); context.nextCallArgs.AddRange(args); context.IsFirstCall = true; while (!context.ExitRequested) { //exit by default; it's up to 'routine' to schedule the continuation context.ExitRequested = true; switch (args.Length) { case 0: routine(context); break; case 1: routine((dynamic)context.nextCallArgs[0], context); break; case 2: routine((dynamic)context.nextCallArgs[0], (dynamic)context.nextCallArgs[1], context); break; case 3: routine((dynamic)context.nextCallArgs[0], (dynamic)context.nextCallArgs[1], (dynamic)context.nextCallArgs[2], context); break; case 4: routine((dynamic)context.nextCallArgs[0], (dynamic)context.nextCallArgs[1], (dynamic)context.nextCallArgs[2], (dynamic)context.nextCallArgs[3], context); break; case 5: routine((dynamic)context.nextCallArgs[0], (dynamic)context.nextCallArgs[1], (dynamic)context.nextCallArgs[2], (dynamic)context.nextCallArgs[3], (dynamic)context.nextCallArgs[4], context); break; } } context.IsFirstCall = false; return((T)context.Result); }
//------------------------------------------------ #if DEBUG //may need to be re-enabled in the future (e.g. for portability reasons) internal static object StaticCall <T>(T arg, Action <T, StackContext> routine) { var context = new StackContext(routine, arg); context.IsFirstCall = true; while (!context.ExitRequested) { //exit by default; it's up to 'routine' to schedule the continuation context.ExitRequested = true; routine((T)context.nextCallArgs[0], context); context.IsFirstCall = false; } return(context.Result); }