Created
March 23, 2018 23:54
-
-
Save marler8997/f24c0ed63f078c99332d629b5f5314aa 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