Re: [Chicken-hackers] testcase -strict-types
From: Peter Bex peter@xs4all.nl Subject: Re: [Chicken-hackers] testcase -strict-types Date: Sun, 31 Mar 2013 01:00:01 +0100 On Sun, Mar 31, 2013 at 12:36:56AM +0100, Felix wrote: Strict-types means you declare that variables never change their type, once a type has been inferred (or explicitly declared). There are a few places in the scrutinizer where it can make stronger assumptions about variable types during flow-analysis, which leads to potentially much better code. In fact, the improvements where the reason that the option is there in the first place - it was just a straightforward thing to do. For normal Scheme code these stronger assumptions are often not valid. But if you use Scheme as a target language for other languages (compiler-generated or by using macros extensively), it may be possible to generate code that will still be valid in strict-types mode. If you think this isn't worth the trouble of users getting confused, we can remove the option and declaration (or simply undocument it). I think this is an interesting target mode, and might be useful in some cases. It's a little hard to pinpoint exactly when it will be useful, though. Perhaps a simple note in the manual as to the expected use cases might be enough? Will do. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
From: John Cowan co...@mercury.ccil.org Subject: Re: [Chicken-hackers] testcase -strict-types Date: Sat, 30 Mar 2013 21:14:49 -0400 Felix scripsit: Strict-types means you declare that variables never change their type, once a type has been inferred (or explicitly declared). That sounds like an excellent feature. But in that case, if the known procedure `null?` is being called on an expression whose type is known to be the type of (), the call should be replaced with #t, and if it is known *not* to be the type of (), the call should be replaced with #f. In neither case should it be a compile-time error to invoke `null?` in that circumstance, and I don't understand why it currently is. It's not a compile-time error, just a warning. The code violates the assumptions that -strict-types apply. I'm not sure how to put it differently. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
From: Felix fe...@call-with-current-continuation.org Subject: Re: [Chicken-hackers] testcase -strict-types Date: Sun, 31 Mar 2013 15:07:33 +0200 (CEST) From: John Cowan co...@mercury.ccil.org Subject: Re: [Chicken-hackers] testcase -strict-types Date: Sat, 30 Mar 2013 21:14:49 -0400 Felix scripsit: Strict-types means you declare that variables never change their type, once a type has been inferred (or explicitly declared). That sounds like an excellent feature. But in that case, if the known procedure `null?` is being called on an expression whose type is known to be the type of (), the call should be replaced with #t, and if it is known *not* to be the type of (), the call should be replaced with #f. In neither case should it be a compile-time error to invoke `null?` in that circumstance, and I don't understand why it currently is. It's not a compile-time error, just a warning. The code violates the assumptions that -strict-types apply. I'm not sure how to put it differently. Or, in other words, the compiler is pointing out that the code in question has no usable effect, and is redundant. Notes (which are only shown in verbose mode) are just style-warnings, so to speak. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Mar 30 2013, Felix wrote: Though in a way the explanation is correct. -strict-types assumes '() to be null from the initialization. Short of a way to declare the type of foobar as (list-of whatever) this fails when it's used as the initial and correct value of type (list-of whatever) with zero length. What the optimizer should do is to see into the doloop and notice the ambiguous type null being refined to a list. ... and this is exactly what the normal type-analysis is doing. But that refinement generalizes the type of a variable to cover all uses of it, and that makes it very difficult to figure out the most specific type, in particular when the type changes during the lifetime of a variable. List-types create more problems as this example shows. So I can only keep suggesting not to use strict-types but in special situations. After I understood that the type analysis would be troubled and there's the (the type init) alternative, I'm actually ok with the situation as it is. I've got around one warning per 2000 lines of code; easily tagged with the intended type. (That is, if there where not this problem to trick the compiler into accepting the init value.) Otherwise I love it for being stricter a check. Dunno so far how much effect it actually has as an optimization. /Jörg ... ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Mar 31 2013, Felix wrote: From: Peter Bex peter@xs4all.nl Subject: Re: [Chicken-hackers] testcase -strict-types Date: Sat, 30 Mar 2013 23:44:01 +0100 On Sat, Mar 30, 2013 at 11:33:37PM +0100, Felix wrote: that refinement generalizes the type of a variable to cover all uses of it, and that makes it very difficult to figure out the most specific type, in particular when the type changes during the lifetime of a variable. List-types create more problems as this example shows. So I can only keep suggesting not to use strict-types but in special situations. Would you be so kind as to explain what exactly is the purported use of strict-types? It's all rather unclear to me right now. Strict-types means you declare that variables never change their type, once a type has been inferred (or explicitly declared). There are a few places in the scrutinizer where it can make stronger assumptions about variable types during flow-analysis, which leads to potentially much better code. In fact, the improvements where the reason that the option is there in the first place - it was just a straightforward thing to do. For normal Scheme code these stronger assumptions are often not valid. But if you use Scheme as a target language for other languages (compiler-generated or by using macros extensively), it may be possible to generate code that will still be valid in strict-types mode. If you think this isn't worth the trouble of users getting confused, we can remove the option and declaration (or simply undocument it). No, please keep it! A typesafe Scheme is not a Scheme in a way anymore. But it's a better Scheme in another way! /Jörg ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Sun, Mar 31, 2013 at 12:36:56AM +0100, Felix wrote: Strict-types means you declare that variables never change their type, once a type has been inferred (or explicitly declared). There are a few places in the scrutinizer where it can make stronger assumptions about variable types during flow-analysis, which leads to potentially much better code. In fact, the improvements where the reason that the option is there in the first place - it was just a straightforward thing to do. For normal Scheme code these stronger assumptions are often not valid. But if you use Scheme as a target language for other languages (compiler-generated or by using macros extensively), it may be possible to generate code that will still be valid in strict-types mode. If you think this isn't worth the trouble of users getting confused, we can remove the option and declaration (or simply undocument it). I think this is an interesting target mode, and might be useful in some cases. It's a little hard to pinpoint exactly when it will be useful, though. Perhaps a simple note in the manual as to the expected use cases might be enough? Cheers, Peter -- http://www.more-magic.net ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
Felix scripsit: Strict-types means you declare that variables never change their type, once a type has been inferred (or explicitly declared). That sounds like an excellent feature. But in that case, if the known procedure `null?` is being called on an expression whose type is known to be the type of (), the call should be replaced with #t, and if it is known *not* to be the type of (), the call should be replaced with #f. In neither case should it be a compile-time error to invoke `null?` in that circumstance, and I don't understand why it currently is. -- You escaped them by the will-death John Cowan and the Way of the Black Wheel. co...@ccil.org I could not. --Great-Souled Samhttp://www.ccil.org/~cowan ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
From: Jörg F. Wittenberger joerg.wittenber...@softeyes.net Subject: [Chicken-hackers] testcase -strict-types Date: 24 Mar 2013 21:00:30 +0100 The attached code fails when compiled with -strict-types. $ csc -strict-types -verbose strcttps.scm /usr/bin/chicken strcttps.scm -output-file strcttps.c -strict-types -verbose Note: in local procedure `doloop9', in toplevel procedure `foo#bar': (strcttps.scm:10) in procedure call to `null?', the predicate is called with an argument of type `null' and will always return true gcc strcttps.c -o strcttps.o -c -fno-strict-aliasing -fwrapv -DHAVE_CHICKEN_CONFIG_H -DC_ENABLE_PTABLES -Os -fomit-frame-pointer -I/usr/include/chicken rm strcttps.c gcc strcttps.o -o strcttps -L/usr/lib -Wl,-R/usr/lib -lchicken -lm -ldl rm strcttps.o $ ./strcttps gaga Hello! -strict-types should be considered experimental. It makes assumptions about the use of types that are very easily violated by normal Scheme code. That particular example you show here demonstrates that very nicely. So my suggestion is not to use -strict-types, unless you have very heavy need for performance or are using machine-generated code. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
Jörg F. Wittenberger joerg.wittenber...@softeyes.net writes: Though in a way the explanation is correct. -strict-types assumes '() to be null from the initialization. Short of a way to declare the type of foobar as (list-of whatever) this fails when it's used as the initial and correct value of type (list-of whatever) with zero length. You should be able to use `the' or `assume' for that purpose. What the optimizer should do is to see into the doloop and notice the ambiguous type null being refined to a list. Given that the description of -strict-types is assume variable do not change their type I think the behavior is correct. Find attached two more variants. strcttps2.scm, which convinces chicken to do the right thing, ans strcttps2.scm, which fails the other way around. Right, here you initialize the variable's type with list (or pair, I don't know what's detected) and then possible change it to null while never checking with null? on the whole list but only on the rest. Looks fine from what I can tell! Moritz ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Mon, Mar 25, 2013 at 09:58:32AM +0100, Jörg F. Wittenberger wrote: Though in a way the explanation is correct. -strict-types assumes '() to be null from the initialization. Short of a way to declare the type of foobar as (list-of whatever) this fails when it's used as the initial and correct value of type (list-of whatever) with zero length. This seems to be a bug, unless I'm mistaken. Could you please file a ticket for this? Thanks! What the optimizer should do is to see into the doloop and notice the ambiguous type null being refined to a list. No, it shouldn't, because you've declared strict types. That explicitly tells it not to do this AFAICT. I'd simply change the code to be functional, this eliminates the problems you're having. All this messing around with set! is needlessly confusing (for the person reading the code as well as the scrutinizer). (module foo (bar) (import scheme chicken) (define (bar . args) (let ((foobar '())) (do ((rest args (cddr rest)) (foobar '() (if (eq? (car rest) #:foobar) (cons (cadr rest) foobar) foobar))) ((null? rest) (if (null? foobar) 'gaga foobar)) (if (null? (cdr rest)) (error (car rest)) ) (import foo) (display (bar #:foobar 42)) (newline) Cheers, Peter -- http://www.more-magic.net ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Mar 25 2013, Moritz Heidkamp wrote: Jörg F. Wittenberger joerg.wittenber...@softeyes.net writes: Though in a way the explanation is correct. -strict-types assumes '() to be null from the initialization. Short of a way to declare the type of foobar as (list-of whatever) this fails when it's used as the initial and correct value of type (list-of whatever) with zero length. You should be able to use `the' or `assume' for that purpose. Where would I find the respective assume to be documented? (Would the syntax break standard Scheme compatibility?) What the optimizer should do is to see into the doloop and notice the ambiguous type null being refined to a list. Given that the description of -strict-types is assume variable do not change their type I think the behavior is correct. Find attached two more variants. strcttps2.scm, which convinces chicken to do the right thing, ans strcttps2.scm, which fails the other way around. Right, here you initialize the variable's type with list (or pair, I don't know what's detected) and then possible change it to null while never checking with null? on the whole list but only on the rest. Looks fine from what I can tell! ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
Jörg F. Wittenberger joerg.wittenber...@softeyes.net writes: [1. text/plain] On Mar 25 2013, Moritz Heidkamp wrote: Jörg F. Wittenberger joerg.wittenber...@softeyes.net writes: Though in a way the explanation is correct. -strict-types assumes '() to be null from the initialization. Short of a way to declare the type of foobar as (list-of whatever) this fails when it's used as the initial and correct value of type (list-of whatever) with zero length. You should be able to use `the' or `assume' for that purpose. Where would I find the respective assume to be documented? In the manual page about the type system, e.g. http://wiki.call-cc.org/man/4/Types (Would the syntax break standard Scheme compatibility?) They are regular Scheme syntax so you can stub them. You could use http://wiki.call-cc.org/eggref/4/type-stubs for other Schemes, too (it is intended to be used with older Chickens). Moritz ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
Jörg F. Wittenberger scripsit: Note: in local procedure `doloop9', in toplevel procedure `foo#bar': (strcttps.scm:10) in procedure call to `null?', the predicate is called with an argument of type `null' and will always return true That strikes me as Just Wrong. Even if a predicate is known to always succeed, it shouldn't be impossible to call it, any more than it should be impossible to call a predicate that always returns #t on any argument. -- The Imperials are decadent, 300 pound John Cowan co...@ccil.org free-range chickens (except they have http://www.ccil.org/~cowan teeth, arms instead of wings, and dinosaurlike tails).--Elyse Grasso ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
John Cowan co...@mercury.ccil.org writes: Jörg F. Wittenberger scripsit: Note: in local procedure `doloop9', in toplevel procedure `foo#bar': (strcttps.scm:10) in procedure call to `null?', the predicate is called with an argument of type `null' and will always return true That strikes me as Just Wrong. Even if a predicate is known to always succeed, it shouldn't be impossible to call it, any more than it should be impossible to call a predicate that always returns #t on any argument. Note that it's just a Note, though :-) I think it's sensible to show this as it might indeed point to some unnecessary / redundant check that could just as well be removed. Moritz ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Mar 24 2013, John Cowan wrote: Jörg F. Wittenberger scripsit: Note: in local procedure `doloop9', in toplevel procedure `foo#bar': (strcttps.scm:10) in procedure call to `null?', the predicate is called with an argument of type `null' and will always return true That strikes me as Just Wrong. Even if a predicate is known to always succeed, it shouldn't be impossible to call it, any more than it should be impossible to call a predicate that always returns #t on any argument. Well, if it's a predicate (as in #:pure) know to return a fixed boolean value, it should reightfully be optimized out. That's actually important in cases like and-let* and also often handy when using macro expanded code. Thus the test being optimized away looks correct to me. The problem I see is that the foobar binding is mutated within the doloop but chicken does not see it and hence believes it's still for sure the initialization value when the doloop terminates. ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
Hi Jörg, Jörg F. Wittenberger joerg.wittenber...@softeyes.net writes: Note: in local procedure `doloop9', in toplevel procedure `foo#bar': (strcttps.scm:10) in procedure call to `null?', the predicate is called with an argument of type `null' and will always return true gcc strcttps.c -o strcttps.o -c -fno-strict-aliasing -fwrapv -DHAVE_CHICKEN_CONFIG_H -DC_ENABLE_PTABLES -Os -fomit-frame-pointer -I/usr/include/chicken rm strcttps.c gcc strcttps.o -o strcttps -L/usr/lib -Wl,-R/usr/lib -lchicken -lm -ldl rm strcttps.o $ ./strcttps gaga The Note points to the problem I think: The specializer seems to just replace your null? check with #t as can be seen when compiling the program like this: $ csc -debug 3 -strict-types strcttps.scm The output contains this: (if #t (k225 'gaga) (k225 foobar8)) I'm not sure how -strict-types could lead to this result. Maybe the type declaration for null? is flawed somehow? Moritz ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] testcase -strict-types
On Sun, Mar 24, 2013 at 10:59:16PM +0100, Moritz Heidkamp wrote: Hi Jörg, The Note points to the problem I think: The specializer seems to just replace your null? check with #t as can be seen when compiling the program like this: $ csc -debug 3 -strict-types strcttps.scm The output contains this: (if #t (k225 'gaga) (k225 foobar8)) I'm not sure how -strict-types could lead to this result. Maybe the type declaration for null? is flawed somehow? As I understand it, strict-types declares variables to never change their types. So once it's looked at the initial declaration of the variable, it assigns it a type of null, and then it can never change. -strict-types assume variable do not change their type The set! would change the type from NULL to LIST (or maybe PAIR), invalidating that assumption. Cheers, Peter -- http://www.more-magic.net ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org https://lists.nongnu.org/mailman/listinfo/chicken-hackers