bug#32644: bytevector bug
Stefan Israelsson Tampe writes: > The code velow does not compile when the define-inlinable of id is active. If > in stead > id defined by define is used it all compiles just fine. The problem was that, in some cases, the type inferrer would call 'ash' with (- 1 (expt 2 64)) as the second argument during compilation. The implementation of 'ash' would raise an exception unless its second argument (the shift count) fits in a C 'long'. This is fixed in commit 011aec7e240ef987931548d90c53e6692c85d01c on the stable-2.2 branch. That commit extends 'ash' and 'round-ash' to gracefully handle several cases where the shift count is too large to fit in a 'long'. Thanks for the report. Mark
bug#21883: unnecessary bit shifting range limits
Zefram writes: > Not really outright bugs, but these responses are less than awesome: > > $ guile -c '(write (logbit? (ash 1 100) 123))' > ERROR: Value out of range 0 to 18446744073709551615: > 1267650600228229401496703205376 > $ guile -c '(write (ash 0 (ash 1 100)))' > ERROR: Value out of range -9223372036854775808 to 9223372036854775807: > 1267650600228229401496703205376 > $ guile -c '(write (ash 123 (ash -1 100)))' > ERROR: Value out of range -9223372036854775808 to 9223372036854775807: > -1267650600228229401496703205376 > > In all three cases, the theoretically-correct result of the expression > is not only representable but easily computed. Commit 011aec7e240ef987931548d90c53e6692c85d01c on the stable-2.2 branch extends 'ash' and 'round-ash' to handle the easily computed cases of huge shifts. > The functions could be improved to avoid failing in these cases, by > adding logic amounting to: > > (define (better-logbit? b v) > (if (>= b (integer-length v)) (< v 0) (logbit? b v))) > > (define (better-ash v s) > (cond > ((= v 0) 0) > ((<= s (- (integer-length v))) (if (< v 0) -1 0)) > (else (ash v s Unfortunately, simple implementations like the ones above slow down the common case with expensive checks that are rarely needed. The aforementioned commit takes pains to avoid slowing down the common case, but at the cost of extra code complexity. In theory we could do something similar with many other procedures that implement operations on bits and bit fields, but I wonder if it's worth the extra complexity. Mark
bug#21901: bit shift wrong on maximal right shift
Zefram writes: > With Guile 2.0.11: > > scheme@(guile-user)> (ash 123 (ash -1 63)) > $1 = 123 > > Correct result would of course be zero. Problem only occurs for > exactly this shift distance: one bit less produces the right answer. Nice catch! It's finally fixed in commit 1990aa916382d0afcebd5315a6d6f555949ff654 on the stable-2.2 branch. The fix will be in Guile 2.2.5. Thanks for the report. Mark
bug#21883: unnecessary bit shifting range limits
how would this slow down the code. just add the correction where you throw the exception which should be in a branch outside the hot path. Den 14 okt 2018 10:19 AM skrev "Mark H Weaver" : Zefram writes: > Not really outright bugs, but these responses are less than awesome: > > $ guile -c '(write (logbit? (ash 1 100) 123))' > ERROR: Value out of range 0 to 18446744073709551615: 1267650600228229401496703205376 > $ guile -c '(write (ash 0 (ash 1 100)))' > ERROR: Value out of range -9223372036854775808 to 9223372036854775807: 1267650600228229401496703205376 > $ guile -c '(write (ash 123 (ash -1 100)))' > ERROR: Value out of range -9223372036854775808 to 9223372036854775807: - 1267650600228229401496703205376 > > In all three cases, the theoretically-correct result of the expression > is not only representable but easily computed. Commit 011aec7e240ef987931548d90c53e6692c85d01c on the stable-2.2 branch extends 'ash' and 'round-ash' to handle the easily computed cases of huge shifts. > The functions could be improved to avoid failing in these cases, by > adding logic amounting to: > > (define (better-logbit? b v) > (if (>= b (integer-length v)) (< v 0) (logbit? b v))) > > (define (better-ash v s) > (cond > ((= v 0) 0) > ((<= s (- (integer-length v))) (if (< v 0) -1 0)) > (else (ash v s Unfortunately, simple implementations like the ones above slow down the common case with expensive checks that are rarely needed. The aforementioned commit takes pains to avoid slowing down the common case, but at the cost of extra code complexity. In theory we could do something similar with many other procedures that implement operations on bits and bit fields, but I wonder if it's worth the extra complexity. Mark
bug#21883: unnecessary bit shifting range limits
Stefan Israelsson Tampe writes: > how would this slow down the code. just add the correction where you > throw the exception which should be in a branch outside the hot path. If you have a suggestion that's simpler than what I did in commits 011aec7e, 9448a078, and 1990aa91, and just as fast in the common cases, feel free to propose a patch. The words above are insufficient. Mark
bug#32580: Setting variables %load-should-autocompile and GUILE_AUTO_COMPILE in ~/.guile doesn't prevent compiling
Hello Seamus, seamus phenetols writes: > Setting GUILE_AUTO_COMPILE in ~/.profile and in ~/.bash_profile > doesn't seem to have any effect. I'm giving up on guile for now. > Thank you very much for helping. I'm sorry it hasn't worked for you! Let's see if we can find out why. What exactly did you put in your ~/.profile or ~/.bash_profile? What version of Guile are you using? When launching a new pseudo terminal (i.e. xterm, gnome-terminal, etc.) and typing 'echo $GUILE_AUTO_COMPILE', does it return the expected value defined in your ~/.profile or ~/.bash_profile? Note that you would need to logout then login of your session for new variable definition to take effect; otherwise you can test it in your current shell by sourcing it: --8<---cut here---start->8--- source ~/.bash_profile # or source ~/.profile --8<---cut here---start->8--- I've put the following Scheme code in a file named 'test-auto-compile.scm' (attached for your convenience): --8<---cut here---start->8--- #!/usr/bin/env guile !# (define (main) "Print whether auto-compilation is enabled or not and exit with an exit status of 1 if it is enabled, 0 otherwise." (let ((guile-auto-compile-value (getenv "GUILE_AUTO_COMPILE"))) (display (format #f "The value of GUILE_AUTO_COMPILE is ~s\n" guile-auto-compile-value)) (when (and guile-auto-compile-value (string=? guile-auto-compile-value "0")) (display "Auto-compilation is disabled.\n") (exit 0)) (display "Auto-compilation is enabled.\n") (exit 1))) (main) --8<---cut here---start->8--- Here's a small demonstration of what the above script gives on my system (guile --version is 2.2.4, but this should work for any Guile version >= 2.0): --8<---cut here---start->8--- echo $GUILE_AUTO_COMPILE maxim@apteryx ~/Documents$ guile test-auto-compile.scm ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 ;;; or pass the --no-auto-compile argument to disable. ;;; compiling /home/maxim/Documents/test-auto-compile.scm ;;; compiled /home/maxim/.cache/guile/ccache/2.2-LE-8-3.A/home/maxim/Documents/test-auto-compile.scm.go The value of GUILE_AUTO_COMPILE is #f Auto-compilation is enabled. maxim@apteryx ~/Documents$ maxim@apteryx ~/Documents$ rm /home/maxim/.cache/guile/ccache/2.2-LE-8-3.A/home/maxim/Documents/test-auto-compile.scm.go maxim@apteryx ~/Documents$ export GUILE_AUTO_COMPILE=0 maxim@apteryx ~/Documents$ guile test-auto-compile.scm The value of GUILE_AUTO_COMPILE is "0" Auto-compilation is disabled. --8<---cut here---end--->8--- I hope this helps, Maxim #!/usr/bin/env guile !# (define (main) "Print whether auto-compilation is enabled or not and exit with an exit status of 1 if it is enabled, 0 otherwise." (let ((guile-auto-compile-value (getenv "GUILE_AUTO_COMPILE"))) (display (format #f "The value of GUILE_AUTO_COMPILE is ~s\n" guile-auto-compile-value)) (when (and guile-auto-compile-value (string=? guile-auto-compile-value "0")) (display "Auto-compilation is disabled.\n") (exit 0)) (display "Auto-compilation is enabled.\n") (exit 1))) (main)
bug#26058: utf16->string and utf32->string don't conform to R6RS
Hi Taylan, taylanbayi...@gmail.com (Taylan Ulrich "Bayırlı/Kammer") writes: > Andy Wingo writes: > >> Adopting the behavior is more or less fine. If it can be done while >> relying on the existing behavior, that is better than something ad-hoc >> in a module. In general, I agree with Andy's sentiment that it would be better to avoid redundant BOM handling code, and moreover, I appreciate his reluctance to apply a fix without careful consideration of our existing BOM semantics. However, as Taylan discovered, Guile does not provide a mechanism to specify a default endianness of a UTF-16 or UTF-32 port in case a BOM is not found. I see no straightforward way to implement these R6RS interfaces using ports. We could certainly add such a mechanism if needed, but I see another problem with this approach: the expense of creating and later collecting a bytevector port object would be a very heavy burden to place on these otherwise fairly lightweight operations. Therefore, I would prefer to avoid that implementation strategy for these operations. Although BOM handling for ports is quite complex with many subtle points to consider, detecting a BOM at the beginning of a bytevector is so trivial that I personally have no objection to this tiny duplication of logic. Therefore, my preference would be to adopt code similar to that proposed by Taylan, although I believe it can, and should, be further simplified: > diff --git a/module/rnrs/bytevectors.scm b/module/rnrs/bytevectors.scm > index 9744359f0..997a8c9cb 100644 > --- a/module/rnrs/bytevectors.scm > +++ b/module/rnrs/bytevectors.scm > @@ -69,7 +69,9 @@ > bytevector-ieee-double-native-set! > > string->utf8 string->utf16 string->utf32 > - utf8->string utf16->string utf32->string)) > + utf8->string > + (r6rs-utf16->string . utf16->string) > + (r6rs-utf32->string . utf32->string))) > > > (load-extension (string-append "libguile-" (effective-version)) > @@ -80,4 +82,52 @@ >`(quote ,sym) >(error "unsupported endianness" sym))) > > +(define (read-bom16 bv) > + (let ((c0 (bytevector-u8-ref bv 0)) > +(c1 (bytevector-u8-ref bv 1))) > +(cond > + ((and (= c0 #xFE) (= c1 #xFF)) > + 'big) > + ((and (= c0 #xFF) (= c1 #xFE)) > + 'little) > + (else > + #f We should gracefully handle the case of an empty bytevector, returning an empty string without error in that case. Also, we should use a single 'bytevector-u16-ref' operation to check for the BOM. Pick an arbitrary endianness for the operation (big-endian?), and compare the resulting integer with both #xFEFF and #xFFFE. That way, the code will be simpler and more efficient. Note that our VM has dedicated instructions for these multi-byte bytevector accessors, and there will be fewer comparison operations as well. Similarly for the utf32 case. What do you think? > +(define r6rs-utf16->string > + (case-lambda > +((bv default-endianness) > + (let ((bom-endianness (read-bom16 bv))) > + (if (not bom-endianness) > + (utf16->string bv default-endianness) > + (substring/shared (utf16->string bv bom-endianness) 1 Better to use plain 'substring' here, I think. The machinery of shared substrings is more expensive, and unnecessary in this case. Otherwise, it looks good to me. Would you like to propose a revised patch? Andy, what do you think? Mark