Skip to content

Commit

Permalink
CTFE support for dual-context functions
Browse files Browse the repository at this point in the history
  • Loading branch information
SSoulaimane committed Apr 23, 2019
1 parent 2c8e49a commit d6139e3
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
9 changes: 8 additions & 1 deletion src/dmd/ctfeexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -1857,7 +1857,14 @@ bool isCtfeValueValid(Expression newval)
{
// e1 should be a CTFE reference
Expression e1 = (cast(AddrExp)newval).e1;
return tb.ty == Tpointer && (e1.op == TOK.structLiteral && isCtfeValueValid(e1) || e1.op == TOK.variable || e1.op == TOK.dotVariable && isCtfeReferenceValid(e1) || e1.op == TOK.index && isCtfeReferenceValid(e1) || e1.op == TOK.slice && e1.type.toBasetype().ty == Tsarray);
return tb.ty == Tpointer &&
(
(e1.op == TOK.structLiteral || e1.op == TOK.arrayLiteral) && isCtfeValueValid(e1) ||
e1.op == TOK.variable ||
e1.op == TOK.dotVariable && isCtfeReferenceValid(e1) ||
e1.op == TOK.index && isCtfeReferenceValid(e1) ||
e1.op == TOK.slice && e1.type.toBasetype().ty == Tsarray
);
}
if (newval.op == TOK.slice)
{
Expand Down
60 changes: 58 additions & 2 deletions src/dmd/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
// except for delegates. (Note that the 'this' pointer may be null).
// Func literals report isNested() even if they are in global scope,
// so we need to check that the parent is a function.
if (fd.isNested() && fd.toParent2().isFuncDeclaration() && !thisarg && istate)
if (fd.isNested() && fd.toParentLocal().isFuncDeclaration() && !thisarg && istate)
thisarg = ctfeStack.getThis();

if (fd.needThis() && !thisarg)
Expand Down Expand Up @@ -876,6 +876,26 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
InterState istatex;
istatex.caller = istate;
istatex.fd = fd;

if (fd.isThis2)
{
Expression arg0 = thisarg;
if (arg0 && arg0.type.ty == Tstruct)
{
Type t = arg0.type.pointerTo();
arg0 = new AddrExp(arg0.loc, arg0);
arg0.type = t;
}
auto elements = new Expressions(2);
(*elements)[0] = arg0;
(*elements)[1] = ctfeStack.getThis();
Type t2 = Type.tvoidptr.sarrayOf(2);
const loc = thisarg ? thisarg.loc : fd.loc;
thisarg = new ArrayLiteralExp(loc, t2, elements);
thisarg = new AddrExp(loc, thisarg);
thisarg.type = t2.pointerTo();
}

ctfeStack.startFrame(thisarg);
if (fd.vthis && thisarg)
{
Expand Down Expand Up @@ -1000,6 +1020,24 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
e = CTFEExp.voidexp;
if (tf.isref && e.op == TOK.variable && (cast(VarExp)e).var == fd.vthis)
e = thisarg;
if (tf.isref && fd.isThis2 && e.op == TOK.index)
{
auto ie = cast(IndexExp)e;
auto pe = ie.e1.isPtrExp();
auto ve = !pe ? null : pe.e1.isVarExp();
if (ve && ve.var == fd.vthis)
{
auto ne = ie.e2.isIntegerExp();
assert(ne);
assert(thisarg.op == TOK.address);
e = (cast(AddrExp)thisarg).e1;
e = (*(cast(ArrayLiteralExp)e).elements)[cast(size_t)ne.getInteger()];
if (e.op == TOK.address)
{
e = (cast(AddrExp)e).e1;
}
}
}
assert(e !is null);

// Leave the function
Expand Down Expand Up @@ -2010,6 +2048,12 @@ public:
if (istate && istate.fd.vthis)
{
result = new VarExp(e.loc, istate.fd.vthis);
if (istate.fd.isThis2)
{
result = new PtrExp(e.loc, result);
result.type = Type.tvoidptr.sarrayOf(2);
result = new IndexExp(e.loc, result, IntegerExp.literal!0);
}
result.type = e.type;
}
else
Expand All @@ -2020,6 +2064,18 @@ public:
result = ctfeStack.getThis();
if (result)
{
if (istate && istate.fd.isThis2)
{
assert(result.op == TOK.address);
result = (cast(AddrExp)result).e1;
assert(result.op == TOK.arrayLiteral);
result = (*(cast(ArrayLiteralExp)result).elements)[0];
if (e.type.ty == Tstruct)
{
result = (cast(AddrExp)result).e1;
}
return;
}
assert(result.op == TOK.structLiteral || result.op == TOK.classReference);
return;
}
Expand Down Expand Up @@ -4980,7 +5036,7 @@ public:
// Member function call

// Currently this is satisfied because closure is not yet supported.
assert(!fd.isNested());
assert(!fd.isNested() || fd.needThis());

if (pthis.op == TOK.typeid_)
{
Expand Down
38 changes: 36 additions & 2 deletions test/runnable/template10.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/********************************************/

void test1()
void test1a()
{
int a = 1;

Expand All @@ -27,6 +27,24 @@ void test1()
assert(v == 3);
}

auto test1b()
{
auto f(alias a)() { return a; }

auto f0()
{
int a = 10;
return f!a();
}
assert(f0() == 10);
}

void test1()
{
test1a();
test1b();
}

/********************************************/

class C2
Expand All @@ -46,6 +64,9 @@ class C2

void test2()
{
if (__ctfe)
return; // nested classes not yet ctfeable

int a = 20;
auto o = new C2;
auto k = o.new C2.K!a(30);
Expand Down Expand Up @@ -109,6 +130,9 @@ struct S4

void test4i(T)(T i)
{
if (__ctfe)
return; // nested classes not yet ctfeable

int b = 2;

assert(i.add(7) == 5+1+6+7);
Expand Down Expand Up @@ -174,6 +198,9 @@ void test5()

void test6a()
{
if (__ctfe)
return; // nested classes not yet ctfeable

int i = 10;
int j, k;

Expand Down Expand Up @@ -281,12 +308,19 @@ void test6()

/********************************************/

void main()
int runTests()
{
test1();
test2();
test3();
test4();
test5();
test6();
return 0;
}

void main()
{
runTests(); // runtime
enum _ = runTests(); // ctfe
}

0 comments on commit d6139e3

Please sign in to comment.