Proposal: user defined attributes

F i L witte2008 at gmail.com
Sun Mar 18 22:33:07 PDT 2012


Walter Bright wrote:
> I'm sorry, I find this *massively* confusing. What is foo? Why 
> are you serializing something marked "NonSerialized"? I really 
> have no idea what is going on with this. What is the 
> serialize() function?

He's giving an example of serialize() below the code you quoted.



Walter Bright wrote:
> Which looks indistinguishable from modifiable at runtime,
> instance specific data.

If you're *only* considering the runtime ability of attributes, 
then it is. This:

     attribute struct A { this(int x, int y); void foo(); }
     @A(1, 2) struct C {}

     void main() {
         auto a = C at A;
         a.foo();
     }

would be conceptually equivalent to writing:

     struct A { this(int x, int y); void foo(); }
     struct C { static auto _A() { return A(1, 2); } }

     void main() {
         auto a = C._A();
         a.foo();
     }

and it's my fault for not illustrating the important difference 
in the first place. Which is: Attributes are understandable by 
the compiler, therefor, attributes can describe behavior of an 
entity and inject code into key places where that entity is 
allocated/constructed/etc. For instance, C# does not directly 
support Unions, however creating the structure is possible, like 
so:

     [StructLayout(LayoutKind.Explicit)]
     struct MyUnion
     {
         [FieldOffset(0)] int a;
         [FieldOffset(0)] long b;
         [FieldOffset(0)] float c;
     }


Because Attributes are defined with unique syntax, they can be 
stored uniquely by the compiler, and then reacted upon _in a 
variety of ways_. They are available at runtime so that runtime 
code can react to them as well.

To illustrate what Trove and I have been talking about, If I 
wanted to "mark" a variable so that the GC wouldn't scan it, I 
might be able to write something like:

     attribute class Memory {
         GC.BlkAttr blkAttr;

         this(GC.BlkAttr attr) { blkAttr = attr; }

         @this(void* entity) {
             // the code in this function gets injected into
             // this() of the entity this class is attached to

             GC.setAttr(entity, blkAttr);
         }
     }

The "@this(void*)" function might always take in a void* (much 
like how new() always takes uint/size_t) which points to the 
entity it's attributing. So if we then write:

     @Memory(GC.BlkAttr.NO_SCAN) string myString;

Then when "myString.init()" is called,
"GC.setAttr(myString, GC.BlkAttr.NO_SCAN)" will also be executed. 
I don't know enough about DMD's internals to know about how this 
would play out internally, but the concept is there.

And I know my syntax has be changing over the last few posts 
(I've been going through different ideas), so I apologize if I'm 
being hard to follow here.


More information about the Digitalmars-d mailing list