예제 #1
0
        // Return the assembly locations that need to be verified
        private string[] SaveAssemblies()
        {
            if (!SaveSnippets)
            {
                return(new string[0]);
            }

            List <string> assemlyLocations = new List <string>();

            // first save all assemblies to disk:
            if (_assembly != null)
            {
                string assemblyLocation = _assembly.SaveAssembly();
                if (assemblyLocation != null)
                {
                    assemlyLocations.Add(assemblyLocation);
                }
                _assembly = null;
            }

            if (_debugAssembly != null)
            {
                string debugAssemblyLocation = _debugAssembly.SaveAssembly();
                if (debugAssemblyLocation != null)
                {
                    assemlyLocations.Add(debugAssemblyLocation);
                }
                _debugAssembly = null;
            }

            return(assemlyLocations.ToArray());
        }
예제 #2
0
        /// <summary>
        /// This takes an assembly name including extension and saves the provided ScriptCode objects into the assembly.  
        /// 
        /// The provided script codes can constitute code from multiple languages.  The assemblyName can be either a fully qualified 
        /// or a relative path.  The DLR will simply save the assembly to the desired location.  The assembly is created by the DLR and 
        /// if a file already exists than an exception is raised.  
        /// 
        /// The DLR determines the internal format of the ScriptCode and the DLR can feel free to rev this as appropriate.  
        /// </summary>
        public static void SaveToAssembly(string assemblyName, params SavableScriptCode[] codes) {
            ContractUtils.RequiresNotNull(assemblyName, "assemblyName");
            ContractUtils.RequiresNotNullItems(codes, "codes");

            // break the assemblyName into it's dir/name/extension
            string dir = Path.GetDirectoryName(assemblyName);
            if (String.IsNullOrEmpty(dir)) {
                dir = Environment.CurrentDirectory;
            }

            string name = Path.GetFileNameWithoutExtension(assemblyName);
            string ext = Path.GetExtension(assemblyName);

            // build the assembly & type gen that all the script codes will live in...
            AssemblyGen ag = new AssemblyGen(new AssemblyName(name), dir, ext, /*emitSymbols*/false);
            TypeBuilder tb = ag.DefinePublicType("DLRCachedCode", typeof(object), true);
            TypeGen tg = new TypeGen(ag, tb);
            var symbolDict = new Dictionary<SymbolId, FieldBuilder>();
            // then compile all of the code

            Dictionary<Type, List<CodeInfo>> langCtxBuilders = new Dictionary<Type, List<CodeInfo>>();
            foreach (SavableScriptCode sc in codes) {
                List<CodeInfo> builders;
                if (!langCtxBuilders.TryGetValue(sc.LanguageContext.GetType(), out builders)) {
                    langCtxBuilders[sc.LanguageContext.GetType()] = builders = new List<CodeInfo>();
                }

                KeyValuePair<MethodBuilder, Type> compInfo = sc.CompileForSave(tg, symbolDict);

                builders.Add(new CodeInfo(compInfo.Key, sc, compInfo.Value));
            }

            MethodBuilder mb = tb.DefineMethod(
                "GetScriptCodeInfo",
                MethodAttributes.SpecialName | MethodAttributes.Public | MethodAttributes.Static,
                typeof(MutableTuple<Type[], Delegate[][], string[][], string[][]>),
                Type.EmptyTypes);

            ILGen ilgen = new ILGen(mb.GetILGenerator());

            var langsWithBuilders = langCtxBuilders.ToArray();

            // lang ctx array
            ilgen.EmitArray(typeof(Type), langsWithBuilders.Length, (index) => {
                ilgen.Emit(OpCodes.Ldtoken, langsWithBuilders[index].Key);
                ilgen.EmitCall(typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) }));
            });

            // builders array of array
            ilgen.EmitArray(typeof(Delegate[]), langsWithBuilders.Length, (index) => {
                List<CodeInfo> builders = langsWithBuilders[index].Value;

                ilgen.EmitArray(typeof(Delegate), builders.Count, (innerIndex) => {
                    ilgen.EmitNull();
                    ilgen.Emit(OpCodes.Ldftn, builders[innerIndex].Builder);
                    ilgen.EmitNew(
                        builders[innerIndex].DelegateType,
                        new[] { typeof(object), typeof(IntPtr) }
                    );
                });
            });

            // paths array of array
            ilgen.EmitArray(typeof(string[]), langsWithBuilders.Length, (index) => {
                List<CodeInfo> builders = langsWithBuilders[index].Value;

                ilgen.EmitArray(typeof(string), builders.Count, (innerIndex) => {
                    ilgen.EmitString(builders[innerIndex].Code.SourceUnit.Path);
                });
            });

            // 4th element in tuple - custom per-language data
            ilgen.EmitArray(typeof(string[]), langsWithBuilders.Length, (index) => {
                List<CodeInfo> builders = langsWithBuilders[index].Value;

                ilgen.EmitArray(typeof(string), builders.Count, (innerIndex) => {
                    ICustomScriptCodeData data = builders[innerIndex].Code as ICustomScriptCodeData;
                    if (data != null) {
                        ilgen.EmitString(data.GetCustomScriptCodeData());
                    } else {
                        ilgen.Emit(OpCodes.Ldnull);
                    }
                });
            });

            ilgen.EmitNew(
                typeof(MutableTuple<Type[], Delegate[][], string[][], string[][]>),
                new[] { typeof(Type[]), typeof(Delegate[][]), typeof(string[][]), typeof(string[][]) }
            );
            ilgen.Emit(OpCodes.Ret);

            mb.SetCustomAttribute(new CustomAttributeBuilder(
                typeof(DlrCachedCodeAttribute).GetConstructor(Type.EmptyTypes),
                ArrayUtils.EmptyObjects
            ));

            tg.FinishType();
            ag.SaveAssembly();
        }
