363 changes: 188 additions & 175 deletions compiler/src/dmd/frontend.h

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,16 @@
buf.writeByte(e.postfix);
}

void visitIString(IStringExp e)
{
buf.writestring("i\"");
foreach (c; e.istring)

Check warning on line 2253 in compiler/src/dmd/hdrgen.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/hdrgen.d#L2252-L2253

Added lines #L2252 - L2253 were not covered by tests
{
writeCharLiteral(buf, c);

Check warning on line 2255 in compiler/src/dmd/hdrgen.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/hdrgen.d#L2255

Added line #L2255 was not covered by tests
}
buf.writeByte('"');

Check warning on line 2257 in compiler/src/dmd/hdrgen.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/hdrgen.d#L2257

Added line #L2257 was not covered by tests
}

void visitArrayLiteral(ArrayLiteralExp e)
{
buf.writeByte('[');
Expand Down Expand Up @@ -2827,6 +2837,7 @@
case EXP.super_: return visitSuper(e.isSuperExp());
case EXP.null_: return visitNull(e.isNullExp());
case EXP.string_: return visitString(e.isStringExp());
case EXP.istring: return visitIString(e.isIStringExp());

Check warning on line 2840 in compiler/src/dmd/hdrgen.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/hdrgen.d#L2840

Added line #L2840 was not covered by tests
case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());
Expand Down
11 changes: 10 additions & 1 deletion compiler/src/dmd/lexer.d
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,16 @@ class Lexer
}
else
goto case_ident;

case 'i':
if (p[1] != '"' || Ccompile)
goto case_ident;

++p;
escapeStringConstant(t);
t.value = TOK.istring;
return;

case '"':
escapeStringConstant(t);
return;
Expand All @@ -517,7 +527,6 @@ class Lexer
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
Expand Down
9 changes: 9 additions & 0 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -2014,6 +2014,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.charLiteral:
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.istring:
case TOK.string_:
case TOK.hexadecimalString:
case TOK.file:
Expand Down Expand Up @@ -5819,6 +5820,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.null_:
case TOK.true_:
case TOK.false_:
case TOK.istring:
case TOK.string_:
case TOK.hexadecimalString:
case TOK.leftParenthesis:
Expand Down Expand Up @@ -7339,6 +7341,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.charLiteral:
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.istring:
case TOK.string_:
case TOK.hexadecimalString:
case TOK.file:
Expand Down Expand Up @@ -8255,6 +8258,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
e.isStringExp().hexString = hexString;
break;
}

case TOK.istring:
e = new AST.IStringExp(loc, token.ustring[0 .. token.len]);
nextToken();
break;

case TOK.void_:
t = AST.Type.tvoid;
goto LabelX;
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/parsetimevisitor.d
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
void visit(AST.TypeidExp e) { visit(cast(AST.Expression)e); }
void visit(AST.TraitsExp e) { visit(cast(AST.Expression)e); }
void visit(AST.StringExp e) { visit(cast(AST.Expression)e); }
void visit(AST.IStringExp e) { visit(cast(AST.Expression)e); }

Check warning on line 186 in compiler/src/dmd/parsetimevisitor.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/parsetimevisitor.d#L186

Added line #L186 was not covered by tests
void visit(AST.NewExp e) { visit(cast(AST.Expression)e); }
void visit(AST.AssocArrayLiteralExp e) { visit(cast(AST.Expression)e); }
void visit(AST.ArrayLiteralExp e) { visit(cast(AST.Expression)e); }
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/strictvisitor.d
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ extern(C++) class StrictVisitor(AST) : ParseTimeVisitor!AST
override void visit(AST.TypeidExp) { assert(0); }
override void visit(AST.TraitsExp) { assert(0); }
override void visit(AST.StringExp) { assert(0); }
override void visit(AST.IStringExp) { assert(0); }
override void visit(AST.NewExp) { assert(0); }
override void visit(AST.AssocArrayLiteralExp) { assert(0); }
override void visit(AST.ArrayLiteralExp) { assert(0); }
Expand Down
16 changes: 16 additions & 0 deletions compiler/src/dmd/tokens.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
import dmd.root.rmem;
import dmd.root.utf;

/* if you change this, remember to update:
compiler/test/unit/lexer/location_offset.d
compiler/src/tests/cxxfrontend.cc
compiler/src/dmd/tokens.h
*/
thewilsonator marked this conversation as resolved.
Show resolved Hide resolved

