I speak of the property rewriting where an expression like foo.prop++;
is rewritten as auto t = foo.prop(); t++; foo.prop(t); So, Walter or Andrei or someone on the planning behind the scenes, please lend me your thoughts: How much time is left to make this sort of thing happen? If a working patch for this showed up, would it have a reasonable chance of acceptance at this point? I really want to make this happen, even if I have to pay someone to do it or finish it off. It's very close but I have almost nil free time for this stuff. Note that I have made it work and seen it in action. There'd be a patch two months ago if I hadn't decided to rebel against the way DMD did things*. Now I'll try and remind you why this patch is important: - I see no other way to make properties behave like lvalues in an elegant manner. Explicit property syntax does not help this. This is quite a semantics problem, and the syntax is completely orthogonal. - Having property rewrites allows the special case for "array.length += foo;" to be removed. Property rewriting is the more general solution that will work for all properties and in arbitrary expressions. - By treating opIndex and opIndexAssign as properties then that pair alone will make cases like "a[i]++;" work correctly without the need for opIndexUnary overloads. Also "a[i] += foo" will work too, as well as anything else you haven't thought of yet. - It has implications for purity. We may want to figure this out before its too late. Consider "foo.prop + bar;", where prop returns a struct with opBinary!("+") defined. It ends up being "foo.prop.opAdd(bar)". In general this is "foo.property.someFunction(args...)". In the general case you want it to call the setter function for the property so that any changes in state get propagated back to foo, as we would expect from an lvalue. If there is no setter, it's an error. However, in the (usual) case of opAdd, this is an unnecessary restriction since opAdd is likely pure and just returns a value -- there is no need to require foo to have a setter. It makes sense to me to allow the purity of member functions to determine whether or not any parent property needs its setter called. Alternatively we could just make member function calls not count as side effects for properties. That would be more dangerous though, because sometimes they ARE side effects. Things like += and -= are not as troubling because they are ALWAYS side effects, so we know what to do with them. I want +=, -=, ++, etc. to be covered even if this purity issue is completely ignored. * So I made it work. Just not well enough for production quality, unfortunately. The problem had nothing to do with the rewrite being difficult or impossible to do. Instead, the problem was me rebelling against the way DMD does things, followed by failing on rare instances of valid code. Calling Expression->semantic() twice on the same expression will do that.** This was all a little over two months ago, back when I was still unemployed. I've hardly touched it since then. ** If you're in the know, you might wonder why I would do a fool thing like call Expression->semantic() twice on the same expression. When I originally wrote the function for doing this rewrite, I wrote it to climb the expression tree with recursive calls. So I tried to keep that quality. I'd let semantic run, then I'd recursive over the tree, then run semantic again. I had an idea in mind to optimize away the second pass for expressions devoid of properties, or to even minimize the scanning to only the branches that had both side effects and properties. I was hoping this would at least make it work. But it doesn't. What I need to do then is rewrite my recursive function for doing the rewrite into a flat and non-recursive function that tracks its state using some combination of variables in Scope and variables in Expression. I'd be done already if I had just written it that way in the first place.