1 2 // This file is part of Visual D 3 // 4 // Visual D integrates the D programming language into Visual Studio 5 // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved 6 // 7 // Distributed under the Boost Software License, Version 1.0. 8 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 9 10 module vdc.util; 11 12 import vdc.lexer; 13 14 import std.conv; 15 import std.string; 16 import std.array; 17 18 //////////////////////////////////////////////////////////////// 19 // use instead of assert() to be nicely breakable and avoid the bad 20 // semantics of assert(false) 21 void _assert(bool cond) 22 { 23 if(!cond) 24 assert(false); 25 } 26 27 //////////////////////////////////////////////////////////////// 28 alias int TokenId; 29 enum NumTokens = TOK_end_Operators; 30 31 struct TextPos 32 { 33 int index; 34 int line; 35 36 int opCmp(ref const(TextPos) tp) const 37 { 38 if(line != tp.line) 39 return line - tp.line; 40 return index - tp.index; 41 } 42 } 43 44 struct TextSpan 45 { 46 TextPos start; 47 TextPos end; 48 } 49 50 // returns < 0 if adr1 < adr2 51 int compareTextSpanAddress(int line1, int index1, int line2, int index2) 52 { 53 int difflines = line1 - line2; 54 if(difflines != 0) 55 return difflines; 56 return index1 - index2; 57 } 58 59 bool textSpanContains(ref const(TextSpan) span, int line, int index) 60 { 61 return compareTextSpanAddress(span.start.line, span.start.index, line, index) <= 0 62 && compareTextSpanAddress(span.end.line, span.end.index, line, index) > 0; 63 } 64 65 66 class Token 67 { 68 TokenId id; // terminals and non-terminals 69 string txt; 70 TextSpan span; 71 72 void copy(const(Token) tok) 73 { 74 id = tok.id; 75 txt = tok.txt; 76 span = tok.span; 77 } 78 } 79 80 //////////////////////////////////////////////////////////////// 81 string genFlagsEnum(string name, string prefix, string[] allMembers) 82 { 83 string s = "enum " ~ name ~ " { "; 84 foreach(i, c; allMembers) 85 s ~= prefix ~ c ~ " = 1 << " ~ to!string(i) ~ ", "; 86 s ~= "}"; 87 return s; 88 } 89 90 // Attribute also used for storage class 91 enum AttrBits 92 { 93 Extern, 94 Synchronized, 95 Static, 96 Final, 97 Abstract, 98 Const, 99 Auto, 100 Scope, 101 Ref, 102 Volatile, 103 Gshared, 104 Thread, 105 Shared, 106 Immutable, 107 Pure, 108 Nothrow, 109 Inout, 110 ExternC, 111 ExternCPP, 112 ExternD, 113 ExternWindows, 114 ExternSystem, 115 Export, 116 Align, 117 Align1, 118 Align2, 119 Align4, 120 Align8, 121 Align16, 122 } 123 124 mixin(genFlagsEnum("", "Attr_", [__traits(allMembers,AttrBits)])); 125 126 enum Attr_AlignMask = Attr_Align | Attr_Align1 | Attr_Align2 | Attr_Align4 | Attr_Align8 | Attr_Align16; 127 enum Attr_CallMask = Attr_ExternC | Attr_ExternCPP | Attr_ExternD | Attr_ExternWindows | Attr_ExternSystem; 128 enum Attr_ShareMask = Attr_Shared | Attr_Gshared | Attr_Thread; 129 130 alias uint Attribute; 131 132 Attribute tokenToAttribute(TokenId tok) 133 { 134 switch(tok) 135 { 136 case TOK_extern: return Attr_Extern; 137 case TOK_synchronized: return Attr_Synchronized; 138 case TOK_static: return Attr_Static; 139 case TOK_final: return Attr_Final; 140 case TOK_abstract: return Attr_Abstract; 141 case TOK_const: return Attr_Const; 142 case TOK_auto: return Attr_Auto; 143 case TOK_scope: return Attr_Scope; 144 case TOK_ref: return Attr_Ref; 145 case TOK_volatile: return Attr_Volatile; 146 case TOK___gshared: return Attr_Gshared; 147 case TOK___thread: return Attr_Thread; 148 case TOK_shared: return Attr_Shared; 149 case TOK_immutable: return Attr_Immutable; 150 case TOK_pure: return Attr_Pure; 151 case TOK_nothrow: return Attr_Nothrow; 152 case TOK_inout: return Attr_Inout; 153 case TOK_export: return Attr_Export; 154 case TOK_align: return Attr_Align; 155 default: return 0; 156 } 157 } 158 159 TokenId attributeToToken(Attribute attr) 160 { 161 switch(attr) 162 { 163 case Attr_Extern: return TOK_extern; 164 case Attr_Synchronized: return TOK_synchronized; 165 case Attr_Static: return TOK_static; 166 case Attr_Final: return TOK_final; 167 case Attr_Abstract: return TOK_abstract; 168 case Attr_Const: return TOK_const; 169 case Attr_Auto: return TOK_auto; 170 case Attr_Scope: return TOK_scope; 171 case Attr_Ref: return TOK_ref; 172 case Attr_Volatile: return TOK_volatile; 173 case Attr_Gshared: return TOK___gshared; 174 case Attr_Thread: return TOK___thread; 175 case Attr_Shared: return TOK_shared; 176 case Attr_Immutable: return TOK_immutable; 177 case Attr_Pure: return TOK_pure; 178 case Attr_Nothrow: return TOK_nothrow; 179 case Attr_Inout: return TOK_inout; 180 case Attr_Export: return TOK_export; 181 case Attr_Align: return TOK_align; 182 default: return -1; 183 } 184 } 185 186 Attribute combineAttributes(Attribute attr, Attribute newAttr) 187 { 188 if(newAttr & Attr_AlignMask) 189 attr &= ~Attr_AlignMask; 190 if(newAttr & Attr_CallMask) 191 attr &= ~Attr_CallMask; 192 if(newAttr & Attr_ShareMask) 193 attr &= ~Attr_ShareMask; 194 return attr | newAttr; 195 } 196 197 string attrToString(Attribute attr) 198 { 199 switch(attr) 200 { 201 case Attr_Extern: return "extern"; 202 case Attr_Synchronized: return "synchronized"; 203 case Attr_Static: return "static"; 204 case Attr_Final: return "final"; 205 case Attr_Abstract: return "abstract"; 206 case Attr_Const: return "const"; 207 case Attr_Auto: return "auto"; 208 case Attr_Scope: return "scope"; 209 case Attr_Ref: return "ref"; 210 case Attr_Volatile: return "volatile"; 211 case Attr_Gshared: return "__gshared"; 212 case Attr_Thread: return "__thread"; 213 case Attr_Shared: return "shared"; 214 case Attr_Immutable: return "immutable"; 215 case Attr_Pure: return "pure"; 216 case Attr_Nothrow: return "nothrow"; 217 case Attr_Inout: return "inout"; 218 case Attr_ExternC: return "extern(C)"; 219 case Attr_ExternCPP: return "extern(C++)"; 220 case Attr_ExternD: return "extern(D)"; 221 case Attr_ExternWindows: return "extern(Windows)"; 222 case Attr_ExternSystem: return "extern(System)"; 223 case Attr_Export: return "export"; 224 case Attr_Align: return "align"; 225 case Attr_Align1: return "align(1)"; 226 case Attr_Align2: return "align(2)"; 227 case Attr_Align4: return "align(4)"; 228 case Attr_Align8: return "align(8)"; 229 case Attr_Align16: return "align(16)"; 230 default: assert(false); 231 } 232 } 233 234 string attrToStringC(Attribute attr) 235 { 236 // Compiler-Specific 237 switch(attr) 238 { 239 case Attr_Extern: return "extern"; 240 case Attr_Synchronized: return ""; 241 case Attr_Static: return "static"; 242 case Attr_Final: return ""; 243 case Attr_Abstract: return ""; 244 case Attr_Const: return "const"; 245 case Attr_Auto: return "auto"; 246 case Attr_Scope: return "scope"; 247 case Attr_Ref: return "ref"; 248 case Attr_Volatile: return "volatile"; 249 case Attr_Gshared: return ""; 250 case Attr_Thread: return "__declspec(thread)"; 251 case Attr_Shared: return "shared"; 252 case Attr_Immutable: return "const"; 253 case Attr_Pure: return ""; 254 case Attr_Nothrow: return ""; 255 case Attr_Inout: return ""; 256 case Attr_ExternC: return "extern \"C\""; 257 case Attr_ExternCPP: return ""; 258 case Attr_ExternD: return ""; 259 case Attr_ExternWindows: return "__stdcall"; 260 case Attr_ExternSystem: return "__stdcall"; 261 case Attr_Export: return "__declspec(dllexport)"; 262 case Attr_Align: return "__declspec(align(4))"; 263 case Attr_Align1: return "__declspec(align(1))"; 264 case Attr_Align2: return "__declspec(align(2))"; 265 case Attr_Align4: return "__declspec(align(4))"; 266 case Attr_Align8: return "__declspec(align(8))"; 267 case Attr_Align16: return "__declspec(align(16))"; 268 default: assert(false); 269 } 270 } 271 272 //////////////////////////////////////////////////////////////// 273 enum AnnotationBits 274 { 275 Deprecated, 276 Override, 277 Private, 278 Package, 279 Protected, 280 Nogc, 281 Public, 282 Export, 283 Disable, 284 Property, 285 Safe, 286 System, 287 Trusted, 288 } 289 290 mixin(genFlagsEnum("", "Annotation_", [__traits(allMembers,AnnotationBits)])); 291 292 alias uint Annotation; 293 294 enum Annotation_ProtectionMask = Annotation_Private | Annotation_Protected | Annotation_Public | Annotation_Package; 295 enum Annotation_SafeMask = Annotation_Safe | Annotation_System | Annotation_Trusted; 296 297 Annotation tokenToAnnotation(TokenId tok) 298 { 299 switch(tok) 300 { 301 case TOK_deprecated: return Annotation_Deprecated; 302 case TOK_override: return Annotation_Override; 303 case TOK_disable: return Annotation_Disable; 304 case TOK_property: return Annotation_Property; 305 case TOK_nogc: return Annotation_Nogc; 306 case TOK_safe: return Annotation_Safe; 307 case TOK_system: return Annotation_System; 308 case TOK_trusted: return Annotation_Trusted; 309 default: return 0; 310 } 311 } 312 313 Annotation tokenToProtection(TokenId tok) 314 { 315 switch(tok) 316 { 317 case TOK_private: return Annotation_Private; 318 case TOK_package: return Annotation_Package; 319 case TOK_protected: return Annotation_Protected; 320 case TOK_public: return Annotation_Public; 321 case TOK_export: return Annotation_Export; 322 default: return 0; 323 } 324 } 325 326 Annotation combineAnnotations(Annotation annot, Annotation newAnnot) 327 { 328 if(newAnnot & Annotation_ProtectionMask) 329 annot &= ~Annotation_ProtectionMask; 330 if(newAnnot & Annotation_SafeMask) 331 annot &= ~Annotation_SafeMask; 332 return annot | newAnnot; 333 } 334 335 string annotationToString(Annotation annot) 336 { 337 switch(annot) 338 { 339 case Annotation_Deprecated:return "deprecated"; 340 case Annotation_Override: return "override"; 341 case Annotation_Disable: return "@disable"; 342 case Annotation_Property: return "@property"; 343 case Annotation_Nogc: return "@nogc"; 344 case Annotation_Safe: return "@safe"; 345 case Annotation_System: return "@system"; 346 case Annotation_Trusted: return "@trusted"; 347 case Annotation_Private: return "private"; 348 case Annotation_Package: return "package"; 349 case Annotation_Protected: return "protected"; 350 case Annotation_Public: return "public"; 351 case Annotation_Export: return "export"; 352 default: assert(false); 353 } 354 } 355 356 //////////////////////////////////////////////////////////////// 357 string _mixinGetClasses(allMembers...)() 358 { 359 string s; 360 foreach(c; allMembers) 361 s ~= "if(is(" ~ c ~ " == class)) classes ~= `" ~ c ~ "`;"; 362 return s; 363 } 364 365 string[] getClasses(allMembers...)() 366 { 367 string[] classes; 368 mixin(_mixinGetClasses!(allMembers)); 369 return classes; 370 } 371 372 string genClassEnum(allMembers...)(string name, string prefix, int off) 373 { 374 string[] classes = getClasses!allMembers(); 375 376 string s = "enum " ~ name ~ " { "; 377 bool first = true; 378 foreach(c; classes) 379 { 380 if(first) 381 s ~= prefix ~ c ~ " = " ~ to!string(off) ~ ", "; 382 else 383 s ~= prefix ~ c ~ ", "; 384 first = false; 385 } 386 if(prefix.length > 0) 387 s ~= prefix ~ "end"; 388 s ~= " }"; 389 return s; 390 } 391 392 version(none) 393 mixin(genClassEnum!(__traits(allMembers,vdc.parser.expr), 394 __traits(allMembers,vdc.parser.decl), 395 __traits(allMembers,vdc.parser.stmt), 396 __traits(allMembers,vdc.parser.mod), 397 __traits(allMembers,vdc.parser.aggr), 398 __traits(allMembers,vdc.parser.misc))("", "NT_", TOK_end_Operators));