Conversation
tests/mux-smoke.dec was 28 bare integers including 2147483654 and
2147483675, and the loader accepts bare integers with no comment syntax,
so nothing in the file could say which part of the encoding each cell
covered. scripts/gen-mux-smoke.fth emits the same image from named
cells: the MOVE, the SUBLEQ that adds 32 to reach 'a', the masked MUX
that builds 'C', and the branch to a negative pc that halts. The emitted
cells are identical to the deleted file apart from spelling its two
negative values unsigned, which load_muxleq() accepts either way.
Building the MOVE encoding from a sign bit and mask address 6 is for
readability only. Unlike MUX_MOVE_C, which the interpreter and its
emitters expand from one macro in one translation unit, a Forth copy of
those constants can drift exactly as far as a literal could, and the
comment says so rather than claiming a guarantee.
The generator asserts its own layout: each datum is emitted through a
word that checks it lands on the address its constant claims, so
reordering the data block fails the build instead of silently rewiring
the code above it. A leading "decimal" pins BASE, which every literal
and the .r output depend on.
The two loader fixtures held one malformed token each, so they become
two printfs in GEN_LOADER_REJECTS, shared by check-loader-rejects and
check-sanitize so the malformed data keeps one spelling. Both images are
generated inline in the recipes, matching how gen-mux-high-image.py is
already invoked in check-mux, so none of this needs a rule or a variable
holding a path.
check-loader-rejects now runs the VM under $(RUN). It was the one target
loading an image without the bound the comment above RUN says every test
run gets, and that only became reachable once the fixtures were
generated rather than committed: a generation bug can produce a valid
looping image, which hangs the gate instead of failing it.
GEN_LOADER_REJECTS joins its printfs with && for the same reason, since
with ";" a failed first write was swallowed.
The deep job's check-analyze failed on findings no contributor could
reproduce: the runner image ships an older shellcheck that reports
SC2015 for no_mext in scripts/rtos-check.sh, which 0.11.0 does not.
shellcheck findings drift between releases the way clang-format output
does, so it is now pinned in that job by version and content hash like
the format job pins shfmt. That is what makes a local check-analyze
predict CI rather than merely resemble it.
no_mext is spelled as an if regardless. The old "A && { ...; } || :"
was correct, since the braces exit and the ":" was unreachable once the
grep hit, but it is the exact shape SC2015 names and the trailing no-op
only existed to keep the no-match case returning 0 under set -e. An if
gets that for free. Both branches verified: no match reaches the end with
status 0, a match still fails loudly with status 1.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tests/mux-smoke.dec was 28 bare integers including 2147483654 and 2147483675, and the loader accepts bare integers with no comment syntax, so nothing in the file could say which part of the encoding each cell covered. scripts/gen-mux-smoke.fth emits the same image from named cells: the MOVE, the SUBLEQ that adds 32 to reach 'a', the masked MUX that builds 'C', and the branch to a negative pc that halts. The emitted cells are identical to the deleted file apart from spelling its two negative values unsigned, which load_muxleq() accepts either way.
Building the MOVE encoding from a sign bit and mask address 6 is for readability only. Unlike MUX_MOVE_C, which the interpreter and its emitters expand from one macro in one translation unit, a Forth copy of those constants can drift exactly as far as a literal could, and the comment says so rather than claiming a guarantee.
The generator asserts its own layout: each datum is emitted through a word that checks it lands on the address its constant claims, so reordering the data block fails the build instead of silently rewiring the code above it. A leading "decimal" pins BASE, which every literal and the .r output depend on.
The two loader fixtures held one malformed token each, so they become two printfs in GEN_LOADER_REJECTS, shared by check-loader-rejects and check-sanitize so the malformed data keeps one spelling. Both images are generated inline in the recipes, matching how gen-mux-high-image.py is already invoked in check-mux, so none of this needs a rule or a variable holding a path.
check-loader-rejects now runs the VM under $(RUN). It was the one target loading an image without the bound the comment above RUN says every test run gets, and that only became reachable once the fixtures were generated rather than committed: a generation bug can produce a valid looping image, which hangs the gate instead of failing it. GEN_LOADER_REJECTS joins its printfs with && for the same reason, since with ";" a failed first write was swallowed.
Summary by cubic
Generate test images at build time instead of committing fixtures to improve readability and catch layout mistakes early. Align local checks with CI by pinning tools and making generators resilient.
tests/mux-smoke.decwith a generated image fromscripts/gen-mux-smoke.fth; skip whengforthis missing; uses named addresses; asserts layout; pinsdecimal.GEN_LOADER_REJECTSfor bothcheck-loader-rejectsandcheck-sanitize; run the VM under$(RUN); join writes with&&to fail fast.shellcheckv0.11.0 by hash; runmake CPPCHECK= check-analyze; reworkscripts/rtos-check.shno_mextto an if-form to drop SC2015.git ls-files(wrapped in$(wildcard ...)) so deleted paths don’t linger; refuse empty lists outside a git checkout.indent: keepclang-formatv20 gate; runblackfor Python andshfmtfor shell when present; lint Forth as before;check-analyzeuses git-enumerated C sources and respectsCPPCHECKto allow explicit CI disable.Written for commit 6ebfedb. Summary will update on new commits.