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