Skip to content

Instantly share code, notes, and snippets.

@pinscript
Created October 18, 2011 10:53
Show Gist options
  • Select an option

  • Save pinscript/1295155 to your computer and use it in GitHub Desktop.

Select an option

Save pinscript/1295155 to your computer and use it in GitHub Desktop.
class Program {
private delegate void BottlesDelegate(int input);
static void Main(string[] args) {
IL();
Console.WriteLine("Done");
Console.ReadLine();
}
private static void IL() {
var method = new DynamicMethod("Bottles", typeof (void), new[] {typeof (int)}, typeof (Program).Module);
var write = typeof(Console).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(x => x.Name == "WriteLine").First(x => x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == typeof(string));
var writeFormatted = typeof (Console).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(x => x.Name == "WriteLine").First(x => x.GetParameters().Length == 2 && x.GetParameters()[0].ParameterType == typeof (string) && x.GetParameters()[1].ParameterType == typeof(object));
var il = method.GetILGenerator();
var work = il.DefineLabel();
// Check if we have any bottles left
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Brtrue, work);
il.Emit(OpCodes.Ldstr, "No more bottles of beer on the wall, no more bottles of beer.");
il.Emit(OpCodes.Call, write);
il.Emit(OpCodes.Ret);
// Print
il.MarkLabel(work);
il.Emit(OpCodes.Ldstr, "{0} bottles of beer on the wall, {0} bottles of beer.");
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Box, typeof (Int32));
il.Emit(OpCodes.Call, writeFormatted);
il.Emit(OpCodes.Ldstr, "Take one down and pass it around. {0} botles of beer.");
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, 1);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Box, typeof (Int32));
il.Emit(OpCodes.Call, writeFormatted);
// Subtract
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4, 1);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Starg, 0);
// Recurse
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, method);
il.Emit(OpCodes.Ret);
var del = method.CreateDelegate(typeof(BottlesDelegate)) as BottlesDelegate;
del(99);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment