1 /** 2 * Copyright: Copyright (c) 2012 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Jan 30, 2012 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module dstep.translator.Type; 8 9 import mambo.core..string; 10 import mambo.core.io; 11 12 import clang.c.Index; 13 import clang.Type; 14 15 import dstep.translator.IncludeHandler; 16 import dstep.translator.Translator; 17 import dstep.translator.Output; 18 19 string translateType (Type type, bool rewriteIdToObjcObject = true, bool applyConst = true) 20 in 21 { 22 assert(type.isValid); 23 } 24 body 25 { 26 string result; 27 28 with (CXTypeKind) 29 { 30 if (type.kind == CXType_BlockPointer || type.isFunctionPointerType) 31 result = translateFunctionPointerType(type); 32 33 else if (type.kind == CXType_ObjCObjectPointer && !type.isObjCBuiltinType) 34 result = translateObjCObjectPointerType(type); 35 36 else if (type.isWideCharType) 37 result = "wchar"; 38 39 else if (type.isObjCIdType) 40 result = rewriteIdToObjcObject ? "ObjcObject" : "id"; 41 42 else 43 switch (type.kind) 44 { 45 case CXType_Pointer: return translatePointer(type, rewriteIdToObjcObject, applyConst); 46 case CXType_Typedef: result = translateTypedef(type); break; 47 48 case CXType_Record: 49 case CXType_Enum: 50 case CXType_ObjCInterface: 51 result = type.spelling; 52 53 if (result.isEmpty) 54 result = getAnonymousName(type.declaration); 55 56 handleInclude(type); 57 break; 58 59 case CXType_ConstantArray: result = translateConstantArray(type, rewriteIdToObjcObject); break; 60 case CXType_Unexposed: result = translateUnexposed(type, rewriteIdToObjcObject); break; 61 62 default: result = translateType(type.kind, rewriteIdToObjcObject); 63 } 64 } 65 66 version (D1) 67 { 68 // ignore const 69 } 70 else 71 { 72 if (applyConst && type.isConst) 73 result = "const " ~ result; 74 } 75 76 return result; 77 } 78 79 string translateSelector (string str, bool fullName = false, bool translateIdentifier = true) 80 { 81 if (fullName) 82 str = str.replace(":", "_"); 83 84 else 85 { 86 auto i = str.indexOf(":"); 87 88 if (i > -1) 89 str = str[0 .. i]; 90 } 91 92 return translateIdentifier ? .translateIdentifier(str) : str; 93 } 94 95 private: 96 97 string translateTypedef (Type type) 98 in 99 { 100 assert(type.kind == CXTypeKind.CXType_Typedef); 101 } 102 body 103 { 104 auto spelling = type.spelling; 105 106 with (CXTypeKind) 107 switch (spelling) 108 { 109 case "BOOL": return translateType(CXType_Bool); 110 111 case "int64_t": return translateType(CXType_LongLong); 112 case "int32_t": return translateType(CXType_Int); 113 case "int16_t": return translateType(CXType_Short); 114 case "int8_t": return "byte"; 115 116 case "uint64_t": return translateType(CXType_ULongLong); 117 case "uint32_t": return translateType(CXType_UInt); 118 case "uint16_t": return translateType(CXType_UShort); 119 case "uint8_t": return translateType(CXType_UChar); 120 121 case "size_t": 122 case "ptrdiff_t": 123 case "sizediff_t": 124 return spelling; 125 126 case "wchar_t": 127 auto kind = type.canonicalType.kind; 128 129 if (kind == CXType_Int) 130 return "dchar"; 131 132 else if (kind == CXType_Short) 133 return "wchar"; 134 135 default: break; 136 } 137 138 handleInclude(type); 139 140 return spelling; 141 } 142 143 string translateUnexposed (Type type, bool rewriteIdToObjcObject) 144 in 145 { 146 assert(type.kind == CXTypeKind.CXType_Unexposed); 147 } 148 body 149 { 150 auto declaration = type.declaration; 151 152 if (declaration.isValid) 153 return translateType(declaration.type, rewriteIdToObjcObject); 154 155 else 156 return translateType(type.kind, rewriteIdToObjcObject); 157 } 158 159 string translateConstantArray (Type type, bool rewriteIdToObjcObject) 160 in 161 { 162 assert(type.kind == CXTypeKind.CXType_ConstantArray); 163 } 164 body 165 { 166 auto array = type.array; 167 auto elementType = translateType(array.elementType, rewriteIdToObjcObject); 168 169 return elementType ~ '[' ~ array.size.toString ~ ']'; 170 } 171 172 string translatePointer (Type type, bool rewriteIdToObjcObject, bool applyConst) 173 in 174 { 175 assert(type.kind == CXTypeKind.CXType_Pointer); 176 } 177 body 178 { 179 static bool valueTypeIsConst (Type type) 180 { 181 auto pointee = type.pointeeType; 182 183 while (pointee.kind == CXTypeKind.CXType_Pointer) 184 pointee = pointee.pointeeType; 185 186 return pointee.isConst; 187 } 188 189 auto result = translateType(type.pointeeType, rewriteIdToObjcObject, false); 190 191 version (D1) 192 { 193 result = result ~ '*'; 194 } 195 else 196 { 197 if (applyConst && valueTypeIsConst(type)) 198 { 199 if (type.isConst) 200 result = "const " ~ result ~ '*'; 201 202 else 203 result = "const(" ~ result ~ ")*"; 204 } 205 else 206 result = result ~ '*'; 207 } 208 209 return result; 210 } 211 212 string translateFunctionPointerType (Type type) 213 in 214 { 215 assert(type.kind == CXTypeKind.CXType_BlockPointer || type.isFunctionPointerType); 216 } 217 body 218 { 219 auto func = type.pointeeType.func; 220 221 Parameter[] params; 222 params.reserve(func.arguments.length); 223 224 foreach (type ; func.arguments) 225 params ~= Parameter(translateType(type)); 226 227 auto resultType = translateType(func.resultType); 228 229 return translateFunction(resultType, "function", params, func.isVariadic, new String); 230 } 231 232 string translateObjCObjectPointerType (Type type) 233 in 234 { 235 assert(type.kind == CXTypeKind.CXType_ObjCObjectPointer && !type.isObjCBuiltinType); 236 } 237 body 238 { 239 auto pointee = type.pointeeType; 240 241 if (pointee.spelling == "Protocol") 242 return "Protocol*"; 243 244 else 245 return translateType(pointee); 246 } 247 248 string translateType (CXTypeKind kind, bool rewriteIdToObjcObject = true) 249 { 250 with (CXTypeKind) 251 switch (kind) 252 { 253 case CXType_Invalid: return "<unimplemented>"; 254 case CXType_Unexposed: return "<unimplemented>"; 255 case CXType_Void: return "void"; 256 case CXType_Bool: return "bool"; 257 case CXType_Char_U: return "<unimplemented>"; 258 case CXType_UChar: return "ubyte"; 259 case CXType_Char16: return "wchar"; 260 case CXType_Char32: return "dchar"; 261 case CXType_UShort: return "ushort"; 262 case CXType_UInt: return "uint"; 263 264 case CXType_ULong: 265 includeHandler.addCompatible(); 266 return "c_ulong"; 267 268 case CXType_ULongLong: return "ulong"; 269 case CXType_UInt128: return "<unimplemented>"; 270 case CXType_Char_S: return "char"; 271 case CXType_SChar: return "byte"; 272 case CXType_WChar: return "wchar"; 273 case CXType_Short: return "short"; 274 case CXType_Int: return "int"; 275 276 case CXType_Long: 277 includeHandler.addCompatible(); 278 return "c_long"; 279 280 case CXType_LongLong: return "long"; 281 case CXType_Int128: return "<unimplemented>"; 282 case CXType_Float: return "float"; 283 case CXType_Double: return "double"; 284 case CXType_LongDouble: return "real"; 285 case CXType_NullPtr: return "null"; 286 case CXType_Overload: return "<unimplemented>"; 287 case CXType_Dependent: return "<unimplemented>"; 288 case CXType_ObjCId: return rewriteIdToObjcObject ? "ObjcObject" : "id"; 289 case CXType_ObjCClass: return "Class"; 290 case CXType_ObjCSel: return "SEL"; 291 292 case CXType_Complex: 293 case CXType_Pointer: 294 case CXType_BlockPointer: 295 case CXType_LValueReference: 296 case CXType_RValueReference: 297 case CXType_Record: 298 case CXType_Enum: 299 case CXType_Typedef: 300 case CXType_FunctionNoProto: 301 case CXType_FunctionProto: 302 case CXType_Vector: 303 case CXType_IncompleteArray: 304 case CXType_VariableArray: 305 case CXType_DependentSizedArray: 306 case CXType_MemberPointer: 307 return "<unimplemented>"; 308 309 default: assert(0, "Unhandled type kind " ~ kind.toString); 310 } 311 }