Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tear-off: expression is not evaluated to object #24357

Closed
sgrekhov opened this issue Sep 16, 2015 · 8 comments
Closed

Tear-off: expression is not evaluated to object #24357

sgrekhov opened this issue Sep 16, 2015 · 8 comments
Assignees
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).

Comments

@sgrekhov
Copy link
Contributor

According Dart spec "16.18.3 General Closurization"

"Evaluation of a property extraction i of the form e#m proceeds as follows:
First, the expression e is evaluated to an object o. Then:..."

But in fact expression is not evaluated to object o. Run the following program

class A {
  int get g => 1;
}

class C {
  A get m => new A();
}

main() { 
  C c = new C();
  var x = c.m#g;
}

Result: error: semicolon expected
var x = c.m#g;

var x = (c.m)#g works well.

Tested on Dart VM version: 1.13.0-dev.2.0 (Tue Sep 8 05:28:05 2015) on "linux_x64"

@floitschG floitschG added the area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. label Sep 16, 2015
@lrhn lrhn added area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). and removed area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. labels Sep 17, 2015
@lrhn
Copy link
Member

lrhn commented Sep 17, 2015

The behavior is what the current grammar specifies:

postfixExpression:
  assignableExpression postfixOperator |
  primary (selector* | ( ‘#’ ( (identifier ‘=’?) | operator)))
  ;

This means that you can't put a "#foo" after a selector like .m - you can do either, but not both. It does work when you wrap it in parentheses because a parenthesized expression is a primary.

@sgrekhov
Copy link
Contributor Author

Isn't it a contradiction with

Evaluation of a property extraction i of the form e#m proceeds as follows:
First, the expression e is evaluated to an object o.?

According this statement getter invocation should be evaluated to the object which is value of the getter

@kmillikin
Copy link

It's not a contradiction, it just doesn't stand on its own. You have to read that section along with the grammar as @lrhn did above.

Consider the analogous: Evaluation of a multiplication expression of the form e0 * e1 proceeds as follows: first the expression e0 is evaluated, then the expression e1 is evaluated, then the result is multiplied.

Now, would you expect x * y + z to first evaluate x, then evaluate y + z, then multiply the results? That's not what actually happens, because if the precedence rules encoded in the grammar.

Edit: to be clear, c.m#g is not a property extraction of the form e#m because it can't be parsed that way. (c.m)#g is a property extraction of the form e#m because that's the way it is parsed.

@iposva-google iposva-google added area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). and removed area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). labels Sep 17, 2015
@iposva-google
Copy link
Contributor

Over to Gilad to validate that the VM's approach is correct here.

@sgrekhov
Copy link
Contributor Author

What about this?

class A {
  int m() => 1;
}

A getA() {
  return new A();
}

main() {
  var f = getA()#m;
}

Result:
error: line 24 pos 17: semicolon expected
var f = getA()#m;
^

@lrhn
Copy link
Member

lrhn commented Sep 21, 2015

getA()#m is still not valid syntax. The grammar allows either a tear-off operation or a "selector" chain (call or member access, basically) after a primary expression. Here you do getA() which is not a primary expression (getA is a primary expression, getA() has the call selector after it so you can't also have a tear-off). Again you need to write (getA())#m if that is what you want to do.

@sgrekhov
Copy link
Contributor Author

Ok, thank you for clarification. But I think this grammar is, at least, not obvious at this point and the above is not what Dart user,who is not deeply familiar with the specification and sophisticated syntax like 'primary (selector* | ( ‘#’ ( (identifier ‘=’?) | operator)))', expects.

getA().m works, getA()#m not. Why? Why this limited (limited comparing with '.') syntax is needed at all?

@munificent
Copy link
Member

Generalized tear-offs are being removed (#27518) so I don't think we have to worry about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).
Projects
None yet
Development

No branches or pull requests

7 participants