/// <summary> /// Builds and adds the needed nested types in a current type representing explicit interfaces /// </summary> /// <param name="currentType"></param> public static void GetExplicitInterfaceTypes(TypeDeclaration currentType) { //Trim the type name to avoid errors with generic types string currentTypeName = currentType.Name.TrimEnd("_Base".ToCharArray()).TrimEnd("_T".ToCharArray()); //SEARCH FOR THE METHODS IN THE CURRENT TYPE THAT SHOULD BE IMPLEMENTED IN A NESTED CLASS List<MethodDeclaration> methodsOfCurrentType = new List<MethodDeclaration>(); foreach (KeyValuePair<AstType, List<MethodDeclaration>> kvp in Cache.GetPrivateImplementation()) { foreach (MethodDeclaration m in kvp.Value) { if (m.TypeMember.Name == currentTypeName) methodsOfCurrentType.Add(m); } } //CREATE A DICTIONARY WITH THE NESTEDCLASS AND METHODS NEEDED (SORTED) Dictionary<AstType, List<MethodDeclaration>> privateImplClass = new Dictionary<AstType, List<MethodDeclaration>>(); foreach (MethodDeclaration m in methodsOfCurrentType) { foreach (KeyValuePair<AstType, List<MethodDeclaration>> kvp in Cache.GetPrivateImplementation()) { if (kvp.Value.Contains(m)) { //If the method private implementation is corresponding to the current key type in the loop, continue if (GetTypeName(m.PrivateImplementationType) == GetTypeName(kvp.Key)) { //REMOVE THE METHOD FROM THE CURRENT TYPE currentType.Members.Remove(m); RemoveHeaderNode(m, currentType); //REMOVE THE PRIVATE IMPLEMENTATION m.PrivateImplementationType = Ast.AstType.Null; //Add the method in the sorted dictionary if (privateImplClass.ContainsKey(kvp.Key)) privateImplClass[kvp.Key].Add((MethodDeclaration)m.Clone()); else privateImplClass.Add(kvp.Key, new List<MethodDeclaration>() { (MethodDeclaration)m.Clone() }); } } } } //CREATE FROM THE NESTED CLASS THE NESTEDTYPEDECLARATION NODE foreach (KeyValuePair<AstType, List<MethodDeclaration>> kvp in privateImplClass) { TypeDeclaration type = new TypeDeclaration(); string nestedTypeName = "_interface_" + GetTypeName(kvp.Key); type.NameToken = new Identifier(nestedTypeName, TextLocation.Empty); type.Name = nestedTypeName; type.ModifierTokens.Add(new CppModifierToken(TextLocation.Empty, Modifiers.Public)); if (kvp.Key is SimpleType) { foreach (AstType tp in (kvp.Key as SimpleType).TypeArguments) type.TypeParameters.Add(new TypeParameterDeclaration() { NameToken = new Identifier(GetTypeName(tp), TextLocation.Empty) }); } //ADD BASE TYPES SimpleType baseType = new SimpleType(GetTypeName(kvp.Key)); if (kvp.Key is SimpleType) { foreach (AstType tp in (kvp.Key as SimpleType).TypeArguments) baseType.TypeArguments.Add((AstType)tp.Clone()); } type.AddChild(baseType, TypeDeclaration.BaseTypeRole); //REMOVE THE BASE TYPE BECAUSE THE NESTED TYPE WILL INHERIT FROM IT try { currentType.BaseTypes.Remove(currentType.BaseTypes.First(x => GetTypeName(x) == GetTypeName(baseType))); } catch (InvalidOperationException) { //The element is not present in the list //Safe to ignore this :) } //ADD METHODS type.Members.AddRange(kvp.Value); //ADD FIELD HeaderFieldDeclaration fdecl = new HeaderFieldDeclaration(); SimpleType nestedType = new SimpleType(nestedTypeName); foreach (TypeParameterDeclaration tp in type.TypeParameters) nestedType.TypeArguments.Add(new SimpleType(tp.Name)); ExplicitInterfaceTypeDeclaration ntype = new Ast.ExplicitInterfaceTypeDeclaration(type); fdecl.ReturnType = nestedType; string _tmp = "_" + GetTypeName(fdecl.ReturnType).ToLower(); fdecl.Variables.Add(new VariableInitializer(_tmp)); fdecl.ModifierTokens.Clear(); fdecl.ModifierTokens.Add(new CppModifierToken(TextLocation.Empty, Modifiers.Private)); //ADD FIELD TO THE GLOBAL CLASS ntype.OutMembers.Add(fdecl); //ADD OPERATORS TO THE GLOBAL CLASS //ADD OPERATOR HEADER NODE ConversionConstructorDeclaration op = new ConversionConstructorDeclaration(); op.ReturnType = new PtrType((AstType)kvp.Key.Clone()); op.ModifierTokens.Add(new CppModifierToken(TextLocation.Empty, Modifiers.Public)); //In the first line of this method we have trimed end the string with the _T and the _Base for searching the lists //At this point we have to add that string if (currentType.TypeParameters.Any()) op.type = currentTypeName + "_T_Base"; else op.type = currentTypeName; BlockStatement blck = new BlockStatement(); Statement st = new ReturnStatement(new AddressOfExpression(new IdentifierExpression(_tmp))); blck.Add(st); op.Body = blck; currentType.Members.Add(op); //If is generic type, we have to implement the operator inside of the templates header if (currentType.TypeParameters.Any()) { op.type = String.Empty; ntype.OutMembers.Add((AttributedNode)op.Clone()); //The method is implemented, we must delete the node from the header nodes RemoveHeaderNode(op, currentType); } else { HeaderConversionConstructorDeclaration hc = new HeaderConversionConstructorDeclaration(); GetHeaderNode(op, hc); //Add the header member to the out members of the nested type ntype.OutMembers.Add(hc); } //ADD NESTED TYPE TO THE HEADER DECLARATION currentType.HeaderNodes.Add(ntype); } }
/// <summary> /// Returns the member string for calling a conversion constructor declaration: i.e. operator IB<Object>*(); /// </summary> /// <param name="conv">The conversion constructor declaration</param> /// <returns>The member string</returns> public static string GetInlineConversionConstructorDeclarationCall(ConversionConstructorDeclaration conv) { //TODO: //ESTA FUNCION NO ME GUSTA NADA ! //HAY QUE CREAR NODOS INLINE string ret = "operator "; ret += Resolver.GetTypeName(conv.ReturnType); if (conv.ReturnType is SimpleType) { if ((conv.ReturnType as SimpleType).TypeArguments.Any()) { bool first = true; ret += "<"; foreach (AstType t in (conv.ReturnType as SimpleType).TypeArguments) { if (first) first = false; else ret += ","; AstType tmp; TryPatchTemplateToObjectType(t, out tmp); ret += Resolver.GetTypeName(tmp); } ret += "*>"; } } else if (conv.ReturnType is PtrType) { PtrType ptr = conv.ReturnType as PtrType; if (ptr.Target is SimpleType) { if ((ptr.Target as SimpleType).TypeArguments.Any()) { bool first = true; ret += "<"; foreach (AstType t in (ptr.Target as SimpleType).TypeArguments) { if (first) first = false; else ret += ","; AstType tmp; TryPatchTemplateToObjectType(t, out tmp); ret += Resolver.GetTypeName(tmp); } ret += ">"; } } ret += "*"; } return ret; }