1 /**
2  * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Jan 29, 2012
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module clang.Type;
8 
9 import mambo.core._;
10 
11 import clang.c.index;
12 import clang.Cursor;
13 import clang.Util;
14 
15 struct Type
16 {
17 	mixin CX;
18 
19 	@property string spelling ()
20 	{
21 		auto r = clang_getTypeDeclaration(cx);
22 		return Cursor(r).spelling;
23 	}
24 	
25 	@property bool isTypedef ()
26 	{
27 		return kind == CXTypeKind.CXType_Typedef;
28 	}
29 
30 	@property bool isEnum ()
31 	{
32 		return kind == CXTypeKind.CXType_Enum;
33 	}
34 	
35 	@property Type canonicalType ()
36 	{
37 		auto r = clang_getCanonicalType(cx);
38 		return Type(r);
39 	}
40 	
41 	@property Type pointeeType ()
42 	{
43 		auto r = clang_getPointeeType(cx);
44 		return Type(r);
45 	}
46 	
47 	@property bool isValid ()
48 	{
49 	    return kind != CXTypeKind.CXType_Invalid;
50 	}
51 	
52 	@property bool isFunctionType ()
53 	{
54 		with (CXTypeKind)
55 			return kind == CXType_FunctionNoProto ||
56 				kind == CXType_FunctionProto || 
57 				// FIXME: This "hack" shouldn't be needed.
58 				func.resultType.isValid;
59 	}
60 	
61 	@property bool isFunctionPointerType ()
62 	{
63 		with (CXTypeKind)
64 			return kind == CXType_Pointer && pointeeType.isFunctionType;
65 	}
66 	
67 	@property bool isObjCIdType ()
68 	{
69 		return isTypedef &&
70 			canonicalType.kind ==  CXTypeKind.CXType_ObjCObjectPointer &&
71 			spelling == "id";
72 	}
73 	
74 	@property bool isObjCClassType ()
75 	{
76 		return isTypedef &&
77 			canonicalType.kind ==  CXTypeKind.CXType_ObjCObjectPointer &&
78 			spelling == "Class";
79 	}
80 	
81 	@property bool isObjCSelType ()
82 	{
83 		with(CXTypeKind)
84 			if (isTypedef)
85 			{
86 				auto c = canonicalType;
87 				return c.kind == CXType_Pointer &&
88 					c.pointeeType.kind == CXType_ObjCSel;
89 			}
90 		
91 			else
92 				return false;
93 	}
94 	
95 	@property bool isObjCBuiltinType ()
96 	{
97 		return isObjCIdType || isObjCClassType || isObjCSelType;
98 	}
99 
100 	@property bool isWideCharType ()
101 	{
102 		with (CXTypeKind)
103 			return kind == CXType_WChar || kind == CXType_SChar;
104 	}
105 	
106 	@property bool isConst ()
107 	{
108 		return clang_isConstQualifiedType(cx) == 1;
109 	}
110 	
111 	@property bool isExposed ()
112 	{
113 		return kind != CXTypeKind.CXType_Unexposed;
114 	}
115 
116 	@property bool isAnonymous ()
117 	{
118 		return spelling.isEmpty;
119 	}
120 
121 	@property Cursor declaration ()
122 	{
123 	    auto r = clang_getTypeDeclaration(cx);
124 	    return Cursor(r);
125 	}
126 	
127 	@property FuncType func ()
128 	{
129 		return FuncType(this);
130 	}
131 	
132 	@property ArrayType array ()
133 	{
134 		return ArrayType(this);
135 	}
136 }
137 
138 struct FuncType
139 {
140 	Type type;
141 	alias type this;
142 
143 	@property Type resultType ()
144 	{
145 		auto r = clang_getResultType(type.cx);
146 		return Type(r);
147 	}
148 	
149 	@property Arguments arguments ()
150 	{
151 		return Arguments(this);
152 	}
153 	
154 	@property bool isVariadic ()
155 	{
156 		return clang_isFunctionTypeVariadic(type.cx) == 1;
157 	}
158 }
159 
160 struct ArrayType
161 {
162 	Type type;
163 	alias type this;
164 	
165 	@property Type elementType ()
166 	{
167 		auto r = clang_getArrayElementType(cx);
168 		return Type(r);
169 	}
170 	
171 	@property long size ()
172 	{
173 		return clang_getArraySize(cx);
174 	}
175 }
176 
177 struct Arguments
178 {
179 	FuncType type;
180 	
181     @property uint length ()
182     {
183 		return clang_getNumArgTypes(type.type.cx);
184     }
185 
186 	Type opIndex (uint i)
187 	{
188 		auto r = clang_getArgType(type.type.cx, i);
189 		return Type(r);
190 	}
191 	
192 	int opApply (int delegate (ref Type) dg)
193 	{
194 		foreach (i ; 0 .. length)
195 		{
196 			auto type = this[i];
197 			
198 			if (auto result = dg(type))
199 				return result;
200 		}
201 
202 		return 0;
203 	}
204 }
205 
206 @property bool isUnsigned (CXTypeKind kind)
207 {
208 	with (CXTypeKind)
209 		switch (kind)
210 		{
211 			case CXType_Char_U: return true;
212 			case CXType_UChar: return true;
213 			case CXType_UShort: return true;
214 			case CXType_UInt: return true;
215 			case CXType_ULong: return true;
216 			case CXType_ULongLong: return true;
217 			case CXType_UInt128: return true;
218 
219 			default: return false;
220 		}
221 }