Proposal: __traits(code, ...) and/or .codeof

deadalnix deadalnix at gmail.com
Sat Mar 24 06:14:06 PDT 2012


Le 22/03/2012 17:00, F i L a écrit :
> So the discussions about Attributes and Aspect Oriented Programming
> (AOP) got me thinking... Basically AOP requires injecting code fragments
> together in a comprehensible way. Similarly, Attributes that go beyond
> @note (such as @GC.NoScan) need similar ability.
>
> D already has the ability to mixin arbitrary code fragments at compile
> time, and to process those in useful ways through CTFE. Which rocks.
> What it lacks is the ability to reflect upon the actual source code due
> to IO limitations of CTFE. So creating a mixin templates which pieces
> together a unique object is, to my knowledge, currently next to
> impossible (and slow since you'd have to parse and isolate code in .d
> file multiple times in a separate process, then compile again to put it
> all together).
>
> So, to quote Walter, what compelling features would it bring? Here's an
> example of a simple AOP program from the AOP wiki page (probably not the
> best implementation, but the concept is there):
>
> struct BankType
> {
> void transfer() { ... }
> void getMoneyBack() { ... }
> }
>
> struct Logger
> {
> void transfer() {
> log("transferring money...");
> }
> void getMoneyBack() {
> log("User requested money back");
> }
> }
>
> and now some magic...
>
> string bankCode(T...)(T aspects) {
> auto code = "struct Bank {";
> auto members = [__traits(allMembers, Bank)];
> foreach (m; members) {
> code ~= "void "~m~"() {";
> code ~= __traits(getMember, Bank, m).codeof;
> foreach (a; aspects) {
> if (__traits(hasMember, a, m) {
> code ~= __traits(getMember, a, m).codeof;
> }
> }
> code ~= "}"
> }
> return code ~ "}";
> }
>
> mixin template Bank(T...)
> {
> mixin(bankCode(T));
> }
>
> mixin Bank!Logger;
>
> void main() {
> auto b = Bank();
> b.transfer(); // logs
> b.getMoneyBack(); // ditto
> }
>
> So this would allow us to make "Compilers" within the Compiler
> (Codeception), since we could parse/strip/append any existing code
> fragments together in endless combination. Generic "Builders" could
> probably be built and put into a std.builder lib for general use.
>
> One particular use I have in mind is for Behavior Objects (Game
> Scripts). Each behavior would hold Property(T) objects which define
> per-property, per-state "binding" dependencies (eg.
> position.x.bind(other.x, State.Idle)) and execution code. On release,
> the Property(T) object would be stripped away (leaving just T) and it's
> behavior code "compressed" with others into optimized functions.
>
> I don't know much about the internals of DMD, so I'm not sure this is a
> realistic request, but I think the idea is compelling. Also, for
> Attributes I'm not sure this technique is really applicable. But it's
> possible that the compiler could exploit this internally for certain
> Attributes like @GC.whatever

As of discussion about properties/attributes, I wanted to do a proposal 
along that line :

@ttribute attributeName(AST ast, other template parameters . . .) {
     // Eponymous trick
     immutable AST attributeName = process(ast);

     auto process(AST ast) {
         // Do some CTFEable ast magic here.
         return newAst;
     }
}

And that would be used that way :
@attributeName(other template parameters if it make sense)
void fun() {}

And allow us to do inception within fun.

Additionally, I wanted to propose @mixin that return the AST of a string.

This isn't as easy as you think, it have a lot lot of implication about 
what you get as string. This is definitively interesting, but require 
more work for a realistic proposal.


More information about the Digitalmars-d mailing list