// This file is part of Visual D // // Visual D integrates the D programming language into Visual Studio // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt module vdc.util; import vdc.lexer; import std.conv; import std.string; import std.array; //////////////////////////////////////////////////////////////// // use instead of assert() to be nicely breakable and avoid the bad // semantics of assert(false) void _assert(bool cond) { if(!cond) assert(false); } //////////////////////////////////////////////////////////////// alias int TokenId; enum NumTokens = TOK_end_Operators; struct TextPos { int index; int line; int opCmp(ref const(TextPos) tp) const { if(line != tp.line) return line - tp.line; return index - tp.index; } } struct TextSpan { TextPos start; TextPos end; } // returns < 0 if adr1 < adr2 int compareTextSpanAddress(int line1, int index1, int line2, int index2) { int difflines = line1 - line2; if(difflines != 0) return difflines; return index1 - index2; } bool textSpanContains(ref const(TextSpan) span, int line, int index) { return compareTextSpanAddress(span.start.line, span.start.index, line, index) <= 0 && compareTextSpanAddress(span.end.line, span.end.index, line, index) > 0; } class Token { TokenId id; // terminals and non-terminals string txt; TextSpan span; void copy(const(Token) tok) { id = tok.id; txt = tok.txt; span = tok.span; } } //////////////////////////////////////////////////////////////// string genFlagsEnum(string name, string prefix, string[] allMembers) { string s = "enum " ~ name ~ " { "; foreach(i, c; allMembers) s ~= prefix ~ c ~ " = 1 << " ~ to!string(i) ~ ", "; s ~= "}"; return s; } // Attribute also used for storage class enum AttrBits { Extern, Synchronized, Static, Final, Abstract, Const, Auto, Scope, Ref, Volatile, Gshared, Thread, Shared, Immutable, Pure, Nothrow, Inout, ExternC, ExternCPP, ExternD, ExternWindows, ExternPascal, ExternSystem, Export, Align, Align1, Align2, Align4, Align8, Align16, } mixin(genFlagsEnum("", "Attr_", [__traits(allMembers,AttrBits)])); enum Attr_AlignMask = Attr_Align | Attr_Align1 | Attr_Align2 | Attr_Align4 | Attr_Align8 | Attr_Align16; enum Attr_CallMask = Attr_ExternC | Attr_ExternCPP | Attr_ExternD | Attr_ExternWindows | Attr_ExternPascal | Attr_ExternSystem; enum Attr_ShareMask = Attr_Shared | Attr_Gshared | Attr_Thread; alias uint Attribute; Attribute tokenToAttribute(TokenId tok) { switch(tok) { case TOK_extern: return Attr_Extern; case TOK_synchronized: return Attr_Synchronized; case TOK_static: return Attr_Static; case TOK_final: return Attr_Final; case TOK_abstract: return Attr_Abstract; case TOK_const: return Attr_Const; case TOK_auto: return Attr_Auto; case TOK_scope: return Attr_Scope; case TOK_ref: return Attr_Ref; case TOK_volatile: return Attr_Volatile; case TOK___gshared: return Attr_Gshared; case TOK___thread: return Attr_Thread; case TOK_shared: return Attr_Shared; case TOK_immutable: return Attr_Immutable; case TOK_pure: return Attr_Pure; case TOK_nothrow: return Attr_Nothrow; case TOK_inout: return Attr_Inout; case TOK_export: return Attr_Export; case TOK_align: return Attr_Align; default: return 0; } } TokenId attributeToToken(Attribute attr) { switch(attr) { case Attr_Extern: return TOK_extern; case Attr_Synchronized: return TOK_synchronized; case Attr_Static: return TOK_static; case Attr_Final: return TOK_final; case Attr_Abstract: return TOK_abstract; case Attr_Const: return TOK_const; case Attr_Auto: return TOK_auto; case Attr_Scope: return TOK_scope; case Attr_Ref: return TOK_ref; case Attr_Volatile: return TOK_volatile; case Attr_Gshared: return TOK___gshared; case Attr_Thread: return TOK___thread; case Attr_Shared: return TOK_shared; case Attr_Immutable: return TOK_immutable; case Attr_Pure: return TOK_pure; case Attr_Nothrow: return TOK_nothrow; case Attr_Inout: return TOK_inout; case Attr_Export: return TOK_export; case Attr_Align: return TOK_align; default: return -1; } } Attribute combineAttributes(Attribute attr, Attribute newAttr) { if(newAttr & Attr_AlignMask) attr &= ~Attr_AlignMask; if(newAttr & Attr_CallMask) attr &= ~Attr_CallMask; if(newAttr & Attr_ShareMask) attr &= ~Attr_ShareMask; return attr | newAttr; } string attrToString(Attribute attr) { switch(attr) { case Attr_Extern: return "extern"; case Attr_Synchronized: return "synchronized"; case Attr_Static: return "static"; case Attr_Final: return "final"; case Attr_Abstract: return "abstract"; case Attr_Const: return "const"; case Attr_Auto: return "auto"; case Attr_Scope: return "scope"; case Attr_Ref: return "ref"; case Attr_Volatile: return "volatile"; case Attr_Gshared: return "__gshared"; case Attr_Thread: return "__thread"; case Attr_Shared: return "shared"; case Attr_Immutable: return "immutable"; case Attr_Pure: return "pure"; case Attr_Nothrow: return "nothrow"; case Attr_Inout: return "inout"; case Attr_ExternC: return "extern(C)"; case Attr_ExternCPP: return "extern(C++)"; case Attr_ExternD: return "extern(D)"; case Attr_ExternWindows: return "extern(Windows)"; case Attr_ExternPascal: return "extern(Pascal)"; case Attr_ExternSystem: return "extern(System)"; case Attr_Export: return "export"; case Attr_Align: return "align"; case Attr_Align1: return "align(1)"; case Attr_Align2: return "align(2)"; case Attr_Align4: return "align(4)"; case Attr_Align8: return "align(8)"; case Attr_Align16: return "align(16)"; default: assert(false); } } string attrToStringC(Attribute attr) { // Compiler-Specific switch(attr) { case Attr_Extern: return "extern"; case Attr_Synchronized: return ""; case Attr_Static: return "static"; case Attr_Final: return ""; case Attr_Abstract: return ""; case Attr_Const: return "const"; case Attr_Auto: return "auto"; case Attr_Scope: return "scope"; case Attr_Ref: return "ref"; case Attr_Volatile: return "volatile"; case Attr_Gshared: return ""; case Attr_Thread: return "__declspec(thread)"; case Attr_Shared: return "shared"; case Attr_Immutable: return "const"; case Attr_Pure: return ""; case Attr_Nothrow: return ""; case Attr_Inout: return ""; case Attr_ExternC: return "extern \"C\""; case Attr_ExternCPP: return ""; case Attr_ExternD: return ""; case Attr_ExternWindows: return "__stdcall"; case Attr_ExternPascal: return "__pascal"; case Attr_ExternSystem: return "__stdcall"; case Attr_Export: return "__declspec(dllexport)"; case Attr_Align: return "__declspec(align(4))"; case Attr_Align1: return "__declspec(align(1))"; case Attr_Align2: return "__declspec(align(2))"; case Attr_Align4: return "__declspec(align(4))"; case Attr_Align8: return "__declspec(align(8))"; case Attr_Align16: return "__declspec(align(16))"; default: assert(false); } } //////////////////////////////////////////////////////////////// enum AnnotationBits { Deprecated, Override, Private, Package, Protected, Nogc, Public, Export, Disable, Property, Safe, System, Trusted, } mixin(genFlagsEnum("", "Annotation_", [__traits(allMembers,AnnotationBits)])); alias uint Annotation; enum Annotation_ProtectionMask = Annotation_Private | Annotation_Protected | Annotation_Public | Annotation_Package; enum Annotation_SafeMask = Annotation_Safe | Annotation_System | Annotation_Trusted; Annotation tokenToAnnotation(TokenId tok) { switch(tok) { case TOK_deprecated: return Annotation_Deprecated; case TOK_override: return Annotation_Override; case TOK_disable: return Annotation_Disable; case TOK_property: return Annotation_Property; case TOK_nogc: return Annotation_Nogc; case TOK_safe: return Annotation_Safe; case TOK_system: return Annotation_System; case TOK_trusted: return Annotation_Trusted; default: return 0; } } Annotation tokenToProtection(TokenId tok) { switch(tok) { case TOK_private: return Annotation_Private; case TOK_package: return Annotation_Package; case TOK_protected: return Annotation_Protected; case TOK_public: return Annotation_Public; case TOK_export: return Annotation_Export; default: return 0; } } Annotation combineAnnotations(Annotation annot, Annotation newAnnot) { if(newAnnot & Annotation_ProtectionMask) annot &= ~Annotation_ProtectionMask; if(newAnnot & Annotation_SafeMask) annot &= ~Annotation_SafeMask; return annot | newAnnot; } string annotationToString(Annotation annot) { switch(annot) { case Annotation_Deprecated:return "deprecated"; case Annotation_Override: return "override"; case Annotation_Disable: return "@disable"; case Annotation_Property: return "@property"; case Annotation_Nogc: return "@nogc"; case Annotation_Safe: return "@safe"; case Annotation_System: return "@system"; case Annotation_Trusted: return "@trusted"; case Annotation_Private: return "private"; case Annotation_Package: return "package"; case Annotation_Protected: return "protected"; case Annotation_Public: return "public"; case Annotation_Export: return "export"; default: assert(false); } } //////////////////////////////////////////////////////////////// string _mixinGetClasses(allMembers...)() { string s; foreach(c; allMembers) s ~= "if(is(" ~ c ~ " == class)) classes ~= `" ~ c ~ "`;"; return s; } string[] getClasses(allMembers...)() { string[] classes; mixin(_mixinGetClasses!(allMembers)); return classes; } string genClassEnum(allMembers...)(string name, string prefix, int off) { string[] classes = getClasses!allMembers(); string s = "enum " ~ name ~ " { "; bool first = true; foreach(c; classes) { if(first) s ~= prefix ~ c ~ " = " ~ to!string(off) ~ ", "; else s ~= prefix ~ c ~ ", "; first = false; } if(prefix.length > 0) s ~= prefix ~ "end"; s ~= " }"; return s; } version(none) mixin(genClassEnum!(__traits(allMembers,vdc.parser.expr), __traits(allMembers,vdc.parser.decl), __traits(allMembers,vdc.parser.stmt), __traits(allMembers,vdc.parser.mod), __traits(allMembers,vdc.parser.aggr), __traits(allMembers,vdc.parser.misc))("", "NT_", TOK_end_Operators));