enum TOK : ubyte
{
reserved,
Expand Down Expand Up @@ -124,6 +130,7 @@
// Leaf operators
identifier,
string_,
istring,
hexadecimalString,
this_,
super_,
Expand Down Expand Up @@ -380,6 +387,7 @@
// Leaf operators
identifier,
string_,
istring,
this_,
super_,
halt,
Expand Down Expand Up @@ -833,6 +841,7 @@
// For debugging
TOK.error: "error",
TOK.string_: "string",
TOK.istring: "istring",
TOK.onScopeExit: "scope(exit)",
TOK.onScopeSuccess: "scope(success)",
TOK.onScopeFailure: "scope(failure)",
Expand Down Expand Up @@ -961,6 +970,7 @@
const bufflen = 3 + 3 * floatvalue.sizeof + 1;
__gshared char[bufflen + 2] buffer; // extra 2 for suffixes
char* p = &buffer[0];
char prefix = 0;
switch (value)
{
case TOK.int32Literal:
Expand Down Expand Up @@ -1023,8 +1033,14 @@
p[length + 2] = 0;
return p[0 .. length + 2];

case TOK.istring:
prefix = 'i';
goto case TOK.string_;

Check warning on line 1038 in compiler/src/dmd/tokens.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/tokens.d#L1036-L1038

Added lines #L1036 - L1038 were not covered by tests

case TOK.string_:
OutBuffer buf;
if (prefix)
buf.writeByte(prefix);

Check warning on line 1043 in compiler/src/dmd/tokens.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/tokens.d#L1043

Added line #L1043 was not covered by tests
buf.writeByte('"');
for (size_t i = 0; i < len;)
{
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ enum class TOK : unsigned char
// Leaf operators
identifier,
string_,
istring,
hexadecimalString,
this_,
super_,
Expand Down Expand Up @@ -390,6 +391,7 @@ enum class EXP : unsigned char
// Leaf operators
identifier,
string_,
istring,
this_,
super_,
halt,
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ class ThisExp;
class SuperExp;
class NullExp;
class StringExp;
class IStringExp;
class TupleExp;
class ArrayLiteralExp;
class AssocArrayLiteralExp;
Expand Down Expand Up @@ -480,6 +481,7 @@ class ParseTimeVisitor
virtual void visit(TypeidExp *e) { visit((Expression *)e); }
virtual void visit(TraitsExp *e) { visit((Expression *)e); }
virtual void visit(StringExp *e) { visit((Expression *)e); }
virtual void visit(IStringExp *e) { visit((Expression *)e); }
virtual void visit(NewExp *e) { visit((Expression *)e); }
virtual void visit(AssocArrayLiteralExp *e) { visit((Expression *)e); }
virtual void visit(ArrayLiteralExp *e) { visit((Expression *)e); }
Expand Down
21 changes: 21 additions & 0 deletions compiler/src/tests/cxxfrontend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/tests/cxxfrontend.c, _cxxfrontend.c)
*/

#include <stdio.h>

#include "root/array.h"
#include "root/bitarray.h"
#include "root/complex_t.h"
Expand Down Expand Up @@ -1686,26 +1688,45 @@ void test_backend(FuncDeclaration *f, Type *t)

int main(int argc, char **argv)
{
fprintf(stderr, "cxxfrontend.cc starting test\n");
frontend_init();

fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_tokens();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_compiler_globals();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_visitors();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_semantic();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_skip_importall();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_expression();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_target();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_parameters();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_types();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_location();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_array();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_outbuffer();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_cppmangle();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_module();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_optional();
fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
test_filename();

fprintf(stderr, "cxxfrontend.cc %d \n", __LINE__);
frontend_term();

fprintf(stderr, "cxxfrontend.cc exit\n");
return 0;
}
14 changes: 14 additions & 0 deletions compiler/test/fail_compilation/dip1027.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* TEST_OUTPUT:
---
fail_compilation/dip1027.d(103): Error: istring ended prematurely
fail_compilation/dip1027.d(104): Error: identifier expected after $
---
*/

#line 100

void test()
{
auto t = i"$";
auto u = i"$7";
}
27 changes: 27 additions & 0 deletions compiler/test/runnable/dip1027.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
TEST_OUTPUT:
---
AliasSeq!("betty %s", 73)
AliasSeq!("betty %d", 73)
AliasSeq!("betty %d", 74)
---
*/
import core.stdc.stdio;

int main()
{
enum x = 73;
pragma(msg, i"betty $x");
pragma(msg, i"betty ${%d}x");
pragma(msg, i"betty ${%d}(x + 1)");

string betty = "betty";
printf(i"hello $(betty.ptr)\n");

int aa = 5;
int bb = 10;
string s = "ate";
printf(i"I $(s.ptr) ${%d}aa apples and ${%d}bb bananas totalling ${%d}(aa + bb) fruits! $$.\n");

return 0;
}
1 change: 1 addition & 0 deletions compiler/test/unit/lexer/location_offset.d
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ enum ignoreTokens
int128Literal,
uns128Literal,
halt,
istring,
tuple,
error,
int128,
Expand Down