PageRenderTime 42ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/BrainFuckCompiler/Program.cs

http://ironbrainfuck.codeplex.com
C# | 130 lines | 126 code | 4 blank | 0 comment | 3 complexity | 26f78e5c0b21785616710cb6c9915217 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. using System.Text;
  8. using ZackFlame.IronBrainFuck.JIT;
  9. namespace BrainFuckCompiler
  10. {
  11. public static class Program
  12. {
  13. static readonly MethodInfo get_In, get_Out;
  14. static Program()
  15. {
  16. get_In = typeof(Console).GetProperty("In").GetGetMethod();
  17. get_Out = typeof(Console).GetProperty("Out").GetGetMethod();
  18. }
  19. public static void Main(string[] args)
  20. {
  21. string compilerName = Path.GetFileName(
  22. System.Reflection.Assembly.GetExecutingAssembly().Location);
  23. if (args.Length < 2)
  24. {
  25. Console.WriteLine(string.Format(
  26. "IronBrainFuck command-line compiler" +
  27. "{0}" +
  28. "{0}Usage: {1} <brainFuckCodeFile> <outputPath>" +
  29. "{0}e.g. {1} brain.bf c:\brain.exe",
  30. Environment.NewLine,
  31. compilerName));
  32. }
  33. else
  34. {
  35. string assemblyName = Path.GetFileNameWithoutExtension(args[1]);
  36. string directory = Path.GetDirectoryName(args[1]);
  37. if (directory.Length == 0)
  38. directory = ".\\";
  39. try
  40. {
  41. string brainFuckProgram = File.ReadAllText(args[0]);
  42. CompileAndSave(brainFuckProgram, assemblyName, directory);
  43. Environment.Exit(0);
  44. }
  45. catch (FileNotFoundException ex)
  46. {
  47. Console.Error.WriteLine("{0}: specified file '{1}' not found",
  48. compilerName, ex.FileName);
  49. Environment.Exit(1);
  50. }
  51. catch (IOException ex)
  52. {
  53. Console.Error.WriteLine("{0}: IO error: {1}",
  54. compilerName, ex.Message);
  55. Environment.Exit(2);
  56. }
  57. catch (System.Security.SecurityException ex)
  58. {
  59. Console.Error.WriteLine("{0}: security error: {1}",
  60. compilerName, ex.Message);
  61. Environment.Exit(3);
  62. }
  63. catch (InvalidProgramException ex)
  64. {
  65. Console.Error.WriteLine("{0}: invalid BrainFuck program: {1}",
  66. compilerName, ex.Message);
  67. Environment.Exit(4);
  68. }
  69. }
  70. }
  71. public static void CompileAndSave(string brainFuckProgram, string assemblyName, string saveDirectory)
  72. {
  73. AppDomain appDomain = AppDomain.CurrentDomain;
  74. AssemblyName name = new AssemblyName(assemblyName);
  75. AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(
  76. name, AssemblyBuilderAccess.RunAndSave, saveDirectory);
  77. ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(
  78. "BrainFuckProgram", assemblyName + ".exe");
  79. TypeBuilder typeBuilder = moduleBuilder.DefineType("Program",
  80. TypeAttributes.Class |
  81. TypeAttributes.Public |
  82. TypeAttributes.Sealed);
  83. MethodBuilder brainMethod = typeBuilder.DefineMethod("Execute",
  84. MethodAttributes.Public |
  85. MethodAttributes.Static,
  86. typeof(UInt16),
  87. new Type[]
  88. {
  89. typeof(UInt16[]), typeof(UInt16), // Cells, CellIndex
  90. typeof(TextReader), typeof(TextWriter) // Input, Output
  91. });
  92. ILGenerator brainIL = brainMethod.GetILGenerator();
  93. BrainCompiler.GenerateIL(brainIL, brainFuckProgram);
  94. MethodBuilder mainMethod = typeBuilder.DefineMethod("Main",
  95. MethodAttributes.HideBySig |
  96. MethodAttributes.Public |
  97. MethodAttributes.Static,
  98. typeof(Int32),
  99. new Type[] { typeof(string[]) });
  100. ILGenerator mainIL = mainMethod.GetILGenerator();
  101. mainIL.Emit(OpCodes.Ldc_I4, (int)UInt16.MaxValue + 1);
  102. mainIL.Emit(OpCodes.Newarr, typeof(UInt16));
  103. mainIL.Emit(OpCodes.Ldc_I4_0);
  104. mainIL.Emit(OpCodes.Call, get_In);
  105. mainIL.Emit(OpCodes.Call, get_Out);
  106. mainIL.Emit(OpCodes.Call, brainMethod);
  107. mainIL.Emit(OpCodes.Ret);
  108. typeBuilder.CreateType();
  109. assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
  110. assemblyBuilder.Save(assemblyName + ".exe",
  111. PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
  112. }
  113. }
  114. }