www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - aspects on methods?

reply jj75607 <jj75607 gmail.com> writes:
I want to use aspect-like annotations to transform

    Lockable
   class Abc
   {
        sync
       void f() {
           writeln("f");
       }

        shared
       void g() {
           writeln("g");
       }
   }

to something like:

   class Abc
   {
       shared(ReadWriteMutex) _lock123;

       this()
       {
           _lock123 = cast(shared)(new ReadWriteMutex());
       }

       void f() {
           synchronized((cast()_lock123).writer) {
               writeln("f");
           }
       }

       void g() {
           synchronized((cast()_lock123).reader) {
               writeln("g");
           }
       }
   }

How can I do that?
Jul 12 2016
next sibling parent Lodovico Giaretta <lodovico giaretart.net> writes:
On Tuesday, 12 July 2016 at 11:26:20 UTC, jj75607 wrote:
 I want to use aspect-like annotations to transform

    Lockable
   class Abc
   {
        sync
       void f() {
           writeln("f");
       }

        shared
       void g() {
           writeln("g");
       }
   }

 to something like:

   class Abc
   {
       shared(ReadWriteMutex) _lock123;

       this()
       {
           _lock123 = cast(shared)(new ReadWriteMutex());
       }

       void f() {
           synchronized((cast()_lock123).writer) {
               writeln("f");
           }
       }

       void g() {
           synchronized((cast()_lock123).reader) {
               writeln("g");
           }
       }
   }

 How can I do that?
I don't think UDAs can be used that way in D, but I'm not an expert. When I want to achieve something similar to this kind of rewriting, I usually use a mix of template mixins[1] and string mixins[2,3]. [1] https://dlang.org/spec/template-mixin.html [2] https://dlang.org/spec/statement.html#MixinStatement [3] https://dlang.org/mixin.html
Jul 12 2016
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 12 July 2016 at 11:26:20 UTC, jj75607 wrote:
you can't. there is no AST macros in D, so you can't rewrite 
parsed source.
Jul 12 2016
prev sibling parent Anonymouse <asdf asdf.net> writes:
On Tuesday, 12 July 2016 at 11:26:20 UTC, jj75607 wrote:
 I want to use aspect-like annotations to transform
[...] Two methods spring to mind but both create new types. You can either write a function that iterates through the members of your class, generating a string mixin that selectively hijacks calls to functions you have annotated with some UDA. Then it would just forward the function call inside synchronized blocks. alias this should hopefully be enough to forward other members. See https://dpaste.dzfl.pl/6a9cc4946caf for a rough example. It's not robust, doesn't work with overloads (needs an additional foreach over __traits(getOverloads, C, memberstring)), but I hope it conveys the idea. The alternative is to write a wrapper that similarly hijacks and wraps calls inside synchronized blocks, but by using opDispatch. The approach is less complex but sadly doesn't work as well; alias this seems to be more or less mutually exclusive to opDispatch, which makes sense. See https://dpaste.dzfl.pl/a5dac71ab4f8. Accessing enums and other types is also iffy since functions can't return types. As long as you make the base class instance public you can always bypass things that way. In both examples it may make sense to have the generated functions return via auto ref, it depends on your use cases.
Jul 13 2016