1 /** 2 Copyright: Copyright (c) 2016, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 */ 10 module cpptooling.data.type; 11 12 import std.traits : isSomeString; 13 import std.typecons : Flag; 14 import std.variant : Algebraic; 15 16 public import cpptooling.data.symbol.types : USRType; 17 import cpptooling.data.kind_type : TypeKind, TypeAttr, TypeKindAttr, TypeResult, toStringDecl; 18 19 static import cpptooling.data.class_classification; 20 21 /// Convert a namespace stack to a string separated by ::. 22 string toStringNs(T)(T ns) @safe if (is(Tx == CppNsStack) || is(Tx == CppNs[])) { 23 import std.algorithm : map; 24 import std.array : join; 25 26 return (cast(CppNs[]) ns).map!(a => cast(string) a).join("::"); 27 } 28 29 /// Locaiton of a symbol. 30 struct Location { 31 import std.format : FormatSpec; 32 33 /// 34 string file; 35 /// 36 uint line; 37 /// 38 uint column; 39 40 /// Create a file with default line and column 41 this(string file) @safe { 42 this(file, 0, 0); 43 } 44 45 /// 46 this(string file, uint line, uint column) @safe { 47 //TODO remove idup if it isn't needed 48 this.file = file; 49 this.line = line; 50 this.column = column; 51 } 52 53 /// Location as File Line Column 54 string toString() @safe pure { 55 import std.exception : assumeUnique; 56 import std.format : FormatSpec; 57 58 char[] buf; 59 buf.reserve(100); 60 auto fmt = FormatSpec!char("%s"); 61 toString((const(char)[] s) { buf ~= s; }, fmt); 62 auto trustedUnique(T)(T t) @trusted { 63 return assumeUnique(t); 64 } 65 66 return trustedUnique(buf); 67 } 68 69 /// ditto 70 void toString(Writer, Char)(scope Writer w, FormatSpec!Char formatSpec) { 71 import std.format : formatValue; 72 import std.range.primitives : put; 73 74 put(w, "File:"); 75 formatValue(w, file, formatSpec); 76 put(w, " Line:"); 77 formatValue(w, line, formatSpec); 78 put(w, " Column:"); 79 formatValue(w, column, formatSpec); 80 } 81 82 /// 83 T opCast(T : string)() @safe pure nothrow { 84 return toString(); 85 } 86 } 87 88 /** Represent a location. 89 * 90 * Either a: 91 * - no location. 92 * - location with data. 93 */ 94 struct LocationTag { 95 import std.format : FormatSpec; 96 97 enum Kind { 98 noloc, 99 loc 100 } 101 102 /// Kind stored. Only use the payload when kind is "loc". 103 Kind kind; 104 105 /// 106 Location payload; 107 alias payload this; 108 109 /// Create either a noloc instance when passed null or a location. 110 this(T)(T t) @safe pure { 111 static if (is(T == typeof(null))) { 112 this.kind = Kind.noloc; 113 } else { 114 this.kind = Kind.loc; 115 this.payload = t; 116 } 117 } 118 119 this(string file, uint line, uint column) { 120 this(Location(file, line, column)); 121 } 122 123 string toString() @safe pure { 124 import std.exception : assumeUnique; 125 import std.format : FormatSpec; 126 127 char[] buf; 128 buf.reserve(100); 129 auto fmt = FormatSpec!char("%s"); 130 toString((const(char)[] s) { buf ~= s; }, fmt); 131 auto trustedUnique(T)(T t) @trusted { 132 return assumeUnique(t); 133 } 134 135 return trustedUnique(buf); 136 } 137 138 void toString(Writer, Char)(scope Writer w, FormatSpec!Char formatSpec) { 139 import std.format : formatValue; 140 import std.range.primitives : put; 141 142 final switch (kind) { 143 case Kind.noloc: 144 put(w, "noloc"); 145 break; 146 case Kind.loc: 147 put(w, this.payload.toString); 148 break; 149 } 150 } 151 } 152 153 auto toString(LocationTag data) @safe pure { 154 static import std.format; 155 156 final switch (data.kind) { 157 case LocationTag.Kind.noloc: 158 return "noloc"; 159 case LocationTag.Kind.loc: 160 return data.toString; 161 } 162 } 163 164 // From this point onward only simple types thus mass apply of attributes. 165 @safe pure nothrow @nogc: 166 167 /// Name of a C++ namespace. 168 struct CppNs { 169 string payload; 170 alias payload this; 171 } 172 173 /** Stack of nested C++ namespaces. 174 * 175 * So A::B::C would be a range of [A, B, C]. 176 */ 177 struct CppNsStack { 178 CppNs[] payload; 179 alias payload this; 180 181 this(CppNs[] fqn) @safe pure nothrow { 182 payload = fqn; 183 } 184 185 this(CppNs[] reside_in_ns, CppNs name) @safe pure nothrow { 186 payload = reside_in_ns ~ name; 187 } 188 189 void put()(CppNs n) { 190 payload ~= n; 191 } 192 193 CppNs front() @safe pure nothrow { 194 assert(!empty, "Can't get front of an empty range"); 195 return payload[$ - 1]; 196 } 197 198 void popFront() @safe pure nothrow { 199 assert(!empty, "Can't pop front of an empty range"); 200 payload = payload[0 .. $ - 1]; 201 } 202 203 bool empty() @safe pure nothrow @nogc { 204 return payload.length == 0; 205 } 206 } 207 208 /// Nesting of C++ namespaces as a string. 209 struct CppNsNesting { 210 string payload; 211 alias payload this; 212 } 213 214 struct CppVariable { 215 string payload; 216 alias payload this; 217 } 218 219 struct TypeKindVariable { 220 TypeKindAttr type; 221 CppVariable name; 222 } 223 224 // Types for classes 225 struct CppClassName { 226 string payload; 227 alias payload this; 228 } 229 230 ///TODO should be Optional type, either it has a nesting or it is "global". 231 /// Don't check the length and use that as an insidential "no nesting". 232 struct CppClassNesting { 233 string payload; 234 alias payload this; 235 } 236 237 // Types for methods 238 struct CppMethodName { 239 string payload; 240 alias payload this; 241 } 242 243 struct CppConstMethod { 244 bool payload; 245 alias payload this; 246 } 247 248 struct CppVirtualMethod { 249 MemberVirtualType payload; 250 alias payload this; 251 } 252 253 struct CppAccess { 254 AccessType payload; 255 alias payload this; 256 257 T opCast(T)() if (isSomeString!T) { 258 import std.conv : to; 259 260 return payload.to!T(); 261 } 262 } 263 264 // Types for free functions 265 struct CFunctionName { 266 string payload; 267 alias payload this; 268 } 269 270 // Shared types between C and Cpp 271 alias VariadicType = Flag!"isVariadic"; 272 alias CxParam = Algebraic!(TypeKindVariable, TypeKindAttr, VariadicType); 273 274 struct CxReturnType { 275 TypeKindAttr payload; 276 alias payload this; 277 } 278 279 //TODO change name to MethodVirtualType 280 enum MemberVirtualType { 281 Unknown, 282 Normal, 283 Virtual, 284 Pure 285 } 286 287 enum AccessType { 288 Public, 289 Protected, 290 Private 291 } 292 293 enum StorageClass { 294 None, 295 Extern, 296 Static 297 } 298 299 /// The kind of language which influences name mangling. 300 enum Language { 301 unknown, 302 c, 303 cpp 304 }