예제 #1
0
 private void MaybeInit()
 {
     if (_typeBuilder == null)
     {
         _typeBuilder = _assemblyGen.DefinePublicType(_typeName, typeof(object), true);
         _typeGen     = new TypeGen(_assemblyGen, _typeBuilder);
         _siteInfos   = new List <SiteInfo>();
     }
 }
예제 #2
0
 private void MaybeInit()
 {
     if (_typeBuilder == null)
     {
         _typeBuilder   = _assemblyGen.DefinePublicType(_typeName, typeof(object), true);
         _typeGen       = new TypeGen(_assemblyGen, _typeBuilder);
         _fieldBuilders = new List <FieldBuilder>();
         _fieldInits    = new List <Expression>();
     }
 }
예제 #3
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);
            // 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);

                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();
        }
예제 #4
0
        public static RecordTypeDescriptor GenerateRecordTypeDescriptor(AssemblyGen ag, object name, object parent, object uid, object issealed, object isopaque, object fields, object fieldtypes)
        {
            string n  = SymbolTable.IdToString(RequiresNotNull <SymbolId>(name));
            string id = uid is SymbolId?SymbolTable.IdToString(RequiresNotNull <SymbolId>(uid)) : uid as string;

            if (id != null)
            {
                RecordTypeDescriptor ngrtd;
                if (nongenerative.TryGetValue(n + id, out ngrtd))
                {
                    return(ngrtd);
                }

                var type = ClrGenerator.GetTypeFast("record." + id + "." + n.Replace("&", "$"));

                if (type != null)
                {
                    return(RecordTypeDescriptor.Create(type, n, id, parent as RecordTypeDescriptor));
                }
            }

            bool @sealed = RequiresNotNull <bool>(issealed);
            bool opaque  = RequiresNotNull <bool>(isopaque);

            RecordTypeDescriptor prtd = parent as RecordTypeDescriptor; // can be #f

            Type parenttype = typeof(object);

            if (prtd != null)
            {
                parenttype = prtd.type;
            }
            else if (n == "&condition")
            {
                parenttype = typeof(Condition);
            }

            TypeAttributes attrs = TypeAttributes.Public | TypeAttributes.Serializable;

            var rtd = new RecordTypeDescriptor
            {
                Name       = n,
                @sealed    = @sealed,
                opaque     = opaque,
                ag         = ag,
                Parent     = prtd,
                uid        = uid,
                generative = id == null || uid is string,
            };

            if (@sealed)
            {
                attrs |= TypeAttributes.Sealed;
            }

            object gid      = (object)id ?? Guid.NewGuid();
            var    ns       = "record." + gid;
            var    typename = ns + "." + n.Replace("&", "$");

            TypeGen tg = ag.DefinePublicType(typename, parenttype, attrs);

            rtd.tg   = tg;
            rtd.type = tg.TypeBuilder;

            if (id != null)
            {
                nongenerative[n + id] = rtd;
            }

            if (parenttype.IsSubclassOf(typeof(Condition)))
            {
                SetSymbolValueFast(SymbolTable.StringToObject(n + "-rtd"), rtd);
            }

            GeneratePredicate(n, rtd, tg);

            GenerateFields(fields, n, rtd, tg, fieldtypes);

            GenerateConstructor(rtd, tg, parenttype);

            return(rtd);
        }
예제 #5
0
        public static RecordTypeDescriptor GenerateRecordTypeDescriptor(AssemblyGen ag, object name, object parent, object uid, object issealed, object isopaque, object fields, object fieldtypes)
        {
            string n = SymbolTable.IdToString(RequiresNotNull<SymbolId>(name));
              string id = uid is SymbolId ? SymbolTable.IdToString(RequiresNotNull<SymbolId>(uid)): uid as string;

              if (id != null)
              {
            RecordTypeDescriptor ngrtd;
            if (nongenerative.TryGetValue(n + id, out ngrtd))
            {
              // this is all nice and well, but when the caller is from a disk assembly, after it has been compiled, there will be a mismatch
              // this is bit hard to check...
              return ngrtd;
            }

            var type = ClrGenerator.GetTypeFast("record." + id + "." + n.Replace("&", "$").Replace("*", "$")); // TODO: Make me better

            if (type != null)
            {
              return RecordTypeDescriptor.Create(type, n, id, parent as RecordTypeDescriptor);
            }
              }

              bool @sealed = RequiresNotNull<bool>(issealed);
              bool opaque = RequiresNotNull<bool>(isopaque);

              RecordTypeDescriptor prtd = parent as RecordTypeDescriptor; // can be #f

              Type parenttype = typeof(object);

              if (prtd != null)
              {
            parenttype = prtd.type;
              }
              else if (n == "&condition")
              {
            parenttype = typeof(Condition);
              }

              TypeAttributes attrs = TypeAttributes.Public | TypeAttributes.Serializable;

              var rtd = new RecordTypeDescriptor
            {
              Name = n,
              @sealed = @sealed,
              opaque = opaque,
              ag = ag,
              Parent = prtd,
              uid = uid,
              generative = id == null || uid is string,
            };

              if (@sealed)
              {
            attrs |= TypeAttributes.Sealed;
              }

              object gid = (object)id ?? Guid.NewGuid();
              var ns = "record." + gid;
              var typename = ns + "." + n.Replace("&", "$").Replace("*", "$"); // TODO: Make me better

              TypeGen tg = ag.DefinePublicType(typename, parenttype, attrs);

              rtd.tg = tg;
              rtd.type = tg.TypeBuilder;

              if (id != null)
              {
            nongenerative[n + id] = rtd;
              }

              if (parenttype.IsSubclassOf(typeof(Condition)))
              {
            SetSymbolValueFast(SymbolTable.StringToObject(n + "-rtd"), rtd);
              }

              GeneratePredicate(n, rtd, tg);

              GenerateFields(fields, n, rtd, tg, fieldtypes);

              GenerateConstructor(rtd, tg, parenttype);

              return rtd;
        }