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

interop mapping for classes that act like interfaces #8

Open
jvasileff opened this issue Feb 7, 2016 · 8 comments
Open

interop mapping for classes that act like interfaces #8

jvasileff opened this issue Feb 7, 2016 · 8 comments

Comments

@jvasileff
Copy link
Owner

In Dart, all classes can be used as interfaces. The Ceylon translation would be:

class MyClass satisfies SomeOtherClass { ... }

which of course is not legal in Ceylon.

There seems to be no option but to have each Dart class map to two separate types: a Ceylon interface and a Ceylon class that satisfies that interface.

Either the class or interface will need a synthetic name.

Scenario 1: Use class DartClass and interface I_DartClass

  • The model loader would map parameters and returns of type DartClass to I_DartClass
  • Use of DartClass for parameter types in Ceylon code would be discouraged; I_DartClass should be used instead, for maximum flexibility.
  • The identifier DartClass would be use for instantiations and extensions in Ceylon code (e.g. DartClass() and ... extends DartClass().
  • I_DartClass would be erased to DartClass by the backend compiler.

Scenario 2: Use class C_DartClass and interface DartClass

  • Parameters and returns would be of the type DartClass.
  • Use of C_DartClass for anything other than instantiations and extensions would be discouraged.
  • C_DartClass would be erased to DartClass by the backend compiler.

Perhaps Scenario 2 is the most natural, since the synthetic name would be used less frequently, and when needed (for instantiation & extension), its use would be forced by the typechecker.

A further concern is that classes DartClass_A and DartClass_B that do not share a subtyping relationship are not guaranteed to be disjoint, which breaks Ceylon's type system. Adopting scenario 2 (which helps reduce unintentional use of the identifier that maps to the class) should help to avoid this unsoundness.

@lucaswerkmeister
Copy link

Especially considering the disjointness problem, it seems to me like the class types shouldn’t be visible at all. Is it possible to make DartClass mean the class in expressions and the interface in types? I. e.:

// Interface      Class
   DartClass c1 = DartClass();

// Interface        Class
   DartClass() c2 = DartClass;

// Interface
   DartClass c3 = c2();

Another question: do native ("dart") Ceylon classes, or perhaps even any Ceylon classes within native ("dart") code, exhibit the same behavior?

@jvasileff
Copy link
Owner Author

Is it possible to make DartClass mean the class in expressions and the interface in types?

Without typechecker support, it would be possible to map Dart constructors to static factory methods. But we'd still be without the ability to extend Dart classes, which may be too limiting/inconvenient.

Beyond that, I'm not sure.

do ... Ceylon classes ... exhibit the same behavior?

Good point. There is no way to prevent things like a Dart class implementing ceylon.language::Sequence. But I'm not convinced it's useful for Dart code to consume Ceylon types except in special cases such as when implementing parts of the language module.

@gavinking
Copy link

In Dart, all classes can be used as interfaces.

What precisely does this mean? Does Dart support multiple inheritance for classes? Or, when I "satisfy" a class, do I have to reimplement all its operations?

I don't understand the semantics here.

@jvasileff
Copy link
Owner Author

There are no interfaces, only classs which may be abstract. There are three ways to inherit a Dart class:

  1. A class may extend one other class
  2. A class may implement zero or more other classes. When implementing a class, the implementations of it's members are not copied into the new class.
  3. A class may mixin zero or more other classes using with. Implementations of the mixed-in class's members are copied into the new class (but not implementations of the mixed-in class's supertypes). Mixed-in classes must not define a constructor.

This issue is primarily focussed on 1 & 2, since I'm not sure 3 adds any additional complexity to subtyping.

@gavinking
Copy link

@jvasileff OK, then could we model this as:

  1. Dart class => Ceylon interface
  2. Dart constructor => Ceylon function

Wouldn't that capture the semantics, without requiring strange generated names?

@jvasileff
Copy link
Owner Author

Yes, I think it's a good idea to map constructors to static functions, but we still need a class to support extending Dart classes in Ceylon.

We also need a name for the functions for default (nameless) Dart constructors.

@jvasileff
Copy link
Owner Author

jvasileff commented Feb 19, 2016

The current implementation status is that we have:

  • Dart Class => Ceylon interface of the same name, and
  • Dart Class => Ceylon class named like DartClass_C, and
  • Dart Class => Ceylon static member class named like DartClass.Class

Of the second two, I'm leaning towards keeping the last.

Gotchas are:

  • Static references to constructors in Ceylon are not very useful since they require an instance of the class as an argument, which is a subtype of the interface that is more commonly used/exposed.
  • The non-disjointedness problem in the issue description.

10/16/2016 edit: classes like DartClass_C are no longer generated.

@gavinking
Copy link

I like the static inner class. Makes sense to me.

Sent from my iPhone

On 19 Feb 2016, at 17:12, John Vasileff [email protected] wrote:

The current implementation status is that we have:

Dart Class => Ceylon interface of the same name, and
Dart Class => Ceylon class named like DartClass_C, and
Dart Class => Ceylon static member class named like DartClass.Class
Of the second two, I'm leaning towards keeping the last.

Gotchas are:

Static references to constructors in Ceylon are not very useful since they require an instance of the class as an argument, which is a subtype of the interface that is more commonly used/exposed.
The non-disjointedness problem in the issue description.

Reply to this email directly or view it on GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants