Created
May 4, 2013 09:07
-
-
Save vtols/5516901 to your computer and use it in GitHub Desktop.
BrainFuck compiler for .NET
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.IO; | |
| using System.Text; | |
| using System.Reflection; | |
| using System.Reflection.Emit; | |
| namespace Translator | |
| { | |
| class Translator | |
| { | |
| public static AssemblyBuilder asb; | |
| public static ModuleBuilder mb; | |
| public static MethodBuilder tb; | |
| public static ILGenerator il; | |
| public static LocalBuilder[] lcb; | |
| public static FileStream fs = new FileStream("Hello.il", FileMode.Create, FileAccess.Write); | |
| public static StreamWriter sw = new StreamWriter(fs); | |
| public static int bropened = 0; | |
| public static int brclosed = 1; | |
| public static int memoryBlockSize = 30000; | |
| public static List<Label> jumps = new List<Label>(); | |
| public static bool error = false; | |
| public static Stack<int> brstack = new Stack<int>(); | |
| public static void Main(string[] args) | |
| { | |
| Console.WriteLine("brainfuck programming language compiler by Valery Tolstov ©2009\n"); | |
| StreamReader sr = new StreamReader("Hello.brfuck"); | |
| string source = sr.ReadToEnd(); | |
| EmitInit(); | |
| EmitText(source); | |
| EmitEnd(); | |
| sw.Close(); | |
| if ((brstack.Count == 0) && (!error)) | |
| { | |
| Console.WriteLine("Program successfully translated to CIL code."); | |
| try | |
| { | |
| mb.CreateGlobalFunctions(); | |
| asb.SetEntryPoint(tb); | |
| asb.Save("Hello.exe"); | |
| } | |
| catch (Exception) | |
| { | |
| Console.WriteLine("\nError writing executable file."); | |
| Console.WriteLine("\n***FAILED***"); | |
| } | |
| } | |
| else | |
| { | |
| int[] brarray = brstack.ToArray(); | |
| for (int i = 0; i < brarray.Length; i++) | |
| { | |
| Console.WriteLine("Source program have single opening bracket №" + (brarray[i] + 1).ToString()); | |
| } | |
| Console.WriteLine("\n***FAILED***"); | |
| } | |
| Console.Read(); | |
| } | |
| public static void EmitText(string text) | |
| { | |
| for (int i = 0; i < text.Length; i++) | |
| { | |
| int c = 0; | |
| switch (text[i]) | |
| { | |
| case '>': | |
| for (; ; ) { ++c; if ((text[i + 1] == '>') && (i < text.Length)) { ++i; } else break; } | |
| EmitNext(c); break; | |
| case '<': | |
| for (; ; ) { ++c; if ((text[i + 1] == '<') && (i < text.Length)) { ++i; } else break; } | |
| EmitPrev(c); break; | |
| case '+': | |
| for (; ; ) { ++c; if ((text[i + 1] == '+') && (i < text.Length)) { ++i; } else break; } | |
| EmitPlus(c); break; | |
| case '-': | |
| for (; ; ) { ++c; if ((text[i + 1] == '-') && (i < text.Length)) { ++i; } else break; } | |
| EmitMinus(c); break; | |
| case '[': EmitLBracket(); break; | |
| case ']': EmitRBracket(); break; | |
| case '.': EmitDot(); break; | |
| //case ',': ; | |
| } | |
| } | |
| } | |
| public static void EmitNext(int count) | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldc.i4.s " + count.ToString()); | |
| sb.AppendLine("add"); | |
| sb.AppendLine("stloc.1"); | |
| sw.WriteLine(sb.ToString()); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldc_I4_S, count); | |
| il.Emit(OpCodes.Add); | |
| il.Emit(OpCodes.Stloc_1); | |
| } | |
| public static void EmitPrev(int count) | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldc.i4.s " + count.ToString()); | |
| sb.AppendLine("sub"); | |
| sb.AppendLine("stloc.1"); | |
| sw.WriteLine(sb.ToString()); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldc_I4_S, count); | |
| il.Emit(OpCodes.Sub); | |
| il.Emit(OpCodes.Stloc_1); | |
| } | |
| public static void EmitPlus(int count) | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldelem.i4"); | |
| sb.AppendLine("ldc.i4.s " + count.ToString()); | |
| sb.AppendLine("add"); | |
| sb.AppendLine("stelem.i4"); | |
| sw.WriteLine(sb.ToString()); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldelem_I4); | |
| il.Emit(OpCodes.Ldc_I4_S, count); | |
| il.Emit(OpCodes.Add); | |
| il.Emit(OpCodes.Stelem_I4); | |
| } | |
| public static void EmitDot() | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.3"); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldelem.i4"); | |
| sb.AppendLine("conv.u2"); | |
| sb.AppendLine("callvirt instance void [mscorlib]System.IO.TextWriter::Write(char)"); | |
| sw.WriteLine(sb.ToString()); | |
| il.Emit(OpCodes.Ldloc_3); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldelem_I4); | |
| il.Emit(OpCodes.Conv_U2); | |
| il.Emit(OpCodes.Callvirt, typeof(TextWriter).GetMethod("Write", new Type[]{typeof(char)})); | |
| } | |
| public static void EmitLBracket() | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldelem.i4"); | |
| sb.AppendLine("brfalse outEndLabel" + bropened.ToString()); | |
| sb.AppendLine("inStartLabel" + bropened.ToString() + ":"); | |
| sw.WriteLine(sb.ToString()); | |
| jumps.Add(il.DefineLabel()); jumps.Add(il.DefineLabel()); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldelem_I4); | |
| il.Emit(OpCodes.Brfalse, jumps[bropened * 2 + 1]); | |
| il.MarkLabel(jumps[bropened * 2]); | |
| brstack.Push(bropened); | |
| ++bropened; | |
| } | |
| public static void EmitRBracket() | |
| { | |
| if (brstack.Count > 0) | |
| { | |
| int br = brstack.Pop(); | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldelem.i4"); | |
| sb.AppendLine("brtrue inStartLabel" + br.ToString()); | |
| sb.AppendLine("outEndLabel" + br.ToString() + ":"); | |
| sw.WriteLine(sb.ToString()); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldelem_I4); | |
| il.Emit(OpCodes.Brtrue, jumps[br * 2]); | |
| il.MarkLabel(jumps[br * 2 + 1]); | |
| } | |
| else | |
| { | |
| error = true; | |
| Console.WriteLine("Source program have single closing bracket №" + (brclosed).ToString()); | |
| } | |
| ++brclosed; | |
| } | |
| public static void EmitMinus(int count) | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldloc.0"); | |
| sb.AppendLine("ldloc.1"); | |
| sb.AppendLine("ldelem.i4"); | |
| sb.AppendLine("ldc.i4.s " + count.ToString()); | |
| sb.AppendLine("sub"); | |
| sb.AppendLine("stelem.i4"); | |
| sw.WriteLine(sb.ToString()); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldloc_0); | |
| il.Emit(OpCodes.Ldloc_1); | |
| il.Emit(OpCodes.Ldelem_I4); | |
| il.Emit(OpCodes.Ldc_I4_S, count); | |
| il.Emit(OpCodes.Sub); | |
| il.Emit(OpCodes.Stelem_I4); | |
| } | |
| public static void EmitInit() | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| Random rnd = new Random(); | |
| string iD = rnd.Next(0, 9).ToString() + rnd.Next(0, 9).ToString() | |
| + rnd.Next(0, 9).ToString() + rnd.Next(0, 9).ToString() | |
| + rnd.Next(0, 9).ToString() + rnd.Next(0, 9).ToString(); | |
| sb.AppendLine(".assembly extern mscorlib{}"); | |
| sb.AppendLine(".assembly brfck" + iD + "{}"); | |
| sb.AppendLine(".method public static void main() cil managed"); | |
| sb.AppendLine("{"); | |
| sb.AppendLine("InitBlock:"); | |
| sb.AppendLine(".locals init ([0] int32[] val, [1] int32 index, [2] class [mscorlib]System.IO.TextReader input,[3] class [mscorlib]System.IO.TextWriter output)"); | |
| sb.AppendLine(".entrypoint"); | |
| sb.AppendLine("ldc.i4 0x" + String.Format("{0:X}", memoryBlockSize)); | |
| sb.AppendLine("newarr [mscorlib]System.Int32"); | |
| sb.AppendLine("stloc.0"); | |
| sb.AppendLine("ldc.i4.0"); | |
| sb.AppendLine("stloc.1"); | |
| sb.AppendLine("call class [mscorlib]System.IO.TextReader [mscorlib]System.Console::get_In()"); | |
| sb.AppendLine("stloc.2"); | |
| sb.AppendLine("call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out()"); | |
| sb.AppendLine("stloc.3"); | |
| sb.AppendLine(""); | |
| sb.AppendLine("ProgramBlock:"); | |
| sw.Write(sb.ToString()); | |
| AssemblyName asn = new AssemblyName("brfck" + iD); | |
| asb = AppDomain.CurrentDomain.DefineDynamicAssembly(asn, AssemblyBuilderAccess.Save); | |
| mb = asb.DefineDynamicModule("Hello.exe"); | |
| tb = mb.DefineGlobalMethod("main", | |
| MethodAttributes.Public | MethodAttributes.Static, | |
| typeof(void), new Type[]{}); | |
| il = tb.GetILGenerator(); | |
| lcb = new LocalBuilder[] | |
| {il.DeclareLocal(typeof(int[])), | |
| il.DeclareLocal(typeof(int)), | |
| il.DeclareLocal(typeof(System.IO.TextReader)), | |
| il.DeclareLocal(typeof(System.IO.TextWriter))}; | |
| il.Emit(OpCodes.Ldc_I4, memoryBlockSize); | |
| il.Emit(OpCodes.Newarr, typeof(int)); | |
| il.Emit(OpCodes.Stloc_0); | |
| il.Emit(OpCodes.Ldc_I4_0); | |
| il.Emit(OpCodes.Stloc_1); | |
| il.Emit(OpCodes.Call, typeof(Console).GetMethod("get_In", new Type[] { })); | |
| il.Emit(OpCodes.Stloc_2); | |
| il.Emit(OpCodes.Call, typeof(Console).GetMethod("get_Out", new Type[] { })); | |
| il.Emit(OpCodes.Stloc_3); | |
| } | |
| public static void EmitEnd() | |
| { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.AppendLine("EndBlock:"); | |
| sb.AppendLine("call int32 [mscorlib]System.Console::Read()"); | |
| sb.AppendLine("pop"); | |
| sb.AppendLine("ret"); | |
| sb.AppendLine("}"); | |
| sw.Write(sb.ToString()); | |
| il.Emit(OpCodes.Call, typeof(Console).GetMethod("Read", new Type[]{})); | |
| il.Emit(OpCodes.Pop); | |
| il.Emit(OpCodes.Ret); | |
| } | |
| public static void T() | |
| { | |
| TextWriter ou = Console.Out; | |
| int[] a = new int[30000]; | |
| int b = 0; | |
| ou.Write((char)a[b]); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment