www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Two Scala annotations

reply "bearophile" <bearophileHUGS lycos.com> writes:
I have found two Scala annotations.

1) The first one is  switch:
http://www.scala-lang.org/api/current/scala/annotation/switch.html

Currently this D2 code compiles:

void main() {
     int x = 2;
     int y = 2;
     switch(x) {
         case 1: break;
         case y: break;
         default:
     }
}

I think that accepting that "case y" is a compiler bug, because y 
is a run-time value, that kills some switch optimization 
possibilities.

Inside D code the presence or absence of an annotation 
semantically related to that Scala  switch is able to disallow / 
allow the presence of a run-time value among the cases.

------------------

2) The second is  implicitNotFound:
http://www.scala-lang.org/api/current/scala/annotation/implicitNotFound.html

More info:
http://suereth.blogspot.it/2011/03/annotate-your-type-classes.html

Maybe a related idea is able to improve/add error messages when 
certain template constraints fail (to be used when you have just 
1 template, where constraints failure means wrong input or 
something clearly missing in user code).

Bye,
bearophile
May 27 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <alex lycus.org> writes:
On 27-05-2012 15:13, bearophile wrote:
 I have found two Scala annotations.

 1) The first one is  switch:
 http://www.scala-lang.org/api/current/scala/annotation/switch.html

 Currently this D2 code compiles:

 void main() {
 int x = 2;
 int y = 2;
 switch(x) {
 case 1: break;
 case y: break;
 default:
 }
 }

 I think that accepting that "case y" is a compiler bug, because y is a
 run-time value, that kills some switch optimization possibilities.

A couple of things here: 1) Any half-decent compiler *will* optimize this thanks to a wide array of standard dataflow analyses. 2) Even if the compiler couldn't optimize cases like this one, I don't think it matters. I don't know from where people got this crazy idea that a switch statement MUST compile to a jump table *no matter what* (though I suspect C is the cause of this madness). I think it's silly. Even a lot of the things D's switch allows (range cases, for example) kill the opportunity to turn it into a jump table. So even if you disallow this case, it won't really buy you anything. If someone is aware of the jump table optimization of switch statements, then surely they know that using a runtime value will kill that optimization. And if they don't know, it doesn't matter anyway! Worst case, it'll just be unrolled to what's equivalent to an if/else forest.
 Inside D code the presence or absence of an annotation semantically
 related to that Scala  switch is able to disallow / allow the presence
 of a run-time value among the cases.

 ------------------

 2) The second is  implicitNotFound:
 http://www.scala-lang.org/api/current/scala/annotation/implicitNotFound.html


 More info:
 http://suereth.blogspot.it/2011/03/annotate-your-type-classes.html

 Maybe a related idea is able to improve/add error messages when certain
 template constraints fail (to be used when you have just 1 template,
 where constraints failure means wrong input or something clearly missing
 in user code).

 Bye,
 bearophile

-- Alex Rønne Petersen alex lycus.org http://lycus.org
May 27 2012
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 27.05.2012 17:13, bearophile wrote:
 I have found two Scala annotations.

 1) The first one is  switch:
 http://www.scala-lang.org/api/current/scala/annotation/switch.html

 Currently this D2 code compiles:

 void main() {
 int x = 2;
 int y = 2;
 switch(x) {
 case 1: break;
 case y: break;
 default:
 }
 }

IMHO if you use annotations for *this* then your language is as good as dead. There are far better things to aim annotations at.
 2) The second is  implicitNotFound:
 http://www.scala-lang.org/api/current/scala/annotation/implicitNotFound.html


 More info:
 http://suereth.blogspot.it/2011/03/annotate-your-type-classes.html

-- Dmitry Olshansky
May 27 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Alex Rønne Petersen:

 1) Any half-decent compiler *will* optimize this thanks to a 
 wide array of standard dataflow analyses.

'y' was meant to be a value unknown at compile-time.
 I don't know from where people got this crazy idea that a 
 switch statement MUST compile to a jump table *no matter what*

I'd like portable computed gotos in D, but they are not coming soon in DMD, it seems.
 If someone is aware of the jump table optimization of switch 
 statements, then surely they know that using a runtime value 
 will kill that optimization.

That annotation doesn't introduce compiler optimizations (the compiler will optimize as much as possible in every cases). It just gives a compile-time error if you use a run-time value in a switch case. It's just meant to avoid mistakes, like using a run-time value instead of a D enum in a switch case, just like that Scala annotation. Bye, bearophile
May 27 2012
prev sibling next sibling parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:dkpmzrcoppslcjqvdnze forum.dlang.org...
 Currently this D2 code compiles:

 void main() {
     int x = 2;
     int y = 2;
     switch(x) {
         case 1: break;
         case y: break;
         default:
     }
 }

 I think that accepting that "case y" is a compiler bug, because y is a 
 run-time value, that kills some switch optimization possibilities.

 Inside D code the presence or absence of an annotation semantically 
 related to that Scala  switch is able to disallow / allow the presence of 
 a run-time value among the cases.

