Exemplo n.º 1
0
        private static void GenerateCode(ProgramNode root, string outputPath)
        {
            outputPath = Path.GetFullPath(outputPath);

            string name = Path.GetFileNameWithoutExtension(outputPath);

            string filename = Path.GetFileName(outputPath);

            AssemblyName assemblyName = new AssemblyName(name);

            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
                assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(outputPath)
                );

            ModuleBuilder moduleBuilder = assembly.DefineDynamicModule(name, filename);

            TypeBuilder programType = moduleBuilder.DefineType("Program");

            MethodBuilder mainMethod = programType.DefineMethod("Main",
                                                                MethodAttributes.Static, typeof(void), System.Type.EmptyTypes);

            assembly.SetEntryPoint(mainMethod);

            //--------------------------------------------------
            // Obtener El Generador Para 'Main'.
            //--------------------------------------------------
            ILGenerator MainILGenerator = mainMethod.GetILGenerator();

            //--------------------------------------------------
            // Generar El Código Para Las Funciones Estándares.
            //--------------------------------------------------
            StandardFunctions.GenerateCodeForStandardFunctions(
                programType, scope);

            //--------------------------------------------------
            // Generar El Metodo 'run' Para Program.
            //--------------------------------------------------
            MethodBuilder run = programType.DefineMethod(
                "run", MethodAttributes.Static | MethodAttributes.Public
                );

            //--------------------------------------------------
            // Desde Main Hacer Un LLamado A 'run'. Encapsular Con
            // try/catch
            //--------------------------------------------------
            LocalBuilder exc = MainILGenerator.DeclareLocal(typeof(Exception));

            MainILGenerator.BeginExceptionBlock();
            MainILGenerator.Emit(OpCodes.Call, run);
            MainILGenerator.BeginCatchBlock(typeof(Exception));
            MainILGenerator.Emit(OpCodes.Stloc_S, exc);
            MainILGenerator.Emit(OpCodes.Call, typeof(Console).GetProperty("Error").GetMethod);
            MainILGenerator.Emit(OpCodes.Ldstr, "Exception of type ‘{0}’ was thrown.");
            MainILGenerator.Emit(OpCodes.Ldloc_S, exc);
            MainILGenerator.Emit(OpCodes.Callvirt, typeof(Exception).GetMethod("GetType"));
            MainILGenerator.Emit(OpCodes.Callvirt, typeof(MemberInfo).GetProperty("Name").GetMethod);
            MainILGenerator.Emit(OpCodes.Call, typeof(String).GetMethod("Format", new Type[] { typeof(string), typeof(string) }));
            MainILGenerator.Emit(OpCodes.Callvirt, typeof(TextWriter).GetMethod("WriteLine", new Type[] { typeof(string) }));
            MainILGenerator.Emit(OpCodes.Ldc_I4, 1);
            MainILGenerator.Emit(OpCodes.Call, typeof(Environment).GetMethod("Exit"));
            MainILGenerator.EndExceptionBlock();

            MainILGenerator.Emit(OpCodes.Ret);

            //--------------------------------------------------
            // Comenzar La Generación De Código.
            //--------------------------------------------------
            root.GenerateCode(moduleBuilder, programType, run.GetILGenerator());

            //--------------------------------------------------
            // Crear 'Program'.
            //--------------------------------------------------
            programType.CreateType();

            moduleBuilder.CreateGlobalFunctions();

            assembly.Save(filename);

            //----------------------------------------------------------------------
            // Open ildasm
            //----------------------------------------------------------------------
            //string ildasm = @"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\ildasm.exe";
            //(new Process()
            //{
            //    StartInfo = { FileName = ildasm, Arguments = @"..\..\program.exe" }
            //}).Start();
        }