Exemplo n.º 1
0
        public string Create(OpValue[] prog)
        {
            string ePath = Path.GetTempFileName();
            ProcessStartInfo info = new ProcessStartInfo("gcc", "-O2 -x c -o " + ePath + " -")
            {
                RedirectStandardInput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (var process = Process.Start(info))
            {
                process.StandardInput.WriteLine(Pre);

                foreach (OpValue op in prog)
                {
                    this.Append(process.StandardInput, op);
                }

                process.StandardInput.WriteLine(Post);

                process.StandardInput.Flush();
                process.StandardInput.Close();

                process.WaitForExit();
            }

            return ePath;
        }
Exemplo n.º 2
0
        private static void RunCompiled(OpValue[] prog)
        {
            Stopwatch sw = Stopwatch.StartNew();
            string exe = new NativeCreator().Create(prog);
            long compileTimeTicks = sw.ElapsedTicks;

            using (var process = Process.Start(exe))
            {
                process.WaitForExit();
                sw.Stop();
            }

            Console.WriteLine("Compiled to " + exe);

            double freq = (double)Stopwatch.Frequency;
            Console.WriteLine("Time to compile and run: {0:N5} seconds", sw.ElapsedTicks / freq);
            Console.WriteLine("Time to compile:         {0:N5} seconds", compileTimeTicks / freq);
            Console.WriteLine("Time to run:             {0:N5} seconds", (sw.ElapsedTicks - compileTimeTicks) / freq);
        }
Exemplo n.º 3
0
        private void Append(StreamWriter sw, OpValue op)
        {
            switch (op.OpCode)
            {
                case OpCode.ShiftRight:
                    sw.WriteLine("ptr += " + op.Data + ";");
                    break;

                case OpCode.ShiftLeft:
                    sw.WriteLine("ptr -= " + op.Data + ";");
                    break;

                case OpCode.Increment:
                    sw.WriteLine("*ptr += " + op.Data + ";");
                    break;

                case OpCode.Decrement:
                    sw.WriteLine("*ptr -= " + op.Data + ";");
                    break;

                case OpCode.CondLeft:
                    sw.WriteLine("while (*ptr) {");
                    break;

                case OpCode.CondRight:
                    sw.WriteLine("}");
                    break;

                case OpCode.Output:
                    sw.WriteLine("putchar(*ptr);");
                    break;

                case OpCode.Input:
                    sw.WriteLine("*ptr = getchar();");
                    break;

                case OpCode.Assign:
                    sw.WriteLine("*ptr = " + op.Data + ";");
                    break;
            }
        }
        private static void Emit(ILProcessor ip, ModuleDefinition mod, VariableDefinition arrayVar, VariableDefinition indexVar, Dictionary<int, Instruction> braces, OpValue[] ops, int i)
        {
            OpValue op = ops[i];
            switch (op.OpCode)
            {
                case BFOpCode.Increment:
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldelem_I4);
                    ip.Emit(OpCodes.Ldc_I4, op.Data);
                    ip.Emit(OpCodes.Add);
                    ip.Emit(OpCodes.Stelem_I4);
                    break;

                case BFOpCode.Decrement:
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldelem_I4);
                    ip.Emit(OpCodes.Ldc_I4, op.Data);
                    ip.Emit(OpCodes.Sub);
                    ip.Emit(OpCodes.Stelem_I4);
                    break;

                case BFOpCode.ShiftRight:
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldc_I4, op.Data);
                    ip.Emit(OpCodes.Add);
                    ip.Emit(OpCodes.Stloc, indexVar);
                    break;

                case BFOpCode.ShiftLeft:
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldc_I4, op.Data);
                    ip.Emit(OpCodes.Sub);
                    ip.Emit(OpCodes.Stloc, indexVar);
                    break;

                case BFOpCode.Output:
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldelem_I4);
                    ip.Emit(OpCodes.Conv_I1);
                    ip.Emit(OpCodes.Call, mod.Import(typeof(Console).GetMethod("Write", new[] { typeof(char) })));
                    break;

                case BFOpCode.Input:
                    ip.Emit(OpCodes.Call, mod.Import(typeof(Console).GetMethod("Read", new Type[0])));
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldelem_I4);
                    ip.Emit(OpCodes.Conv_I1);
                    break;

                case BFOpCode.CondLeft:
                    var leftB = ip.Create(OpCodes.Ldloc, arrayVar);
                    var rightB = ip.Create(OpCodes.Nop);
                    ip.Append(leftB);
                    braces[i] = leftB;
                    braces[op.Data] = rightB;
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldelem_I4);
                    ip.Emit(OpCodes.Brfalse, rightB);
                    ip.Emit(OpCodes.Nop);
                    break;

                case BFOpCode.CondRight:
                    ip.Emit(OpCodes.Br, braces[op.Data]);
                    ip.Append(braces[i]);
                    break;

                case BFOpCode.Assign:
                    ip.Emit(OpCodes.Ldloc, arrayVar);
                    ip.Emit(OpCodes.Ldloc, indexVar);
                    ip.Emit(OpCodes.Ldc_I4, op.Data);
                    ip.Emit(OpCodes.Stelem_I4);
                    break;
            }
        }
        public MethodInfo Create(OpValue[] prog)
        {
            const string OutNamespace = "BF";
            const string OutTypeName = "CompiledProgram";
            const string OutMethodName = "Main";

            var name = new AssemblyNameDefinition(OutNamespace, new Version(1, 0, 0, 0));
            var asm = AssemblyDefinition.CreateAssembly(name, OutNamespace + ".dll", ModuleKind.Dll);

            asm.MainModule.Import(typeof(int));
            var voidret = asm.MainModule.Import(typeof(void));

            var method = new MethodDefinition(OutMethodName,
                                              MethodAttributes.Static | MethodAttributes.Public,
                                              voidret);

            var arrayVar = new VariableDefinition("array", asm.MainModule.Import(typeof(int[])));
            var indexVar = new VariableDefinition("idx", asm.MainModule.Import(typeof(int)));

            method.Body.Variables.Add(arrayVar);
            method.Body.Variables.Add(indexVar);

            var ip = method.Body.GetILProcessor();

            ip.Emit(OpCodes.Ldc_I4_0);
            ip.Emit(OpCodes.Stloc, indexVar);

            ip.Emit(OpCodes.Ldc_I4, 300000);
            ip.Emit(OpCodes.Newarr, asm.MainModule.Import(typeof(int)));

            ip.Emit(OpCodes.Stloc, arrayVar);

            Dictionary<int, Instruction> braces = new Dictionary<int, Instruction>();

            for (int i = 0; i < prog.Length; i++)
            {
                Emit(ip, asm.MainModule, arrayVar, indexVar, braces, prog, i);
            }

            ip.Emit(OpCodes.Ret);

            var type = new TypeDefinition(OutNamespace,
                                          OutTypeName,
                                          TypeAttributes.AutoClass | TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit,
                                          asm.MainModule.Import(typeof(object)));

            asm.MainModule.Types.Add(type);
            type.Methods.Add(method);

            asm.EntryPoint = method;

            byte[] rawAsm;
            using (var ms = new MemoryStream())
            {
                asm.Write(ms);
                rawAsm = ms.ToArray();
            }

            var reflected = Assembly.Load(rawAsm);
            return reflected.GetType(OutNamespace + "." + OutTypeName)
                            .GetMethod(OutMethodName);
        }
