1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity low) 4 module dil.semantic.Mangler; 5 6 import dil.ast.Visitor, 7 dil.ast.Node, 8 dil.ast.Expressions; 9 import dil.semantic.TypesEnum; 10 import dil.i18n.Messages; 11 import dil.Float, 12 dil.Unicode, 13 dil.String, 14 dil.Diagnostics; 15 import common; 16 17 /// Mangles expressions used as template arguments. 18 class TArgMangler : Visitor2 19 { 20 char[] text; /// The mangled text. 21 Diagnostics diag; 22 string filePath; 23 24 void mangleFloat(Float f) 25 { 26 if (f.isNaN()) 27 text ~= "NAN"; 28 // FIXME: 29 // Replace('-', 'N') 30 // Ignore('+', 'X', '.') 31 // Ignore leading 0. E.g.: "0X123" -> "123" 32 33 // Converting from Float to long double is probably inaccurate. 34 // Matching the mangled strings of DMD will be difficult. 35 // Just use Float.toString() for now. 36 text ~= f.toString(); 37 } 38 39 /// Issues an error message. 40 void error(Token* tok, MID mid, ...) 41 { 42 auto location = tok.getErrorLocation(filePath); 43 auto msg = diag.formatMsg(mid, _arguments, _argptr); 44 auto error = new SemanticError(location, msg); 45 diag ~= error; 46 } 47 48 void utf16Error(Token* tok, cwstring s, size_t i) 49 { 50 auto e = dil.Unicode.utf16Error(s, i); 51 ushort arg1 = s[i-1], arg2 = arg1; 52 MID mid = MID.InvalidUTF16Sequence; 53 if (e == UTF16Error.Invalid) 54 arg1 = s[i-2]; 55 else if (e == UTF16Error.LoSurrogate) 56 mid = MID.MissingLowSurrogate; 57 else if (e == UTF16Error.HiSurrogate) 58 mid = MID.MissingHighSurrogate; 59 else 60 assert(0); 61 error(tok, mid, arg1, arg2); 62 } 63 64 override: 65 alias visit = super.visit; 66 67 void unhandled(Node n) 68 { 69 error(n.begin, MID.InvalidTemplateArgument, n.toText()); 70 } 71 72 void visit(IntExpr e) 73 { 74 if (cast(long)e.number < 0) 75 text ~= 'N' ~ itoa(-e.number); 76 else 77 text ~= 'i' ~ itoa(e.number); 78 } 79 80 void visit(FloatExpr e) 81 { 82 text ~= 'e'; 83 mangleFloat(e.number); 84 } 85 86 void visit(ComplexExpr e) 87 { 88 text ~= 'c'; 89 mangleFloat(e.re); 90 text ~= 'c'; 91 mangleFloat(e.im); 92 } 93 94 void visit(NullExpr e) 95 { 96 text ~= 'n'; 97 } 98 99 void visit(StringExpr e) 100 { // := MangleChar UTF8StringLength "_" UTF8StringInHex 101 char mc; // Mangle character. 102 cstring utf8str; 103 char[] tmp; 104 switch (e.charType.tid) 105 { 106 case TYP.Char: 107 mc = 'a'; 108 utf8str = e.getString(); 109 break; 110 case TYP.WChar: 111 mc = 'w'; 112 auto str = e.getWString(); 113 for (size_t i; i < str.length;) 114 { 115 auto c = decode(str, i); 116 if (c == ERROR_CHAR) { 117 utf16Error(e.begin, str, i); 118 break; 119 } 120 else 121 encode(tmp, c); 122 } 123 utf8str = tmp; 124 break; 125 case TYP.DChar: 126 mc = 'd'; 127 auto str = e.getDString(); 128 foreach (dchar c; str) 129 if (!isValidChar(c)) { 130 error(e.begin, MID.InvalidUTF32Character, c+0); 131 break; 132 } 133 else 134 encode(tmp, c); 135 utf8str = tmp; 136 break; 137 default: assert(0); 138 } 139 auto s = String(utf8str); 140 // Finally append the mangled string. 141 text ~= mc ~ itoa(s.len) ~ "_" ~ s.tohex()[]; 142 } 143 144 void visit(ArrayLiteralExpr e) 145 { 146 text ~= 'A' ~ itoa(e.values.length); 147 foreach (val; e.values) 148 visitN(val); 149 } 150 151 void visit(AArrayLiteralExpr e) 152 { 153 text ~= 'A' ~ itoa(e.values.length); 154 foreach (i, key; e.keys) 155 visitN(key), visitN(e.values[i]); 156 } 157 158 void visit(StructInitExpr e) 159 { 160 text ~= 'S' ~ itoa(e.values.length); 161 foreach (val; e.values) 162 if (val.kind == NodeKind.VoidInitExpr) 163 text ~= 'v'; 164 else 165 visitN(val); 166 } 167 }