Last active
December 19, 2015 21:39
-
-
Save JamesTryand/6021607 to your computer and use it in GitHub Desktop.
Abuse of yield to expose to the statemachine within it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| using System.Collections; | |
| using System.Reflection; | |
| namespace BurgerMonkey | |
| { | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| var spotty = new BurgerMonkey(); | |
| spotty.ServeGimp(); | |
| spotty.FlipBurger(); | |
| spotty.ServeGimp(); | |
| spotty.ServeGimp(); | |
| spotty.HandFood(); | |
| spotty.FlipBurger(); | |
| spotty.FlipBurger(); | |
| spotty.HandFood(); | |
| spotty.HandFood(); | |
| Console.ReadLine(); | |
| } | |
| } | |
| public class BurgerMonkey | |
| { | |
| public readonly Action ServeGimp; | |
| public readonly Action FlipBurger; | |
| public readonly Action HandFood; | |
| private Action Action; | |
| private IEnumerator CurrentState; | |
| public BurgerMonkey() | |
| { | |
| PrepareActions(); | |
| CurrentState = MoveState().GetEnumerator(); | |
| CurrentState.MoveNext(); | |
| } | |
| #region This is where the magic happens ;-) | |
| private void PrepareActions() | |
| { | |
| var type = GetType(); | |
| foreach (var field in type.GetFields( | |
| BindingFlags.Public | | |
| BindingFlags.Instance) | |
| .Where(f => f.FieldType == typeof(Action))) | |
| { | |
| field.SetValue(this, BuildAction()); | |
| } | |
| } | |
| private Action BuildAction() | |
| { | |
| Action x = null; | |
| x = () => | |
| { | |
| Action = x; | |
| CurrentState.MoveNext(); | |
| }; | |
| return x; | |
| } | |
| private void InAction(string excuse) | |
| { | |
| throw new InvalidOperationException(string.Format("Fucksake, {0} Broken", excuse)); | |
| } | |
| #endregion | |
| // This is where the work of the yeild state machine happens. it's a single statement that _should_ | |
| // ( if written correctly ) never complete, nor should it fall through to the other states (cases) | |
| // while the external statemoves provide the stimulus to change state, it can (as demonstrated by the | |
| // move to loungingAbout happen due to conditions of internal state). | |
| // The requirement for goto's here is to allow the control flow WITHIN THIS ONE METHOD to occur. | |
| // Note that as this is intended to be non-completing, the goto's only move within the scope of this method. | |
| // | |
| private IEnumerable MoveState() | |
| { | |
| loungingAbout: | |
| Console.WriteLine("he just sits there"); | |
| yield return null; | |
| if (Action == ServeGimp) { goto serveGimp; } | |
| if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; } | |
| InAction("idleness kills our hero"); | |
| flipBurger: | |
| NumbersOf[The.BurgersNeedingToBeCooked] = | |
| NumbersOf[The.BurgersNeedingToBeCooked] - 1; | |
| Ready[AllThe.BurgersReady] = Ready[AllThe.BurgersReady] + 1; | |
| Console.WriteLine("using a plasterers trowel he flips the burgers"); | |
| yield return null; | |
| if (Action == ServeGimp) { goto serveGimp; } | |
| if (Action == HandFood) { goto handFood; } | |
| if (Action == FlipBurger) { goto flipBurger; } | |
| if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; } | |
| InAction("the burger landed on the floor and the 5 second rule was"); | |
| handFood: | |
| NumbersOf[The.PeopleBeingWaitingToBeServed] = | |
| NumbersOf[The.PeopleBeingWaitingToBeServed] - 1; | |
| Ready.Keys.ToList().ForEach(thingy => Ready[thingy] = Ready[thingy] - 1); | |
| yield return null; | |
| if (Action == ServeGimp) { goto serveGimp; } | |
| if (Action == FlipBurger) { goto flipBurger; } | |
| if (Action == HandFood) { goto handFood; } | |
| if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; } | |
| InAction("our hero has a seizure from boredom"); | |
| serveGimp: | |
| NumbersOf.Keys.ToList().ForEach(thingy => NumbersOf[thingy] = NumbersOf[thingy] + 1); | |
| Console.WriteLine("blah blah blah? would you like fries with that"); | |
| yield return null; | |
| if (Action == ServeGimp) { goto serveGimp; } | |
| if (Action == HandFood) { goto handFood; } | |
| if (Action == FlipBurger) { goto flipBurger; } | |
| if (NumbersOf.Values.Sum() < 1) { goto loungingAbout; } | |
| InAction("falling on his face, his nose was"); | |
| } | |
| private enum The { PeopleBeingWaitingToBeServed, BurgersNeedingToBeCooked }; | |
| private enum AllThe { PeopleBeingWaitingForFood, BurgersReady}; | |
| private Dictionary<The, int> NumbersOf = new Dictionary<The, int>() { | |
| { The.BurgersNeedingToBeCooked, 0 }, | |
| { The.PeopleBeingWaitingToBeServed, 0 } | |
| }; | |
| private Dictionary<AllThe, int> Ready = new Dictionary<AllThe, int>() { | |
| { AllThe.BurgersReady, 0 }, | |
| { AllThe.PeopleBeingWaitingForFood, 0 } | |
| }; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment