Skip to content

Commit

Permalink
Enhanced version of dip1036 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdruppe committed Nov 14, 2023
1 parent 37bdb7f commit c6c4ec7
Show file tree
Hide file tree
Showing 20 changed files with 764 additions and 182 deletions.
20 changes: 20 additions & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,7 @@ struct ASTBase
inout(SuperExp) isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
inout(NullExp) isNullExp() { return op == EXP.null_ ? cast(typeof(return))this : null; }
inout(StringExp) isStringExp() { return op == EXP.string_ ? cast(typeof(return))this : null; }
inout(InterpExp) isInterpExp() { return op == EXP.interpolated ? cast(typeof(return))this : null; }
inout(TupleExp) isTupleExp() { return op == EXP.tuple ? cast(typeof(return))this : null; }
inout(ArrayLiteralExp) isArrayLiteralExp() { return op == EXP.arrayLiteral ? cast(typeof(return))this : null; }
inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == EXP.assocArrayLiteral ? cast(typeof(return))this : null; }
Expand Down Expand Up @@ -4907,6 +4908,25 @@ struct ASTBase
}
}

extern (C++) final class InterpExp : Expression
{
InterpolatedSet interpolatedSet;
char postfix = 0; // 'c', 'w', 'd'

extern (D) this(const ref Loc loc, InterpolatedSet* interpolatedSet, char postfix = 0)
{
super(loc, EXP.interpolatedSet, __traits(classInstanceSize, InterpExp));
this.interpolatedSet = interpolatedSet;
this.postfix = postfix;
}

override void accept(Visitor v)
{
v.visit(this);
}
}


extern (C++) final class StringExp : Expression
{
union
Expand Down
29 changes: 29 additions & 0 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ extern (C++) abstract class Expression : ASTNode
inout(SuperExp) isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
inout(NullExp) isNullExp() { return op == EXP.null_ ? cast(typeof(return))this : null; }
inout(StringExp) isStringExp() { return op == EXP.string_ ? cast(typeof(return))this : null; }
inout(InterpExp) isInterpExp() { return op == EXP.interpolated ? cast(typeof(return))this : null; }
inout(TupleExp) isTupleExp() { return op == EXP.tuple ? cast(typeof(return))this : null; }
inout(ArrayLiteralExp) isArrayLiteralExp() { return op == EXP.arrayLiteral ? cast(typeof(return))this : null; }
inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == EXP.assocArrayLiteral ? cast(typeof(return))this : null; }
Expand Down Expand Up @@ -1884,6 +1885,33 @@ extern (C++) final class StringExp : Expression
}
}

extern (C++) final class InterpExp : Expression
{
char postfix = NoPostfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe = OwnedBy.code;
InterpolatedSet* interpolatedSet;

enum char NoPostfix = 0;

extern (D) this(const ref Loc loc, InterpolatedSet* set, char postfix = NoPostfix) scope
{
super(loc, EXP.interpolated);
this.interpolatedSet = set;
this.postfix = postfix;
}

static InterpExp create(const ref Loc loc, InterpolatedSet* set)
{
return new InterpExp(loc, set);
}

override void accept(Visitor v)
{
v.visit(this);
}
}


