Replace lots of mostly-duplicated "Mf-<platform>" and "<platform>.def"
files with just a few "Mf-unix" and and "unix.def" files plus
configuration within "configure" and "workarea". Also change
"version.h" to infer more OS details (as was used for pb, anyway).
This change simplifies setting up configurations for different
platforms, and it makes it easier to share among similar
configurations.
Document the fact that `prop:object-name` takes precedence for the
`object-name` result, and make printing also use `object-name` instead
of the propcedure's name when they're differet.
Also, repair constructor-style printing of a transparent structure
type that has `prop:object-name`.
Closes#2585
Link "liblz4.dll" with the right LZ4 library for /MT mode. It looks
like VS 2017 links anyway, but VS 2015 (and probably earlier) does not
link with the wrong library.
In a normal build, "liblz4.dll" is not needed, but it's linked in case
it turns out to be useful to compress or decompress boot files. A
normal build will construct boot files with the intended final
compression, at least when all the right flags are passed around to
the right places.
The inlined version of `in-value` in a `for` form did not bind the
left-hand identifier at the right layer relative to other bindings in
`for/fold`, which caused the inlined `in-value` to behave differently
than a non-inlined `in-value`. Confusing about this `in-value`, in
turn, had led to incorrect documentation on `for/fold`.
It would be nice to clean up a little more of the evaluator and
availability of bindings in `for/fold`, but doing so runs a
significant risk of breaking existing code (unlike fixing `in-value`,
which behaved even worse and where the repair seems less likely to
break existing programs).
Closes#1659 (again)
Add a `#:permissions` optional argument that is a permissions integer
in the same style as `file-or-directory-permissions` and that is used
when a file is created. On Unix, the given permissions are combined
with the process's umask.
Closes#1654
Making `syntax-local-lift-require` during `#%module-begin` expansion
provides a solution to a long-standing problem with composing
languages via `#%module-begin`, where the bindings of some lanuage
should be made available for expanding the module body by
`#%module-begin` expansion (i.e., the language is *not* the initial
import). If the language does not support `require`, then there was no
way to expand and expose the language import dependency.
Closes#1352
Set the source location of a function call that implements an indirect
import to be the original identifier, so a use-before-definition error
has the right location.
Closes#1324
As noted by @rmculpepper, using an underlying input port as an evt to
indicate more SSL input is not right if data can be pumped from the
underlying input port meanwhile. This commit uses progress evts (real
or synthesized) to avoid that problem.
[The commit include more whitespace changes than I'd normally like,
but it seems like some past tabify went wrong.]
Closes#3804
Match BC's long-standing behavior of only flushing the original output
and error ports on input from the original input port when the output
and/or error port is a terminal port.
During the time that the procedure in a guard-evt is called by `sync`,
it's possible for the `sync` evt choice to become determined. If the
guard-evt procedure then returns a choice-evt, the BC implementation
of `sync` could lose track of the selected evt; the selection is
represented by an index, and choice-evt splicing can shift indices.
Possibly related to #3004
Although retaining the original stream argument to `stream-ref`,
`stream-tail`, or `stream-take` can enable a better error message if
the stream runs out of elements too soon, it can also interfere with
the intended memory use of a stream.
Closes#2870
Although commit 5b0f0cee23 was sufficient to make `rename-in` expand
to `rename` with srcloc for the original name, it turns out it did not
address a similar issue with `only-in` renaming.
Do so by supplying the original (not renamed) identifier syntax as the
`orig-stx` for `make-import`.
Now specifies that the ftype pointer parameter types - `(* ftype)` and
`(& ftype)` - actually require an `ftype-name` (i.e., the syntax
requires an identifier in that position). This clarifies the problem
encountered in issue cisco/ChezScheme#557 (although further examples
would be helpful, of course).
When a negative bignum is shifted right by a multiple of the bigint
bit size (which is 32), when a shifted-off bit is non-0, and when the
result would be a sequence of bigints with all 1 bits before rounding
to deal with the dropped bits, a carry that should have been delivered
to a new high bigint was dropped.
Closes#3794
The current output for `--help` is quite messy and hard to
navigate.
I added some indentation and spacing to make the document
easier to read. For example,
File and expression options:
-e <exprs>, --eval <exprs>
Evaluate <exprs>, print results
-f <file>, --load <file>
Like -e '(load "<file>")' without printing
The new layout is longer, but at least it is readable. It
might be better if we could move all the options to a man
page and only select a few common ones to put in `--help`.
Currently `(make-readtable #f #\a 'dispatch-macro)` produces the error
message
```
; make-readtable: expected procedure argument after symbol argument
; given: 'dispatch-macro
```
which is very confusing, because it sounds like `'dispatch-macro` is
incorrect, but it is in fact correct already.
This PR adjusts the error message to:
```
; make-readtable: expected procedure argument after symbol argument
; symbol: 'dispatch-macro
```
which is the convention that is already used when the mode argument is not given.
One effect of using rktio instead of fwrite is that Windows output
produces LF instead of CRLF. Writing CRLF is arguably more correct,
but it likely doesn't matter, and consistency with normal Racket
output is helpful.
Adjust top-level compilation to accomodate an `#%app` macro that
expands to definitions. Allowing `#%app` to expand to a non-expression
is more consistent with expansion in a module.
There's still an issue with top-level expansion where
(define-syntax-rule (#%app id)
(begin
(define-syntax (id stx) 'ok)
id))
does not work, because the kind of partial expansion used for the top
level doesn't trigger `#%app`, and so the macro and use are expanded
together in a `begin` instead of separately. Changing that would be
subtle and maybe not worthwhile for the top level. Also, although the
behavior of the (very) old expander may not be relevant anymore, it
behaved the same way on that example.
Closes#3728
Really, `raco demod` is adapted here to work with any linklet-based VM
by compiling modules to machine-independent form, which is essentially
a wrapper around linklet S-expressions. The BC-specific implementation
remains in place, and it has the advantage of being able to work with
existing module compilations, while the implementation based on
machine-independent form must recompile all modules before attempting
to combine them (but that recompilation is easily cached).
Use `--work <dir>` to use `<dir>` as a cache for multiple
demodularizations.
Getting `raco demod` to work involved several incidental improvements:
* make `racket/linklet` work with machine-independent forms;
* add `linklet-body-reserved-symbol?`;
* fix schemify for linklets that have unexported definitions (which
the expander never generates, but the demodularizer does);
* add `current-multi-compile-any` to expose CM's multi-target
compilation mode programmatically; and
* repair a bug in CS JIT mode.
The demodularizer could be a lot smarter to prune demodularized code
before sending it off to the compiler. Of course, the compiler should
be able to figure out improvements itself, but sending a smaller chunk
of code to the compiler can avoid the hybrid interpreter--compiler
mode that is used for large linklets and that prevents optimizers like
cp0 from doing much to prune definitions.
The demodularizer has a lot in common with the expander's flattener
that is used for bootstrapping, and a smarter demodularizer would have
even more in common. It would be nice to have one implementation
instead of two.
Commit 24c6b2450c fixes a problem with 'text mode output, but "io.scm"
needed to be sync'ed for that repair to take effect. The repair
exposed a problem with position counting for 'text mode input, which
is repaied here.
This commit includes a relatively unrelated repair to `_list` and
`_vector`, which was exposed by a combination of the I/O demo
bootstrap and a recent repair for `malloc` to recognizes `_bytes` as a
GCable type.
Compressing boot files is a trade-off in file size versus startup
time. Compressed boot files take about 10MB instead of 40MB, but using
uncompressed boot files cuts the minimum startup time (for `racket
-n`) by around 25%.
On Unix-like platforms, we favor startup time by default. Although an
extra 30MB isn't small, it's also not that much, and the Unix culture
favors small excutables that start quickly (although Racket's startup
time is not as fast as we'd like).
On Windows, we try the opposite choice with this commit. Windows
doesn't have the same culture of little excutables, slower filesystems
(especially networked ones) seem more common, and the savings for
stand-alone executables seem more worthwhile.
Add a `configure` argument to enable even more compression in ".zo"
forms, and introduce environment variables to enable compression
control for Windows builds using MSVC.
When cross compiling, use the same fasl compression mode as non-cross
compilation on linklet bundles --- instead of always compressing,
which slows down module loading in most environments.
This is another way that cross compilation differed from direct
compilation, overlooked before because it's an argumen to
`compile-to-port` instead of a parameter.
The hashing protocol has been adjusted since the Patricia trie
implementation so that the result can be negative. Force it to
avoid breaking an assumption in the Patricia-trie implementation
(even though this implementation is not currently used).
Currently, a common way to generate an inclusive range is to
use `in-range`, but users need to figure out an appropriate
upper bound, which (1) is error-prone and (2) obscures the intention.
As an example, https://docs.racket-lang.org/pict/Animation_Helpers.html
uses `(in-range 0 1.2 0.2)` to generate `'(0 0.2 0.4 0.6 0.8 1.0)`.
It is also quite common to use `(in-range 1 (add1 n))` to generate
`(list 1 2 ... n)`. Both examples are subpar.
This PR adds `in-inclusive-range` as a counterpart to `in-range`, and
`inclusive-range` as a counterpart to `range`, to make inclusive range
construction easier.
An alternative API is to modify `in-range` to accept a keyword argument
like `#:inclusive? #t`, but this is more verbose and no other sequence
generating function accepts keyword arguments.
Therefore, I think `(in-)inclusive-range` is more appropriate.
1. Forms like rename-out supply the original "export-id" syntax to
make-export as orig-stx, as well as the symbol value as out-sym. In
such a case -- that is, when (eq? (syntax-e (export-orig-stx export))
(export-out-sym export)) -- expand using orig-stx, retaining its
source location and other properties.
2. Otherwise, at least expand using out-sym as an identifier with
srcloc from orig-stx. Rationale: Although that source location might
not be exactly correct it is probably better than none at all.
Note: The spirit of this commit is to treat this as a private
implementation detail -- as opposed to stating some new official API
for renaming provide transformers in general -- so this commit doesn't
update documentation for e.g. `make-export`.
The `cast` function is supposed to auto-promote its second argument to
a GCable type if the value to convert is a GCable pointer. This
promotion did not happen for `_bytes` and other string-like types.
Also, in CS, `malloc` did not alocate GCable memory by default when
given the `_bytes` type, which would sometimes interfere with getting
a GCable pointer result.
This bug explains why the "draw-test/tests/racket/draw/dc.rkt" test
would occassionally have an `unscaled-alpha-set` failure on DrDr (for
many years).
The new functions provide a more direct way to serialize and
deserialize syntax objects than compiling and running a `quote-syntax`
form. The new functions also offer additional configuration related to
preserving extra syntax properties and limiting the use of shared
"bulk binding" tables (i.e., tables that must provided by module
declarations in the namespace).
This change does not add syntax-object support to `serialize` or
`s-exp->fasl`, because serialized syntax objects are still in many
ways like code: they are version-specific, and their invariants can be
broken by mangling the serialized form (in much the same way that
compiled code can be broken by mangling, and with similar safetly
implications).
When referring to a Git repo with a "https://" URL, the URL must end
with ".git" to distinguish the URL for directory and file URLs. A
"git+https://" URL specifies that the Git-over-HTTP protocol should be
where the URL cannot contain ".git". For example, SourceHut URLs do
not include ".git" (while hosting services like GitHub or BitBucket
allow ".git" to be in the URL).
When using `raco pkg`, it was possible to specify `--type git` for an
"https://" reference, but for consistency and internal tracking, a
".git" would be added to the URL, anyway. Using `--type git-url` can
similarly force the interpretation of an "https://" reference without
triggering the addition of ".git". The new state is mostly internal,
but it is reflected in the output of `raco pkg show`, which shows
`git` for such references (as opposed to `url` as shown for others).
The CS implementation was missing a level of indirection. It worked
for a typical handler `(lambda (thunk) (thunk))` for the case when the
callback can run atomically, but it did not work for caces where
`thunk` is made to run later (potentially out of atomic mode).
Also, fix the management of interrupt state, including for some place-
and future-related asynchronous callbacks.
Thanks to @rmculpepper for the `async-apply` report, new `async-apply`
tests, and the repair for the interrupt-state bug.
Add `#:eager` options to `stream-cons` to control whether the head
and/or tail expression is delayed. Also add `stream-lazy` to
explicitly construct a lazy stream and `stream-force` (normally not
needed) to force a stream.
Delayed expressions in `stream-cons` are now non-reentrant, like
promises created by `delay`. This is a change in behavior, but I'm
hoping that no one relied on the old behavior, which has the bad
property that the delayed expression is retained until its result is
received.
For consistency, this commit also changes `stream*` to delay the
stream-construction expression when its the only one expression that
is given.
Internally, changes to the stream implementation reduce allocation.
The `stream-lazy` form would be more natrally called `stream-delay`,
but that creates a conflict with existing packages.
The cross-library inlining improvement in commit 6020b944ef did not
manage internal names correctly, and it could mix up bindings that
have the same printed form.
Closesracket/ChezScheme#35
In this example, after the check with eq? or eqv? the value of
the variables x and y are known, so cptypes replaced the
reference to the variable with it. But it can interact badly
with the eq? test, for example in this case the first (eq? x y)
can be #f and the second be reduced by the compiler to #t.
In spite eq? cannot be used to compare numbers reliably, this
behavior is too confusing and it's better to avoid it.
(define (one)
(let ([r (random 2)])
(if (= r 0) (one) r)))
(define (f x y)
(define first-comparison (eq? x y))
(when (and (eqv? x 7.0)
(eqv? y 7.0))
(define second-comparison (eq? x y))
(eq? first-comparison second-comparison)))
(f (+ 6.0 (one)) (+ 6.0 (one)))))
BC did not take a lock for `hash-clear!`. Maybe the intent was that a
lock isn't needed from the perspective of `hash-clear!` when it isn't
traversing the table, but failing to take a lock before modifying the
table can break other operations (that do take a lock) in progress.
Furthermore, some iterations that intentionally did not take a lock
also did not guard against changes well enough. Various repairs here
avoid crashes, and now `hash-clear!` consistently takes a lock.
CS had a similar (but more subtle and more limited) instance of the
problem in `hash-map` and `hash-for-each`. That problem is corrected
(without adding any new lock acquisitions).
The existing CS implementation of `equal-hash-code` for hash tables
takes a lock more than the BC implementation. A possibly surprising
result: when attempting to add a mutable hash table to itself as part
of a key, the `hash-set!` can block forever on the hash table's lock,
instead of doing something more random as a result of having a mutated
key. The documentation now notes that possibility.
Related to #3738
With list-assuming-immutable? and the internal construct
immutable-list the compiler can assume that some lists will
not be mutated.
Also, change the definition of interned-char?, because in CS all chars
are interned.
This commit partly reverts c305dba649 and 88fc9a979f, which was
discusssed in #366.
The original discussion was about allowing an extra argument to
`member` to pick the equality predicate. That change is still in place
in the same (private) Racket module.
The `memq` and `memv` functions are in Scheme for Racket CS and back
to being and in C for Racket BC. The old motivation for moving `memv`
and `memq` --- to get them out of C --- is subsumed by the switch to
CS (granting that some C code got added back to BC meanwhile). The
advantage of moving `memq` and `memv` back to the runtime core is that
the compiler can do more with them, at least in CS.
When `memq` and `memv` were moved previously, they lost checking for
cyclic lists. That wasn't discussed and presumably wasn't on purpose;
check is restored here, including for `member`.
There's no significant performance change in CS, except in cases like
`(memq x '(a b c))` that the compiler unpacks into a combination of
`eq?`s. For BC, the C version is a little faster (10-40%, depending on
the length of the list), but still slower than CS (probably because
`pair?` is slower, which due to representation differences).
This change makes
(begin-encourage-inline
(define-values (f g h) (values e1 e2 e3)))
equivalent to
(begin-encourage-inline
(define f e1)
(define g e2)
(define h e3))
The `current-place` place-local variable was initialized relatively
late in the set of place-creation steps. It was possible for the
thread scheduler to get involved before `current-place` was set ---
and in that case, it was possible for semaphores and Racket threads to
end up being used in the wrong place.
Register allocation needs fresh machine-register state for each
compilation, and that was previously implemented by allocating a new
register record and indirecting references through a parameter. Move
the indirection to the places where conflict-set, index, and precolor
state is manipulated, and pass a state vector though to keep access
efficient. This change makes compilation slightly faster, and it makes
registers easier to work with by not having to introduce
indirections/delays in various places for register references.
Moving the np-expand-primtives pass to a separately compiled source
file reduces peak memory use when compiling Chez Scheme from about 1.3
GB to about 0.7 GB on a 64-bit platform. It's also nice from a
code-navigation perspective to split a 19k-line file to a 10k-line
file plus 8k-line file (and some additional small files).
The overall time for Chez Scheme to compile itself is only slightly
affected, even though some support functions, macros, and record
declarations end up getting compiled twice.
More generally, make the path-fixup step insensitive to specific
filenames in the "lib" directory, making it more like the handling of
the "bin" directory.
The logic was added in the previous commits, but it's necesary to add
the mapping from the names in primdata to cptypes.
Also add a few subsets of fixnum.
Running a `starter`-based executable with an argv[0] different
than the executable's path can make sense in various situations, but
it doesn't work for finding code embedded in the enxecutable. On
platforms where it's possible to get the current process's executable
(not looking at you, OpenBSD), then use that instead of argv[0] for
the purposes of loading embedded code.
Related to #3685
chars are immediates, so the previous change doesn't add automatically
the combinations like maybe-char. Add also eof/char that is commonly
used and has the same problem.
And rename in ctypes the internal symbol $immediate/true to
true-immediate because in all the other instances / is used for unions.
An an example of better error handling,
(f (error 'x "x") y x)
turns into
(error 'x "x")
which may allow further propagation through `begin` and `if` as
alerady implemented.
Also, make cp0 and cptypes more aware of
`call-{setting,getting,cosuming}-continuation-attachment` in terms of
result types and single-valuedness. The single-valued part requires
some generalization to the existing `single-valued?` support (by
default, "single-valued" => "doesn't inspect/changed immediate mark")
in both cp0 and cptypes.
Finally, the "optimize.rktl" test suite is now enabled for Racket CS.
The tests helped expose some missed opportunities and bugs, and it
should be particularly helpful going forward, since we're back to
having a place for Racket-level optimization tests. Not all tests
written for BC pass with CS. Grep for 'chez-scheme for missed
optimization opportunities.
CS: When `with-continuation-mark` for a chaperoned key is in tail
position for a mark (such as a `parameterize`), make sure the existing
mark is still in place while (non-tail-)calling the chaperone's
interposition function.
BC: Don't collapse immediately nested `with-continuation-mark`s for
the same key if the key might be chaperoned. Also, repair treatment of
module-level bindings as potentially chaperoned.
When the schemify inliner tries to inline, and inlining is supposed to
succeed with a result expression `#f`, the #f was being treated as a
failure to inline.
The repair involvea adding a `-E` flag to Racket for use by the wrap
executable that `raco exe` created, because OpenBSD (intentionally)
does not have a way to access the executable file of the current
process.
Closes#3717
Close#3603
* skip keywords in invalid-option-placement
* replace check-duplicate with check-duplicates
* add skip keywords test
* add require and fix syntax-e error
* update comment of invalid-option-placement
* add mixture keywords and arguments test
* forget to skip keyword in loop
* and another two tests for syntax-parse
* define splicing-formals-no-rest as @Metaxal suggested
* add formals link
* rename splicing-formals-no-rest to formals-no-rest
* add attributes to formals
* remove racket/dict import
The fact that a non-zip archive has always been silently ignored seems
bad, but adding an error might break code that (probably accidentally)
relies on the behavior. This change makes sane behavior at least
available by adding a `#:must-unzip?` option.
Relevant to #3613
These changes facilitate building Chez Scheme in environments where
utility commands are not available at their usual absolute paths,
such as Nix and GNU Guix.
Specific changes:
- `cc` -> `$(CC)`
- `/bin/rm` -> `rm`
- `/bin/ln` -> `ln`
- `/bin/cp` -> `cp`
- `/bin/echo` -> `echo`
- in `makefiles/installsh`, add a case to find `true`
at an unusual path or as a shell builtin
Related to https://github.com/racket/racket/issues/3707
Also, provide workarounds for some broken conversions --- especially
the 'string/utf-16 conversion for reading. For writing, allow
specifying raw bytes that end up in REG_SZ or REG_EXPAND_SZ via
'bytes/string or 'bytes/expand-string.
Send bytes directly to `path-list-string->path-list`, since it can
handle bytes and convert directly to paths. Also check that the
argument to `path-list-string->path-list` has no nul character or byte.
Actually, use a more general decomposition with a part for an
$immediate, a part for a $record and a third part for other types
like string?, vector?, ...
This is not as general as an arbitrary union, but it is enough for
the common cases, and also to handles the common objects in Racket
that are implemented in CS as the corresponding object and a record
for the impersonator.