* truth of %nil @ 2009-06-29 21:12 Andy Wingo 2009-06-29 21:44 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Andy Wingo @ 2009-06-29 21:12 UTC (permalink / raw) To: guile-devel Hi all, Daniel came up with an interesting test case: scheme@(guile-user)> (if %nil 1 2) 1 We could fix this transparently by changing scm_is_false in boolean.h from: #define scm_is_false(x) scm_is_eq ((x), SCM_BOOL_F) to #define scm_is_false(x) (scm_is_eq ((x), SCM_BOOL_F) || SCM_NILP (x)) I'm not really sure if this is the right place for this to go, though. It seems that it is. (Ideally the two values would differ by one bit only, and we could mask that bit away and just have the one test.) What do people think? Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-06-29 21:12 truth of %nil Andy Wingo @ 2009-06-29 21:44 ` Neil Jerram 2009-06-29 22:11 ` Andy Wingo 2009-07-02 14:28 ` Mark H Weaver 0 siblings, 2 replies; 38+ messages in thread From: Neil Jerram @ 2009-06-29 21:44 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Andy Wingo <wingo@pobox.com> writes: > Hi all, > > Daniel came up with an interesting test case: > > scheme@(guile-user)> (if %nil 1 2) > 1 > > We could fix this transparently by changing scm_is_false in boolean.h > from: > > #define scm_is_false(x) scm_is_eq ((x), SCM_BOOL_F) > > to > > #define scm_is_false(x) (scm_is_eq ((x), SCM_BOOL_F) || SCM_NILP (x)) > > I'm not really sure if this is the right place for this to go, though. > It seems that it is. (Ideally the two values would differ by one bit > only, and we could mask that bit away and just have the one test.) What > do people think? > > Andy > -- > http://wingolog.org/ Seems wrong to me. In Scheme #f should be the only false value. What's the argument for %nil being false in Scheme code? Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-06-29 21:44 ` Neil Jerram @ 2009-06-29 22:11 ` Andy Wingo 2009-06-30 22:22 ` Neil Jerram 2009-07-02 14:28 ` Mark H Weaver 1 sibling, 1 reply; 38+ messages in thread From: Andy Wingo @ 2009-06-29 22:11 UTC (permalink / raw) To: Neil Jerram; +Cc: guile-devel On Mon 29 Jun 2009 23:44, Neil Jerram <neil@ossau.uklinux.net> writes: > Andy Wingo <wingo@pobox.com> writes: > >> scheme@(guile-user)> (if %nil 1 2) >> 1 >> >> #define scm_is_false(x) (scm_is_eq ((x), SCM_BOOL_F) || SCM_NILP (x)) > Seems wrong to me. In Scheme #f should be the only false value. > What's the argument for %nil being false in Scheme code? I thought the original plan regarding %nil and #f and '() was that %nil wasn't supposed to be seen normally from Scheme, and for that reason (and (null? %nil) (not %nil)) would not be a problem. Guile has treated %nil as false for quite some time: scheme@(guile-user)> ,o interp #t scheme@(guile-user)> (if %nil 1 2) $1 = 2 Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-06-29 22:11 ` Andy Wingo @ 2009-06-30 22:22 ` Neil Jerram 2009-07-01 6:45 ` Daniel Kraft 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-06-30 22:22 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Andy Wingo <wingo@pobox.com> writes: > On Mon 29 Jun 2009 23:44, Neil Jerram <neil@ossau.uklinux.net> writes: > >> Andy Wingo <wingo@pobox.com> writes: >> >>> scheme@(guile-user)> (if %nil 1 2) >>> 1 >>> >>> #define scm_is_false(x) (scm_is_eq ((x), SCM_BOOL_F) || SCM_NILP (x)) > >> Seems wrong to me. In Scheme #f should be the only false value. >> What's the argument for %nil being false in Scheme code? > > I thought the original plan regarding %nil and #f and '() was that %nil > wasn't supposed to be seen normally from Scheme, and for that reason > (and (null? %nil) (not %nil)) would not be a problem. > > Guile has treated %nil as false for quite some time: > > scheme@(guile-user)> ,o interp #t > scheme@(guile-user)> (if %nil 1 2) > $1 = 2 I'm sorry... you're completely right. Brain storm on my part. But then I don't understand the cause of your suggestion. Is it that master has somehow regressed, so as to cause (if %nil 1 2) => 1 ? Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-06-30 22:22 ` Neil Jerram @ 2009-07-01 6:45 ` Daniel Kraft 2009-07-01 21:54 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Daniel Kraft @ 2009-07-01 6:45 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, guile-devel Hi Neil, Neil Jerram wrote: > Andy Wingo <wingo@pobox.com> writes: >> Guile has treated %nil as false for quite some time: >> >> scheme@(guile-user)> ,o interp #t >> scheme@(guile-user)> (if %nil 1 2) >> $1 = 2 > > I'm sorry... you're completely right. Brain storm on my part. > > But then I don't understand the cause of your suggestion. Is it that > master has somehow regressed, so as to cause (if %nil 1 2) => 1 ? it seems so. Doing just a scheme@(guile-user)> (if %nil 1 2) 1 with a recent build (of at least my elisp branch, but that did not change anything in this respect of course) gives that answer. Doing ,o interp #t as Andy did however also gives the right answer for me. BTW, I've just changed my elisp compiler to use real nil instead of #f for nil, but now it doesn't have the right semantics of course (that's the motivation here). Yours, Daniel ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-01 6:45 ` Daniel Kraft @ 2009-07-01 21:54 ` Neil Jerram 2009-07-05 13:07 ` Mark H Weaver 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-07-01 21:54 UTC (permalink / raw) To: Daniel Kraft; +Cc: Andy Wingo, guile-devel Daniel Kraft <d@domob.eu> writes: > it seems so. Doing just a > > scheme@(guile-user)> (if %nil 1 2) > 1 > > with a recent build (of at least my elisp branch, but that did not > change anything in this respect of course) gives that answer. > > Doing ,o interp #t as Andy did however also gives the right answer for > me. BTW, I've just changed my elisp compiler to use real nil instead > of #f for nil, but now it doesn't have the right semantics of course > (that's the motivation here). OK, I see. The point is that VM ops like br-if use SCM_FALSEP (which is equivalent to scm_is_false), and hence you're wondering if it would be easier to change the definition of scm_is_false, than to modify those ops to say (SCM_FALSEP (x) || SCM_NILP (x)). I think the balance of arguments is clearly against doing that: - There are lots of places that use scm_is_false where there is no need to allow for the value being tested being %nil. Changing scm_is_false would be a performance hit for those places. - There are only a handful of places (I think) that you need to change to get %nil-falseness in the VM. - There is a similar number of places which already implement %nil-falseness in the interpreter by using (scm_is_false (x) || SCM_NILP (x)), and these would logically have to be changed if you made your proposed change. - It would be an incompatible API change. So please just change the relevant places in the VM to say (scm_is_false (x) || SCM_NILP (x)) instead. Regards, Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-01 21:54 ` Neil Jerram @ 2009-07-05 13:07 ` Mark H Weaver 2009-08-30 11:07 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Mark H Weaver @ 2009-07-05 13:07 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, Daniel Kraft, guile-devel I would like to argue that the definitions of scm_is_false, scm_is_true, and scm_is_null should indeed be changed to test for %nil. Do a grep-find in the tree for uses of these macros. I think you'll find that the majority of places where they are used should also be checking for %nil, but they are not. The only times when we can safely avoid testing for %nil is when we know *statically* that the value being tested was not created by elisp code. Of course, in scheme, it is extremely rare that we can know this statically. Even bindings like `and', `or', and `not' could in principle be bound to elisp functions. More importantly, scm_is_false, scm_is_true, and scm_is_null in code outside of guile's source tree should almost always be checking for %nil, unless they know statically that their own code created the value in question (because they shouldn't make assumptions about what libguile's code will do in the future), which again is very rare. Right now, there are scores of bugs in guile's tree that will only show up sporadically for those doing heavy mixing of elisp and scheme, because most code written in C (almost everything except for the evaluator itself) is failing to check for %nil even though it should. Do a quick grep for uses of scm_is_null in the C code for srfi-1, for just one example. The default should be to test for %nil. If, in a particular use, it can be proved statically that the value was not created by an elisp function (which we can almost never prove), then that is a case where we can use some faster test. But someone will have to think about each of these cases individually anyway, so it makes sense that these faster tests should be named something different than the old names, and preferably with a longer name, calling attention to the fact that it is a potential source of bugs -- because even if at some point a tested value can be proved to never be %nil, this might very well change later, thus creating a new rarely-triggered bug in old code. Maybe names something like this: scm_is_false_xxx_assume_never_nil scm_is_true_xxx_assume_never_nil scm_if_null_xxx_assume_never_nil One category of place where these could be used is code dealing with data structures created internally by the evaluator -- though I'm not very familiar with guile's internals, so I don't know how common these data structures are, if indeed they exist at all. Best regards, Mark On Wed, Jul 01, 2009 at 10:54:50PM +0100, Neil Jerram wrote: > OK, I see. The point is that VM ops like br-if use SCM_FALSEP (which > is equivalent to scm_is_false), and hence you're wondering if it would > be easier to change the definition of scm_is_false, than to modify > those ops to say (SCM_FALSEP (x) || SCM_NILP (x)). > > I think the balance of arguments is clearly against doing that: > > - There are lots of places that use scm_is_false where there is no > need to allow for the value being tested being %nil. Changing > scm_is_false would be a performance hit for those places. > > - There are only a handful of places (I think) that you need to change > to get %nil-falseness in the VM. > > - There is a similar number of places which already implement > %nil-falseness in the interpreter by using (scm_is_false (x) || > SCM_NILP (x)), and these would logically have to be changed if you > made your proposed change. > > - It would be an incompatible API change. > > So please just change the relevant places in the VM to say > (scm_is_false (x) || SCM_NILP (x)) instead. > > Regards, > Neil > > > ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-05 13:07 ` Mark H Weaver @ 2009-08-30 11:07 ` Neil Jerram 2009-08-30 14:11 ` Mark H Weaver 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-08-30 11:07 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, Daniel Kraft, guile-devel Hi Mark! Mark H Weaver <mhw@netris.org> writes: > I would like to argue that the definitions of scm_is_false, > scm_is_true, and scm_is_null should indeed be changed to test for > %nil. OK, thanks to your arguments, I now agree with this. > Do a grep-find in the tree for uses of these macros. I think you'll > find that the majority of places where they are used should also be > checking for %nil, but they are not. I started doing this. Actually some of the first ones are in backtrace.c (testing for the file and line source properties), and I think those may be counter-examples... but I agree that there are many many cases that should be allowing for %nil. But then I thought that this argument isn't really about the numbers. It's that we have effectively taken a decision to treat Elisp as a special case, among the set of languages that Guile may eventually support - a fact which I now realize more clearly thanks to your and others' querying of the treatment of nil, and thanks to the developing language support - specifically in the sense of being able to pass data between Scheme and Elisp without requiring any translation. And therefore it makes sense that libguile's most immediately available APIs - i.e. scm_is_false/true/bool/null - should allow for their args coming from either Scheme or Elisp. So, thanks for persisting with the argument. > If, in a particular use, it > can be proved statically that the value was not created by an elisp > function (which we can almost never prove), then that is a case where > we can use some faster test. But someone will have to think about > each of these cases individually anyway, so it makes sense that these > faster tests should be named something different than the old names, This is of course something that you've included in your patch, and I'm happy with that. This is also something that could (potentially!) be optimized at runtime or by the compiler (reminds me of the class of calls where type checking could be eliminated if the compiler can prove that objects will always be of the required type). So, if you would be happy to do so, can I suggest that you rework your patches so that they also make (and then assume, obviously) the scm_is_false/true/bool/null change, and incorporate my other comments? It would also be more convenient - and better for giving you your deserved attribution - if you could submit them as Git patches. Would that be possible? Alternatively, if you have your own Git repository, we could pull from that. Also, we will need documentation of the new APIs, and to explain the overall concept; and a NEWS entry; and maybe a couple of tests to check where data that includes %nil is passed to some of the fixed functions. Would you be willing to prepare all those too? > One category of place where these could be used is code dealing with > data structures created internally by the evaluator -- though I'm not > very familiar with guile's internals, so I don't know how common these > data structures are, if indeed they exist at all. Yes, indeed. In the updated patch(es), I suggest that you mark the cases that you are not sure about, then I and other developers can help work out what kind of check they should be doing. Many thanks! Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-30 11:07 ` Neil Jerram @ 2009-08-30 14:11 ` Mark H Weaver 2009-09-01 22:00 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Mark H Weaver @ 2009-08-30 14:11 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, Daniel Kraft, guile-devel Neil wrote: > > I would like to argue that the definitions of scm_is_false, > > scm_is_true, and scm_is_null should indeed be changed to test for > > %nil. > > OK, thanks to your arguments, I now agree with this. Excellent! What about scm_is_bool? I'm tempted to suggest that it should work the same way as "boolean?" within scheme, whatever that may be. I tend to think they ought to treat %nil as boolean, though I'm less sure of this than about scm_is_true/false/null. It's the right thing for type-checking an argument that is expected to be boolean, which seems to be fairly common in guile. More complex code that is dispatching on type (such as the aforementioned GOOPS code) will in general have to be fixed to take into account that %nil is both a boolean and a list. One more thing: scheme code can reasonably expect to "write" a list of simple values and then "read" it back in. But now, lists might be terminated by %nil instead of '(). Therefore, I think "read" needs to be able to read SCM_LISP_NIL in whatever form we "write" it in. I'll let someone more knowledgable about guile reader issues decide what that form should be. Currently we write it as "#nil". > > If, in a particular use, it > > can be proved statically that the value was not created by an elisp > > function (which we can almost never prove), then that is a case where > > we can use some faster test. [...] > > [...] > > This is also something that could (potentially!) be optimized at > runtime or by the compiler (reminds me of the class of calls where > type checking could be eliminated if the compiler can prove that > objects will always be of the required type). Yes, I've also given this some thought. If we were using C++ (I'm very glad we're not, btw!) then I'm pretty sure we could use the type system to mark certain functions as never returning %nil, and then arrange to optimize away the %nil checks in those cases, but I can't think of a way to do it with C, even with GCC's extensions. Maybe, if we can develop a reasonable proposal, we can get sufficient functionality added to GCC. > So, if you would be happy to do so, can I suggest that you rework your > patches so that they also make (and then assume, obviously) the > scm_is_false/true/bool/null change, and incorporate my other comments? I will gladly do so. > It would also be more convenient - and better for giving you your > deserved attribution - if you could submit them as Git patches. Would > that be possible? Will do. > Also, we will need documentation of the new APIs, and to explain the > overall concept; and a NEWS entry; and maybe a couple of tests to > check where data that includes %nil is passed to some of the fixed > functions. Would you be willing to prepare all those too? Yes, certainly. > > One category of place where these could be used is code dealing with > > data structures created internally by the evaluator -- though I'm not > > very familiar with guile's internals, so I don't know how common these > > data structures are, if indeed they exist at all. > > Yes, indeed. In the updated patch(es), I suggest that you mark the > cases that you are not sure about, then I and other developers can > help work out what kind of check they should be doing. Indeed, some of the usage cases are difficult for me to evaluate, so your help will be much appreciated! Also, I signed my copyright assignment papers a while ago, and the relevant file on fencepost has been updated accordingly. Best, Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-30 14:11 ` Mark H Weaver @ 2009-09-01 22:00 ` Neil Jerram 2009-09-02 15:57 ` Mark H Weaver 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-09-01 22:00 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, Daniel Kraft, guile-devel Mark H Weaver <mhw@netris.org> writes: > What about scm_is_bool? I'm tempted to suggest that it should work > the same way as "boolean?" within scheme, whatever that may be. I > tend to think they ought to treat %nil as boolean, though I'm less > sure of this than about scm_is_true/false/null. It's the right thing > for type-checking an argument that is expected to be boolean, which > seems to be fairly common in guile. More complex code that is > dispatching on type (such as the aforementioned GOOPS code) will in > general have to be fixed to take into account that %nil is both a > boolean and a list. I agree (i.e. I think scm_is_bool (SCM_LISP_NIL) should be 1). > One more thing: scheme code can reasonably expect to "write" a list of > simple values and then "read" it back in. But now, lists might be > terminated by %nil instead of '(). Therefore, I think "read" needs to > be able to read SCM_LISP_NIL in whatever form we "write" it in. I'll > let someone more knowledgable about guile reader issues decide what > that form should be. Currently we write it as "#nil". Interesting point, but seems like one that could be left until it crops up for real somewhere. I assume the mainline case of writing a proper list will be fine, because a list like (a b c . #nil) will be written out as "(a b c)" - right? Then, when read in again, it would become (a b c . ()) - I think we may have to wait for real cases to know if that's actually a problem at all. > Yes, I've also given this some thought. If we were using C++ (I'm > very glad we're not, btw!) then I'm pretty sure we could use the type > system to mark certain functions as never returning %nil, and then > arrange to optimize away the %nil checks in those cases, but I can't > think of a way to do it with C, even with GCC's extensions. Maybe, if > we can develop a reasonable proposal, we can get sufficient > functionality added to GCC. I was actually meaning the VM compiler... but yes, maybe there are also C things we could do. >> So, if you would be happy to do so, can I suggest that you rework your >> patches so that they also make (and then assume, obviously) the >> scm_is_false/true/bool/null change, and incorporate my other comments? > > I will gladly do so. Fantastic, thanks (and also for your 'Yes's to the other add-on pieces)! > Also, I signed my copyright assignment papers a while ago, and the > relevant file on fencepost has been updated accordingly. Yes, indeed; we (maintainers) got notified about that at the time; apologies for not closing the loop with you then. Regards, Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-09-01 22:00 ` Neil Jerram @ 2009-09-02 15:57 ` Mark H Weaver 2009-09-17 21:21 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Mark H Weaver @ 2009-09-02 15:57 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, Daniel Kraft, guile-devel Neil Jerram wrote: > > One more thing: scheme code can reasonably expect to "write" a list of > > simple values and then "read" it back in. But now, lists might be > > terminated by %nil instead of '(). Therefore, I think "read" needs to > > be able to read SCM_LISP_NIL in whatever form we "write" it in. I'll > > let someone more knowledgable about guile reader issues decide what > > that form should be. Currently we write it as "#nil". > > Interesting point, but seems like one that could be left until it > crops up for real somewhere. > > I assume the mainline case of writing a proper list will be fine, > because a list like (a b c . #nil) will be written out as "(a b c)" - > right? Then, when read in again, it would become (a b c . ()) - I > think we may have to wait for real cases to know if that's actually a > problem at all. Certainly writing (a b c . #nil) as (a b c) would be most natural and convenient, and maybe it's the best compromise, but I'm not entirely sure it's safe. What if we have an association list mapping symbols to booleans that came from elisp? Such a alist might look something like ((a . #t) (b . #nil)), and can reasonably be assumed to be written and then read back in, but doing so would then result in ((a . #t) (b . ())), magically changing the false to a true. This also violates the idea the CARs and CDRs should be treated the same way. I'm tempted to suggest that "write" should write (a . #nil) as "(a . #nil)", and "display" should write it as "(a)". Best, Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-09-02 15:57 ` Mark H Weaver @ 2009-09-17 21:21 ` Neil Jerram 0 siblings, 0 replies; 38+ messages in thread From: Neil Jerram @ 2009-09-17 21:21 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, Daniel Kraft, guile-devel Mark H Weaver <mhw@netris.org> writes: > Certainly writing (a b c . #nil) as (a b c) would be most natural and > convenient, and maybe it's the best compromise, but I'm not entirely > sure it's safe. > > What if we have an association list mapping symbols to booleans that > came from elisp? Such a alist might look something like > ((a . #t) (b . #nil)), and can reasonably be assumed to be written > and then read back in, but doing so would then result in > ((a . #t) (b . ())), magically changing the false to a true. Hmmm... From the elisp point of view it's still false, of course. From the scheme point of view your point stands. > This also violates the idea the CARs and CDRs should be treated the > same way. Also a good point. > I'm tempted to suggest that "write" should write (a . #nil) as > "(a . #nil)", and "display" should write it as "(a)". For now I'm happy with any reasonable position (such as this), because I don't think we've got any data to help decide between the options. Hopefully it won't be too long before we have some real non-trival Guile/Scheme/Elisp interactions. Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-06-29 21:44 ` Neil Jerram 2009-06-29 22:11 ` Andy Wingo @ 2009-07-02 14:28 ` Mark H Weaver 2009-07-02 14:50 ` Ludovic Courtès 2009-07-02 22:50 ` Neil Jerram 1 sibling, 2 replies; 38+ messages in thread From: Mark H Weaver @ 2009-07-02 14:28 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, guile-devel I've been considering writing a python compiler for guile. For python (and others) there are several values considered to be false, such as 0 and various empty collections, and so a different approach will have to be taken to this problem. If we want guile to handle many different languages, should we not try to find an approach to "false-ness" that handles many languages, and not just a few? It seems to me that some code might misbehave in the presence of two values which are both null? but not eq? to each other. Also, it seems more consistent to use the same strategy for handling various languages' notions of false-ness. To my mind, we should not be changing the data (which only works for lisp), but rather the constructs that decide whether a given value is false. So how about having elisp `if' and `cond' compile not to scheme `if' and `cond', but rather to scheme `elisp-if' and `elisp-cond'? Or perhaps compile `(if c a b)' to `(if (elisp-true? c) a b)'. This approach, unlike the %nil approach, will work for other languages too. It also means that Guile's normal `if' and `cond' won't be slowed down by having to check for two values instead of one. That overhead may be insignificant now, but when we have a native code compiler, it will be quite significant in code size at least, even if the representations of %nil and #f differ by only one bit. What do you think? Mark On Mon, Jun 29, 2009 at 10:44:54PM +0100, Neil Jerram wrote: > Seems wrong to me. In Scheme #f should be the only false value. > What's the argument for %nil being false in Scheme code? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-02 14:28 ` Mark H Weaver @ 2009-07-02 14:50 ` Ludovic Courtès 2009-07-02 22:50 ` Neil Jerram 1 sibling, 0 replies; 38+ messages in thread From: Ludovic Courtès @ 2009-07-02 14:50 UTC (permalink / raw) To: guile-devel Hi, Mark H Weaver <mhw@netris.org> writes: > I've been considering writing a python compiler for guile. For python > (and others) there are several values considered to be false, such as > 0 and various empty collections, and so a different approach will have > to be taken to this problem. [...] > So how about having elisp `if' and `cond' compile not to scheme `if' > and `cond', but rather to scheme `elisp-if' and `elisp-cond'? Or > perhaps compile `(if c a b)' to `(if (elisp-true? c) a b)'. I concur (but I haven't followed the elisp discussion closely). Regardless of which approach the elisp front-end takes, this is something other languages can already do. This is something the ECMAScript front-end does: see how `if' is handled in `language/ecmascript/compile-ghil.scm' and the definition of `->boolean' in `language/ecmascript/base.scm'. Thanks, Ludo'. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-02 14:28 ` Mark H Weaver 2009-07-02 14:50 ` Ludovic Courtès @ 2009-07-02 22:50 ` Neil Jerram 2009-07-03 15:32 ` Mark H Weaver 1 sibling, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-07-02 22:50 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, guile-devel Mark H Weaver <mhw@netris.org> writes: > I've been considering writing a python compiler for guile. Great! > For python > (and others) there are several values considered to be false, such as > 0 and various empty collections, and so a different approach will have > to be taken to this problem. > > If we want guile to handle many different languages, should we not try > to find an approach to "false-ness" that handles many languages, and > not just a few? There's been loads of prior discussion on this subject. Here are pointers to some of that. http://sourceware.org/ml/guile/1999-07/msg00251.html http://sourceware.org/ml/guile/1998-07/msg00187.html http://lists.gnu.org/archive/html/guile-devel/2001-09/msg00140.html http://lists.gnu.org/archive/html/guile-devel/2001-11/msg00016.html > It seems to me that some code might misbehave in the presence of two > values which are both null? but not eq? to each other. Example? (This seems quite unlikely to me.) > Also, it seems more consistent to use the same strategy for handling > various languages' notions of false-ness. > > To my mind, we should not be changing the data (which only works for > lisp), but rather the constructs that decide whether a given value is > false. > > So how about having elisp `if' and `cond' compile not to scheme `if' > and `cond', but rather to scheme `elisp-if' and `elisp-cond'? Or > perhaps compile `(if c a b)' to `(if (elisp-true? c) a b)'. > > This approach, unlike the %nil approach, will work for other languages > too. Certainly this is a possible approach. In what's been done so far, and what we do in future, I don't think there are any arguments that trump all the other considerations. It's just a matter of balancing performance, robustness, and so on. If more non-Lisp-like languages are added, your consideration of cross-language consistency would gain more weight. On a matter of detail, I don't understand your statement that the current %nil approach won't work for other languages. As the query that started this thread shows, it is perfectly possible to code a new language (VM-Scheme, in this case) in which %nil is true. If I understand it correctly, a key point of the thinking up till now is that Elisp is a special case because it is so `tantalizingly similar' (as Jim put it) to Scheme. This similarity creates the possibility of passing data directly between Elisp and Scheme, and the fact that Guile Scheme treats %nil as both #f and '() follows from that; otherwise it would be necessary to convert data as it passes from one language to the other. In other words - a performance point. Now we have Brainfuck and ECMAScript too, but I don't know if they are complex enough to cast significant doubt on the existing balance. (To be honest, I'm not sure if that's true for ECMAScript, I need to look at Andy's code.) Python on the other hand would be plenty complex enough, and I assume it has arbitrarily complex data structures. How do you envisage data transfer working between Python and other languages? > It also means that Guile's normal `if' and `cond' won't be slowed down > by having to check for two values instead of one. That overhead may > be insignificant now, but when we have a native code compiler, it will > be quite significant in code size at least, even if the > representations of %nil and #f differ by only one bit. Do you really think so? Just because of two compare operations instead of one? Perhaps I'm misunderstanding you. > On Mon, Jun 29, 2009 at 10:44:54PM +0100, Neil Jerram wrote: >> Seems wrong to me. In Scheme #f should be the only false value. >> What's the argument for %nil being false in Scheme code? (Just for the record, my statement here was wrong, and I've since corrected it.) Regards, Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-02 22:50 ` Neil Jerram @ 2009-07-03 15:32 ` Mark H Weaver 2009-07-05 2:41 ` Mark H Weaver 2009-07-23 21:12 ` Andy Wingo 0 siblings, 2 replies; 38+ messages in thread From: Mark H Weaver @ 2009-07-03 15:32 UTC (permalink / raw) To: Neil Jerram; +Cc: guile-devel Thank you, Neil, for the pointers to earlier discussions of this subject. Having read them, I've been convinced that the %nil approach is reasonable and probably the best way to deal with elisp<->scheme interoperability. Though, like you, I was not willing to easily accept two false values and two end-of-list values :) > Python on the other hand would be plenty complex enough, and I assume > it has arbitrarily complex data structures. How do you envisage data > transfer working between Python and other languages? I'll answer this in a later email. > > It also means that Guile's normal `if' and `cond' won't be slowed down > > by having to check for two values instead of one. That overhead may > > be insignificant now, but when we have a native code compiler, it will > > be quite significant in code size at least, even if the > > representations of %nil and #f differ by only one bit. > > Do you really think so? Just because of two compare operations > instead of one? Perhaps I'm misunderstanding you. A single compare and branch is a very short instruction sequence, especially (on some architectures at least) if the constant being compared is a small number. When there are two values to compare against, that means either two compares and two conditional branches, or, if the two values differ by only one bit, ANDing with a mask before the compare. Either way, the code size increases quite a bit. This price will be paid for every boolean test, and every end-of-list test, which are obviously very common. It might be worth considering a build-time option to disable %nil, so that it's possible to build a version of guile which doesn't pay this price. Best, Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-03 15:32 ` Mark H Weaver @ 2009-07-05 2:41 ` Mark H Weaver 2009-07-05 9:19 ` Andy Wingo 2009-07-06 21:46 ` truth of %nil Neil Jerram 2009-07-23 21:12 ` Andy Wingo 1 sibling, 2 replies; 38+ messages in thread From: Mark H Weaver @ 2009-07-05 2:41 UTC (permalink / raw) To: Neil Jerram; +Cc: guile-devel Below is a proposal for how to make boolean tests and end-of-list tests faster and more compact, by renumbering the representations for SCM_ELISP_NIL, SCM_EOL, SCM_UNDEFINED, and SCM_EOF_VAL. But first, I decided to quantify the increase in code size testing against two constants instead of one, by compiling the following short test program with gcc -Os on three architectures: x86-32, arm, and sparc: (specifically, I did "gcc -Os -S foo.c" and then "as -a foo.s") loop1(int *p) { while (*p != 0x004) p++; } loop2(int *p) { while ((*p & ~0x200) != 0x004) p++; } The size of the resulting loop bodies, in bytes, are as follows: arch loop1 loop2 -------------------- x86-32 8 13 arm 12 16 sparc 16 20 -------------------- I guess this is not too bad. The constants chosen above are based on the following proposal on how best to make SCM_BOOL_F and SCM_ELISP_NIL differ by only one bit, and the same for SCM_EOL and SCM_ELISP_NIL. This can be accomplished by making: SCM_ELISP_NIL equal to SCM_MAKIFLAG (2) i.e. 0x204, and SCM_EOL equal to SCM_MAKIFLAG (3) i.e. 0x304. These values are currently used by SCM_UNDEFINED and SCM_EOF_VAL, but I'm hoping it won't be too disruptive to renumber those, especially if it's done before the release of 2.0. Then, testing for boolean truth becomes: if ((x & ~0x200) != 0x004) and testing for end-of-list becomes: if ((x & ~0x100) == 0x204) These should of course be written differently, perhaps as follows: if ((x & ~(SCM_ELISP_NIL ^ SCM_BOOL_F)) != (SCM_ELISP_NIL & SCM_BOOL_F)) and for end-of-list: if ((x & ~(SCM_ELISP_NIL ^ SCM_EOL)) == (SCM_ELISP_NIL & SCM_EOL)) along with a regression test somewhere to complain unless both of the XOR subexpressions above are powers of two: #define IS_POWER_OF_TWO(x) ((x) & ((x)-1) == 0) #define DIFFER_BY_ONLY_ONE_BIT(x, y) IS_POWER_OF_TWO((x)^(y)) if ( ! DIFFER_BY_ONLY_ONE_BIT(SCM_ELISP_NIL, SCM_BOOL_F) ) complain(); if ( ! DIFFER_BY_ONLY_ONE_BIT(SCM_ELISP_NIL, SCM_EOL) ) complain(); What do you think? Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-05 2:41 ` Mark H Weaver @ 2009-07-05 9:19 ` Andy Wingo 2009-07-07 11:14 ` Mark H Weaver 2009-07-06 21:46 ` truth of %nil Neil Jerram 1 sibling, 1 reply; 38+ messages in thread From: Andy Wingo @ 2009-07-05 9:19 UTC (permalink / raw) To: Mark H Weaver; +Cc: guile-devel, Neil Jerram On Sun 05 Jul 2009 03:41, Mark H Weaver <mhw@netris.org> writes: > Below is a proposal for how to make boolean tests and end-of-list > tests faster and more compact, by renumbering the representations for > SCM_ELISP_NIL, SCM_EOL, SCM_UNDEFINED, and SCM_EOF_VAL. That looks like great work, Mark!! I don't think it's a problem to renumber these constants, no. A couple of questions though: > loop1(int *p) > { > while (*p != 0x004) > p++; > } Did you mean while (p != 0x004) ? Also, can you make a third test, equivalent to p == SCM_EOL || p == SCM_ELISP_NIL ? > The size of the resulting loop bodies, in bytes, are as follows: > > arch loop1 loop2 > -------------------- > x86-32 8 13 > arm 12 16 > sparc 16 20 > -------------------- > > I guess this is not too bad. I realize this is a bit of a silly benchmark, but can you time these? Actually, can you time Guile? The changes to Guile should be minimal, after all. > What do you think? Excellence, good sir, excellence! Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-05 9:19 ` Andy Wingo @ 2009-07-07 11:14 ` Mark H Weaver 2009-07-08 13:17 ` Mark H. Weaver 2009-08-30 11:13 ` Neil Jerram 0 siblings, 2 replies; 38+ messages in thread From: Mark H Weaver @ 2009-07-07 11:14 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel, Neil Jerram Having thought more about optimizing %nil handling, it occurs to me that we will also want boolean tests from within lisp to be optimized. From lisp, three values are considered to be false: #f, '(), and %nil. We can use the same bit-masking trick to do these tests quickly if we make sure that these three values differ in only two bit positions. Therefore, I suggest that the first four SCM_MAKIFLAG values should be #f, %nil, '(), and another never-to-be-used value which would also be considered false by lisp code as a side effect of the masking trick. In my previous proposal, I made sure to keep SCM_BOOL_F and SCM_BOOL_T in IFLAG numbers 0 and 1. If this is important, it could still be arranged by making the aforementioned two bit positions something other than the lowest two bits of the IFLAG number, but that would mean our three lisp-false values would be spread out (e.g. 0/2/4/6). Therefore, unless someone tells me otherwise, I'm going to assume it's okay to put SCM_BOOL_F and SCM_BOOL_T in IFLAG numbers 0 and 4. These still have the property that SCM_BOOL_F and SCM_BOOL_T differ by only one bit, and that SCM_BOOL_F is IFLAG number 0, both of which seem potentially useful. So, in my new proposal, the first five IFLAGS are as follows: #define SCM_BOOL_F SCM_MAKIFLAG (0) #define SCM_ELISP_NIL SCM_MAKIFLAG (1) /* SCM_MAKIFLAG (2) would also be considered "false" by lisp code * and therefore should remain unassigned */ #define SCM_EOL SCM_MAKIFLAG (3) #define SCM_BOOL_T SCM_MAKIFLAG (4) This numbering has the nice properties that 0 is #f, the first two are considered false by scheme, and the first four are considered false by lisp. [An alternative numbering for which the following macros would also work is: ((#f 0) (#t 1) (%nil 2) (unused 4) (() 6)), if it's important to keep #f and #t together] The testing macros would be as follows (these can of course be renamed if my other pending proposal is rejected): #define scm_is_false(x) \ (((x) & ~(SCM_ELISP_NIL ^ SCM_BOOL_F)) == (SCM_ELISP_NIL & SCM_BOOL_F)) #define scm_is_true(x) \ (((x) & ~(SCM_ELISP_NIL ^ SCM_BOOL_F)) != (SCM_ELISP_NIL & SCM_BOOL_F)) #define scm_is_null(x) \ (((x) & ~(SCM_ELISP_NIL ^ SCM_EOL)) == (SCM_ELISP_NIL & SCM_EOL)) #define scm_is_false_xxx_assume_not_lisp_nil(x) ((x) == SCM_BOOL_F) #define scm_is_true_xxx_assume_not_lisp_nil(x) ((x) != SCM_BOOL_F) #define scm_is_null_xxx_assume_not_lisp_nil(x) ((x) == SCM_EOL) And the lisp boolean tests would be something like this: /* * Since we know SCM_ELISP_NIL and SCM_BOOL_F differ by exactly one * bit, and that SCM_ELISP_NIL and SCM_EOL differ by exactly one bit, * and that they of course can't be the same bit (or else SCM_BOOL_F * and SCM_EOL be would equal), it follows that SCM_BOOL_F and SCM_EOL * differ by exactly two bits, and those are the ones we need to * mask out to collapse all three values together. */ #define scm_is_lisp_false(x) \ (((x) & ~(SCM_BOOL_F ^ SCM_EOL)) == (SCM_BOOL_F & SCM_EOL)) #define scm_is_lisp_true(x) \ (((x) & ~(SCM_BOOL_F ^ SCM_EOL)) != (SCM_BOOL_F & SCM_EOL)) What do you think? Also, you may have noticed that I've been using the term "lisp" instead of "elisp". This is because guile may support other lisps in the future, and they will also need the same %nil handling. (For that matter, we could even use %nil to implement an "old scheme" language which treats '() as false.) With this in mind, should SCM_ELISP_NIL be renamed to SCM_LISP_NIL? Andy: thanks for the warm reception, and I'll answer your questions in a later email. Best regards, Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-07 11:14 ` Mark H Weaver @ 2009-07-08 13:17 ` Mark H. Weaver 2009-08-30 11:20 ` Neil Jerram 2009-08-30 11:13 ` Neil Jerram 1 sibling, 1 reply; 38+ messages in thread From: Mark H. Weaver @ 2009-07-08 13:17 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, Neil Jerram, guile-devel I've discovered two more tests that can be optimized using the same bit masking tricks: scm_is_bool and scm_is_bool_or_lisp_nil (newly created). Since SCM_BOOL_F and SCM_BOOL_T differ by only one bit, that one is easy. The other one can be implemented the same way as scm_is_lisp_false in my last proposal, by making IFLAG 5 another never-to-be-used value. That way, IFLAGS 0/1/4/5 (#f %nil #t dont-use-2) are all the same except for two bit positions. So I was thinking that scm_is_bool and scm_is_bool_or_lisp_nil could be implemented as macros, which are as fast and as compact as testing for boolean truth. What do you think? Also, since writing my last email, I've realized that my testing macros need to use SCM_UNPACK. I'm currently in the process of preparing a patch. As part of that process, I'm reviewing all uses of the affected macros, and evaluating for each use case how %nil should be handled. In order to remain flexible with regards my other pending proposal, I'm forking macros into two variants: one which checks for %nil when appropriate, and one which doesn't. We can decide what their names should be later. I found one thorny use of scm_is_bool and scm_is_null, and request your collective wisdom: scm_class_of() in goops.c tries to determine the class of a scheme value. If scm_is_bool returns true, it's classified as scm_class_boolean, and if scm_is_null returns true, it's classified as scm_class_null. Right now, that code doesn't consider %nil at all. How do you all think %nil should be handled by goops? It seems to me that it would be nice to try to support %nil transparently when possible. Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-08 13:17 ` Mark H. Weaver @ 2009-08-30 11:20 ` Neil Jerram 0 siblings, 0 replies; 38+ messages in thread From: Neil Jerram @ 2009-08-30 11:20 UTC (permalink / raw) To: Mark H. Weaver; +Cc: Andy Wingo, guile-devel "Mark H. Weaver" <mhw@netris.org> writes: > I found one thorny use of scm_is_bool and scm_is_null, and request > your collective wisdom: > > scm_class_of() in goops.c tries to determine the class of a scheme > value. If scm_is_bool returns true, it's classified as > scm_class_boolean, and if scm_is_null returns true, it's classified as > scm_class_null. Right now, that code doesn't consider %nil at all. So currently the code (using your clarified APIs) gives scm_class_unknown, right? > How do you all think %nil should be handled by goops? Given the %nil concept, I suppose what matters is that a %nil value should be able to match both (define-method f (arg <null>)) and (define-method f (arg <boolean>)) That suggests to me that there should be a class <nil> that inherits from both <null> and <boolean>, and that (class-of %nil) should be <nil>. What do you think? Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-07 11:14 ` Mark H Weaver 2009-07-08 13:17 ` Mark H. Weaver @ 2009-08-30 11:13 ` Neil Jerram 2009-08-30 14:15 ` Mark H Weaver ` (2 more replies) 1 sibling, 3 replies; 38+ messages in thread From: Neil Jerram @ 2009-08-30 11:13 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, guile-devel Mark H Weaver <mhw@netris.org> writes: > This numbering has the nice properties that 0 is #f. Just to be clear: will this mean that (SCM_BOOL_F == 0) ? As things stand I don't think it will, because SCM_MAKIFLAG shifts and adds 0x04. Just checking this because Ludovic said recently that (SCM_BOOL_F == 0) would have nice properties for BDW-GC. > Also, you may have noticed that I've been using the term "lisp" > instead of "elisp". This is because guile may support other lisps in > the future, and they will also need the same %nil handling. (For that > matter, we could even use %nil to implement an "old scheme" language > which treats '() as false.) With this in mind, should SCM_ELISP_NIL > be renamed to SCM_LISP_NIL? Yes, that sounds like a good argument to me - i.e. I can't see any reason why the special-case-ness of Elisp shouldn't apply equally to other Lisps - so please do rename "ELISP" things to "LISP", where this argument supports that. Thanks, Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-30 11:13 ` Neil Jerram @ 2009-08-30 14:15 ` Mark H Weaver 2009-09-01 21:50 ` Neil Jerram 2009-08-30 22:01 ` Ken Raeburn 2009-08-31 21:55 ` SCM_BOOL_F == 0 and BDW-GC Ludovic Courtès 2 siblings, 1 reply; 38+ messages in thread From: Mark H Weaver @ 2009-08-30 14:15 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, guile-devel On Sun, Aug 30, 2009 at 12:13:59PM +0100, Neil Jerram wrote: > Mark H Weaver <mhw@netris.org> writes: > > > This numbering has the nice properties that 0 is #f. > > Just to be clear: will this mean that (SCM_BOOL_F == 0) ? As things > stand I don't think it will, because SCM_MAKIFLAG shifts and adds > 0x04. Yes, that's correct. SCM_BOOL_F is 4. What I should have said above is that #f is IFLAG number 0. > > Also, you may have noticed that I've been using the term "lisp" > > instead of "elisp". This is because guile may support other lisps in > > the future, and they will also need the same %nil handling. (For that > > matter, we could even use %nil to implement an "old scheme" language > > which treats '() as false.) With this in mind, should SCM_ELISP_NIL > > be renamed to SCM_LISP_NIL? > > Yes, that sounds like a good argument to me - i.e. I can't see any > reason why the special-case-ness of Elisp shouldn't apply equally to > other Lisps - so please do rename "ELISP" things to "LISP", where this > argument supports that. Sounds good! Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-30 14:15 ` Mark H Weaver @ 2009-09-01 21:50 ` Neil Jerram 0 siblings, 0 replies; 38+ messages in thread From: Neil Jerram @ 2009-09-01 21:50 UTC (permalink / raw) To: Mark H Weaver; +Cc: Andy Wingo, guile-devel Mark H Weaver <mhw@netris.org> writes: > On Sun, Aug 30, 2009 at 12:13:59PM +0100, Neil Jerram wrote: >> Mark H Weaver <mhw@netris.org> writes: >> >> > This numbering has the nice properties that 0 is #f. >> >> Just to be clear: will this mean that (SCM_BOOL_F == 0) ? As things >> stand I don't think it will, because SCM_MAKIFLAG shifts and adds >> 0x04. > > Yes, that's correct. SCM_BOOL_F is 4. What I should have said above > is that #f is IFLAG number 0. Thanks for clarifying that. (And from other threads it seems clear now that SCM_BOOL_F == 0 would actually be a problem!) Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-30 11:13 ` Neil Jerram 2009-08-30 14:15 ` Mark H Weaver @ 2009-08-30 22:01 ` Ken Raeburn 2009-08-31 21:59 ` Ludovic Courtès 2009-08-31 21:55 ` SCM_BOOL_F == 0 and BDW-GC Ludovic Courtès 2 siblings, 1 reply; 38+ messages in thread From: Ken Raeburn @ 2009-08-30 22:01 UTC (permalink / raw) To: Neil Jerram; +Cc: Andy Wingo, Mark H Weaver, guile-devel On Aug 30, 2009, at 07:13, Neil Jerram wrote: > Mark H Weaver <mhw@netris.org> writes: > This numbering has the nice properties that 0 is #f. > Just to be clear: will this mean that (SCM_BOOL_F == 0) ? As things > stand I don't think it will, because SCM_MAKIFLAG shifts and adds > 0x04. > > Just checking this because Ludovic said recently that (SCM_BOOL_F == > 0) would have nice properties for BDW-GC. Was that in list email? Maybe I overlooked it. Having all-bits-zero be a valid object would make some things easier in my guile-emacs work too, but could cause other problems as well. In Emacs all-bits-zero is now integer-zero, and in some places Lisp_Object variables are used or made visible to GC before being explicitly set, so I have to set them. In guile-emacs, I can check in key places (like 'cons', or the 'EQ' macro) for all-bits-zero and flag an error, or in certain cases patch over the problem temporarily. While the integration is still minimal, I suppose SCM_BOOL_F shouldn't be showing up in elisp processing, so that still works, but if it gets moved further along as I'm hoping, that could change. Having the default C initializer change from one valid value to another between Emacs and Guile-Emacs could make the bugs much more subtle. I kind of assumed that making all-bits-zero an invalid value was a conscious choice by the Guile (or SCM?) designers which wasn't likely to be revisited. It is, after all, a fairly easy way of highlighting a certain class of uninitialized-value problems -- choosing strict checking and debugging over letting the programmer be lazy. I think I'm mildly in favor of keeping all-bits-zero as an invalid representation. But, if it's a huge win for BDW-GC, maybe it's worth it. Ken ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-30 22:01 ` Ken Raeburn @ 2009-08-31 21:59 ` Ludovic Courtès 2009-08-31 23:39 ` Ken Raeburn 0 siblings, 1 reply; 38+ messages in thread From: Ludovic Courtès @ 2009-08-31 21:59 UTC (permalink / raw) To: guile-devel Hi, Ken Raeburn <raeburn@raeburn.org> writes: > I kind of assumed that making all-bits-zero an invalid value was a > conscious choice by the Guile (or SCM?) designers which wasn't likely > to be revisited. It is, after all, a fairly easy way of highlighting > a certain class of uninitialized-value problems -- choosing strict > checking and debugging over letting the programmer be lazy. Indeed, that could have been one reason. We could ask Aubrey Jaffer about this. > I think I'm mildly in favor of keeping all-bits-zero as an invalid > representation. But, if it's a huge win for BDW-GC, maybe it's worth > it. As discussed in my other message, it would actually be harmful. Thanks, Ludo'. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-08-31 21:59 ` Ludovic Courtès @ 2009-08-31 23:39 ` Ken Raeburn 0 siblings, 0 replies; 38+ messages in thread From: Ken Raeburn @ 2009-08-31 23:39 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel On Aug 31, 2009, at 17:59, Ludovic Courtès wrote: >> I think I'm mildly in favor of keeping all-bits-zero as an invalid >> representation. But, if it's a huge win for BDW-GC, maybe it's worth >> it. > > As discussed in my other message, it would actually be harmful. Then I'm definitely in favor of keeping it as invalid! :-) Ken ^ permalink raw reply [flat|nested] 38+ messages in thread
* SCM_BOOL_F == 0 and BDW-GC 2009-08-30 11:13 ` Neil Jerram 2009-08-30 14:15 ` Mark H Weaver 2009-08-30 22:01 ` Ken Raeburn @ 2009-08-31 21:55 ` Ludovic Courtès 2009-09-17 22:00 ` Neil Jerram 2 siblings, 1 reply; 38+ messages in thread From: Ludovic Courtès @ 2009-08-31 21:55 UTC (permalink / raw) To: guile-devel Hello! Neil Jerram <neil@ossau.uklinux.net> writes: > Just checking this because Ludovic said recently that (SCM_BOOL_F == > 0) would have nice properties for BDW-GC. Actually he wasn't quite right when he said that. :-) The issue with BDW-GC is that "disappearing links" (weak pointers in libgc parlance) replace pointers to objects that have been reclaimed by NULL, and there's no way to tell it to use some other value. That leads to insanities in the weak hash table implementation [0, 1], which I thought could somehow vanish if SCM_BOOL_F == 0. Unfortunately that's not true; it would even make things worse because NULL would now be a valid Scheme value. Instead what's really needed is a special pointer-to-reclaimed-object value that can be distinguished from valid Scheme values since that value ends up in the car or cdr of weak pairs in hash table buckets. As such, SCM_PACK (NULL) was a good choice until now. SCM_UNDEFINED == 0 would work fine because SCM_UNDEFINED is not a valid Scheme value, but it wouldn't change the implementation. Thoughts? Thanks, Ludo'. [0] http://git.savannah.gnu.org/cgit/guile.git/tree/libguile/weaks.c?h=boehm-demers-weiser-gc#n40 [1] http://git.savannah.gnu.org/cgit/guile.git/tree/libguile/hashtab.c?h=boehm-demers-weiser-gc#n97 ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: SCM_BOOL_F == 0 and BDW-GC 2009-08-31 21:55 ` SCM_BOOL_F == 0 and BDW-GC Ludovic Courtès @ 2009-09-17 22:00 ` Neil Jerram 2009-09-17 22:28 ` Ludovic Courtès 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-09-17 22:00 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel ludo@gnu.org (Ludovic Courtès) writes: > Hello! > > Neil Jerram <neil@ossau.uklinux.net> writes: > >> Just checking this because Ludovic said recently that (SCM_BOOL_F == >> 0) would have nice properties for BDW-GC. > > Actually he wasn't quite right when he said that. :-) > > The issue with BDW-GC is that "disappearing links" (weak pointers in > libgc parlance) replace pointers to objects that have been reclaimed by > NULL, and there's no way to tell it to use some other value. > > That leads to insanities in the weak hash table implementation [0, 1], > which I thought could somehow vanish if SCM_BOOL_F == 0. They're not so bad. But I agree that it would be nicer not to have to use SCM_WEAK_PAIR_CAR, and just use SCM_CAR instead. > Unfortunately that's not true; it would even make things worse because > NULL would now be a valid Scheme value. Yes, I see. > Instead what's really needed is a special pointer-to-reclaimed-object > value that can be distinguished from valid Scheme values since that > value ends up in the car or cdr of weak pairs in hash table buckets. As > such, SCM_PACK (NULL) was a good choice until now. Here I'm confused again. I thought we now had no choice about the pointer-to-reclaimed-object value, because BDW-GC always uses NULL. > SCM_UNDEFINED == 0 would work fine because SCM_UNDEFINED is not a valid > Scheme value, but it wouldn't change the implementation. I'm afraid I don't understand "but it wouldn't change the implementation". 0 is also used for procedures that haven't been extended to primitive-generic - see SCM_SUBR_GENERIC - but I think making SCM_UNDEFINED == 0 would be fine there too. > Thoughts? SCM_UNDEFINED == 0 is sounding promising... Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: SCM_BOOL_F == 0 and BDW-GC 2009-09-17 22:00 ` Neil Jerram @ 2009-09-17 22:28 ` Ludovic Courtès 2009-09-18 20:51 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Ludovic Courtès @ 2009-09-17 22:28 UTC (permalink / raw) To: guile-devel Hello, Neil Jerram <neil@ossau.uklinux.net> writes: > ludo@gnu.org (Ludovic Courtès) writes: [...] >> Instead what's really needed is a special pointer-to-reclaimed-object >> value that can be distinguished from valid Scheme values since that >> value ends up in the car or cdr of weak pairs in hash table buckets. As >> such, SCM_PACK (NULL) was a good choice until now. > > Here I'm confused again. I thought we now had no choice about the > pointer-to-reclaimed-object value, because BDW-GC always uses NULL. True. So, what I meant is that ((SCM) NULL) must be distinguishable from valid Scheme values. >> SCM_UNDEFINED == 0 would work fine because SCM_UNDEFINED is not a valid >> Scheme value, but it wouldn't change the implementation. > > I'm afraid I don't understand "but it wouldn't change the > implementation". Ugly stuff like ‘scm_fixup_weak_alist ()’ would still be needed. > SCM_UNDEFINED == 0 is sounding promising... Yeah. Sorry for the false hope about SCM_BOOL_F == 0. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: SCM_BOOL_F == 0 and BDW-GC 2009-09-17 22:28 ` Ludovic Courtès @ 2009-09-18 20:51 ` Neil Jerram 2009-09-20 17:21 ` Ludovic Courtès 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-09-18 20:51 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel ludo@gnu.org (Ludovic Courtès) writes: > Hello, > > Neil Jerram <neil@ossau.uklinux.net> writes: >> >> Here I'm confused again. I thought we now had no choice about the >> pointer-to-reclaimed-object value, because BDW-GC always uses NULL. > > True. So, what I meant is that ((SCM) NULL) must be distinguishable > from valid Scheme values. OK. >>> SCM_UNDEFINED == 0 would work fine because SCM_UNDEFINED is not a valid >>> Scheme value, but it wouldn't change the implementation. >> >> I'm afraid I don't understand "but it wouldn't change the >> implementation". > > Ugly stuff like ‘scm_fixup_weak_alist ()’ would still be needed. Thanks, I understand now. scm_fixup_weak_alist looks OK to me. Surely we must have had something like that with Guile GC too? (Except that it was probably mixed up with the GC'ing code, and so was even uglier!) >> SCM_UNDEFINED == 0 is sounding promising... > > Yeah. Sorry for the false hope about SCM_BOOL_F == 0. So are you going to try out SCM_UNDEFINED == 0 ? Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: SCM_BOOL_F == 0 and BDW-GC 2009-09-18 20:51 ` Neil Jerram @ 2009-09-20 17:21 ` Ludovic Courtès 2009-09-20 21:03 ` Neil Jerram 0 siblings, 1 reply; 38+ messages in thread From: Ludovic Courtès @ 2009-09-20 17:21 UTC (permalink / raw) To: guile-devel Hello, Neil Jerram <neil@ossau.uklinux.net> writes: > ludo@gnu.org (Ludovic Courtès) writes: [...] >> Ugly stuff like ‘scm_fixup_weak_alist ()’ would still be needed. > > Thanks, I understand now. scm_fixup_weak_alist looks OK to me. Surely > we must have had something like that with Guile GC too? (Except that it > was probably mixed up with the GC'ing code, and so was even uglier!) Well, indeed. >>> SCM_UNDEFINED == 0 is sounding promising... >> >> Yeah. Sorry for the false hope about SCM_BOOL_F == 0. > > So are you going to try out SCM_UNDEFINED == 0 ? Who, me? :-) I’ll add it to my to-do list and report back, then. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: SCM_BOOL_F == 0 and BDW-GC 2009-09-20 17:21 ` Ludovic Courtès @ 2009-09-20 21:03 ` Neil Jerram 2009-09-20 21:36 ` Ludovic Courtès 0 siblings, 1 reply; 38+ messages in thread From: Neil Jerram @ 2009-09-20 21:03 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel ludo@gnu.org (Ludovic Courtès) writes: > Hello, Hi Ludo, > Neil Jerram <neil@ossau.uklinux.net> writes: > >> So are you going to try out SCM_UNDEFINED == 0 ? > > Who, me? :-) > > I’ll add it to my to-do list and report back, then. I'm sorry, I didn't exactly mean that you _should_ add it to your list - especially since I'm sure your list is already very long. What I should have said is that it seems like something that someone could try out, and that perhaps I could do that, but that I don't want to duplicate if you're already planning to do it very soon. Regards, Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: SCM_BOOL_F == 0 and BDW-GC 2009-09-20 21:03 ` Neil Jerram @ 2009-09-20 21:36 ` Ludovic Courtès 0 siblings, 0 replies; 38+ messages in thread From: Ludovic Courtès @ 2009-09-20 21:36 UTC (permalink / raw) To: guile-devel Hi! Neil Jerram <neil@ossau.uklinux.net> writes: > ludo@gnu.org (Ludovic Courtès) writes: >> Neil Jerram <neil@ossau.uklinux.net> writes: >> >>> So are you going to try out SCM_UNDEFINED == 0 ? >> >> Who, me? :-) >> >> I’ll add it to my to-do list and report back, then. > > I'm sorry, I didn't exactly mean that you _should_ add it to your list - > especially since I'm sure your list is already very long. What I should > have said is that it seems like something that someone could try out, > and that perhaps I could do that, but that I don't want to duplicate if > you're already planning to do it very soon. I’m not planning to do it soon, so I’m happy if someone else gives it a try. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-05 2:41 ` Mark H Weaver 2009-07-05 9:19 ` Andy Wingo @ 2009-07-06 21:46 ` Neil Jerram 2009-07-06 23:54 ` Mark H Weaver 2009-07-08 8:08 ` Ludovic Courtès 1 sibling, 2 replies; 38+ messages in thread From: Neil Jerram @ 2009-07-06 21:46 UTC (permalink / raw) To: Mark H Weaver; +Cc: guile-devel Mark H Weaver <mhw@netris.org> writes: > Below is a proposal for how to make boolean tests and end-of-list > tests faster and more compact, by renumbering the representations for > SCM_ELISP_NIL, SCM_EOL, SCM_UNDEFINED, and SCM_EOF_VAL. Interesting. I haven't looked at every detail but I'm happy to go along with Andy's impression. Assuming you are planning to work on the code changes for this, we will need copyright assignment papers from you. Will that be OK? > along with a regression test somewhere to complain unless both of the > XOR subexpressions above are powers of two: > > #define IS_POWER_OF_TWO(x) ((x) & ((x)-1) == 0) > #define DIFFER_BY_ONLY_ONE_BIT(x, y) IS_POWER_OF_TWO((x)^(y)) > > if ( ! DIFFER_BY_ONLY_ONE_BIT(SCM_ELISP_NIL, SCM_BOOL_F) ) > complain(); > if ( ! DIFFER_BY_ONLY_ONE_BIT(SCM_ELISP_NIL, SCM_EOL) ) > complain(); There are ways of writing compile time asserts; see http://www.jaggersoft.com/pubs/CVu11_3.html for some. I don't know how portable these all are, but at work we use the case label one, and that seems to be good on common platforms. Regards, Neil ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-06 21:46 ` truth of %nil Neil Jerram @ 2009-07-06 23:54 ` Mark H Weaver 2009-07-08 8:08 ` Ludovic Courtès 1 sibling, 0 replies; 38+ messages in thread From: Mark H Weaver @ 2009-07-06 23:54 UTC (permalink / raw) To: Neil Jerram; +Cc: guile-devel On Mon, Jul 06, 2009 at 10:46:11PM +0100, Neil Jerram wrote: > Assuming you are planning to work on the code changes for this, we > will need copyright assignment papers from you. Will that be OK? Yes, certainly. I live in the Boston area, so I'll stop by the FSF office and take care of that soon. > There are ways of writing compile time asserts; see > http://www.jaggersoft.com/pubs/CVu11_3.html for some. Thanks for the pointer! I confess I'd been thinking of using #if and #error, which works on GNU CPP but is apparently not portable. Best, Mark ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-06 21:46 ` truth of %nil Neil Jerram 2009-07-06 23:54 ` Mark H Weaver @ 2009-07-08 8:08 ` Ludovic Courtès 1 sibling, 0 replies; 38+ messages in thread From: Ludovic Courtès @ 2009-07-08 8:08 UTC (permalink / raw) To: guile-devel Hi, Neil Jerram <neil@ossau.uklinux.net> writes: > There are ways of writing compile time asserts; see > http://www.jaggersoft.com/pubs/CVu11_3.html for some. I don't know > how portable these all are, but at work we use the case label one, and > that seems to be good on common platforms. Gnulib's `verify' module provides macros for compile-time assertions. Thanks, Ludo'. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: truth of %nil 2009-07-03 15:32 ` Mark H Weaver 2009-07-05 2:41 ` Mark H Weaver @ 2009-07-23 21:12 ` Andy Wingo 1 sibling, 0 replies; 38+ messages in thread From: Andy Wingo @ 2009-07-23 21:12 UTC (permalink / raw) To: Mark H Weaver; +Cc: guile-devel, Neil Jerram On Fri 03 Jul 2009 17:32, Mark H Weaver <mhw@netris.org> writes: > It might be worth considering a build-time option to disable %nil, so > that it's possible to build a version of guile which doesn't pay this > price. You probably found it, but Guile does have such an option. (Jeez, I didn't think I'd ever find myself in the position of struggling to keep up with mail to guile-devel ;-) Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2009-09-20 21:36 UTC | newest] Thread overview: 38+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-06-29 21:12 truth of %nil Andy Wingo 2009-06-29 21:44 ` Neil Jerram 2009-06-29 22:11 ` Andy Wingo 2009-06-30 22:22 ` Neil Jerram 2009-07-01 6:45 ` Daniel Kraft 2009-07-01 21:54 ` Neil Jerram 2009-07-05 13:07 ` Mark H Weaver 2009-08-30 11:07 ` Neil Jerram 2009-08-30 14:11 ` Mark H Weaver 2009-09-01 22:00 ` Neil Jerram 2009-09-02 15:57 ` Mark H Weaver 2009-09-17 21:21 ` Neil Jerram 2009-07-02 14:28 ` Mark H Weaver 2009-07-02 14:50 ` Ludovic Courtès 2009-07-02 22:50 ` Neil Jerram 2009-07-03 15:32 ` Mark H Weaver 2009-07-05 2:41 ` Mark H Weaver 2009-07-05 9:19 ` Andy Wingo 2009-07-07 11:14 ` Mark H Weaver 2009-07-08 13:17 ` Mark H. Weaver 2009-08-30 11:20 ` Neil Jerram 2009-08-30 11:13 ` Neil Jerram 2009-08-30 14:15 ` Mark H Weaver 2009-09-01 21:50 ` Neil Jerram 2009-08-30 22:01 ` Ken Raeburn 2009-08-31 21:59 ` Ludovic Courtès 2009-08-31 23:39 ` Ken Raeburn 2009-08-31 21:55 ` SCM_BOOL_F == 0 and BDW-GC Ludovic Courtès 2009-09-17 22:00 ` Neil Jerram 2009-09-17 22:28 ` Ludovic Courtès 2009-09-18 20:51 ` Neil Jerram 2009-09-20 17:21 ` Ludovic Courtès 2009-09-20 21:03 ` Neil Jerram 2009-09-20 21:36 ` Ludovic Courtès 2009-07-06 21:46 ` truth of %nil Neil Jerram 2009-07-06 23:54 ` Mark H Weaver 2009-07-08 8:08 ` Ludovic Courtès 2009-07-23 21:12 ` Andy Wingo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).