I ran into this last week while working on bug 6169 - this is the only case (I could see) where the compiler cannot tell whether a value must be evaulated at compile time or not by simply looking at the context. The idea being you can ignore normal safety and purity checks if you know the expression will be evaluated at compile time. They seems like a corner case that somehow slipped through. Could we just get rid of them?
Jun 30 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/27/2012 6:13 AM, bearophile wrote:
 Currently this D2 code compiles:

 void main() {
      int x = 2;
      int y = 2;
      switch(x) {
          case 1: break;
          case y: break;
          default:
      }
 }

 I think that accepting that "case y" is a compiler bug, because y is a run-time
 value, that kills some switch optimization possibilities.

It's not a bug. It's deliberate, and is there to support mechanical translation of Java code.
Jun 30 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/30/2012 6:05 PM, bearophile wrote:
 Walter Bright:

 It's not a bug. It's deliberate, and is there to support mechanical
 translation of Java code.

Is this stuff written somewhere in a D design rationales page? Now that D is several years old, how much Java code was ported to D? (Despite there is no mechanical Java->D translator yet).

Yes, a mechanical translator was used extensively to create dwt.
 Was this automatic translation
 desire worth the troubles (like inner classes,

Yes.
 like the risk of killing switch optimizations by mistake)?

Calling it a "risk" and "killing" is way, way overstating things.
 This post is about two Scala annotations. If that's not a bug, is something
like
 that first Scala annotation useful in D too?

I don't really see any problem requiring a solution. If you're working on optimizations at that level, you ought to be comfortable examining the asm output for that and all the other stuff, too. Setting a store on just one aspect of switch implementations is a large mistake.
Jun 30 2012
parent reply Don Clugston <dac nospam.com> writes:
On 01/07/12 04:00, Walter Bright wrote:
 On 6/30/2012 6:05 PM, bearophile wrote:
 Walter Bright:

 It's not a bug. It's deliberate, and is there to support mechanical
 translation of Java code.

Is this stuff written somewhere in a D design rationales page? Now that D is several years old, how much Java code was ported to D? (Despite there is no mechanical Java->D translator yet).

Yes, a mechanical translator was used extensively to create dwt.
 Was this automatic translation
 desire worth the troubles (like inner classes,

Yes.
 like the risk of killing switch optimizations by mistake)?

Calling it a "risk" and "killing" is way, way overstating things.
 This post is about two Scala annotations. If that's not a bug, is
 something like
 that first Scala annotation useful in D too?

I don't really see any problem requiring a solution. If you're working on optimizations at that level, you ought to be comfortable examining the asm output for that and all the other stuff, too. Setting a store on just one aspect of switch implementations is a large mistake.

The problem isn't the effect on optimization. The problem is that the semantics are insane. They are like nothing else in the language, and they don't make any sense. It's a very complicated feature: eg what happens if the case is a shared variable? Under what circumstances is a symbol treated as a variable, rather than a constant? As far as I know, no other language works anything like this. Either switch accepts only constants, or it accepts arbitrary expressions. Not this bizarre combination of both. Do you have a reference for this Java behaviour? I did a quick google, and everything I found indicates that case labels must be constants.
Jul 02 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/2/2012 7:37 AM, bearophile wrote:
 I have compiled this Java code:

 class Main {
      public static void main(String[] args) {
          int x = 2;
          int y = 2;
          switch(x) {
              case 1: break;
              case y: break;
          }
      }
 }


 It gives:

 Main.java:7: error: constant expression required
              case y: break;
                   ^
 1 error

 As you see:
 http://ideone.com/wAXMZ

Put "final" in front of y, and it will compile. Remember, this was done for D1 that didn't have const.
Jul 02 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/2/2012 1:04 PM, bearophile wrote:
 Walter Bright:

 Put "final" in front of y, and it will compile. Remember, this was done for D1
 that didn't have const.

I see. So in D2 are we going to require that y to be immutable?

No. I don't agree there's a problem. Nor do I care to break existing D1 code (and D2 for that matter) without an awfully good reason, and I don't see one here.
Jul 02 2012
parent Don Clugston <dac nospam.com> writes:
On 02/07/12 23:20, Walter Bright wrote:
 On 7/2/2012 1:04 PM, bearophile wrote:
 Walter Bright:

 Put "final" in front of y, and it will compile. Remember, this was
 done for D1
 that didn't have const.

I see. So in D2 are we going to require that y to be immutable?

