|
Hi all,
as many may know we started with the project Grumpy, an annotation @StaticTypes, which will do static type checking on Groovy code. Of course that means not all groovy programs will compile in this mode. The semantics of the groovy program stay the same though. Anyway, this post is not really to discuss grumpy in its all, it is more about needing a decision on how we should let it behave in a certain situation. In Java if you have long x = 1; int y = x; then the compiler will complain because the long value may not fit in the int and you will need to add a cast to force this to pass. In standard Groovy the same program will pass, in fact it will compile the program as this: long x = 1; int y = (int) x; that means the cast required in Java is there already, even though it is an implicit one. And we support things like int[] x = [1,2,3] Dimension d = [100,200] for example, which is far from what Java allows you to do. Now the question is how grumpy should handle this. Should it go the Java path, disallowing a large part of groovy programs and not leaving a nice way to create arrays... or should we stay in the groovy path, meaning there are almost no type checks on assignment? bye blackdrag -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
I'd say that Grumpy should be grumpy enough to require an explicit cast.
(this should be a rather easy codenarc-style rule ;-) A second question is whether to require an explicit call to castToType. I'm not yet decided on this one. The code will not look nice anymore but not requiring it would defeat the purpose of Grumpy. cheers Dierk P.S. great to see this effort going forward! Am 07.10.2011 um 22:55 schrieb Jochen Theodorou: > Hi all, > > as many may know we started with the project Grumpy, an annotation @StaticTypes, which will do static type checking on Groovy code. Of course that means not all groovy programs will compile in this mode. The semantics of the groovy program stay the same though. > > Anyway, this post is not really to discuss grumpy in its all, it is more about needing a decision on how we should let it behave in a certain situation. > > In Java if you have > > long x = 1; > int y = x; > > then the compiler will complain because the long value may not fit in the int and you will need to add a cast to force this to pass. > > In standard Groovy the same program will pass, in fact it will compile the program as this: > > long x = 1; > int y = (int) x; > > that means the cast required in Java is there already, even though it is an implicit one. And we support things like > > int[] x = [1,2,3] > Dimension d = [100,200] > > for example, which is far from what Java allows you to do. Now the question is how grumpy should handle this. Should it go the Java path, disallowing a large part of groovy programs and not leaving a nice way to create arrays... or should we stay in the groovy path, meaning there are almost no type checks on assignment? > > bye blackdrag > > -- > Jochen "blackdrag" Theodorou - Groovy Project Tech Lead > blog: http://blackdragsview.blogspot.com/ > german groovy discussion newsgroup: de.comp.lang.misc > For Groovy programming sources visit http://groovy-lang.org > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Le 08/10/2011 00:39, Dierk König a écrit :
> I'd say that Grumpy should be grumpy enough to require an explicit cast. > (this should be a rather easy codenarc-style rule ;-) > > A second question is whether to require an explicit call to castToType. > I'm not yet decided on this one. I'm not sure I understand what you mean. Can you give an example ? BTW, there's now a Groovy Enhancement Proposal page for the static type checking mode. Here is the link : http://docs.codehaus.org/display/GroovyJSR/GEP+8+-+Static+type+checking I will update the page based on our different discussions. Cédric --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Jochen Theodorou
"grumpy" should only allow what it can prove to be safe. Your three examples are safe coercions, and if "grumpy" can prove them safe, it should allow them. It's more a question of how smart you can and want to make "grumpy", and what other goals you have for it (like leveraging it for a static compilation mode).
Cheers, Peter |
|
In reply to this post by Dierk König
Perhaps you can elaborate on your expectations for Grumpy?
What would you like it to tell you for some cases you could think of? Where do you think it should be pretty strict, where it should be more relaxed, etc.
Guillaume
On Sat, Oct 8, 2011 at 00:39, Dierk König <[hidden email]> wrote: I'd say that Grumpy should be grumpy enough to require an explicit cast. Guillaume Laforge Groovy Project Manager Head of Groovy Development at SpringSource http://www.springsource.com/g2one |
|
In reply to this post by Peter Niederwieser
Peter, perhaps you could tell us a few words of what you'd like this "grumpy" static type checking mode to do?
Do you have some particular ideas of things that you think Grumpy should be complaining about?
As well as other aspects it should be cool with? Guillaume
On Sat, Oct 8, 2011 at 18:02, Peter Niederwieser <[hidden email]> wrote: "grumpy" should only allow what it can prove to be safe. Your three examples Guillaume Laforge Groovy Project Manager Head of Groovy Development at SpringSource http://www.springsource.com/g2one |
|
In reply to this post by Jochen Theodorou
What if in static mode, no coercion takes place much like Haskell?
The traditional argument for static are type and speed. This is an optional mode, so if someone care enough to want to turn this on, seems no coercion is worth exploring as a path On Oct 7, 2011, at 4:55 PM, Jochen Theodorou <[hidden email]> wrote: > Hi all, > > as many may know we started with the project Grumpy, an annotation @StaticTypes, which will do static type checking on Groovy code. Of course that means not all groovy programs will compile in this mode. The semantics of the groovy program stay the same though. > > Anyway, this post is not really to discuss grumpy in its all, it is more about needing a decision on how we should let it behave in a certain situation. > > In Java if you have > > long x = 1; > int y = x; > > then the compiler will complain because the long value may not fit in the int and you will need to add a cast to force this to pass. > > In standard Groovy the same program will pass, in fact it will compile the program as this: > > long x = 1; > int y = (int) x; > > that means the cast required in Java is there already, even though it is an implicit one. And we support things like > > int[] x = [1,2,3] > Dimension d = [100,200] > > for example, which is far from what Java allows you to do. Now the question is how grumpy should handle this. Should it go the Java path, disallowing a large part of groovy programs and not leaving a nice way to create arrays... or should we stay in the groovy path, meaning there are almost no type checks on assignment? > > bye blackdrag > > -- > Jochen "blackdrag" Theodorou - Groovy Project Tech Lead > blog: http://blackdragsview.blogspot.com/ > german groovy discussion newsgroup: de.comp.lang.misc > For Groovy programming sources visit http://groovy-lang.org > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Am 08.10.2011 19:26, schrieb Wilson MacGyver:
> What if in static mode, no coercion takes place much like Haskell? This is not about a static compilation, this is only about a static compile time checking. If you mean with coercion what "our" as-operator does, then there is no coercion. But the standard Groovy cast contains transformations of values into other types, like for example widening - like Java, but of course also much more. The result would thus be, that quite many Groovy programs would be rejected by grumpy, even though they would work. bye blackdrag -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
On Sat, Oct 8, 2011 at 1:33 PM, Jochen Theodorou <[hidden email]> wrote:
> Am 08.10.2011 19:26, schrieb Wilson MacGyver: >> >> What if in static mode, no coercion takes place much like Haskell? > > This is not about a static compilation, this is only about a static compile > time checking. If you mean with coercion what "our" as-operator does, then > there is no coercion. But the standard Groovy cast contains transformations > of values into other types, like for example widening - like Java, but of > course also much more. The result would thus be, that quite many Groovy > programs would be rejected by grumpy, even though they would work. right, I understand your original point. I assumed grumpy will reject a bunch of valid regular groovy code. So to me the question is how much to reject. Unless you are saying grumpy mode aims for 100% compatibility with regular groovy, and this is purely a performance play? -- Omnem crede diem tibi diluxisse supremum. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Am 08.10.2011 20:24, schrieb Wilson MacGyver:
[...] > Unless you are saying grumpy mode aims for 100% compatibility with > regular groovy, and this is purely a performance play? 100% compatibility is impossible, since the checks are static and Groovy is a dynamic language. It will always reject programs that are perfectly find in Groovy. The question is more to waht extend this should be done. Performance doesn't matter here at all for now. On the other hand, if you compare "Dimension d = [100,200]" and "Dimension d = new Dimension(100,200)", then there is no real performance hit in this - at least none that has to be there. Actually the same for "long x=1; int y=x" So even if we statically compile this, performance would be no reason, if then the user would do what the compiler does for him. Performance becomes a reason, if that would cause the suer to change the code in a way that does not require to bypass the compiler... for example making x an int. But have these code transformation cases really more weight than the ability to write less code in all? bye blackdrag -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
How is static mode going to handle DGMs? Will they not be allowed?
If they are, then how would it handle something like this? Would this be a compile error? ["foo", "bar"].each { print it.substring(0) } Will you need to explicitly type the closure argument? ["foo", "bar"].each { String it -> print it.substring(0) } The latter seems a bit of a shame because the typing is redundant in a way. But, the former is a real problem for a static checker since the type of 'it' can only be inferred from the special semantics of 'each'. And of course, this problem is not limited to 'each'. This happens with just about every DGM that takes a closure. To me, it feels like requiring this extra typing takes all of the fun out of programming in groovy. I would hope that even something like static mode would retain some of the fun (and brevity) of the core language. It should be possible to add a little smarts to the static checker so that it can handle things like DGMs. I don't know what your plans are in this area, so perhaps I have no reason to complain at all. --a On Sat, Oct 8, 2011 at 1:29 PM, Jochen Theodorou <[hidden email]> wrote: > Am 08.10.2011 20:24, schrieb Wilson MacGyver: > [...] >> >> Unless you are saying grumpy mode aims for 100% compatibility with >> regular groovy, and this is purely a performance play? > > 100% compatibility is impossible, since the checks are static and Groovy is > a dynamic language. It will always reject programs that are perfectly find > in Groovy. The question is more to waht extend this should be done. > Performance doesn't matter here at all for now. On the other hand, if you > compare "Dimension d = [100,200]" and "Dimension d = new > Dimension(100,200)", then there is no real performance hit in this - at > least none that has to be there. Actually the same for "long x=1; int y=x" > > So even if we statically compile this, performance would be no reason, if > then the user would do what the compiler does for him. Performance becomes a > reason, if that would cause the suer to change the code in a way that does > not require to bypass the compiler... for example making x an int. But have > these code transformation cases really more weight than the ability to write > less code in all? > > bye blackdrag > > -- > Jochen "blackdrag" Theodorou - Groovy Project Tech Lead > blog: http://blackdragsview.blogspot.com/ > german groovy discussion newsgroup: de.comp.lang.misc > For Groovy programming sources visit http://groovy-lang.org > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Am 09.10.2011 04:42, schrieb Andrew Eisenberg:
> How is static mode going to handle DGMs? Will they not be allowed? That is for later. At some point we will have to support DGMs in some way I think. > If they are, then how would it handle something like this? Would this > be a compile error? > > ["foo", "bar"].each { print it.substring(0) } > > Will you need to explicitly type the closure argument? NO, I don't think you will have to type the closure in this example. If the element type of the list cannot be determined, then of course the substring method won't be available. > ["foo", "bar"].each { String it -> print it.substring(0) } > > The latter seems a bit of a shame because the typing is redundant in a > way. But, the former is a real problem for a static checker since the > type of 'it' can only be inferred from the special semantics of > 'each'. And of course, this problem is not limited to 'each'. This > happens with just about every DGM that takes a closure. yes... you may remember in an earlier post I was thinking of using an annotation to store information that goes beyond generics in our own format and for our own needs, set by the groovy compiler. That makes the integration story with Java not as pleasant, but well, one death you will have to die. bye blackdrag -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Cédric Champeau
>> A second question is whether to require an explicit call to castToType.
>> I'm not yet decided on this one. > I'm not sure I understand what you mean. Can you give an example ? java.awt.Dimension dim = (java.awt.Dimension) [100,200] would be an explicit cast but the method call that casts a list into a Dimension would still be implied. cheers Dierk --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Jochen Theodorou
> yes... you may remember in an earlier post I was thinking of using an
> annotation to store information that goes beyond generics in our own format > and for our own needs, set by the groovy compiler. That makes the > integration story with Java not as pleasant, but well, one death you will > have to die. Great. Using an annotation was one of the solutions I was going to get at. There is another related issue is this. Since we are only talking about compile time checking and not performance enhancements at first, it would be nice to have a more general way of specifying types of expressions that aren't statically known. So, for example, let's take some simple metaprogramming: class Foo { Object getProperty(String name) { if (name == "hello") { "hello" } else { throw new MissingPropertyExcepion() } } } And a script: def myVar = new Foo().hello I'm guessing that static mode would raise a compiler problem for the script since it can't statically determine that 'hello' is a property of Foo, or what the type of 'hello' is. Would a simple 'as String' be sufficient to make static mode happy? Or would it still complain about a missing property? I would hope that it would complain, and if so, I would propose something like this: def myVar = new Foo().hello typed String At runtime and when not in static mode, 'typed' has the same semantics as 'as' (ie- casting). However, when static mode is enabled, 'typed' says "ignore whatever is inside this expression and assume that the expression type is String". Essentially, it is a way to untype a region of code. I don't know if 'typed' is the right keyword, but it does seem to get the meaning across. --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
> def myVar = new Foo().hello > > I'm guessing that static mode would raise a compiler problem for the > script since it can't statically determine that 'hello' is a property > of Foo, or what the type of 'hello' is. > > Would a simple 'as String' be sufficient to make static mode happy? > Or would it still complain about a missing property? I would hope > that it would complain, and if so, I would propose something like > this: > > def myVar = new Foo().hello typed String > > At runtime and when not in static mode, 'typed' has the same semantics > as 'as' (ie- casting). the current implementation works with an AST transformation, so with the regular Groovy grammar. However, to answer your question, the current goal is to throw an error if a property is not found (static mode). We can discuss that. If we choose not to throw an error, then the "hello as String" thing would work, because the global type of the expression would be a String. Cédric --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Dierk König
Le 09/10/2011 19:35, Dierk König a écrit :
>>> A second question is whether to require an explicit call to castToType. >>> I'm not yet decided on this one. >> I'm not sure I understand what you mean. Can you give an example ? > java.awt.Dimension dim = (java.awt.Dimension) [100,200] > > would be an explicit cast but the method call that casts a list into a > Dimension would still be implied. > Ok, I thought you talked about int y = x ;) I think we must separate the two things : 1. int int = y where there's a possible loose of precision, that is to say in a static world a possibility of unwanted behaviour 2. Dimension d = [100,200] where this syntax is nothing but syntactic sugar. In this case, I don't see why we should throw an error or require an explicit cast. I'm still unsure about #1... > cheers > Dierk Cedric --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Cédric Champeau
Am 10.10.2011 um 09:07 schrieb Cédric Champeau: >> def myVar = new Foo().hello typed String >> >> At runtime and when not in static mode, 'typed' has the same semantics >> as 'as' (ie- casting). > I don't think we should introduce new keywords enabled in static mode +1 Dierk --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Andrew Eisenberg
Am 10.10.2011 00:23, schrieb Andrew Eisenberg:
[...] > def myVar = new Foo().hello [...] > Or would it still complain about a missing property? I would hope > that it would complain, and if so, I would propose something like > this: > > def myVar = new Foo().hello typed String [...] > At runtime and when not in static mode, 'typed' has the same semantics > as 'as' (ie- casting). However, when static mode is enabled, 'typed' > says "ignore whatever is inside this expression and assume that the > expression type is String". Essentially, it is a way to untype a > region of code. I don't know if 'typed' is the right keyword, but it > does seem to get the meaning across. I think we can go with an annotation here as well. bye blackdrag -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Cédric Champeau
Assigning a long to an int should definitely be forbidden except in cases where Grumpy (funny name for a type checker btw, and not a very positive one) can figure out that the actual long value fits into int (as in Jochen's example). Same for List to Dimension - Grumpy should only allow it if it can figure out that the list elements are assignment-compatible with the constructor parameters. If it can never figure this out, it should never allow it. Otherwise, what's the purpose of Grumpy? Cheers, Peter |
|
Am 10.10.2011 14:42, schrieb Peter Niederwieser:
[...] > Assigning a long to an int should definitely be forbidden except in cases > where Grumpy (funny name for a type checker btw, and not a very positive > one) can figure out that the actual long value fits into int (as in Jochen's > example). Same for List to Dimension - Grumpy should only allow it if it can > figure out that the list elements are assignment-compatible with the > constructor parameters. If it can never figure this out, it should never > allow it. Otherwise, what's the purpose of Grumpy? Grumpy is the project name we will use for discussion. A final name is not yet selected As for the discussion here... I think we can come to this conclusion: "long x = 1; int y = x;" will cause an error, because y might be too big "long x = 1; int y = (int) x;" will work, because x can be converted to an int, under possible loss of data. "int x = 1l" can work, because 1l fits in x, this works only for assignment with constants. "Dimension d = list" will fail, because even if we know that the list contains only elements of the type we need, we cannot be sure about the length, and tuple types are not part of the language yet. "Dimension d = [10, 20]" will work, because we know of the rhs the number of elements and their types - poor mans tuples so to say. "Dimension d = (Dimension) list" will work, because it is now the responsibility of the user to ensure the list is of right size and the elements of right type. It may still fail at runtime though. though one question arises from this logic.... if we have for example "Dimension d = ...; List l = (List) d" then normal Groovy will fail at runtime, should this still pass in grumpy? I tend to say the cast should still be checked if the transformation is likely to pass at runtime. bye blackdrag -- Jochen "blackdrag" Theodorou - Groovy Project Tech Lead blog: http://blackdragsview.blogspot.com/ german groovy discussion newsgroup: de.comp.lang.misc For Groovy programming sources visit http://groovy-lang.org --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
| Powered by Nabble | Edit this page |
