Beispiel #1
0
 public static MosaType ToArray(this MosaType type, MosaArrayInfo info)
 {
     MosaType result = type.ToSZArray();
     using (var arrayType = type.TypeSystem.Controller.MutateType(result))
     {
         arrayType.TypeCode = MosaTypeCode.Array;
         arrayType.ArrayInfo = info;
         return result;
     }
 }
        public static MosaType ToArray(this MosaType type, MosaArrayInfo info)
        {
            MosaType array = type.TypeSystem.GetTypeByName(type.TypeSystem.CorLib, "System", "Array");
            MosaType result = type.TypeSystem.Controller.CreateType(array);
            using (var arrayType = type.TypeSystem.Controller.MutateType(result))
            {
                // See Partition II 14.2 Arrays

                arrayType.Module = type.Module;
                arrayType.DeclaringType = type.DeclaringType;
                arrayType.Namespace = type.Namespace;
                arrayType.Name = type.Name;

                arrayType.HasOpenGenericParams = type.HasOpenGenericParams;
                arrayType.BaseType = array;
                arrayType.ElementType = type;
                arrayType.TypeCode = MosaTypeCode.Array;
                arrayType.ArrayInfo = info;

                AddArrayMethods(type.TypeSystem, result, arrayType, info);

                return result;
            }
        }
        private static void AddArrayMethods(TypeSystem typeSystem, MosaType arrayType, MosaType.Mutator type, MosaArrayInfo info)
        {
            // Remove all methods & fields --> Since BaseType = System.Array, they're automatically inherited.
            type.Methods.Clear();
            type.Fields.Clear();

            // Add three array accessors as defined in standard (Get, Set, Address)
            // Also, constructor.

            uint rank = info.Rank;

            MosaMethod methodGet = typeSystem.Controller.CreateMethod();
            using (var method = typeSystem.Controller.MutateMethod(methodGet))
            {
                method.DeclaringType = arrayType;
                method.Name = "Get";
                method.IsInternalCall = true;
                method.IsRTSpecialName = method.IsSpecialName = true;
                method.IsFinal = true;
                method.HasThis = true;

                List<MosaParameter> parameters = new List<MosaParameter>();
                for (uint i = 0; i < rank; i++)
                {
                    var indexParam = typeSystem.Controller.CreateParameter();
                    using (var mosaParameter = typeSystem.Controller.MutateParameter(indexParam))
                    {
                        mosaParameter.Name = "index" + i;
                        mosaParameter.ParameterAttributes = MosaParameterAttributes.In;
                        mosaParameter.ParameterType = typeSystem.BuiltIn.I4;
                        mosaParameter.DeclaringMethod = methodGet;
                    }
                    parameters.Add(indexParam);
                }
                method.Signature = new MosaMethodSignature(arrayType.ElementType, parameters);
            }
            type.Methods.Add(methodGet);

            MosaMethod methodSet = typeSystem.Controller.CreateMethod();
            using (var method = typeSystem.Controller.MutateMethod(methodSet))
            {
                method.DeclaringType = arrayType;
                method.Name = "Set";
                method.IsInternalCall = true;
                method.IsRTSpecialName = method.IsSpecialName = true;
                method.IsFinal = true;
                method.HasThis = true;

                List<MosaParameter> parameters = new List<MosaParameter>();
                for (uint i = 0; i < rank; i++)
                {
                    var indexParam = typeSystem.Controller.CreateParameter();
                    using (var mosaParameter = typeSystem.Controller.MutateParameter(indexParam))
                    {
                        mosaParameter.Name = "index" + i;
                        mosaParameter.ParameterAttributes = MosaParameterAttributes.In;
                        mosaParameter.ParameterType = typeSystem.BuiltIn.I4;
                        mosaParameter.DeclaringMethod = methodSet;
                    }
                    parameters.Add(indexParam);
                }

                var valueParam = typeSystem.Controller.CreateParameter();
                using (var mosaParameter = typeSystem.Controller.MutateParameter(valueParam))
                {
                    mosaParameter.Name = "value";
                    mosaParameter.ParameterAttributes = MosaParameterAttributes.In;
                    mosaParameter.ParameterType = arrayType.ElementType;
                    mosaParameter.DeclaringMethod = methodSet;
                }
                parameters.Add(valueParam);

                method.Signature = new MosaMethodSignature(typeSystem.BuiltIn.Void, parameters);
            }
            type.Methods.Add(methodSet);

            MosaMethod methodAdrOf = typeSystem.Controller.CreateMethod();
            using (var method = typeSystem.Controller.MutateMethod(methodAdrOf))
            {
                method.DeclaringType = arrayType;
                method.Name = "AddressOr";
                method.IsInternalCall = true;
                method.IsRTSpecialName = method.IsSpecialName = true;
                method.IsFinal = true;
                method.HasThis = true;

                List<MosaParameter> parameters = new List<MosaParameter>();
                for (uint i = 0; i < rank; i++)
                {
                    var indexParam = typeSystem.Controller.CreateParameter();
                    using (var mosaParameter = typeSystem.Controller.MutateParameter(indexParam))
                    {
                        mosaParameter.Name = "index" + i;
                        mosaParameter.ParameterAttributes = MosaParameterAttributes.In;
                        mosaParameter.ParameterType = typeSystem.BuiltIn.I4;
                        mosaParameter.DeclaringMethod = methodAdrOf;
                    }
                    parameters.Add(indexParam);
                }
                method.Signature = new MosaMethodSignature(arrayType.ElementType.ToManagedPointer(), parameters);
            }
            type.Methods.Add(methodAdrOf);

            MosaMethod methodCtor = typeSystem.Controller.CreateMethod();
            using (var method = typeSystem.Controller.MutateMethod(methodCtor))
            {
                method.DeclaringType = arrayType;
                method.Name = ".ctor";
                method.IsInternalCall = true;
                method.IsRTSpecialName = method.IsSpecialName = true;
                method.IsFinal = true;
                method.HasThis = true;

                List<MosaParameter> parameters = new List<MosaParameter>();
                for (uint i = 0; i < rank; i++)
                {
                    var lengthParam = typeSystem.Controller.CreateParameter();
                    using (var mosaParameter = typeSystem.Controller.MutateParameter(lengthParam))
                    {
                        mosaParameter.Name = "length" + i;
                        mosaParameter.ParameterAttributes = MosaParameterAttributes.In;
                        mosaParameter.ParameterType = typeSystem.BuiltIn.I4;
                        mosaParameter.DeclaringMethod = methodCtor;
                    }
                    parameters.Add(lengthParam);
                }
                method.Signature = new MosaMethodSignature(typeSystem.BuiltIn.Void, parameters);
            }
            type.Methods.Add(methodCtor);
        }
        private MosaType Load(TypeSig typeSig)
        {
            if (typeSig is LeafSig)
            {
                if (typeSig is TypeDefOrRefSig)
                {
                    throw new AssemblyLoadException();                      // Should have been loaded in MetadataLoader
                }
                else if (typeSig is GenericInstSig)
                {
                    return(LoadGenericTypeInstanceSig((GenericInstSig)typeSig));
                }
                else if (typeSig is GenericSig)
                {
                    return(LoadGenericParam((GenericSig)typeSig));
                }
                else if (typeSig is FnPtrSig)
                {
                    MethodSig            fnPtr      = (MethodSig)((FnPtrSig)typeSig).MethodSig;
                    MosaType             returnType = GetType(fnPtr.RetType);
                    List <MosaParameter> pars       = new List <MosaParameter>();
                    for (int i = 0; i < fnPtr.Params.Count; i++)
                    {
                        var parameter = metadata.Controller.CreateParameter();

                        using (var mosaParameter = metadata.Controller.MutateParameter(parameter))
                        {
                            mosaParameter.Name = "A_" + i;
                            mosaParameter.ParameterAttributes = MosaParameterAttributes.In;
                            mosaParameter.ParameterType       = GetType(fnPtr.Params[i]);
                        }

                        pars.Add(parameter);
                    }
                    return(metadata.TypeSystem.ToFnPtr(new MosaMethodSignature(returnType, pars)));
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            else                // Non-leaf signature
            {
                MosaType elementType = GetType(typeSig.Next);
                MosaType result;
                switch (typeSig.ElementType)
                {
                case ElementType.Ptr:
                    result = elementType.ToUnmanagedPointer();
                    using (var ptrType = metadata.Controller.MutateType(result))
                        ptrType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig);
                    break;

                case ElementType.ByRef:
                    result = elementType.ToManagedPointer();
                    using (var ptrType = metadata.Controller.MutateType(result))
                        ptrType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig);
                    break;

                case ElementType.CModReqd:
                case ElementType.CModOpt:
                    result = metadata.Controller.CreateType(elementType);
                    using (var modType = metadata.Controller.MutateType(result))
                    {
                        modType.Modifier         = GetType(((ModifierSig)typeSig).Modifier.ToTypeSig());
                        modType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig);
                        modType.ElementType      = elementType;
                    }
                    break;

                case ElementType.Pinned:
                    result = elementType;                                // Pinned types are indicated in MosaLocal
                    return(result);                                      // Don't add again to controller

                case ElementType.SZArray:
                    GetType(new GenericInstSig(szHelperSig, typeSig.Next));
                    GetType(new GenericInstSig(iListSig, typeSig.Next));
                    result = elementType.ToSZArray();
                    using (var arrayType = metadata.Controller.MutateType(result))
                        arrayType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig);
                    metadata.Resolver.EnqueueForArrayResolve(result);
                    return(result);

                case ElementType.Array:
                    ArraySig      array     = (ArraySig)typeSig;
                    MosaArrayInfo arrayInfo = new MosaArrayInfo(array.LowerBounds, array.Rank, array.Sizes);
                    result = elementType.ToArray(arrayInfo);
                    using (var arrayType = metadata.Controller.MutateType(result))
                        arrayType.UnderlyingObject = elementType.GetUnderlyingObject <UnitDesc <TypeDef, TypeSig> >().Clone(typeSig);
                    break;

                default:
                    throw new AssemblyLoadException();
                }
                metadata.Controller.AddType(result);
                return(result);
            }
        }