コード例 #1
0
        void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any
            //objx arg is enclosing objx, not this


            // Create the function instance
            LocalBuilder fnLocal = ilg.DeclareLocal(CompiledType);

            if (CompiledType == typeof(RestFnImpl))
            {
                ilg.EmitInt(_variadicMethod.RequiredArity);
                ilg.EmitNew(Compiler.Ctor_RestFnImpl_1);
            }
            else
            {
                ilg.EmitNew(Compiler.Ctor_AFnImpl);
            }

            ilg.Emit(OpCodes.Stloc, fnLocal);

            //ilg.EmitString(String.Format("Creating fn {0}", Name));
            //ilg.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

            // Set up the methods

            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                int      key    = GetMethodKey(method);

                string fieldName = IsVariadic && method.IsVariadic
                    ? "_fnDo" + (key - 1)  // because key is arity+1 for variadic
                    : "_fn" + key;

                FieldInfo fi = CompiledType.GetField(fieldName);

                ilg.Emit(OpCodes.Ldloc, fnLocal);


                EmitGetDynMethod(key, ilg);
                ilg.EmitType(fi.FieldType);
                ilg.Emit(OpCodes.Ldloc, fnLocal);
                ilg.Emit(OpCodes.Callvirt, Method_DynamicMethod_CreateDelegate);
                ilg.Emit(OpCodes.Castclass, fi.FieldType);

                ilg.EmitFieldSet(fi);
            }



            // setup the constants and locals
            ilg.Emit(OpCodes.Ldloc, fnLocal);

            if (Constants.count() > 0)
            {
                EmitGetCompiledConstants(ilg);
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            if (Closes.count() > 0)
            {
                int maxIndex = Closes.Max(c => ((LocalBinding)c.key()).Index);

                ilg.EmitInt(maxIndex + 1);
                ilg.Emit(OpCodes.Newarr, typeof(object));

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    ilg.Emit(OpCodes.Dup);
                    ilg.EmitInt(lb.Index);
                    objx.EmitLocal(ilg, lb);
                    ilg.EmitStoreElement(typeof(object));
                }
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            // Create the closure
            ilg.EmitNew(Compiler.Ctor_Closure_2);

            // Assign the clojure
            ilg.EmitCall(Compiler.Method_IFnClosure_SetClosure);

            // Leave the instance on the stack.
            ilg.Emit(OpCodes.Ldloc, fnLocal);
        }
