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

dynamic and switch #604

Closed
gavinking opened this issue Feb 15, 2013 · 21 comments
Closed

dynamic and switch #604

gavinking opened this issue Feb 15, 2013 · 21 comments

Comments

@gavinking
Copy link
Member

This is not sound:

dynamic {
    value foo = value {};
    switch (foo)
    case (is Object) {}
    case (is Null) {}
}

We need to require an else clause.

@ghost ghost assigned gavinking Feb 15, 2013
@RossTate
Copy link
Member

No, you need to throw a type error at run time if foo doesn't fall into either case. That's the more consistent solution.

@gavinking
Copy link
Member Author

Hurrm, is it?

I suppose it is....

@gavinking
Copy link
Member Author

@chochos, Ross is right, let's make it a runtime check.

@chochos
Copy link
Member

chochos commented Feb 16, 2013

shit... ok; can you open an issue in ceylon-js please?

@gavinking
Copy link
Member Author

Another interesting case is generic invocations and instantiations (and this includes tuple and iterable enumeration).

If we were erasing generics, then Singleton(unknownTypedThing) would be OK, and we could check at runtime that unknownTypedThing was a Ceylon object. But since we have reified generics, where does it get its type args from? From the runtime type of unknownTypedThing?

@chochos @RossTate WDYT?

@gavinking gavinking reopened this Feb 16, 2013
@RossTate
Copy link
Member

Yes, you need to get it from the run-time type. This is why you need to make sure type-argument inference behaves nicely (which it doesn't yet).

@gavinking
Copy link
Member Author

Yes, you need to get it from the run-time type.

There is no runtime type. This is JavaScript. Get runtime types out of your head.

This is why you need to make sure type-argument inference behaves nicely (which it doesn't yet)

It behaves gorgeously. I don't know what you're talking about.

@gavinking
Copy link
Member Author

To clarify: there is a meaningful runtime type only for instances of classes defined in Ceylon. For other classes it would need to be a runtime exception. So you could not have a Singleton(foo) where foo is a native js object.

@RossTate
Copy link
Member

There is no runtime type. This is JavaScript. Get runtime types out of your head.

There may not be an explicit tag indicating the type, but there is still a type. The absence of such a tag would mean the type is something like JSObject, which is a supertype of Object and a subtype of Anything but might not include null.

It behaves gorgeously. I don't know what you're talking about.

Heh, I'm sensing sarcasm.

So you could not have a Singleton(foo) where foo is a native js object.

Sure you can. It's a [JSObject].

@gavinking
Copy link
Member Author

Heh, I'm sensing sarcasm.

No, seriously. Our type arg inference is awe-inspiring.

Sure you can. It's a [JSObject].

No, because the impl of Singleton uses properties of Ceylon Objects that aren't true for JavaScript objects.

@RossTate
Copy link
Member

No, seriously. Our type arg inference is awe-inspiring.

But not necessarily good enough for dynamically typed invocation of generic methods.

No, because the impl of Singleton uses properties of Ceylon Objects that aren't true for JavaScript objects.

Ah, I missed the given Element satisfies Object clause for Singleton. Well then what should happen here is:

  1. Type-argument inference occurs at run time and looks up the dynamic type of foo. Let's call that type Foo.
  2. It then infers that the type argument for the type parameter Element of the constructor of Singleton should be Foo.
  3. It then checks whether the given clauses are satisfied, in this case checking whether Foo is a subtype of Object. If so, it calls the constructor Singleton<Foo>(foo). If not, it throws a type error.

So if foo is a Ceylon Object, the call will work. If not, the call will fail since JSObject is not a subtype of Object and while get a run-time type error indicating the problem.

@gavinking
Copy link
Member Author

Right, well, I think that's probably right. But usually, if I write:

Object o = "hello";
value singleton = Singleton(o);

I've been thinking I would I get a Singleton<Object> as the runtime type, not a Singleton<String>. (Is that what you've implemented, @FroMage?) But here, if I write:

dynamic {
    value o = someJavaScriptMethodThatReturnsAString();
    value singleton = Singleton(o);
}

Then I will get a Singleton<String>. That's a little surprising.

@RossTate
Copy link
Member

That's true, and it's an important problem. Basically, the second program is more accurate in a sense. That's why I've been advocating a semantics which is compatible with this.

@chochos
Copy link
Member

chochos commented Mar 6, 2013

Actually, that last example will give you a Singleton<Anything>, and that's because we do some stuff to js strings for interop. Remember that there's already a runtime check to make sure we only pass Ceylon objects to Ceylon methods.

@RossTate
Copy link
Member

RossTate commented Mar 6, 2013

Wait, that's the case even if someJavaScriptMethodThatReturnsAString returned a Ceylon String?

@chochos
Copy link
Member

chochos commented Mar 6, 2013

Yes. The type parameter is calculated at compile time, and since it's unknown we can only set it to be Anything and make sure the value passed is indeed a Ceylon object.

@RossTate
Copy link
Member

RossTate commented Mar 6, 2013

If, statically, we know someJavaScriptMethodThatReturnsAString returns a Ceylon String, then statically we know singleton is a Singleton<String>, so that's the type we should give it in that case. Regardless, if at run time we get an o that is a Ceylon String, then at run time the type of singleton should be Singleton<String>. You can implement this by using the reification information in o.

Essentially, the property we want for dynamic is that, if we were to take some code that type checks and produces a result of (static) type T, then should we throw away the types in that code and instead use dynamic we should still get a result whose run time type is T or better. This is because at run time we have strictly more information than we do at compile time.

@chochos
Copy link
Member

chochos commented Mar 7, 2013

Statically (at compile time) we have absolutely no way of knowing if someJavaScriptBla returns a Ceylon String. We can check if it returns a Ceylon object (we already do that actually) - ah well in this case we might be able to pass that type as a type parameter. No idea how, right now.

@RossTate
Copy link
Member

RossTate commented Mar 7, 2013

Yes, that's what we should aim for.

@gavinking
Copy link
Member Author

I'm sure there are still some corner cases we need to think through, and perhaps we even need a written-down-definition of all the runtime checks that should happen. But I can't quite get this straight in my head today, so I need to revisit this properly with Enrique for M6.

@gavinking
Copy link
Member Author

For now, I have decided to force you to explicitly specify type args instead of letting you infer a nonsense unknown type for a type argument in a generic invocation.

So I think the typechecker side of this is done (for now) and we just need to make sure the backend does the right thing with switches and generic invocations.

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