⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emitcodegen.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
    

    /***************************************************************************\
    *
    * EmitCodeGen.CreateCLREnumType
    * 
    \***************************************************************************/
    public virtual System.Type CreateCLREnumType(SymbolEngine.EnumTypeEntry symEnum)
    {
        TypeAttributes mods = TypeAttributes.Sealed;
                    
#if Bug_In_EnumBuilder

        string stName = symEnum.FullName;

        TypeBuilder bld;
        
        // Handle nesting
        SymbolEngine.TypeEntry tParent = symEnum.GetContainingType();
        if (tParent == null)
        {
            if (symEnum.Mods.IsPublic)
                mods |= TypeAttributes.Public;
            else
                mods |= TypeAttributes.NotPublic;
            
            Log.WriteLine(Log.LF.CodeGen, "Define enum:{0}", stName);
            bld = m_bldModule.DefineType(stName, mods, typeof(System.Enum));
        } else {
            if (symEnum.Mods.IsPublic)
                mods |= TypeAttributes.NestedPublic;
            else if (symEnum.Mods.IsPrivate)
                mods |= TypeAttributes.NestedPrivate;
            else if (symEnum.Mods.IsProtected)
                mods |= TypeAttributes.NestedFamily;
            else if (symEnum.Mods.IsInternal)
                mods |= TypeAttributes.NestedAssembly;                                
                
                
            Log.WriteLine(Log.LF.CodeGen, "Define nested enum:{0}", stName);
            TypeBuilder bldParent = tParent.CLRType as TypeBuilder;
            bld = bldParent.DefineNestedType(symEnum.Name, mods, typeof(System.Enum));
            // DefineNestedType says it wants the 'full name', but name Name can't inclue [,],\,+            
            // So we're in a pickle. And then when the TypeResolve event is fired, we don't
            // get enough info (we just get the short name).
            
            //string stName2 = symEnum.FullName.Replace('+', '\\');            
            //bld = bldParent.DefineNestedType(stName2, mods, typeof(System.Enum));
            
        }
        
        // Enums have a default magical field: 
        bld.DefineField("value__", typeof(int), 
            FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
#else
        #error - need a DefineNestedEnum()
        EnumBuilder bld = m_bldModule.DefineEnum(stName, mods, typeof(int));
#endif
        return bld;
    }

    /***************************************************************************\
    *
    * EmitCodeGen.SetCLRClassType
    * 
    \***************************************************************************/
    public virtual System.Type
    CreateCLRClass(
        SymbolEngine.TypeEntry symBlueType
    )
    {
        // We call DefineType to get a TypeBuilder, which derives from Type
        // We have to pass DefineType all the interesting parameters (ie, we
        // have to know stuff like the base class now, not later)

        // We get namespaces for free by using the full name
        // We also handle nested classes here.
        
        string stClassName = symBlueType.FullName;
        System.Type typeBaseClass = null;
        TypeAttributes attrClass = (TypeAttributes) 0;                           

        SymbolEngine.TypeEntry [] arBlueInterfaces = symBlueType.BaseInterfaces;
        System.Type [] arClrInterfaces = new System.Type[arBlueInterfaces.Length];
        for(int i =0; i < arClrInterfaces.Length; i++)
        {
            arClrInterfaces[i] = arBlueInterfaces[i].CLRType;
            Debug.Assert(arClrInterfaces[i] != null);
        }
        
        
        // Setup modifiers
        AST.Modifiers mods = symBlueType.Mods;
        TypeBuilder bldClass;
        
        if (symBlueType.IsInterface)        
            attrClass |= TypeAttributes.Interface | TypeAttributes.Abstract;
        else
        {
            typeBaseClass = symBlueType.Super.CLRType;
            Debug.Assert(typeBaseClass != null);
        }
        
        if (mods.IsSealed)
            attrClass |= TypeAttributes.Sealed;
        if (mods.IsAbstract)
            attrClass |= TypeAttributes.Abstract;
        if (mods.IsSealed)
            attrClass |= TypeAttributes.Sealed;            
        
        // Handle nesting
        SymbolEngine.TypeEntry tParent = symBlueType.GetContainingType();
        if (tParent == null)
        {
            // Not nested
            if (mods.IsPublic)
                attrClass |= TypeAttributes.Public;
            else
                attrClass |= TypeAttributes.NotPublic;                    
                            
            Log.WriteLine(Log.LF.CodeGen, "Define type:{0}", stClassName);                
            bldClass = m_bldModule.DefineType(
                stClassName, 
                attrClass, 
                typeBaseClass, 
                arClrInterfaces
            );
        } else {
            // Nested
            if (mods.IsPublic)
                attrClass |= TypeAttributes.NestedPublic;
            else if (mods.IsPrivate)
                attrClass |= TypeAttributes.NestedPrivate;
            else if (mods.IsProtected)
                attrClass |= TypeAttributes.NestedFamily;
            else if (mods.IsInternal)
                attrClass |= TypeAttributes.NestedAssembly;   
                
            Log.WriteLine(Log.LF.CodeGen, "Define nested type:{0}", stClassName);                
            TypeBuilder bldParent = tParent.CLRType as TypeBuilder;
            bldClass = bldParent.DefineNestedType(symBlueType.Name, attrClass, typeBaseClass, arClrInterfaces);       
        }            
        
        Debug.Assert(bldClass != null, "Should have TypeBuilder by now");
        
        // Make sure that we can lookup the type that we just created
        #if DEBUG                
        System.Type tNatural = this.FindType(stClassName);
        Debug.Assert(tNatural == bldClass);
        #endif        
        
        // Sanity check that the type builder is complete enough to do
        // clr inheritence checks
        #if DEBUG
        if (typeBaseClass != null)
            Debug.Assert(bldClass.IsSubclassOf(typeBaseClass));

        foreach(System.Type t in arClrInterfaces)
        {   
            bool f1 = SymbolEngine.TypeEntry.IsAssignable(bldClass, t);
            Debug.Assert(f1);
        }
        #endif


        // Return the type and the symbol engine will set it
        return bldClass;
    }
    
    //-------------------------------------------------------------------------
    // Create a CLR event for use w/ reflection-emit
    //-------------------------------------------------------------------------
    public System.Reflection.EventInfo 
    CreateCLREvent(
        SymbolEngine.EventExpEntry symEvent
    )
    {
        string stName = symEvent.Name;
        
        // Get class that we're defined in
        TypeBuilder bldClass = symEvent.SymbolClass.CLRType as TypeBuilder;
        Debug.Assert(bldClass != null);
        
        
        EventAttributes attrs = EventAttributes.None;
        AST.Modifiers mods = symEvent.Node.Mods;
        
        
        EventBuilder bld = bldClass.DefineEvent(
            stName, attrs, symEvent.EventType.CLRType
        );
        Debug.Assert(bld != null);
        
        return null;
    }
    
    /***************************************************************************\
    *
    * EmitCodeGen.SetCLRMethodType
    *
    \***************************************************************************/
    public virtual  System.Reflection.PropertyInfo 
    CreateCLRProperty(
        SymbolEngine.PropertyExpEntry symProperty
    )
    {
        string stName = symProperty.Name;
        
        // Get class that we're defined in
        TypeBuilder bldClass = symProperty.SymbolClass.CLRType as TypeBuilder;
        Debug.Assert(bldClass != null);
        
        PropertyAttributes attrs = PropertyAttributes.None;
                
        // Create the property builder
        PropertyBuilder bld = bldClass.DefineProperty(
            stName,
            attrs, 
            symProperty.PropertyType.CLRType,
            new Type[0]
            
        );
        
        // Create builders for the get / set accessors        
        if (symProperty.SymbolGet != null)
        {
            symProperty.SymbolGet.SetInfo(this);
            bld.SetGetMethod(symProperty.SymbolGet.Info as MethodBuilder);
        }
        
        if (symProperty.SymbolSet != null)
        {
            symProperty.SymbolSet.SetInfo(this);
            bld.SetSetMethod(symProperty.SymbolSet.Info as MethodBuilder);
        }
        
        return bld;
    }
    
    /***************************************************************************\
    *
    * EmitCodeGen.SetCLRMethodType
    *
    \***************************************************************************/
    
    public virtual  System.Reflection.MethodBase 
    CreateCLRMethod(
        SymbolEngine.MethodExpEntry symBlueMethod
    )
    {
        // Call DefineMethod on the TypeBuilder to get a MethodBuilder
        // MethodBuilder derives from MethodInfo
        string stMethodName         = symBlueMethod.Name;

        Debug.Assert(symBlueMethod.Node != null);
        
        AST.Modifiers mods = symBlueMethod.Node.Mods;        
        MethodAttributes attrMethod = (MethodAttributes) 0;
        
        // Everything seems to have this; but what does it do?
        attrMethod = MethodAttributes.HideBySig;
                
        if (mods.IsPublic)
            attrMethod |= MethodAttributes.Public;
        else if (mods.IsProtected)
            attrMethod |= MethodAttributes.Family;
        else if (mods.IsPrivate)
            attrMethod |= MethodAttributes.Private;
        else if (mods.IsInternal)
            attrMethod |= MethodAttributes.Assembly;
            
        
        if (symBlueMethod.IsSpecialName)
            attrMethod |= MethodAttributes.SpecialName;
            
        if (mods.IsStatic)
        {
            attrMethod |= MethodAttributes.Static;
        }
        
        if (mods.IsVirtual)
            attrMethod |= MethodAttributes.Virtual | MethodAttributes.NewSlot;
        
        if (mods.IsAbstract)
            attrMethod |= MethodAttributes.Abstract | MethodAttributes.Virtual | MethodAttributes.NewSlot;
                
        if (mods.IsOverride)
        {
            attrMethod |= MethodAttributes.Virtual;
        }
        
        if (mods.IsSealed)
            attrMethod |= MethodAttributes.Final;
        
        
        
        // Overloaded operators have a magical bit sit
        if (symBlueMethod.Node.IsOpOverload)
            attrMethod |= MethodAttributes.SpecialName;
                
        // Get signature from the parameters        
        #if false
        Type [] alParamTypes = new Type[symBlueMethod.ParamCount];            
        for(int iParam = 0; iParam < symBlueMethod.ParamCount; iParam++)
        {            
            alParamTypes[iParam] = symBlueMethod.ParamCLRType(iParam);
        }        
        #else
        Type [] alParamTypes = symBlueMethod.ParamTypes(false);
        #endif       
        
        // Get class that we're defined in
        TypeBuilder bldClass = symBlueMethod.SymbolClass.CLRType as TypeBuilder;
        Debug.Assert(bldClass != null);
        
        bool fIsCtor = symBlueMethod.IsCtor;
        
        System.Reflection.MethodBase bld = null;           
                
        // Get the builder        
        if (fIsCtor)
        {   
            
            ConstructorBuilder bldCtor = bldClass.DefineConstructor(attrMethod, CallingConventions.Standard, alParamTypes);    

            if (AST.DelegateDecl.IsDelegate(symBlueMethod.SymbolClass.CLRType))
            {
                bldCtor.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);                
            }

            //return bldCtor;        
            bld = bldCtor;
        }
        else 
        {                        
            Type typeReturn = symBlueMethod.RetType.CLRType;
            Debug.Assert(typeReturn != null, "Semantic check should catch null return type");
            
            MethodBuilder bldMethod = bldClass.DefineMethod(stMethodName, attrMethod, typeReturn, alParamTypes);
            
            // The members of a delegate are special because they're implemented by the runtime.
            if (AST.DelegateDecl.IsDelegate(symBlueMethod.SymbolClass.CLRType))
            {
                bldMethod.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
            }
            
            
            //return bldMethod;
            bld = bldMethod;
        }
        
        
        // Double check that we set the attributes on the new CLR method properly.
        // Do this by converting back to blue modifier from CLR method and comparing
        // that modifier to the original.        
        
        #if DEBUG
        AST.Modifiers modsCheck = new AST.Modifiers(bld);
        string stPretty = symBlueMethod.PrettyDecoratedName;
        string stBlue = mods.ToString();
        string stCLR = modsCheck.ToString();
        
        // The 'new' modifier just tells the C# compiler to suppress warnings. There's
        // no IL bit for it, so we lose it when we roundtrip. So just add it to both
        // of them.
        mods.SetNew();
        modsCheck.SetNew();
        Debug.Assert(modsCheck == mods, "Modifer mismatch in creating CLR method");
        #endif
        
        return bld;
        
    }
    
#endregion
    

#region Implementation for Codegen Driver
    //-------------------------------------------------------------------------
    // Helper class called when a resolve type event is fired.
    // This is called when we CreateType() and it needs to also create an inner
    // type.
    //-------------------------------------------------------------------------
        
    public Assembly ResolveCreateType(Object sender, ResolveEventArgs args)
    {
        Log.WriteLine(Log.LF.CodeGen, "... got TypeResolveEvent for '{0}'", args.Name);
        
        // Get the full name of whoever originally called CreateType()
        string stParent = (string) m_CreateTypeStack.Peek();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -