1 module bamboo.util; 2 3 import bamboo.types; 4 5 /// Generates a hashmap of builtin types. 6 Type[string] genbuiltins() 7 { 8 import std.algorithm : map; 9 import std.conv : to; 10 import std.traits : EnumMembers; 11 import std.typecons : tuple; 12 13 Type[string] types; 14 15 enum arr = [EnumMembers!Type].map!(x => tuple(x, x.to!string)); 16 17 foreach (item; arr) 18 { 19 types[item[1]] = item[0]; 20 } 21 22 return types; 23 } 24 25 /++ 26 Interpolated string (ie, variable expansion). 27 Any D expression can be placed inside ${ and }. Everything between the curly 28 braces will be evaluated inside your current scope, and passed as a parameter 29 (or parameters) to std.conv.text. 30 The curly braces do NOT nest, so variable expansion will end at the first 31 closing brace. If the closing brace is missing, an Exception will be thrown 32 at compile-time. 33 Author: https://github.com/Abscissa 34 License: zlib/libpng 35 Example: 36 ------------ 37 // Output: The number 21 doubled is 42! 38 int num = 21; 39 writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); 40 // Output: Empty braces output nothing. 41 writeln( mixin(interp!"Empty ${}braces ${}output nothing.") ); 42 // Output: Multiple params: John Doe. 43 auto first = "John", last = "Doe"; 44 writeln( mixin(interp!`Multiple params: ${first, " ", last}.`) ); 45 ------------ 46 +/ 47 string interp(string str)() 48 { 49 enum State 50 { 51 normal, 52 dollar, 53 code, 54 } 55 56 auto state = State.normal; 57 58 string buf; 59 buf ~= '`'; 60 61 foreach(char c; str) 62 final switch(state) 63 { 64 case State.normal: 65 if(c == '$') 66 // Delay copying the $ until we find out whether it's 67 // the start of an escape sequence. 68 state = State.dollar; 69 else if(c == '`') 70 buf ~= "`~\"`\"~`"; 71 else 72 buf ~= c; 73 break; 74 75 case State.dollar: 76 if(c == '{') 77 { 78 state = State.code; 79 buf ~= "`~_interp_text("; 80 } 81 else if(c == '$') 82 buf ~= '$'; // Copy the previous $ 83 else 84 { 85 buf ~= '$'; // Copy the previous $ 86 buf ~= c; 87 state = State.normal; 88 } 89 break; 90 91 case State.code: 92 if(c == '}') 93 { 94 buf ~= ")~`"; 95 state = State.normal; 96 } 97 else 98 buf ~= c; 99 break; 100 } 101 102 // Finish up 103 final switch(state) 104 { 105 case State.normal: 106 buf ~= '`'; 107 break; 108 109 case State.dollar: 110 buf ~= "$`"; // Copy the previous $ 111 break; 112 113 case State.code: 114 throw new Exception( 115 "Interpolated string contains an unterminated expansion. "~ 116 "You're missing a closing curly brace." 117 ); 118 } 119 120 return buf; 121 } 122 string _interp_text(T...)(T args) 123 { 124 static import std.conv; 125 static if(T.length == 0) 126 return null; 127 else 128 return std.conv.text(args); 129 }