Exemplo n.º 6
0
 /// <summary>
 /// Fails when called.
 /// </summary>
 /// <param name="opData">Stack object (won't be used)</param>
 /// <param name="error">Error message (contains name of the operation that caused the failure)</param>
 /// <returns>False (always failing)</returns>
 public sealed override bool Run(IOpData opData, out string error)
 {
     error = $"Can not run an OP_{OpValue.ToString()} operation.";
     return(false);
 }
Exemplo n.º 7
0
        private static void RunInterpreter(OpValue[] prog)
        {
            Stopwatch sw = Stopwatch.StartNew();
            int[] b = new int[30000];
            int next = 0;
            int idx = 0;
            while (next < prog.Length)
            {
                OpValue op = prog[next];
                switch (op.OpCode)
                {
                    case OpCode.ShiftRight:
                        idx += op.Data;
                        next++;
                        break;

                    case OpCode.ShiftLeft:
                        idx -= op.Data;
                        next++;
                        break;

                    case OpCode.Increment:
                        b[idx] += op.Data;
                        next++;
                        break;

                    case OpCode.Decrement:
                        b[idx] -= op.Data;
                        next++;
                        break;

                    case OpCode.Output:
                        char oCh = (char)b[idx];
                        Console.Write(oCh);

                        next++;
                        break;

                    case OpCode.Input:
                        b[idx] = (char)Console.Read();
                        next++;
                        break;

                    case OpCode.CondLeft:
                        if (b[idx] == 0)
                        {
                            next = op.Data;
                        }

                        next++;
                        break;

                    case OpCode.CondRight:
                        next = op.Data;
                        break;

                    case OpCode.Assign:
                        b[idx] = op.Data;
                        next++;
                        break;

                    default:
                        next++;
                        break;
                }
            }

            sw.Stop();
            Console.WriteLine("Time to interpret: {0:N5} seconds", sw.ElapsedTicks / (double)Stopwatch.Frequency);
        }
Exemplo n.º 8
0
        private static void RunJIT(OpValue[] prog)
        {
            Stopwatch sw = Stopwatch.StartNew();
            System.Reflection.MethodInfo compiled = new AssemblyCreator().Create(prog);

            long compileTimeTicks = sw.ElapsedTicks;

            compiled.Invoke(null, null);
            sw.Stop();

            double freq = (double)Stopwatch.Frequency;
            Console.WriteLine("Time to JIT and run: {0:N5} seconds", sw.ElapsedTicks / freq);
            Console.WriteLine("Time to JIT:         {0:N5} seconds", compileTimeTicks / freq);
            Console.WriteLine("Time to run:         {0:N5} seconds", (sw.ElapsedTicks - compileTimeTicks) / freq);
        }