コード例 #2
0
        /// <summary>
        /// Constructor. Compiles a rules assembly from the given source files.
        /// </summary>
        /// <param name="Scope">The scope of items created by this assembly</param>
        /// <param name="BaseDirs">The base directories for this assembly</param>
        /// <param name="Plugins">All the plugins included in this assembly</param>
        /// <param name="ModuleFileToContext">List of module files to compile</param>
        /// <param name="TargetFiles">List of target files to compile</param>
        /// <param name="AssemblyFileName">The output path for the compiled assembly</param>
        /// <param name="bContainsEngineModules">Whether this assembly contains engine modules. Used to initialize the default value for ModuleRules.bTreatAsEngineModule.</param>
        /// <param name="DefaultBuildSettings">Optional override for the default build settings version for modules created from this assembly.</param>
        /// <param name="bReadOnly">Whether the modules and targets in this assembly are installed, and should be created with the bUsePrecompiled flag set</param>
        /// <param name="bSkipCompile">Whether to skip compiling this assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        internal RulesAssembly(RulesScope Scope, List <DirectoryReference> BaseDirs, IReadOnlyList <PluginInfo> Plugins, Dictionary <FileReference, ModuleRulesContext> ModuleFileToContext, List <FileReference> TargetFiles, FileReference AssemblyFileName, bool bContainsEngineModules, BuildSettingsVersion?DefaultBuildSettings, bool bReadOnly, bool bSkipCompile, RulesAssembly Parent)
        {
            this.Scope                  = Scope;
            this.BaseDirs               = BaseDirs;
            this.Plugins                = Plugins;
            this.ModuleFileToContext    = ModuleFileToContext;
            this.bContainsEngineModules = bContainsEngineModules;
            this.DefaultBuildSettings   = DefaultBuildSettings;
            this.bReadOnly              = bReadOnly;
            this.Parent                 = Parent;

            // Find all the source files
            HashSet <FileReference> AssemblySourceFiles = new HashSet <FileReference>();

            AssemblySourceFiles.UnionWith(ModuleFileToContext.Keys);
            AssemblySourceFiles.UnionWith(TargetFiles);

            // Compile the assembly
            if (AssemblySourceFiles.Count > 0)
            {
                List <string> PreprocessorDefines = GetPreprocessorDefinitions();
                CompiledAssembly = DynamicCompilation.CompileAndLoadAssembly(AssemblyFileName, AssemblySourceFiles, PreprocessorDefines: PreprocessorDefines, DoNotCompile: bSkipCompile);
            }

            // Setup the module map
            foreach (FileReference ModuleFile in ModuleFileToContext.Keys)
            {
                string ModuleName = ModuleFile.GetFileNameWithoutAnyExtensions();
                if (!ModuleNameToModuleFile.ContainsKey(ModuleName))
                {
                    ModuleNameToModuleFile.Add(ModuleName, ModuleFile);
                }
            }

            // Setup the target map
            foreach (FileReference TargetFile in TargetFiles)
            {
                string TargetName = TargetFile.GetFileNameWithoutAnyExtensions();
                if (!TargetNameToTargetFile.ContainsKey(TargetName))
                {
                    TargetNameToTargetFile.Add(TargetName, TargetFile);
                }
            }

            // Write any deprecation warnings for methods overriden from a base with the [ObsoleteOverride] attribute. Unlike the [Obsolete] attribute, this ensures the message
            // is given because the method is implemented, not because it's called.
            if (CompiledAssembly != null)
            {
                foreach (Type CompiledType in CompiledAssembly.GetTypes())
                {
                    foreach (MethodInfo Method in CompiledType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                    {
                        ObsoleteOverrideAttribute Attribute = Method.GetCustomAttribute <ObsoleteOverrideAttribute>(true);
                        if (Attribute != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: {1}", Location, Attribute.Message);
                        }
                    }
                    if (CompiledType.BaseType == typeof(ModuleRules))
                    {
                        ConstructorInfo Constructor = CompiledType.GetConstructor(new Type[] { typeof(TargetInfo) });
                        if (Constructor != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: Module constructors should take a ReadOnlyTargetRules argument (rather than a TargetInfo argument) and pass it to the base class constructor from 4.15 onwards. Please update the method signature.", Location);
                        }
                    }
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Constructor. Compiles a rules assembly from the given source files.
        /// </summary>
        /// <param name="Plugins">All the plugins included in this assembly</param>
        /// <param name="ModuleFiles">List of module files to compile</param>
        /// <param name="TargetFiles">List of target files to compile</param>
        /// <param name="ModuleFileToPluginInfo">Mapping of module file to the plugin that contains it</param>
        /// <param name="AssemblyFileName">The output path for the compiled assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        public RulesAssembly(IReadOnlyList <PluginInfo> Plugins, List <FileReference> ModuleFiles, List <FileReference> TargetFiles, Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo, FileReference AssemblyFileName, RulesAssembly Parent)
        {
            this.Plugins = Plugins;
            this.ModuleFileToPluginInfo = ModuleFileToPluginInfo;
            this.Parent = Parent;

            // Find all the source files
            List <FileReference> AssemblySourceFiles = new List <FileReference>();

            AssemblySourceFiles.AddRange(ModuleFiles);
            AssemblySourceFiles.AddRange(TargetFiles);

            // Compile the assembly
            if (AssemblySourceFiles.Count > 0)
            {
                List <string> PreprocessorDefines = new List <string>();
                PreprocessorDefines.Add("WITH_FORWARDED_MODULE_RULES_CTOR");
                PreprocessorDefines.Add("WITH_FORWARDED_TARGET_RULES_CTOR");

                // Define macros for the UE4 version, starting with 4.17
                BuildVersion Version;
                if (BuildVersion.TryRead(out Version))
                {
                    for (int MinorVersion = 17; MinorVersion <= Version.MinorVersion; MinorVersion++)
                    {
                        PreprocessorDefines.Add(String.Format("UE_4_{0}_OR_LATER", MinorVersion));
                    }
                }

                CompiledAssembly = DynamicCompilation.CompileAndLoadAssembly(AssemblyFileName, AssemblySourceFiles, PreprocessorDefines: PreprocessorDefines);
            }

            // Setup the module map
            foreach (FileReference ModuleFile in ModuleFiles)
            {
                string ModuleName = ModuleFile.GetFileNameWithoutAnyExtensions();
                if (!ModuleNameToModuleFile.ContainsKey(ModuleName))
                {
                    ModuleNameToModuleFile.Add(ModuleName, ModuleFile);
                }
            }

            // Setup the target map
            foreach (FileReference TargetFile in TargetFiles)
            {
                string TargetName = TargetFile.GetFileNameWithoutAnyExtensions();
                if (!TargetNameToTargetFile.ContainsKey(TargetName))
                {
                    TargetNameToTargetFile.Add(TargetName, TargetFile);
                }
            }

            // Write any deprecation warnings for methods overriden from a base with the [ObsoleteOverride] attribute. Unlike the [Obsolete] attribute, this ensures the message
            // is given because the method is implemented, not because it's called.
            if (CompiledAssembly != null)
            {
                foreach (Type CompiledType in CompiledAssembly.GetTypes())
                {
                    foreach (MethodInfo Method in CompiledType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                    {
                        ObsoleteOverrideAttribute Attribute = Method.GetCustomAttribute <ObsoleteOverrideAttribute>(true);
                        if (Attribute != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: {1}", Location, Attribute.Message);
                        }
                    }
                    if (CompiledType.BaseType == typeof(ModuleRules))
                    {
                        ConstructorInfo Constructor = CompiledType.GetConstructor(new Type[] { typeof(TargetInfo) });
                        if (Constructor != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: Module constructors should take a ReadOnlyTargetRules argument (rather than a TargetInfo argument) and pass it to the base class constructor from 4.15 onwards. Please update the method signature.", Location);
                        }
                    }
                }
            }
        }