August 05, 2012
Adam D. Ruppe:

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

The -property switch is present since lot of time, and I think most people that write D2 code compile their libraries with -property. So I don't think it breaks lot of D2 code today.


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

I understand. Don't rush things, even if your design takes few days we are dealing with those problems since years, so few more days are not a problem.

Bye,
bearophile
August 05, 2012
On Sunday, August 05, 2012 05:59:34 bearophile wrote:
> Adam D. Ruppe:
> > You have the -property switch for breaking piles of perfectly good code while enabling no new functionality.
> 
> The -property switch is present since lot of time, and I think most people that write D2 code compile their libraries with -property. So I don't think it breaks lot of D2 code today.

I'd be very surprised if all that many people compile with -property. I'm pretty sure that there are a lot of people (the majority?) who don't even compile with -w or -wi. Obviously, some people do, but from what I've seen, I'd guess that most people compile with the bare minimum flags required, and - property is _very_ buggy anyway.

- Jonathan M Davis
August 05, 2012
On 2012-08-04 21:28, Jonathan M Davis wrote:

> That would be kind of cool, though I would have suggested that putting
> @property on a variable would make it so that you couldn't do anything with it
> that you couldn't do with a property (e.g. taking the address of a variable
> will break when it's switched to a property, and @property on the variable
> could prevent that). But maybe your proposal is better - though I'm not sure
> how much I'd end up using it, because if you wanted to actually use the member
> variable, you'd get into naming issues. You proposed bar_ here, but I'd have
> gone with _bar, whereas some would have suggested m_bar, and regardless,
> there's no way to indicate the name with this syntax, so you'd have to either
> just know how the compiler names such variables or statically disallow using
> the property through anything other than the proprty functions. And if all the
> property does is get and set with _nothing_ else, then how is that any better
> than a public member variable, assuming that switching between a variable and
> a property is seemless like it's supposed to be? So, I think that I'd still
> prefer the approach of making it so that marking variables @property makes it
> so that you can only use them in ways that you can use a property function,
> since it gives you the same result without needing to actually create any
> functions or come up with naming schemes for implicit member variables or
> whatnot.

I see two reasons:

1. The generated methods will be virtual
2. I'm thinking that it would be possible to override either the getter or setter. Meaning you would get one for free

class Foo
{
    @property int bar:

    @property int bar (int value)
    {
        validate(value);
        return bar_ = value;
    }
}

In the above code, only a getter will be generated.

About the name of generate instance variable, we could add syntax making it possible to change the name:

class Foo
{
    @property(name=m_bar) int bar:
}

-- 
/Jacob Carlborg
August 05, 2012
On 2012-08-04 21:25, Adam D. Ruppe wrote:

> Yes, I agree in general, but if a getter returns a ref, you should
> be able to write to it... I think anyway, but it is an lvalue anyway.

Or we could disallow getters returning by reference.

> What I just added to my hacked compiler is this:
>
> =====
>   else if(e1->op == TOKcall) {
>              // for property work, if there is a setter, we should
> revert to the older style
>              // handling. If not, we can keep it as a CallExp
>              CallExp* ce = (CallExp*) e1;
>              Expression* temp_e1 = ce->e1;
>              if((temp_e1->op == TOKvar &&
> temp_e1->type->toBasetype()->ty == Tfunction)) {
>                  // this is potentially a setter.... but not necessarily
>                  fd = ((VarExp *)temp_e1)->var->isFuncDeclaration();
>                  ethis = NULL;
>                  assert(fd);
>                  FuncDeclaration *f = fd;
>                  Expressions a;
>                  a.push(e2);
>
>                  fd = f->overloadResolve(loc, ethis, &a, 1);
>                  if (fd && fd->type) {
>                      e1 = temp_e1;
>                      goto Lsetter;
>                  }
>              }
> =====
>
>
> To line 10320 - right above where the old style setter code is. It isn't
> perfect yet because it doesn't ensure we are dealing with a @property,
> but it is closer.
>
>
>
> The idea is: if we have a setter function, we should try to use it, just
> like dmd does today. If not, we'll leave the call there and see what
> happens. (If it returns ref, it will work, otherwise, it errors saying
> the property is not an lvalue.)
>
>
> So far this is passing my simple test for assignment, but not yet the op
> assigns.
>
> int a;
> @property int funcprop() {
>          return a;
> }
>
> // setter
> @property int funcprop(int s) {
>          return a = s + 10;
> }
>
> funcprop = 10; // works, funcprop == 20 now

Doesn't this already work?

> True. I think all the other uses should just work though.

Yes. Have a look at this for a workaround:

http://forum.dlang.org/thread/gknbobkfhmfszshqenng@forum.dlang.org#post-jvjs5j:248ov:241:40digitalmars.com

-- 
/Jacob Carlborg
August 05, 2012
On 2012-08-04 23:35, 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.

Awesome :)

