ceylon / ceylon-compiler

DEPRECATED
GNU General Public License v2.0
138 stars 36 forks source link

Optimise obtaining case type values via metamodel #1614

Open FroMage opened 10 years ago

FroMage commented 10 years ago

We should generate a method $caseValues$()in every toplevel type which has case values that returns a sequence of those values, so we can substitute any calls to `Type.caseValueswithType.$caseValues$()` to bypass the metamodel entirely.

Now, the problem is that either we create that method for every type, even those who don't have case values, and we're binary/incremental compatible. Or we do it just for those which do have case values, and substitute an empty sequence [] on call sites, but then we're not binary/incremental compatible.

Not quite sure how best to proceed here. I don't quite like adding this method to every toplevel type.

FroMage commented 10 years ago

This is related to ceylon/ceylon.language#329

tombentley commented 10 years ago

I think it's perfectly fine that adding/removing an of clause is not BC -- adding an extends or satisfies clause isn't, afterall.

FroMage commented 10 years ago

Well, the issue is that if we compile a call site to Type.$caseValues$() because it has case values, and then later we remove the case values, the call site is going to have an error rather than an empty sequence as the metamodel would return.

tombentley commented 10 years ago

If a class Foo satisfies Bar and is assigned to a Bar somewhere and Foo later changes to no longer satisfy Bar then you end up with either a compile or link time error. The only question is whether the compile time error will be caught by the typechecker (I agree that we should avoid this being a backend error).

Alternatively what's stopping us from using a hidden interface (like ReifiedType)? It would then be trivial to write a little method in Metamodel or Util which did the instanceof and returned the result, or threw a meaningful exception.

FroMage commented 10 years ago

Ah! Now that's brilliant! Thanks for the idea :)

FroMage commented 10 years ago

Argg… no that doesn't work. It needs to be a static method :(

FroMage commented 10 years ago

Moving to 1.2 unless we find a good way to do this.

tombentley commented 10 years ago

It's basically the same problem that Java faces with it's Enum: In order to implement the static Enum.valueOf() it seems to be happy to reflectively invoke the static values() method of the Enum implementation.

So we could still use a hidden interface as a marker (or I guess we could use the existing cases annotation) and have the Util method invoke reflectively only when we know it's an enumerated type.

FroMage commented 10 years ago

Yes but the JVM can do magic for those. Hey, perhaps this should be resolved with an indy call?

tombentley commented 10 years ago

Yes but the JVM can do magic for those.

WDYM?

FroMage commented 10 years ago

Ah sorry, I didn't read properly. Yes, Enum.valueOf needs reflection to work, but not it's redefined in each enum subtype, and that one doesn't need reflection.

Also if E is not an enum anymore (binary-incremental) then E.values() will throw, which is not acceptable in our case.

tombentley commented 10 years ago

I think you're still misunderstanding (or I'm misunderstanding you; I'm pretty sure there's a misunderstanding here somewhere).

I'm saying we generate a static method in each type with case values, and that in some method in Util we:

So if the once-enumerated type ceases to be be enumerated at runtime that's OK.

AFAICS that's the best we can do.

FroMage commented 10 years ago

Well, no, that's still using reflection so it's not optimal. Java's E.values() does not use reflection so that's what we're going to be compared against. I think we should use indy for that.

tombentley commented 10 years ago

But Java's E.values() is a static invocation, of course it's not reflective. But sure, use indy if you want.

FroMage commented 10 years ago

I know it's not reflective, I'm saying that we need to optimise `E.caseValuesin Ceylon to something as efficient asE.values()` in Java.

tombentley commented 10 years ago

Riiight. Well, yes you're going to want to use indy for this so you have some control at link time.

FroMage commented 10 years ago

That's what I said, didn't I? ;)