Am 10.08.2011, 20:34 Uhr, schrieb Nick Sabalausky <a@a.a>:

"Adam D. Ruppe" <destructiona...@gmail.com> wrote in message
news:j1ufc0$avd$1...@digitalmars.com...
Marco Leise wrote:
An unlikely example would be a C compiler within CTFE that takes a
string of C source code and turns it into a D mixin. Is that
possible?

It'd be a fair amount of work, but it should be possible.

It's tempting to try to implement that as an alternative to D
bindings modules.

mixin include_C ( import("stdio.h") );


It's a neat possibility, but the downside of that approach, I suspect, is
that it may slow down compilation.

With that approach, "stdio.h" has to be processed *every* time your program is compiled, not just whenever "stdio.h" is changed (which is what you would
get if the conversion were done with a separate tool and a proper
buildsystem). Also, I'm sure that CTFE is probably slower than running an
already compiled tool. It would have to be slower, since it *is*
interpreted, after all.

This is another reason why CTFE really needs to support IO access (I really believe the strict adherance to "CTFE must be *guaranteed* stateless" is a
mistake. It's right to strongly discourage it, but making the ban this
strict is taking things too far - similar to Java's ban on pointers). Then,
include_C could be implemented roughly like this:

string include_C(string filename)
{
    auto cache = filename~".cache";
    if(exists(cache) && timestamp(cache) >= timestamp(filename))
        return loadFile(cache);
    else
    {
        auto result = convert_C(loadFile(filename));
        saveFile(cache, result);
        return result;
    }
}

string convert_C(string src)
{
    // Do the conversion, possibly even by invoking a pre-compiled tool.
}

// Only gets processed if stdio.h has changed
mixin( include_C_file("stdio.h") );

The other big benefit, of course, if that we'd finally get compile-time
write*() for free.

This would also open the door for a CTFE/library-based buildsystem that
doesn't require a dedicated "makefile" or equivalent, which is an
interesting prospect.

Although there are other languages allowing you to call external programs during compilation it feels like opening Pandora's box and people will start sending code around that does "rm -rf ~/*". Then again, the same effect can be accomplished later at runtime so I don't know if there is really any objective difference. I wouldn't mind if there was a compiler switch to enable compile-time I/O for exactly the things you mentioned.

For starters, how about this?:
    static string someExternalText = __ctfeReadFile("external.txt");
    static byte[] chipInitialState = __ctfeReadFile("initial_state.bin");
Every external file used in compiling a source file would be added to the list of files to check for their modification date in relation to the resulting object file. This ensures that the object is recreated when either of the sources change. The list can be in a separate file per each D source using this feature.

This offers:
- no execution of arbitrary commands
- usual compile-if-newer logic doesn't reinvent the wheel
- compile-time conversion of C headers
- add snippets in domain specific languages by their own respective source files
- include microcode blobs and other binary data in your modules if desired

Personally I think this idea rocks, but YMMV :p .

Reply via email to