Exemple #1
0
        private Type CompileNode(CompilationContext ctx, IBranch b)
        {
#if FORCE_SINGLE_THREADED
            Application.DoEvents();
#endif
            // vault modifications guard
            if (!ctx.StillInTouch()) throw new CompilerOutOfTouchException();

            // type
            var t_parent = ctx.PrevSuccessfulType(b.VPath) ?? typeof(CompiledNode);
            (t_parent == typeof(CompiledNode) ^ (ctx.CumulativeCompilation && ctx.ScheduledCumulations.ContainsKey(b))).AssertTrue();
            var t = _mod.DefineType(ctx.RequestName(b.GetClassName()), TA.Public, t_parent);

#if TRACE
            try
            {
#endif
                // constructor
                var ctor = t.DefineConstructor(MA.PublicCtor, CallingConventions.Standard, typeof(CompiledNode).MkArray());
                ctor.DefineParameter(1, ParmA.None, "parent");
                ctor.il().ld_args(2).basector(typeof(CompiledNode), typeof(CompiledNode)).ret();

                // the [VPath(...)] attribute for reflection-based analysis
                t.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(VPathAttribute).GetConstructor(typeof(String).MkArray()),
                    b.VPath.ToString().MkArray()));

                // the [Revision(...)] attribute for reflection-based analysis
                t.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(RevisionAttribute).GetConstructor(new[] { typeof(ulong) }),
                    new object[] { Vault.Revision }));

                // the [Seq(...)] attribute for synchronization and namespacing purposes
                t.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(SeqAttribute).GetConstructor(new[] { typeof(int) }),
                    new object[] { ctx.WorkerSeq }));

                // trivial overrides
                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Name"))
                    .il()
                    .ldstr(b.GetClassName() + "_seq" + ctx.WorkerSeq)
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("VPath"))
                    .il()
                    .ldstr(b.VPath)
                    .newobj(typeof(VPath), typeof(String))
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Revision"))
                    .il()
                    .ldc_i8(Vault.Revision)
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Seq"))
                    .il()
                    .ldc_i4(ctx.WorkerSeq)
                    .ret();

                ImplementCreateChildren(ctx, t, b);
                ImplementCreateProperties(ctx, t, b);

                // finalize the type
                var t_created = t.CreateType();
                _types.Add(t_created);

                // create a factory method for this class
                var factoryName = b.GetClassName().Substring(b.GetClassName().LastIndexOf(".") + 1);
                var factoryMethod = ctx.FactoryType.DefineMethod("Create_" + ctx.RequestName(factoryName), MA.PublicStatic, typeof(CompiledNode), typeof(CompiledNode).MkArray());
                factoryMethod.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(VPathAttribute).GetConstructor(typeof(String).MkArray()),
                    b.VPath.ToString().MkArray()));
                factoryMethod.il().ldarg(0).newobj(t_created, typeof(CompiledNode).MkArray()).ret();

                // register self within the factory
                ctx.Factory.il()
                    .ldarg(0)
                    .ldstr(b.VPath.ToString())
                    .newobj(typeof(VPath), typeof(String))
                    .ldnull()
                    .ldftn(factoryMethod)
                    .newobj(typeof(Func<CompiledNode, CompiledNode>), typeof(Object), typeof(IntPtr))
                    .callvirt(typeof(NodeFactory).GetMethod("Register", BF.All));

                return t_created;
#if TRACE
            }
            finally
            {
                // attempts to finalize the type so that we can dump an assembly to disk after certain exceptions
                if (!t.IsCreated())
                {
                    Action<Action> neverFail = code => {try{code();}catch{}};
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Name")).il().ldnull().ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("VPath")).il().ldnull().ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Revision")).il().ldc_i8(0).ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Seq")).il().ldc_i4(0).ret());
                    neverFail(() => t.DefineOverride(typeof(CompiledNode).GetMethod("CreateChildren", BF.All)).il().ret());
                    neverFail(() => t.DefineOverride(typeof(CompiledNode).GetMethod("CreateProperties", BF.All)).il().ret());
                    neverFail(() => ctx.CCs[t].il().ret());
                    neverFail(() => ctx.CPs[t].il().ret());
                    neverFail(() => t.CreateType());
                }
            }
#endif
        }
