private CliInterface(HighTypeDef typeDef, TypeSpecClassTag typeSpec, TypeSpecTag[] genericParameters, TypeSpecClassTag[] parentInterfaces, HighClassVtableSlot[] slots, Dictionary<MethodDeclTag, uint> slotTagToCliSlot, Dictionary<MethodDeclTag, uint> slotTagToRealSlot, uint numRealSlots, TypeSpecClassTag[] interfaceImpls) { m_typeDef = typeDef; m_typeSpec = typeSpec; m_genericParameters = genericParameters; m_slots = slots; m_slotTagToCliSlot = slotTagToCliSlot; m_slotTagToRealSlot = slotTagToRealSlot; m_numRealSlots = numRealSlots; m_interfaceImpls = interfaceImpls; m_isCreated = true; }
public CliInterface Instantiate(Compiler compiler, TypeSpecTag[] argTypes) { if (!m_isCreated) throw new RpaCompileException("Attempted to instantiate an uncreated open interface."); if (m_typeDef.NumGenericParameters != (uint)argTypes.Length) throw new ArgumentException("Interface parameter count doesn't match typedef count"); if (m_typeDef.NumGenericParameters == 0) return this; List<HighClassVtableSlot> slots = new List<HighClassVtableSlot>(); foreach (HighClassVtableSlot slot in m_slots) { MethodSignatureTag signature = slot.Signature.Instantiate(compiler.TagRepository, argTypes); HighClassVtableSlot newSlot = new HighClassVtableSlot(slot.SlotTag, signature, null, true, false); slots.Add(newSlot); } List<TypeSpecClassTag> parentInterfaces = new List<TypeSpecClassTag>(); foreach (TypeSpecClassTag classTag in m_parentInterfaces) parentInterfaces.Add((TypeSpecClassTag)classTag.Instantiate(compiler.TagRepository, argTypes)); TypeSpecClassTag typeSpec = (TypeSpecClassTag)m_typeSpec.Instantiate(compiler.TagRepository, argTypes); Dictionary<TypeSpecClassTag, int> uniqueDeps = new Dictionary<TypeSpecClassTag, int>(); foreach (TypeSpecClassTag ifc in m_interfaceImpls) AddUniqueInterface(uniqueDeps, (TypeSpecClassTag)ifc.Instantiate(compiler.TagRepository, argTypes)); TypeSpecClassTag[] interfaceImpls = UnrollUniqueInterfaces(uniqueDeps); return new CliInterface(m_typeDef, typeSpec, argTypes, parentInterfaces.ToArray(), slots.ToArray(), m_slotTagToCliSlot, m_slotTagToRealSlot, m_numRealSlots, interfaceImpls); }
public bool Create(Compiler compiler) { HighTypeDef typeDef = compiler.GetTypeDef(m_typeName); TypeSpecClassTag parentClassSpec = null; HighClassVtableSlot[] newSlots; HighClassVtableSlot[] replacedSlots; HighInterfaceImplementation[] typeInterfaceImpls; if (typeDef.Semantics == TypeSemantics.Struct || typeDef.Semantics == TypeSemantics.Class) { if (typeDef.Semantics == TypeSemantics.Struct) { m_isStruct = true; TypeNameTag valueTypeName = new TypeNameTag("mscorlib", "System", "ValueType", 0, null); valueTypeName = compiler.TagRepository.InternTypeName(valueTypeName); TypeSpecClassTag vtClassTag = new TypeSpecClassTag(valueTypeName, new TypeSpecTag[0]); vtClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(vtClassTag); parentClassSpec = vtClassTag; } else if (typeDef.Semantics == TypeSemantics.Class) { m_isStruct = false; parentClassSpec = typeDef.ParentClass; RestrictedExtensionType thisRet = GetRestrictedExtensionType(m_typeName); if (parentClassSpec == null) { if (thisRet != RestrictedExtensionType.Object) throw new Exception("Parentless class is not [mscorlib]System.Object"); } else { if (thisRet == RestrictedExtensionType.Object) throw new Exception("[mscorlib]System.Object has a parent"); RestrictedExtensionType parentRet = GetRestrictedExtensionType(parentClassSpec.TypeName); bool isExtensionOK = false; switch (parentRet) { case RestrictedExtensionType.ValueType: if (thisRet == RestrictedExtensionType.Enum) isExtensionOK = true; break; case RestrictedExtensionType.Delegate: if (thisRet == RestrictedExtensionType.MulticastDelegate) isExtensionOK = true; break; case RestrictedExtensionType.Enum: case RestrictedExtensionType.MulticastDelegate: case RestrictedExtensionType.NullableSZArray: case RestrictedExtensionType.RefSZArray: case RestrictedExtensionType.ValueSZArray: break; case RestrictedExtensionType.Object: case RestrictedExtensionType.None: isExtensionOK = true; break; case RestrictedExtensionType.Array: if (thisRet == RestrictedExtensionType.NullableSZArray || thisRet == RestrictedExtensionType.ValueSZArray || thisRet == RestrictedExtensionType.RefSZArray) isExtensionOK = true; break; default: throw new ArgumentException(); } if (!isExtensionOK) throw new Exception("Invalid extension of a restricted class"); } } m_instanceFields = typeDef.InstanceFields; m_methods = typeDef.Methods; m_staticFields = typeDef.StaticFields; m_isSealed = typeDef.IsSealed; m_isAbstract = typeDef.IsAbstract; replacedSlots = typeDef.ReplacedSlots; newSlots = typeDef.NewSlots; typeInterfaceImpls = typeDef.InterfaceImpls; } else if (typeDef.Semantics == TypeSemantics.Delegate) { m_isStruct = false; TypeNameTag dgTypeName = new TypeNameTag("mscorlib", "System", typeDef.IsMulticastDelegate ? "MulticastDelegate" : "Delegate", 0, null); dgTypeName = compiler.TagRepository.InternTypeName(dgTypeName); TypeSpecClassTag dgClassTag = new TypeSpecClassTag(dgTypeName, new TypeSpecTag[0]); dgClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(dgClassTag); parentClassSpec = dgClassTag; m_instanceFields = new HighField[0]; m_methods = new HighMethod[0]; m_staticFields = new HighField[0]; m_isSealed = false; m_isAbstract = true; replacedSlots = new HighClassVtableSlot[0]; MethodDeclTag invokeTag = new MethodDeclTag("Invoke", typeDef.DelegateSignature, m_typeName); invokeTag = compiler.TagRepository.InternMethodDeclTag(invokeTag); HighClassVtableSlot invokeSlot = new HighClassVtableSlot(invokeTag, typeDef.DelegateSignature, null, true, false); newSlots = new HighClassVtableSlot[1] { invokeSlot }; typeInterfaceImpls = new HighInterfaceImplementation[0]; } else if (typeDef.Semantics == TypeSemantics.Enum) { m_isStruct = false; TypeNameTag dgTypeName = new TypeNameTag("mscorlib", "System", "Enum", 0, null); dgTypeName = compiler.TagRepository.InternTypeName(dgTypeName); TypeSpecClassTag dgClassTag = new TypeSpecClassTag(dgTypeName, new TypeSpecTag[0]); dgClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(dgClassTag); parentClassSpec = dgClassTag; string underlyingTypeName; switch (typeDef.UnderlyingType) { case HighTypeDef.EnumUnderlyingType.Int8: underlyingTypeName = "SByte"; break; case HighTypeDef.EnumUnderlyingType.Int16: underlyingTypeName = "Int16"; break; case HighTypeDef.EnumUnderlyingType.Int32: underlyingTypeName = "Int32"; break; case HighTypeDef.EnumUnderlyingType.Int64: underlyingTypeName = "Int64"; break; case HighTypeDef.EnumUnderlyingType.UInt8: underlyingTypeName = "Byte"; break; case HighTypeDef.EnumUnderlyingType.UInt16: underlyingTypeName = "Int16"; break; case HighTypeDef.EnumUnderlyingType.UInt32: underlyingTypeName = "UInt32"; break; case HighTypeDef.EnumUnderlyingType.UInt64: underlyingTypeName = "UInt64"; break; default: throw new Exception(); } TypeNameTag underlyingTypeNameTag = new TypeNameTag("mscorlib", "System", underlyingTypeName); underlyingTypeNameTag = compiler.TagRepository.InternTypeName(underlyingTypeNameTag); TypeSpecClassTag underlyingTypeSpec = new TypeSpecClassTag(underlyingTypeNameTag, new TypeSpecTag[0]); underlyingTypeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(underlyingTypeSpec); HighField fld = new HighField("value__", underlyingTypeSpec); m_instanceFields = new HighField[1] { fld }; m_methods = new HighMethod[0]; m_staticFields = new HighField[0]; m_isSealed = true; m_isAbstract = false; replacedSlots = new HighClassVtableSlot[0]; newSlots = new HighClassVtableSlot[0]; typeInterfaceImpls = new HighInterfaceImplementation[0]; } else throw new ArgumentException(); if (parentClassSpec != null) { if (compiler.GetTypeDef(parentClassSpec.TypeName).Semantics != TypeSemantics.Class) throw new RpaCompileException("Can't extend class with non-class semantics"); if (!compiler.HaveCliOpenClass(parentClassSpec.TypeName)) return false; CliClass parentClass = compiler.GetClosedClass(parentClassSpec); if (parentClass.m_isSealed) throw new RpaCompileException("Can't extend sealed CLI class"); m_parentClass = parentClass; } m_numGenericParameters = typeDef.NumGenericParameters; // Update vtable { Dictionary<MethodDeclTag, uint> declTagToMethod = new Dictionary<MethodDeclTag, uint>(); uint methodIndex = 0; foreach (HighMethod method in m_methods) { if (declTagToMethod.ContainsKey(method.MethodDeclTag)) throw new Exception("Duplicate method declaration"); declTagToMethod.Add(method.MethodDeclTag, methodIndex++); } m_declTagToMethod = declTagToMethod; } m_declTagToVTableSlot = new Dictionary<MethodDeclTag, uint>(); m_ifcToIfcSlot = new Dictionary<TypeSpecClassTag, uint>(); List<CliVtableSlot> slots = new List<CliVtableSlot>(); if (m_parentClass != null) { foreach (KeyValuePair<MethodDeclTag, uint> dttvs in m_parentClass.m_declTagToVTableSlot) m_declTagToVTableSlot.Add(dttvs.Key, dttvs.Value); foreach (CliVtableSlot parentSlot in m_parentClass.m_vtable) { CliMethodIndex methodIndex = parentSlot.MethodIndex; if (methodIndex == null) slots.Add(parentSlot); else { CliMethodIndex newIndex = new CliMethodIndex(methodIndex.Depth + 1, methodIndex.Index); slots.Add(new CliVtableSlot(newIndex, parentSlot.MethodSignature, parentSlot.IsSealed)); } } } foreach (HighClassVtableSlot slot in replacedSlots) { uint index; if (!m_declTagToVTableSlot.TryGetValue(slot.SlotTag, out index)) throw new Exception("Unmatched vtable slot replacement"); CliVtableSlot existingSlot = slots[(int)index]; if (existingSlot.IsSealed) throw new Exception("Can't replace sealed vtable slot"); if (existingSlot.MethodSignature != slot.Signature) throw new Exception("VTable slot override signature doesn't match"); CliMethodIndex methodIndex = null; if (!slot.IsAbstract) { HighMethod method; methodIndex = this.FindMethod(slot.ImplementingMethodTag, out method); if (method.MethodSignature != slot.Signature) throw new Exception("Signature of method used by vtable slot doesn't match vtable slot's signature"); } slots[(int)index] = new CliVtableSlot(methodIndex, slot.Signature, slot.IsFinal); } foreach (HighClassVtableSlot slot in newSlots) { CliMethodIndex methodIndex = null; if (!slot.IsAbstract) { HighMethod method; methodIndex = this.FindMethod(slot.ImplementingMethodTag, out method); if (method.MethodSignature != slot.Signature) throw new Exception("Signature of method used by vtable slot doesn't match vtable slot's signature"); } m_declTagToVTableSlot.Add(slot.SlotTag, (uint)slots.Count); slots.Add(new CliVtableSlot(methodIndex, slot.Signature, slot.IsFinal)); } m_vtable = slots.ToArray(); if (!m_isAbstract) foreach (CliVtableSlot slot in m_vtable) if (slot.MethodIndex == null) throw new RpaCompileException("Non-abstract class has unoverrided abstract methods"); m_nameToInstanceFieldSlot = new Dictionary<string, uint>(); for (uint i = 0; i < m_instanceFields.Length; i++) { string fldName = m_instanceFields[i].Name; if (m_nameToInstanceFieldSlot.ContainsKey(fldName)) throw new RpaCompileException("Duplicate field name"); m_nameToInstanceFieldSlot.Add(fldName, i); } m_nameToStaticFieldSlot = new Dictionary<string, uint>(); for (uint i = 0; i < m_staticFields.Length; i++) { string fldName = m_staticFields[i].Name; if (m_nameToStaticFieldSlot.ContainsKey(fldName)) throw new RpaCompileException("Duplicate field name"); m_nameToStaticFieldSlot.Add(fldName, i); } HashSet<TypeSpecClassTag> explicitImpls = new HashSet<TypeSpecClassTag>(); List<CliInterfaceImpl> interfaceImpls = new List<CliInterfaceImpl>(); foreach (HighInterfaceImplementation ifcImpl in typeInterfaceImpls) { if (!explicitImpls.Add(ifcImpl.Interface)) throw new Exception("Duplicate interface implementation"); interfaceImpls.Add(ResolveInterfaceImpl(compiler, ifcImpl)); } m_interfaceImpls = interfaceImpls.ToArray(); m_parentClassSpec = parentClassSpec; m_explicitInterfaceSpecs = typeDef.ParentInterfaces; if (m_explicitInterfaceSpecs == null) m_explicitInterfaceSpecs = new TypeSpecClassTag[0]; List<TypeSpecTag> thisGenericParameters = new List<TypeSpecTag>(); for (uint i = 0; i < m_numGenericParameters; i++) { TypeSpecGenericParamTypeTag gptt = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.Var); TypeSpecGenericParamTag gpTag = new TypeSpecGenericParamTag(gptt, i); gpTag = (TypeSpecGenericParamTag)compiler.TagRepository.InternTypeSpec(gpTag); thisGenericParameters.Add(gpTag); } TypeSpecClassTag thisClass = new TypeSpecClassTag(m_typeName, thisGenericParameters.ToArray()); thisClass = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(thisClass); m_typeSpec = thisClass; m_typeDeclarationOrder = new Dictionary<TypeSpecClassTag, uint>(); ResolveTDOForClass(this); m_isCreated = true; return true; }