eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
398 stars 62 forks source link

Optimise obtaining case type values via metamodel #1614

Open CeylonMigrationBot opened 10 years ago

CeylonMigrationBot commented 10 years ago

[@FroMage] 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.

[Migrated from ceylon/ceylon-compiler#1614]

CeylonMigrationBot commented 10 years ago

[@FroMage] This is related to #5207

CeylonMigrationBot commented 10 years ago

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

CeylonMigrationBot commented 10 years ago

[@FroMage] 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.

CeylonMigrationBot commented 10 years ago

[@tombentley] 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.

CeylonMigrationBot commented 10 years ago

[@FroMage] Ah! Now that's brilliant! Thanks for the idea :)

CeylonMigrationBot commented 10 years ago

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

CeylonMigrationBot commented 10 years ago

[@FroMage] Moving to 1.2 unless we find a good way to do this.

CeylonMigrationBot commented 10 years ago

[@tombentley] 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.

CeylonMigrationBot commented 10 years ago

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

CeylonMigrationBot commented 10 years ago

[@tombentley]

Yes but the JVM can do magic for those.

WDYM?

CeylonMigrationBot commented 10 years ago

[@FroMage] 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.

CeylonMigrationBot commented 10 years ago

[@tombentley] 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.

CeylonMigrationBot commented 10 years ago

[@FroMage] 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.

CeylonMigrationBot commented 10 years ago

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

CeylonMigrationBot commented 10 years ago

[@FroMage] 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.

CeylonMigrationBot commented 10 years ago

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

CeylonMigrationBot commented 10 years ago

[@FroMage] That's what I said, didn't I? ;)