Exemple #2
0
        private Type CompileScenarioRecursively(CompilationContext ctx)
        {
#if FORCE_SINGLE_THREADED
            Application.DoEvents();
#endif
            // vault modifications guard
            if (!ctx.StillInTouch()) throw new CompilerOutOfTouchException();

            // type
            var t_parent = ctx.PrevSuccessfulType("scenario") ?? typeof(CompiledScenario);
            (t_parent == typeof(CompiledScenario) ^ ctx.CumulativeCompilation).AssertTrue();
            var t = _mod.DefineType(ctx.RequestName(Vault.GetClassName()), TA.Public, t_parent);
#if TRACE
            try
            {
#endif
                // constructors
                var ctorDesignMode = t.DefineConstructor(MA.PublicCtor, CallingConventions.Standard,
                    new[] { typeof(IVault) });
                ctorDesignMode.DefineParameter(1, ParmA.None, "scenario");
                ctorDesignMode.il().ld_args(2).basector(typeof(CompiledScenario), typeof(IVault)).ret();
                var ctorRuntimeMode = t.DefineConstructor(MA.PublicCtor, CallingConventions.Standard,
                    new[] { typeof(IVault), typeof(IVault) });
                ctorRuntimeMode.DefineParameter(1, ParmA.None, "scenario");
                ctorRuntimeMode.DefineParameter(2, ParmA.None, "repository");
                ctorRuntimeMode.il().ld_args(3).basector(typeof(CompiledScenario), typeof(IVault), typeof(IVault)).ret();

                // the [Version(...)] attribute for reflection-based analysis
                t.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(VersionAttribute).GetConstructor(new[] { typeof(String), typeof(ulong) }),
                    new object[] { Vault.Id.ToString(), Vault.Revision }));

                // the [Seq(...)] attribute for synchronization and namespacing purposes
                t.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(SeqAttribute).GetConstructor(new[] { typeof(int) }),
                    new object[] { ctx.WorkerSeq }));

                // trivial overrides
                t.DefineOverrideReadonly(typeof(CompiledScenario).GetProperty("Version"))
                    .il()
                    .ldstr(Vault.Id.ToString())
                    .newobj(typeof(Guid), typeof(String))
                    .ldc_i8(Vault.Revision)
                    .newobj(typeof(Version), typeof(Guid), typeof(ulong))
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Name"))
                    .il()
                    .ldstr(Vault.GetClassName() + "_seq" + ctx.WorkerSeq)
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("VPath"))
                    .il()
                    .call(typeof(VPath).GetProperty("Empty").GetGetMethod())
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Revision"))
                    .il()
                    .ldc_i8(Vault.Revision)
                    .ret();

                t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Seq"))
                    .il()
                    .ldc_i4(ctx.WorkerSeq)
                    .ret();

                // factory initialization
                var parentFactory = ctx.PrevSuccessfulType("factory") ?? typeof(NodeFactory);
                ctx.FactoryType = _mod.DefineType(ctx.RequestName(t.Name + "_factory"), TA.Public, parentFactory);
                ctx.FactoryType.SetCustomAttribute(new CustomAttributeBuilder(
                    typeof(SeqAttribute).GetConstructor(new[] { typeof(int) }),
                    new object[] { ctx.WorkerSeq }));

                // setting up the factory method
                ctx.Factory = ctx.FactoryType.DefineConstructor(MA.PublicCtor, CallingConventions.Standard, new Type[0]);
                ctx.Factory.il().ldarg(0).basector(parentFactory);

                // complex overrides (the main work is here, below the stack)
                if (ctx.CompilingBaseline)
                {
                    // baseline compilation involves creating classes and properties 
                    // for every single node and svd/fla in the scenario
                    ImplementCreateChildren(ctx, t, Vault);
                    ImplementCreateProperties(ctx, t, Vault);
                }
                else
                {
                    var cum = ctx.ScheduledCumulations;
                    MTLog.Say(String.Format("Scheduled cumulations: [{0}]{1}",
                        cum.Count,
                        cum.Count == 0 ? String.Empty : Environment.NewLine +
                            cum.Select(kvp =>
                                String.Format("[{0}] {1}{2}",
                                    kvp.Value.Length,
                                    kvp.Key,
                                    cum.Count == 0 ? String.Empty : Environment.NewLine +
                                        kvp.Value.Select(co =>
                                            String.Format(">>{0}: {1}", co.Reason, co.Subject)
                                        ).StringJoin(Environment.NewLine))
                            ).StringJoin(Environment.NewLine)));

                    // cumulative compilation only should regenerate pieces of code 
                    // that are affected by events mentioned in ctx.NormalizedChangeSet
                    cum.Keys.ForEach(host => CompileNode(ctx, host));
                }

                // factory finalization
                ctx.Factory.il().ret();
                var t_factory_created = ctx.FactoryType.CreateType();
                _types.Add(t_factory_created);
                var createNodeFactory = t.DefineOverride(typeof(CompiledScenario).GetMethod("CreateNodeFactory", BF.All));
                createNodeFactory.il().newobj(t_factory_created).ret();

                // finalize the type
                var t_created = t.CreateType();
                _types.Add(t_created);
                return t_created;
#if TRACE
            }
            finally
            {
                // attempts to finalize the type so that we can dump an assembly to disk even after exceptions
                if (!t.IsCreated())
                {
                    Action<Action> neverFail = code => {try{code();}catch{}};
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledScenario).GetProperty("Version")).il().ldc_i4(0).ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Name")).il().ldnull().ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("VPath")).il().ldnull().ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Revision")).il().ldc_i8(0).ret());
                    neverFail(() => t.DefineOverrideReadonly(typeof(CompiledNode).GetProperty("Seq")).il().ldc_i4(0).ret());
                    neverFail(() => t.DefineOverride(typeof(CompiledNode).GetMethod("CreateChildren", BF.All)).il().ret());
                    neverFail(() => t.DefineOverride(typeof(CompiledNode).GetMethod("CreateProperties", BF.All)).il().ret());
                    neverFail(() => ctx.CCs[t].il().ret());
                    neverFail(() => ctx.CPs[t].il().ret());
                    neverFail(() => t.DefineOverride(typeof(CompiledScenario).GetMethod("CreateNodeFactory", BF.All)).il().ldnull().ret());
                    neverFail(() => t.CreateType());
                }

                if (!ctx.FactoryType.IsCreated())
                {
                    Action<Action> neverFail = code => {try{code();}catch{}};
                    neverFail(() => ctx.Factory.il().ret());
                    neverFail(() => ctx.FactoryType.CreateType());
                }
            }
#endif
        }