/***********************************************************
* A sequence of expressions
*
Expand Down Expand Up @@ -5529,6 +5557,7 @@ private immutable ubyte[EXP.max+1] expSize = [
EXP.preMinusMinus: __traits(classInstanceSize, PreExp),
EXP.identifier: __traits(classInstanceSize, IdentifierExp),
EXP.string_: __traits(classInstanceSize, StringExp),
EXP.interpolated: __traits(classInstanceSize, InterpExp),
EXP.this_: __traits(classInstanceSize, ThisExp),
EXP.super_: __traits(classInstanceSize, SuperExp),
EXP.halt: __traits(classInstanceSize, HaltExp),
Expand Down
16 changes: 16 additions & 0 deletions compiler/src/dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class TemplateDeclaration;
class ClassDeclaration;
class OverloadSet;
class StringExp;
class InterpExp;
class LoweredAssignExp;
#ifdef IN_GCC
typedef union tree_node Symbol;
Expand Down Expand Up @@ -129,6 +130,7 @@ class Expression : public ASTNode
SuperExp* isSuperExp();
NullExp* isNullExp();
StringExp* isStringExp();
InterpExp* isInterpExp();
TupleExp* isTupleExp();
ArrayLiteralExp* isArrayLiteralExp();
AssocArrayLiteralExp* isAssocArrayLiteralExp();
Expand Down Expand Up @@ -370,6 +372,20 @@ class StringExp final : public Expression
void writeTo(void* dest, bool zero, int tyto = 0) const;
};

class InterpExp final : public Expression
{
public:
utf8_t postfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe;
void* interpolatedSet;

static InterpExp *create(const Loc &loc, void* set);

void accept(Visitor* v) override { v->visit(this); }
}



// Tuple

class TupleExp final : public Expression
Expand Down
78 changes: 78 additions & 0 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -4113,6 +4113,84 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
}

override void visit(InterpExp e)
{
// the lexer breaks up into an odd/even array of literals and expression code
// we need to turn that into:
/+
tuple(
.object.imported!"core.interpolation".InterpolationHeader(),
...
.object.imported!"core.interpolation".InterpolationFooter()
)

There the ... loops through them all, making the even ones
.object.imported!"core.interpolation".InterpolatedLiteral!str()
and making the odd ones
.object.imported!"core.interpolation".InterpolatedExpression!str(),
the code represented by str

Empty string literals are skipped as they provide no additional information.
+/

if (e.postfix)
error(e.loc, "String postfixes on interpolated expression sequences are not allowed.");

Expression makeNonTemplateItem(Identifier which) {
Expression id = new IdentifierExp(e.loc, Id.empty);
id = new DotIdExp(e.loc, id, Id.object);
auto moduleNameArgs = new Objects();
moduleNameArgs.push(new StringExp(e.loc, "core.interpolation"));
id = new DotTemplateInstanceExp(e.loc, id, Id.imported, moduleNameArgs);
id = new DotIdExp(e.loc, id, which);
id = new CallExp(e.loc, id, new Expressions());
return id;
}

Expression makeTemplateItem(Identifier which, string arg) {
Expression id = new IdentifierExp(e.loc, Id.empty);
id = new DotIdExp(e.loc, id, Id.object);
auto moduleNameArgs = new Objects();
moduleNameArgs.push(new StringExp(e.loc, "core.interpolation"));
id = new DotTemplateInstanceExp(e.loc, id, Id.imported, moduleNameArgs);
auto tiargs = new Objects();
auto templateStringArg = new StringExp(e.loc, arg);
// banning those instead of forwarding them
// templateStringArg.postfix = e.postfix; // forward the postfix to these literals
tiargs.push(templateStringArg);
id = new DotTemplateInstanceExp(e.loc, id, which, tiargs);
id = new CallExp(e.loc, id, new Expressions());
return id;
}

auto arguments = new Expressions();
arguments.push(makeNonTemplateItem(Id.InterpolationHeader));

foreach (idx, str; e.interpolatedSet.parts)
{
if (idx % 2 == 0)
{
if (str.length > 0)
arguments.push(makeTemplateItem(Id.InterpolatedLiteral, str));
}
else
{
arguments.push(makeTemplateItem(Id.InterpolatedExpression, str));
Expressions* mix = new Expressions();
mix.push(new StringExp(e.loc, str));
// FIXME: i'd rather not use MixinExp but idk how to do it lol
arguments.push(new MixinExp(e.loc, mix));
}
}

arguments.push(makeNonTemplateItem(Id.InterpolationFooter));

auto loweredTo = new TupleExp(e.loc, arguments);
visit(loweredTo);

result = loweredTo;
}

override void visit(StringExp e)
{
static if (LOGSEMANTIC)
Expand Down
Loading

0 comments on commit c6c4ec7

Please sign in to comment.