예제 #3
0
        public static void SaveNewTypes(string assemblyName, IList<PythonTuple> types) {
            Assert.NotNull(assemblyName, types);

            AssemblyGen ag = new AssemblyGen(new AssemblyName(assemblyName), ".", ".dll", false);
            TypeBuilder tb = ag.DefinePublicType(_constructorTypeName, typeof(object), true);
            tb.SetCustomAttribute(typeof(PythonCachedTypeInfoAttribute).GetConstructor(Type.EmptyTypes), new byte[0]);

            MethodBuilder mb = tb.DefineMethod(_constructorMethodName, MethodAttributes.Public | MethodAttributes.Static, typeof(CachedNewTypeInfo[]), Type.EmptyTypes);
            ILGenerator ilg = mb.GetILGenerator();
            
            // new CachedTypeInfo[types.Count]
            // we leave this on the stack (duping it) and storing into it.
            EmitInt(ilg, types.Count);
            ilg.Emit(OpCodes.Newarr, typeof(CachedNewTypeInfo));
            int curType = 0;

            foreach (var v in types) {
                NewTypeInfo nti = NewTypeInfo.GetTypeInfo(String.Empty, v);
                
                var typeInfos = new NewTypeMaker(nti).SaveType(ag, "Python" + _typeCount++ + "$" + nti.BaseType.Name);

                // prepare for storing the element into our final array
                ilg.Emit(OpCodes.Dup);
                EmitInt(ilg, curType++);

                // new CachedNewTypeInfo(type, specialNames, interfaceTypes):

                // load the type
                ilg.Emit(OpCodes.Ldtoken, typeInfos.Key);
                ilg.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));                

                // create the dictionary<str, str[]> of special names
                ilg.Emit(OpCodes.Newobj, typeof(Dictionary<string, string[]>).GetConstructor(new Type[0]));
                foreach (var specialName in typeInfos.Value) {
                    // dup dict
                    ilg.Emit(OpCodes.Dup);
                    
                    // emit key
                    ilg.Emit(OpCodes.Ldstr, specialName.Key);

                    // emit value
                    int iVal = specialName.Value.Length;
                    EmitInt(ilg, iVal);
                    ilg.Emit(OpCodes.Newarr, typeof(string));
                    for (int i = 0; i < specialName.Value.Length; i++) {
                        ilg.Emit(OpCodes.Dup);
                        EmitInt(ilg, i);
                        ilg.Emit(OpCodes.Ldstr, specialName.Value[0]);
                        ilg.Emit(OpCodes.Stelem_Ref);
                    }

                    // assign to dict
                    ilg.Emit(OpCodes.Call, typeof(Dictionary<string, string[]>).GetMethod("set_Item"));                    
                }

                // emit the interface types (if any)
                if (nti.InterfaceTypes.Count != 0) {
                    EmitInt(ilg, nti.InterfaceTypes.Count);
                    ilg.Emit(OpCodes.Newarr, typeof(Type));

                    for (int i = 0; i < nti.InterfaceTypes.Count; i++) {
                        ilg.Emit(OpCodes.Dup);
                        EmitInt(ilg, i);
                        ilg.Emit(OpCodes.Ldtoken, nti.InterfaceTypes[i]);
                        ilg.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
                        ilg.Emit(OpCodes.Stelem_Ref);
                    }
                } else {
                    ilg.Emit(OpCodes.Ldnull);
                }

                // crated the CachedNewTypeInfo and store it in the array
                ilg.Emit(OpCodes.Newobj, typeof(CachedNewTypeInfo).GetConstructors()[0]);
                ilg.Emit(OpCodes.Stelem_Ref);
            }
            ilg.Emit(OpCodes.Ret);
            tb.CreateType();
            ag.SaveAssembly();
        }