-- 
/Jacob Carlborg
August 05, 2012
On 2012-08-04 22:53, Adam D. Ruppe wrote:

> I did this and now I think this thing is almost done
>
> ===
> int a;
> @property int funcprop() {
>          writeln("calling the getter and getting ", a);
>      return a;
> }
> @property int funcprop(int s) {
>      writeln("calling the setter with ", s);
>      return a = s;
> }
> void main() {
>      funcprop = 40;
>      funcprop += 10;
> }
> ===
>
> run:
>
> calling the setter with 40
> calling the getter and getting 40
> calling the setter with 50
>
> Looks right to me. Now I just have to check for the @property tag on
> some of these rewrites and then clean it up and test for a pull request.

BTW, how will this interact with overloaded operators and similar more advanced features? Say that I have a getter that returns a struct/class which overloads the += operator.

-- 
/Jacob Carlborg
August 05, 2012
On Sunday, 5 August 2012 at 12:18:52 UTC, Jacob Carlborg wrote:
> BTW, how will this interact with overloaded operators and similar more advanced features? Say that I have a getter that returns a struct/class which overloads the += operator.

I'm not sure yet... stuff like this is one reason why it didn't work out right last night. (I have it working in about 90% of cases, but it is interaction with those last advanced features that always keep the D bugzilla active.)


With the rewrite right now, it does getter -> opOpAssign -> setter, which isn't quite right...
August 05, 2012
On Sunday, 5 August 2012 at 12:14:41 UTC, Jacob Carlborg wrote:
> Doesn't this already work?

Yes, but it is in my test file to make sure it still works, without any additional pointless function calls.

Right now the basics all work, but member template function that happen to be getters can break - this is the assertion failure I saw last night. I think my fix to implicit this calls broke it, ugh.

And then I need to check the operator overloading.

> Yes. Have a look at this for a workaround:

I saw it, but one step at a time for now...
August 05, 2012
On 2012-08-04 21:28, Jonathan M Davis wrote:

> That would be kind of cool, though I would have suggested that putting
> @property on a variable would make it so that you couldn't do anything with it
> that you couldn't do with a property (e.g. taking the address of a variable
> will break when it's switched to a property, and @property on the variable
> could prevent that). But maybe your proposal is better - though I'm not sure
> how much I'd end up using it, because if you wanted to actually use the member
> variable, you'd get into naming issues. You proposed bar_ here, but I'd have
> gone with _bar, whereas some would have suggested m_bar, and regardless,
> there's no way to indicate the name with this syntax, so you'd have to either
> just know how the compiler names such variables or statically disallow using
> the property through anything other than the proprty functions. And if all the
> property does is get and set with _nothing_ else, then how is that any better
> than a public member variable, assuming that switching between a variable and
> a property is seemless like it's supposed to be? So, I think that I'd still
> prefer the approach of making it so that marking variables @property makes it
> so that you can only use them in ways that you can use a property function,
> since it gives you the same result without needing to actually create any
> functions or come up with naming schemes for implicit member variables or
> whatnot.

A few more reasons:

3. Binary compatibility
4. Read only fields. I quite often want to have read only fields and basically the only way to that is by using a getter property method. In D1 I could sometimes avoid this by declaring the instance variable as const, but that doesn't work in D2

-- 
/Jacob Carlborg
August 05, 2012
On 2012-08-05 15:51, Adam D. Ruppe wrote:

> And then I need to check the operator overloading.

I see.

> I saw it, but one step at a time for now...

Hehe, yes, of course. No pressure :)

-- 
/Jacob Carlborg