www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Decorators, Annotations, Macros, AST =?UTF-8?Q?transforms=E2=80=A6?=

reply Russel Winder <russel winder.org.uk> writes:
…choose you favourite term.

Following on from trying to use D to write CPython extensions without
using PyD: entry points will be functions:

extern(C) type name() {
  initializeIfNoAlreadyDone();
  …
}

This immediately looks like a job for a Python decorator.

 pythonentry type name() {
  …
}

From searching the Web there is DIP6 and DIP50, but what is the current
official way of doing this source to source transform in D just now. Thanks. -- Russel. ============================================================================= Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.net 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Feb 04 2014
parent reply "Dicebot" <public dicebot.lv> writes:
There is no such thing as transformation of existing entity on 
compile-time in D. Despite having similar syntax Python 
decorators don't really have much in common with User-Defined 
Attributes. Attributes can never change symbol/type they are 
attached to, they only represent additional information available 
at compile-time.

Right now idiomatic D way to do such thing is via two-step 
declaration and mixin:

```pythonEntry.d
private string generateFromImpl(alias func)()
{
     import std.string : format;
     import std.array : join;
     import std.traits : ParameterIdentifierTuple;

     string code;

     // signature
     code ~= "extern(C) ";
     code ~= cloneFunctionDeclaration!func(
         __traits(identifier, func)[$-4, $] // new name, XImpl -> X
     );

     // body
     code ~= format(
         q{
             {
                 initializeIfNoAlreadyDone();
                 %s(%s);
             }
          },
          fullyQualifiedName!func,
          [ ParameterIdentifierTuple!func ].join(",")
     );
}

public mixin template pythonEntry(alias func)
{
     mixin(generateFromImpl!func());
}
```

```main.d
import pythonEntry;

auto nameImpl() {
     // ...
}

mixin pythonEntry!nameImpl; // will add `name` function you want
```

As you can see it is not very obvious. In practice it is even 
much more complicated as I have skipped implementation of 
cloneFunctionDeclaration - one that I use for vibe.d takes quite 
a lot of space - 
https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/internal/meta/codegen.d#L177

One can also use module introspection + UDA to automatically do 
such mixin for all function attrbiuted with  pythonentry but it 
is even more code so I'd prefer to not paste it here :)

Unfortunately Phobos is currently lacking some very common code 
generation helpers used in idiomatic D metaprogramming. I plan to 
work on improvements in that direction after tuple situation is 
taken care of.

P.S. If my talk proposal for DConf is going to be accepted, it 
will cover this very topic, extensively :P
Feb 04 2014
parent "Dicebot" <public dicebot.lv> writes:
P.P.S. proof-of-concept implemenation of function attributes a
bit more similar t python decorators :
https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/internal/meta/funcattr.d
Feb 04 2014