Created
March 23, 2018 23:54
-
-
Save marler8997/d693cf9196bce846ffa5a7bff80eaf2f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void main() | |
{ | |
int a = 42; | |
import std.stdio; | |
import std.conv : text; | |
// | |
// Want to create the string "a is 42" | |
// | |
writeln("Looking for 'a is 42':"); | |
string attempt1 = text(mixin(interp("a is $(a)"))); | |
writefln("attempt1 '%s'", attempt1); // NOPE | |
//assert(attempt1 == "a is 42"); // Fails | |
string attempt2 = text(interp("a is $(a)")); | |
writefln("attempt2 '%s'", attempt2); // NOPE | |
//assert(attempt2 == "a is 42"); // Fails | |
string attempt3 = text(mixin("a is $(a)".interp)); | |
writefln("attempt3 '%s'", attempt3); // NOPE | |
//assert(attempt3 == "a is 42"); // Fails | |
} | |
// | |
// | |
// TODO: move what's below into std/experimental/typecons.d | |
// | |
// | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// NEED TO PUBLICLY IMPORT THE `tuple` SYMBOL BECAUSE THE CODE GENERATED BY | |
// THE interpolate FUNCTION REQUIRES IT. | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
// !!!!!!!!!!!!!!!!!!!!!!! | |
public import std.typecons : tuple; | |
/** | |
Returns code meant to be used inside a "mixin" that creates a tuple. | |
*/ | |
string interpolate(string str) pure @safe | |
{ | |
return "tuple(" ~ interpolateHelper1(str) ~ ")"; | |
} | |
/// ditto | |
alias interp = interpolate; // optional shorthand | |
private string interpolateHelper1(string str) pure @safe | |
{ | |
import std.string : indexOf; | |
auto dollarIndex = str.indexOf("$"); | |
if (dollarIndex < 0) | |
return `"` ~ str ~ `"`; | |
else if (dollarIndex == 0) | |
return interpolateHelper2(str[1 .. $]); | |
else | |
return `"` ~ str[0 .. dollarIndex] ~ `", ` ~ interpolateHelper2(str[dollarIndex + 1 .. $]); | |
} | |
// str starts with a dollar expression (just after the '$' character) | |
private string interpolateHelper2(string str) pure @safe | |
{ | |
if (str[0] == '(') | |
{ | |
uint depth = 1; | |
size_t i = 1; | |
for (;; i++) | |
{ | |
if (i >= str.length) | |
throw new InterpolateException("unterminted $(...) expression"); | |
if (str[i] == ')') | |
{ | |
depth--; | |
if (depth == 0) | |
break; | |
} | |
else if (str[i] == '(') | |
{ | |
depth++; | |
} | |
// TODO: handle parens inside comments/string literals, etc | |
// need a simple lexer that ignore comments/string literals | |
} | |
if (i == str.length - 1) | |
return str[1 .. i]; | |
return str[1 .. i] ~ `,` ~ interpolateHelper1(str[i + 1 .. $]); | |
} | |
else if (str[0] == '$') | |
throw new InterpolateException("interpolate $$ not implemented"); | |
else | |
throw new InterpolateException("interpolated expression $ currently requires parens $(...)"); | |
} | |
class InterpolateException : Exception | |
{ | |
this(string msg) pure @safe | |
{ | |
super(msg); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment