public static void SaveToAssembly(string assemblyName, IDictionary <string, object> assemblyAttributes, params SavableScriptCode[] codes)
        {
            ContractUtils.RequiresNotNull(assemblyName, nameof(assemblyName));
            ContractUtils.RequiresNotNullItems(codes, nameof(codes));

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

            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, assemblyAttributes);
            TypeBuilder tb = ag.DefinePublicType("DLRCachedCode", typeof(object), true);
            TypeGen     tg = new TypeGen(ag, tb);
            // then compile all of the code

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

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

                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[][]>),
                ReflectionUtils.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(nameof(Type.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(ReflectionUtils.EmptyTypes),
                                      ArrayUtils.EmptyObjects
                                      ));

            tg.FinishType();
            ag.SaveAssembly();
        }
예제 #2
0
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            ContractUtils.RequiresNotNull(info, "info");

            info.AddValue("symbolName", SymbolTable.IdToString(this));
        }
예제 #3
0
파일: ErrorSink.cs 프로젝트: stantoxt/dlr
 public ErrorCounter(ErrorSink /*!*/ sink)
 {
     ContractUtils.RequiresNotNull(sink, "sink");
     _sink = sink;
 }
예제 #4
0
        // When leaving a context we serialize out our ID as a name
        // rather than a raw ID.  When we enter a new context we
        // consult it's FieldTable to get the ID of the symbol name in
        // the new context.

        private SymbolId(SerializationInfo info, StreamingContext context)
        {
            ContractUtils.RequiresNotNull(info, "info");

            _id = SymbolTable.StringToId(info.GetString("symbolName"))._id;
        }
예제 #5
0
파일: ScriptCode.cs 프로젝트: kerwon/dlr
        protected ScriptCode(SourceUnit sourceUnit)
        {
            ContractUtils.RequiresNotNull(sourceUnit, nameof(sourceUnit));

            _sourceUnit = sourceUnit;
        }