This PR in a sense reverts f83cec1b04 and attempts to directly fix
the bug that the commit tries to address with an approach similar to the
original one.
The problem with the aforementioned commit is that, Gosper's hack
only works efficiently when the length of `l` is small enough that
the number representation can fit into a fixnum
(so that all bit operations take constant time).
When the length of `l` is large, the number representation could
become a bignum with length proportional to the length of `l`.
This is not ideal because it causes the time complexity of the algorithm
to be `O({|l| choose k} |l|)` instead of `O({|l| choose k} k)`, which
would be a significant performance degradation when `|l|` is much
larger than `k`.
Currently, in Racket BC, the following program:
```
(srcloc->string (make-srcloc "x.rkt" #f #f 90 #f))
(srcloc->string (make-srcloc "x.rkt" #f 80 #f #f))
(srcloc->string (make-srcloc "x.rkt" #f #f #f #f))
(srcloc->string (make-srcloc "x.rkt" #f 80 90 #f))
(srcloc->string (make-srcloc "x.rkt" 70 #f 90 #f))
(srcloc->string (make-srcloc "x.rkt" 70 80 #f #f))
(srcloc->string (make-srcloc "x.rkt" 70 80 90 #f))
```
results in:
```
"x.rkt::90"
"x.rkt::80"
"x.rkt::-1"
"x.rkt::80"
"x.rkt:70:90"
"x.rkt:70:80"
"x.rkt:70:80"
```
This output is very confusing and inconsistent.
When we see "x.rkt::90", we can never be sure if it's a srcloc
whose position is 90, or a srcloc whose column is 90.
The same applies for "x.rkt:70:90".
Moreover, the srloc "x.rkt::-1" is weird and is arguably incorrect
(see #1371).
For CS, the output would sometimes contain `#f`, and that is fixed
here by not trying to add position information when it's not available.
Non-atomic mode is questionable at best with BC, and more so with CS.
With BC, a thread swap at least copies the fragment of the C stack
that is between a foreign call and a callback; that can work with some
C libraries, but it goes wrong often enough that it really shouldn't
be relied on. On the plus side, if it's going to go wrong, at least it
tends to go wrong right away (i.e., something in the C frame tends to
get broken in normal runs).
With CS, the C stack is not captured as part of a thread, and so
non-atomic mode 's even more broken. Non-atomic mode could work if you
know that no other thread is running that can involve foreign calls
and callbacks, but that assumption is usually not a good one. Worse,
when things finally go wrong, it's likely several scheduling steps and
thread interleavings away from the problem (e.g., #3459).
There's a chance that this change will stop some existing programs
from working ok on CS. It's more likely to make existing programs work
as intended on CS; the common case is that atomic mode is technically
needed even though non-atomic mode happened to work in practice with
BC.
I think that in general, `null-terminated?` should admit all patterns
that _could_ match a list, instead of just the ones that _only_ match
a list. That means that `(app f)` patterns and many others should also
be valid, though those are harder to implement, so I haven't tried
those yet.
This change is mostly for making CS consistent with BC, but in the
case of `(object-name #'x)`, it also makes BC consistent with BC
before the macro-expander rewrite.
Closesracket/pconvert#9
Commit 9a3eb15d8b broke atomic-timeout handling. As aresult, for
example, using the scroll thumb on Mac OS could freeze DrRacket as
long as something is running for a canvas refresh.
Change the representation of records to keep an ancestor vector
instead of just a parent, so a record-type predicate (for a non-sealed
type) can be constant-time.
Reluctantly, with intentionally oxymoronic names, and with the key
caveat: using these requires making correct assumptions about Racket's
implementation.
With BC, a related assumption was that `unsafe-set-mcar!` and
`unsafe-set-mcdr!` mutate pairs, but that's not the case with CS. So,
adding these functions supports a kind of portability between BC and
CS.
The `fake-installers[-from-built]` target drives a distribution build
like `installers[-from-built]`, but instead of building on clients,
just copies a "README" as an installer.
The UTF-8-ish decoder incorrectly allowed a surrogate pair encoded as
two unpaired surrogates, and it treated an unpaired surrogate at the
of a stream as complete instead of a potential error.
Related to #3578
Related to #1500.
This improves the following aspects of the CI config:
* The config now tracks the current stable version of Racket so
package authors don't have to remember to upgrade the config on new
releases. This is a double-edged sword, because it makes it easy to
use features of new Racket version and potentially break
backwards-compatibility by accident. Running CI against a set of
static Racket versions doesn't have this problem since any such change
would end up failing. Maybe a better change here would be to
interpolate the current `(version)` into the CI file instead.
* The job is now set to fail on the first error it encounters on the
assumption that most packages fail due to internal issues and not due
to mismatches between Racket versions. The intent with this change is
to use fewer resources overall when possible. Additionally, the
packages' dependencies are now validated during the setup step.
* Lastly, the install step now avoids building documentation for
dependencies, which can shave off significant amounts of time.
Calling `rationalize` with `+nan.0` as the second argument was causing
a "no exact representation error." This commit changes it to produce
`+nan.0`.
There was an unexercised set of tests for `rationalize` in the test
suite which, once called, demonstrate the bug.
Those tests also specify that `rationalize` should produce an exact
result when the first argument is exact and the second is an infinity.
That's not what the implementation does; it coerces the result to
inexact. I changed the test cases to match the implementation, which
is consistent with other Schemes (Chez, MIT) and standards (R6RS).
When a {u,s}16vector points to memory that's not bytes (e.g. from ffi)
then referencing or setting the memory results in a Chez error:
```
foreign-set!: unrecognized type 'int16
```
The fix is to change the type argument to `'integer-16` and
`'unsigned-16`.