August 04, 2012
OK, I just compiled one of my work apps with the hacked up dmd.

It caught me using properties as functions in a few places, which I had to fix by removing the parenthesis from some places, and the @property from a few other places (the functions weren't really properties, I just marked them as such for the syntax...)


But hey if it compiles this thing with only a few, very minor changes, I think we're in business. We should be able to close those gazillion ancient property bugs once and for all, with minimal code breakage.

I'll push it up to github later tonight for additional review.
August 04, 2012
On Saturday, August 04, 2012 23:35:47 Adam D. Ruppe wrote:
> OK, I just compiled one of my work apps with the hacked up dmd.
> 
> It caught me using properties as functions in a few places, which I had to fix by removing the parenthesis from some places, and the @property from a few other places (the functions weren't really properties, I just marked them as such for the syntax...)
> 
> 
> But hey if it compiles this thing with only a few, very minor changes, I think we're in business. We should be able to close those gazillion ancient property bugs once and for all, with minimal code breakage.
> 
> I'll push it up to github later tonight for additional review.

If you can get properties working properly that quickly, that's fantastic.

- Jonathan M Davis
August 04, 2012
On Saturday, 4 August 2012 at 21:47:44 UTC, Jonathan M Davis wrote:
> If you can get properties working properly that quickly, that's fantastic.

I did just realize I missed something.... but I'm convinced the problem before is we were going at it at the wrong time, doing the property rewrites too late, meaning it had to be duplicated a lot and was hard to check fully.

My approach here is to rewrite the properties almost immediately into function calls instead of leaving them as just function references until the last minute.

(And then in a couple places, they need to be turned back into references so you can look up the setter, but I say better to only need two special cases than twenty.)
August 04, 2012
There was a very long discussion on this before that lead me to write this:

http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Property

I should draw attention to the tables near the bottom.  It is really too bad that variables in D allow the taking of addresses by default.  If things were non-addressable by default, then they could always be promoted to properly-implemented properties.  Addressabilitiy could be added explicitly by authors that are confident that they will never need to turn their public fields into properties.  Too late for all of that now.

I tried to get DMD to do property rewriting in a vaguely general sense.  I think it's still very worthwhile to attempt it.

It didn't work for me because this was in the days of SVN and I tend to get my free time in 1-3 hour chunks.  By the time I had more free time I'd spend it all merging/updating my code to the latest revision.  I also spent a lot of my time learning how DMD's semantic analysis works.  It's pretty tangled (sorry, Walter).  So yeah, I didn't get to spend much time actually working on the property rewrite due to confusion and backtracking.  I realized that while I really wanted the feature, I wasn't having fun, nor did I have any free time to program at all. (Implementing the recursive logic for such a rewrite is really easy! Dealing with DMDs architectural corner cases... (was) not so easy.)

It'd probably be good to be minimal about it.  We might not be able to do property rewriting in a %100 awesome way without breaking backwards compatibility.  It'll still be worth it to get the property rewriting that doesn't break backwards compatibility.  Example:

struct Bar
{
	private Foo m_a;
	
	@property Foo a()
	{
		return m_a;
	}
}

struct Foo
{
	private int qux;

	Foo opBinary(string op : "+")(Foo other)
	{
		Foo result;
		result.qux = this.qux + other.qux
		return result;
	}
}

void main()
{
	Bar a;
	Foo b;

	// Error: attempt to write to a non-writable property a.a
	b = a.a + b;
}

To make the property rewrite bulletproof, we have to assume that (a.f + b) will modify a.a because a.a.opBinary!("+") is non-const.  We should then compile-time-error because the property a.a does not have a setter.
However, in current code, this would not give a compile-time error. Instead it would just work, because the caller and callee implicitly assume that the opBinary call is const, even if it's not marked as such.  There is probably a significant amount of code that would no longer compile because of this.  The answer would be to mark all such functions as const, but I'm not sure that Walter & Co would be fine with that.

It's OK though.  If Walter & Co don't want to break various calls to non-const functions at the end of expressions containing properties, then we can let that slide and only focus on the more likely cases like using += on a property field that returns a value type like an int (array.length += 1 is the classic case, with its own special-cased solution and everything).  It'd be extremely useful and possibly remove a lot of potential sources of bugs/headaches.

Anyhow, that's a lot of my background info on this subject.  I do hope someone else tackles this.  They will probably be more successful than I.  If not, I might still try it someday if the pull request might get accepted.
August 04, 2012
On Saturday, 4 August 2012 at 22:19:17 UTC, Chad J wrote:
> There was a very long discussion on this before that lead me to write this:

I'll have to read it... my thing right now works, as far as I can tell, perfectly on free function properties.

But member properties are different and I haven't gotten them to work without massive breakage yet. (I forgot all about them until just an hour ago.) For some reason, rewriting the members breaks random things like opCall too.

The good is the free function change doesn't actually break anything... the bad is member properties are the more interesting ones and if they don't work, this isn't cool....

But it doesn't look like I'll be done with this today after all :( I still have a lot of stuff I was supposed to be doing today!
August 04, 2012
On 08/04/2012 06:50 PM, Adam D. Ruppe wrote:
> On Saturday, 4 August 2012 at 22:19:17 UTC, Chad J wrote:
>> There was a very long discussion on this before that lead me to write
>> this:
>
> I'll have to read it... my thing right now works, as far as I can tell,
> perfectly on free function properties.
>
> But member properties are different and I haven't gotten them to work
> without massive breakage yet. (I forgot all about them until just an
> hour ago.) For some reason, rewriting the members breaks random things
> like opCall too.
>
> The good is the free function change doesn't actually break anything...
> the bad is member properties are the more interesting ones and if they
> don't work, this isn't cool....
>
> But it doesn't look like I'll be done with this today after all :( I
> still have a lot of stuff I was supposed to be doing today!

Best of luck, and thank you for thinking about this and getting the ball rolling!
August 05, 2012
Adam D. Ruppe:

> I should add: if a function is not marked @property, it should not change at all: it should be callable with and without parens,

I think I'd like functions not marked with @property to require the ().

Bye,
bearophile
August 05, 2012
On Sunday, 5 August 2012 at 02:17:18 UTC, bearophile wrote:
> I think I'd like functions not marked with @property to require the ().

You have the -property switch for breaking piles of perfectly good code while enabling no new functionality.

What I'm doing is completely independent of -property: I'm making @properties actually work.


And I'm almost there... I just got the struct members working but introduced a regression where dmd assert fails.
August 05, 2012
On Sunday, August 05, 2012 04:17:13 bearophile wrote:
> Adam D. Ruppe:
> > I should add: if a function is not marked @property, it should not change at all: it should be callable with and without parens,
> 
> I think I'd like functions not marked with @property to require
> the ().

I wholeheartedly agree, but it's a divisive subject. Some of us feel very strongly that functions not marked with @property should require parens, and others feel very strongly that they should be optional.

- Jonathan M Davis
August 05, 2012
On Sunday, August 05, 2012 04:25:26 Adam D. Ruppe wrote:
> On Sunday, 5 August 2012 at 02:17:18 UTC, bearophile wrote:
> > I think I'd like functions not marked with @property to require
> > the ().
> 
> You have the -property switch for breaking piles of perfectly good code while enabling no new functionality.
> 
> What I'm doing is completely independent of -property: I'm making @properties actually work.
> 
> 
> And I'm almost there... I just got the struct members working but introduced a regression where dmd assert fails.

And I think that the only thing that the -property switch currently gets _right_ is complaining about non-property functions getting called with parens. It's very buggy.

Regardless, there are indeed two general issues here:

1. Make @property work in general.

2. Make -property work correctly.

- Jonathan M Davis