@property

Adam D. Ruppe destructionator at gmail.com
Sat Aug 4 10:13:04 PDT 2012


So the existing -property in the compiler as absolutely 
worthless. It is semantically wrong.

@property void function() func() {
         return { assert(0, "success"); };
}

void main() {
         func(); // should assert 0 success, doesn't
	auto dele = &func;
	dele(); // should assert 0 success, doesn't
}

Does the same thing with and without -property, and it is
wrong both ways.


Now, let's talk about doing it right. First, I think the entire
getter design in the compiler is counter productive. It looks
like it is part of the AssignExp... but you want getters to work
in a lot of places, not just AssignExp.



It looks to me that it actually belongs in the resolveProperties 
function in expression.c, or maybe even somewhere else since I 
tried this and it didn't quite work. I think this is operating on 
a whole line, not just the individual pieces. But regardless, it 
definitely belongs on a lower level than it is.



See, if you ask me, every single mention of a function name that 
is marked @property needs to be rewritten. This might break 
setters, but we'll cross that bridge when we come to it.


When we look back at the test code:

         func(); // should assert 0 success, doesn't
	auto dele = &func;


These two lines both currently refer to the getter function
itself. We want the getter function to be completely invisible
to all other code.


This should be rewritten kinda like if this were in the code:
   #define func (func())


This would also fix things like

func += 10;

if func returned a ref int.

===
@property ref int func() {
         static int a;
         return a;
}

void main() {
         // all of these should work; func should look just like 
an int to the outside world
         int a = func;
         int* b = &func;
         func += 10;
}
===
callexp.d(19): Error: cannot implicitly convert expression (& 
func) of type int function() @property ref to int*




Let's try running our "macro" over it

void main() {
         int a = (func());
         int* b = &(func());
         (func()) += 10;
}


What ACTUALLY happens right now is that works. Indeed, you HAVE 
to use the () right now to make it work!


What SHOULD happen:

callexp.d(18): Error: function expected before (), not func() of 
type int
callexp.d(20): Error: function expected before (), not func() of 
type int

Or something like that. Since @property ref int func() is 
supposed to be interchangable for a plain int func;, no special 
enforcement of @property syntax is required: it is illegal to 
call an int like a function, and func is an int as far as the 
outside world is concerned.


This is how the property syntax is enforced: by the compiler's 
existing type checks. No additional code should be there to check 
syntax.





So, I have two questions:

1) Do we all agree that @properties should be interchangeable for 
plain variables of the return value's type in all contexts? That 
is, if I can make this work with a pull request, is that going to 
be acceptable?

2) Does anyone who knows the compiler better want to give me some 
hints on the implementation? I'm still pretty sure the 
resolveProperties function is too far into it, but func on its 
own is just a void* to the function I believe at this point so... 
yeah that is complicating things. Perhaps *that* is what needs to 
change.


I'm also open to ideas on setters, but right now getter is what I 
want to focus on. If we have to rewrite a getter call on the left 
hand side of an assign exp into a setter call, we can figure that 
out later. Hell, it might even just work.  But one thing at a 
time.


More information about the Digitalmars-d mailing list