ceylon / ceylon.language

DEPRECATED
Apache License 2.0
153 stars 57 forks source link

Add backend parameters to native annotation #252

Open chochos opened 11 years ago

chochos commented 11 years ago

The native annotation is incomplete; there is a lot of stuff in the language module annotated native which can be compiled to js, so it's really only annotated for the jvm compiler.

So the annotation should have a parameter which is the list of backends that the declaration is native for; no args means it's native for all backends.

Question is: should the backends be objects, or simply strings?

i.e.

native("jvm") class Bla(){}
native(jvm) class Ble(){}

we can define a Backend or Platform class with two cases, jvm and javascript. It can even be used in the process object, which I think already has a platform property.

chochos commented 11 years ago

This will enabled us to properly process native in the js compiler, and probably remove the nativejs hack.

FroMage commented 11 years ago

How is that related to nativejs?

I would agree that it could be useful. I would make the list of backends an enum, but because we don't have real enums in the JVM sense, I don't think we can use enum values as annotation parameters ATM. @tombentley can confirm/deny.

As far as the JVM backend is concerned those native annotations are ignored anyways ATM.

chochos commented 11 years ago

what? you ignore native as well? then WTF do we even have it for?

Regarding nativejs, it's something Tako added to the js backend for the DOM module he wrote, but the js compiler only deals with nativejs annotation when using declarations annotated with it, not when generating code for those declarations.

Maybe it's two separate things and the nativejs annotation will remain, but I believe we definitely should add the backend(s) to the native annotation. So strings then?

FroMage commented 11 years ago

Well, I guess we should not ignore it, but build support for it. ATM it's only used by the language module and we do not include the bits with native in the list of files to compile, so the backend never sees any of those. If it would see one of them, it would get confused because there's a duplicate in a java file.

gavinking commented 11 years ago

The native annotation is supposed to let you write a class in Ceylon and have, for example, just one method implemented in Java + JavaScript. But that's not supported yet, and we have not yet defined what that would look like from the java/js side.

Sent from my iPhone

On 10/07/2013, at 6:19 PM, Stéphane Épardaud notifications@github.com wrote:

Well, I guess we should not ignore it, but build support for it. ATM it's only used by the language module and we do not include the bits with native in the list of files to compile, so the backend never sees any of those. If it would see one of them, it would get confused because there's a duplicate in a java file.

— Reply to this email directly or view it on GitHub.

quintesse commented 11 years ago

@chochos Are you sure there are things marked native in the language module that can be compiled by the JS backend but not by the JVM backend? It doesn't really seem to make sense to me. Supposedly native is used for those cases when we cannot express in Ceylon what we need the code to do.

We did have some examples of backend-specific native code before, but that was when the JVM compiler had some restrictions. Do we still have those problems now? (And if we can only come up with one or two simple cases is it worth the trouble?)

And nativejs is indeed a different beast and I'm still doubtful we can merge the two. Because native means that although the code is written natively it still is Ceylon code (proper naming, it has meta information, reified generics, etc), while nativejs means the code is entirely native and we should not try to apply Ceylon's naming rules or otherwise expect it will behave as a Ceylon object. (I'm not sure if that means we'll never be able to make nativejs work properly for more complex cases where you want to use is or meta models etc)

gavinking commented 11 years ago

So then you can use nativejs to make something a Ceylon class even though it doesn't conform to the mappings of Ceylon to JS or even know it's own type?! Doesn't that mean it breaks as soon as you assign an instance to Object?

Sent from my iPhone

On 10/07/2013, at 6:40 PM, Tako Schotanus notifications@github.com wrote:

@chochos Are you sure there are things marked native in the language module that can be compiled by the JS backend but not by the JVM backend? It doesn't really seem to make sense to me. Supposedly native is sued for those cases when we cannot express in Ceylon what we need the code to do.

We did have some examples of backend-specific native code before, but that was when the JVM compiler had some restrictions. Do we still have those problems now? (And if we can only come up with one or two simple cases is it worth the trouble?)

And nativejs is indeed a different beast and I'm still doubtful we can merge the two. Because native means that although the code is written natively it still is Ceylon code (proper naming, it has meta information, reified generics, etc), while nativejs means the code is entirely native and we should not try to apply Ceylon's naming rules or otherwise expect it will behave as a Ceylon object. (I'm not sure if that means we'll never be able to make nativejs work properly for more complex cases where you want to use is or meta models etc)

— Reply to this email directly or view it on GitHub.

quintesse commented 11 years ago

I knew it would have enough information to know its own type, but now looking at the code in the web backend I see that at a later date even meta model information was added. I didn't implement that so I'm not sure how much it supports, I think @chochos or @ikasiuk will be able to give more details.

gavinking commented 11 years ago

I knew it would have enough information to know its own type

How does that work, precisely?

quintesse commented 11 years ago

As far as I can remember + what I can deduce from the code is that we extend the JS type with the information required by Ceylon. So we take an existing JS type and add onto it the information we supply with Ceylon interfaces marked "nativejs".

For example, the native toplevel attribute document is defined as being of type Document. In the file defining all the DOM interfaces (https://github.com/ceylon/ceylon-web-ide-backend/blob/master/src/main/ceylon/browser/dom/main.ceylon) exists a type Document with its members and a parent interface Node. The code will now add that available meta information to the prototype of the JS type, basically turning it into a Ceylon class (see https://github.com/ceylon/ceylon-web-ide-backend/blob/master/src/main/webapp/scripts/modules/browser/1.0.0/browser-1.0.0.js).

The advantage of this method is that a) we have type safety and b) it works in cases where wrappers wouldn't (for example in the case of the DOM tree it's the browser that's in control of creating / deleting most of the tree elements).

The disadvantage is (right now at least) that it's a lot of manual work.

chochos commented 11 years ago

@quintesse Exception is one example of a type that is annotated native and yet we can compile it to JS and it works.

quintesse commented 11 years ago

@chochos true, but that's also an example of a very trivial class, I'm wondering if there's anything that has a bit more "meat" to it. Just to see if it's worth the trouble.

tombentley commented 11 years ago

I would make the list of backends an enum, but because we don't have real enums in the JVM sense, I don't think we can use enum values as annotation parameters ATM. @tombentley can confirm/deny.

Right now the JVM compiler doesn't support this, but it will once I add the extra transformation which handles all these funky cases. It makes me wonder how we will document it though, since the native annotation would then not be present as an Java annotation, so ceylondoc (in its current form) would have trouble 'seeing' it. There are a number of way to address that, but I won't pollute this thread with them.

chochos commented 11 years ago

We could just use strings then, as long as we properly document what the valid backends are it shouldn't be a big problem.

Right now we're only using it in the language module but it could be used in other modules as well. I'm thinking of a way to make it more useful for js, but I think I'll elaborate on that repo, not here.