On Mon, 18 Oct 2010 20:07:16 -0400, Nick Sabalausky <a...@a.a> wrote:
I don't know if others have noticed this before, but I think I've found a
notable limitation in D's metaprogramming potential: There doesn't appear to
be a way to have mutable global state at compile-time.

Challange:

Create two..."things"...they can be functions, templates, variables,
mix-n-match, whatever. One of them increments a counter, and the other can
be used to retreive the value. But both of these must operate at
compile-time, and they must both be callable (directly or indirectly,
doesn't matter) from within the context of any module that imports them.

This is an example, except it operates at run-time, not compile-time:

-----------------------------------
// a.d
module a;
int value=0;
void inc()
{
    value++;
}
int get()
{
    return value;
}

void incFromA()
{
    inc();
}

//b.d
module b;
import a;
void incFromB()
{
    inc();
}

//main.d
import a;
import b;
import std.stdio;
void main()
{
    inc();
    incFromA();
    incFromB();
    writeln(get());
}
-----------------------------------

The goal of this challenge is to define a global-level manifest constant
enum that holds a value that has been incremented from multiple modules:

enum GOAL = ????;

It can, of course, then be displayed via:
pragma(msg, std.conv.to!string(GOAL));

At this point, I'm not concerned about order-of-execution issues resulting in unexpected or unpredictable values. As long as a value can be incremented
at compile-time from multiple modules and used to initialize an enum
manifest constant, that satisfies this challenge.


This isn't exactly what you're looking for, but you can abuse conditional compilation + D's symbol table to create a scoped counter:

string nthLabel(int n) {
    return "__Global_"~ to!string(n);
}
string incGlobal() {
return `mixin("alias int "~nthLabel( getGlobal!(__FILE__, __LINE__) )~";");`;
}
template getGlobal(string file = __FILE__, int line = __LINE__, int N = 0) {
    static if( !__traits(compiles, mixin(nthLabel(N)) ) )
        enum getGlobal = N;
    else
        enum getGlobal = getGlobal!(file,line, N+1 );
}

enum Foo    = getGlobal!(__FILE__, __LINE__) ;
mixin( incGlobal() );
enum Bar    = getGlobal!(__FILE__, __LINE__);
mixin( incGlobal() );
enum FooBar = getGlobal!(__FILE__, __LINE__);


void main(string[] args) {
    //      0        1        2
    writeln(Foo,'\t',Bar,'\t',FooBar);
    return;
}

Reply via email to