No. I don't agree there's a problem. Nor do I care to break existing D1 code (and D2 for that matter) without an awfully good reason, and I don't see one here.

This behaviour is *not* currently in the spec. And if you give any other kind of runtime expression, you get an error message which suggests it shouldn't work: void main() { int x; int y; switch(x) { case *&y: break; } } bug.d(10): Error: case must be a string or an integral constant, not *&y ---------- It would be really difficult to define the current behaviour. I don't understand it. Let me explain how bizarre it is. What it does is, run optimize(WANTvar) on the expression. If at the end of optimization, it is a VarExp of type integer or class, then it can be a run-time value. It must be a VarExp, it cannot be a DotVar. Now, what does optimize(WANTvar) actually do? Under what circumstances can it produce a VarExp? I'm not sure. You really need to check every code path in optimize.c and constfold.c. It can happen with comma expressions, for example. So this: case 7+8, y: is accepted. Are there circumstances where X.Y can be accepted? Maybe some combination involving alias this or opDispatch ? I don't know.
Jul 03 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 It's not a bug. It's deliberate, and is there to support 
 mechanical translation of Java code.

Is this stuff written somewhere in a D design rationales page? Now that D is several years old, how much Java code was ported to D? (Despite there is no mechanical Java->D translator yet). Was this automatic translation desire worth the troubles (like inner classes, like the risk of killing switch optimizations by mistake)? This post is about two Scala annotations. If that's not a bug, is something like that first Scala annotation useful in D too? Bye, bearophile
Jun 30 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, June 30, 2012 19:00:29 Walter Bright wrote:
 On 6/30/2012 6:05 PM, bearophile wrote:
 Walter Bright:
 It's not a bug. It's deliberate, and is there to support mechanical
 translation of Java code.

Is this stuff written somewhere in a D design rationales page? Now that D is several years old, how much Java code was ported to D? (Despite there is no mechanical Java->D translator yet).

Yes, a mechanical translator was used extensively to create dwt.
 Was this automatic translation
 desire worth the troubles (like inner classes,

Yes.
 like the risk of killing switch optimizations by mistake)?

Calling it a "risk" and "killing" is way, way overstating things.
 This post is about two Scala annotations. If that's not a bug, is
 something like that first Scala annotation useful in D too?

I don't really see any problem requiring a solution. If you're working on optimizations at that level, you ought to be comfortable examining the asm output for that and all the other stuff, too. Setting a store on just one aspect of switch implementations is a large mistake.

I would have thought that while having a variable as a case value rather than a compile-time constant may make the switch statement less efficient, it would have zero effect on switch statements which didn't use any variables for their cases. That being the case, it would only impact people who choose to use variables in their case statements, and anyone who would have preferred to have the be disallowed is unaffected by it (unless they use code from someone who does use variables in their case statements), since they're not using it in their code. Personally, I would have preferred that case statement values all be constant, but it sounds like we have a good, technical reason for allowing them, and I don't see how they could negatively affect me as long as I don't use them. Anyone who thinks that the compiler is doing a poor job of optimizing switch statements is free to work on the compiler and provide a pull request with their improvements. - Jonathan M Davis
Jun 30 2012
prev sibling next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 27 May 2012 at 14:04:48 UTC, Dmitry Olshansky wrote:
 IMHO if you use annotations for *this* then your language is as 
 good as dead.
 There are far better things to aim annotations at.

cases in a language with pattern matching, but in D, it's probably worse than useless.
Jun 30 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Don Clugston:

 Do you have a reference for this Java behaviour? I did a quick 
 google, and everything I found indicates that case labels must 
 be constants.

Thank you for your answer, Don. I have compiled this Java code: class Main { public static void main(String[] args) { int x = 2; int y = 2; switch(x) { case 1: break; case y: break; } } } It gives: Main.java:7: error: constant expression required case y: break; ^ 1 error As you see: http://ideone.com/wAXMZ Bye, bearophile
Jul 02 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter Bright:

 Put "final" in front of y, and it will compile. Remember, this 
 was done for D1 that didn't have const.

I see. So in D2 are we going to require that y to be immutable? Bye, bearophile
Jul 02 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, July 03, 2012 09:42:58 Don Clugston wrote:
 On 02/07/12 23:20, Walter Bright wrote:
 On 7/2/2012 1:04 PM, bearophile wrote:
 Walter Bright:
 Put "final" in front of y, and it will compile. Remember, this was
 done for D1
 that didn't have const.

I see. So in D2 are we going to require that y to be immutable?

No. I don't agree there's a problem. Nor do I care to break existing D1 code (and D2 for that matter) without an awfully good reason, and I don't see one here.

This behaviour is *not* currently in the spec.

Related: http://d.puremagic.com/issues/show_bug.cgi?id=6176 - Jonathan M Davis
Jul 03 2012