|
|
Created:
6 years ago by gbracha Modified:
6 years ago Reviewers:
Lasse Reichstein Nielsen CC:
reviews_dartlang.org Visibility:
Public. |
DescriptionMain function of a script can be function valued getter.
R=lrn@google.com
Committed: https://code.google.com/p/dart/source/detail?r=42464
Patch Set 1 #
Total comments: 9
Patch Set 2 : #
Total comments: 4
Patch Set 3 : #
Total comments: 1
Patch Set 4 : #Messages
Total messages: 10 (1 generated)
gbracha@google.com changed reviewers: + lrn@google.com
Per issue https://code.google.com/p/dart/issues/detail?id=21521, we allow main to be a function valued top level getter.
Oops that should be issue 21535
https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:1806: \item It is a static warning if a concrete class has an abstract member (declared or inherited). Above you say that the class doesn't inherit the super-interfaces, but its interface does. Does it then make sense to say that the *class* has an inherited abstract member? https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:1810: \item If multiple superinterfaces of an interface define a member with the same name $m$, then at most one member is inherited. That member (if it exists) is the one whose type is a subtype of all the others. If there is no such member, then: Did we ever figure out if there should be a warning for: class A { int foo(int a) => 42 * a; } abstract class B { int foo(int a, [int b]); } class C extends A implements B {} In this case C's interface inherits "foo" from "B" (it's a subtype of "foo" from "A", so it's the "at most one member" mentioned above. So we have a class C that doesn't implement its own interface, but its "foo" isn't abstract either. It's not clear to me that "It is a static warning if a concrete class does not have an implementation for a method in any of its superinterfaces" below will catch this, because it has an implementation for "foo", it's just not the right type. Or, in other words, it's not clear how to interpret "does not have an implementation for a method". (analyzer warns, dart2js doesn't). https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:6389: A {\em script} is a library whose exported namespace (\ref{exports}) includes either a top-level function or a function-valued top-level getter named \code{main}. Being a "script" looks and sounds like a static property, but a getter being function valued can only be determined at runtime, by calling the getter and looking at the value. How about just: "A script is a library whose exported namespace contains a member named \code{main}". Then you can have badly constructed scripts that crash when you run them, but they are still scripts. Running a script is equivalent to invoking "main()" (perhaps with arguments) in that exported scope. Example: get main => const bool.fromEnvironment("WTF") ? 0 : _main; _main() {...} Obscurity through obscenity! This "main" is not necessarily function valued, it's not function typed (but it is dynamic), and in most cases it runs perfectly fine. Just thought of another abuse: Static initializers! final main = (){ realMain(); return (){}; }(); That allows us to execute the entire program before even calling "main". Are you really sure this is a good idea? Shouldn't we just restrict to main *function declarations* as script entry points? I doubt any real code will break since it's only the VM that allows it, and it wasn't in the spec. By adding this text, we are highlighting that it's a possibility, and we can't put the genie back in the bottle then. (Unless you actually do want functions and function-valued getters to be equivalent in general, which is a perfectly reasonable stance - but not one compatible with our current inheritance rules). https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:6400: It is a run time error if $S$ does not declare or import either a top-level function or a function-valued top-level getter named \code{main}. It is a static warning if \code{main} has more than two required parameters. Maybe: "It's a static warning if the static type of \code{main} is a function with more than two required parameters." Or even: "It's a static warning if the static type of \code{main} is not a function, or if it is a function with more than two required parameters." - if we want to consider non-function typed main declarations as (potenital) script entry points. Or should it be "assignable to a function type" to accommodate "dynamic"? This warning applies to all libraries that have a "main" member, right? Not just the one being used as a script.
Rev'ed static warning per your suggestion. PTAL. https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:1806: \item It is a static warning if a concrete class has an abstract member (declared or inherited). On 2014/12/16 08:27:36, Lasse Reichstein Nielsen wrote: > Above you say that the class doesn't inherit the super-interfaces, but its > interface does. Does it then make sense to say that the *class* has an inherited > abstract member? This non-normative text, so it doesn't need to be super finicky. It just gives intuition. https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:1810: \item If multiple superinterfaces of an interface define a member with the same name $m$, then at most one member is inherited. That member (if it exists) is the one whose type is a subtype of all the others. If there is no such member, then: On 2014/12/16 08:27:36, Lasse Reichstein Nielsen wrote: > Did we ever figure out if there should be a warning for: > > class A { > int foo(int a) => 42 * a; > } > abstract class B { > int foo(int a, [int b]); > } > class C extends A implements B {} > > In this case C's interface inherits "foo" from "B" (it's a subtype of "foo" from > "A", so it's the "at most one member" mentioned above. > So we have a class C that doesn't implement its own interface, but its "foo" > isn't abstract either. > > It's not clear to me that "It is a static warning if a concrete class does not > have an implementation for a method in any of its superinterfaces" below will > catch this, because it has an implementation for "foo", it's just not the right > type. Or, in other words, it's not clear how to interpret "does not have an > implementation for a method". > > (analyzer warns, dart2js doesn't). From 10.10 (next section) It is a static warning if the implicit interface of a class C includes an instance member m of type F and C declares or inherits a corresponding instance member m of type F′ if F′ is not a subtype of F. C inherits A.foo of type F' = (int) -> int. The interface of C inherits B.foo of type F= (int, [int]) -> int. Now F <: F' but not vice versa. So as I see it, we get a static warning. https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:6389: A {\em script} is a library whose exported namespace (\ref{exports}) includes either a top-level function or a function-valued top-level getter named \code{main}. On 2014/12/16 08:27:36, Lasse Reichstein Nielsen wrote: > Being a "script" looks and sounds like a static property, but a getter being > function valued can only be determined at runtime, by calling the getter and > looking at the value. > > How about just: "A script is a library whose exported namespace contains a > member named \code{main}". > Then you can have badly constructed scripts that crash when you run them, but > they are still scripts. > Running a script is equivalent to invoking "main()" (perhaps with arguments) in > that exported scope. > > > Example: > get main => const bool.fromEnvironment("WTF") ? 0 : _main; > _main() {...} > Obscurity through obscenity! > > This "main" is not necessarily function valued, it's not function typed (but it > is dynamic), and in most cases it runs perfectly fine. > > Just thought of another abuse: Static initializers! > > final main = (){ realMain(); return (){}; }(); > > That allows us to execute the entire program before even calling "main". > > Are you really sure this is a good idea? Shouldn't we just restrict to main > *function declarations* as script entry points? > > I doubt any real code will break since it's only the VM that allows it, and it > wasn't in the spec. By adding this text, we are highlighting that it's a > possibility, and we can't put the genie back in the bottle then. > (Unless you actually do want functions and function-valued getters to be > equivalent in general, which is a perfectly reasonable stance - but not one > compatible with our current inheritance rules). We have tried to allow getters and methods to be treated uniformly though it isn't always the case. That desire for uniformity is a big part of the motivation for the proposed change. I don't see why we should fret over super-perverse examples like the ones above. https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:6400: It is a run time error if $S$ does not declare or import either a top-level function or a function-valued top-level getter named \code{main}. It is a static warning if \code{main} has more than two required parameters. On 2014/12/16 08:27:36, Lasse Reichstein Nielsen wrote: > Maybe: "It's a static warning if the static type of \code{main} is a function > with more than two required parameters." > > Or even: "It's a static warning if the static type of \code{main} is not a > function, or if it is a function with more than two required parameters." - if > we want to consider non-function typed main declarations as (potenital) script > entry points. > > Or should it be "assignable to a function type" to accommodate "dynamic"? Yes, I think that would be fine. Rev'ed it accordingly. > > This warning applies to all libraries that have a "main" member, right? > Not just the one being used as a script. Yes. The analyzer doesn't even know what is being used as a script. It only knows that something is a script, by definition, if it has a main.
https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/800413003/diff/1/docs/language/dartLangSpec.t... docs/language/dartLangSpec.tex:1810: \item If multiple superinterfaces of an interface define a member with the same name $m$, then at most one member is inherited. That member (if it exists) is the one whose type is a subtype of all the others. If there is no such member, then: Thanks. https://codereview.chromium.org/800413003/diff/20001/docs/language/dartLangSp... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/800413003/diff/20001/docs/language/dartLangSp... docs/language/dartLangSpec.tex:6389: A {\em script} is a library whose exported namespace (\ref{exports}) includes either a top-level function or a function-valued top-level getter named \code{main}. I'm still wary at the "function-valued ... getter" since getters do not have fixed values. If a "main" getter alternates between returning functions and integers, the file should not switch between being a script and not. Still think it's safer to just say "a script is a library whose exported namespace (\ref{exports}) includes a member named \code{main}." Then it's an erroneous script if that "main" member doesn't provide a function when read, but still a script. https://codereview.chromium.org/800413003/diff/20001/docs/language/dartLangSp... docs/language/dartLangSpec.tex:6400: It is a run time error if $S$ does not declare or import either a top-level function or a function-valued top-level getter named \code{main}. It is a static warning if the static type of \code{main} is not assignable to a function type or is a function type with more than two required parameters. Ok, if this only applies to the entry-point script library - which is what I assume from the juxtaposition with the first sentence. So, summary of my understanding of this: The definition of "script" above is such that it can only be checked at runtime (at least in some cases) by executing a "main" getter. Giving a static warning here is not about being a script or not, it's about being executed as one. If it's changed as I suggest, then this text is still fine.
Ok, I think this should be better. https://codereview.chromium.org/800413003/diff/20001/docs/language/dartLangSp... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/800413003/diff/20001/docs/language/dartLangSp... docs/language/dartLangSpec.tex:6389: A {\em script} is a library whose exported namespace (\ref{exports}) includes either a top-level function or a function-valued top-level getter named \code{main}. On 2014/12/17 19:02:01, Lasse Reichstein Nielsen wrote: > I'm still wary at the "function-valued ... getter" since getters do not have > fixed values. If a "main" getter alternates between returning functions and > integers, the file should not switch between being a script and not. > > Still think it's safer to just say "a script is a library whose exported > namespace (\ref{exports}) includes a member named \code{main}." > > Then it's an erroneous script if that "main" member doesn't provide a function > when read, but still a script. Done. I've also moved the static warning text up, so it is clear what is static and what is dynamic. https://codereview.chromium.org/800413003/diff/20001/docs/language/dartLangSp... docs/language/dartLangSpec.tex:6400: It is a run time error if $S$ does not declare or import either a top-level function or a function-valued top-level getter named \code{main}. It is a static warning if the static type of \code{main} is not assignable to a function type or is a function type with more than two required parameters. On 2014/12/17 19:02:01, Lasse Reichstein Nielsen wrote: > Ok, if this only applies to the entry-point script library - which is what I > assume from the juxtaposition with the first sentence. > > So, summary of my understanding of this: The definition of "script" above is > such that it can only be checked at runtime (at least in some cases) by > executing a "main" getter. Giving a static warning here is not about being a > script or not, it's about being executed as one. > If it's changed as I suggest, then this text is still fine. Now it should be more clear that the run time error occurs when you execute the script. I also changed import to export. I don't think import makes any sense.
lgtm https://codereview.chromium.org/800413003/diff/40001/docs/language/dartLangSp... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/800413003/diff/40001/docs/language/dartLangSp... docs/language/dartLangSpec.tex:6401: It is a run time error if $S$ does not declare or export either a top-level function or a function-valued top-level getter named \code{main}. I think that is better. The structure now makes it clear that this is just about execution. How about changing "function-valued .. getter" to "function-returning .. getter"?
On 2014/12/18 07:02:39, Lasse Reichstein Nielsen wrote: > lgtm > > https://codereview.chromium.org/800413003/diff/40001/docs/language/dartLangSp... > File docs/language/dartLangSpec.tex (right): > > https://codereview.chromium.org/800413003/diff/40001/docs/language/dartLangSp... > docs/language/dartLangSpec.tex:6401: It is a run time error if $S$ does not > declare or export either a top-level function or a function-valued top-level > getter named \code{main}. > I think that is better. The structure now makes it clear that this is just about > execution. > How about changing "function-valued .. getter" to "function-returning .. > getter"? Done (more or less).
Message was sent while issue was closed.
Committed patchset #4 (id:60001) manually as r42464 (presubmit successful). |