From 1a9b142d80c4b1c29a77d8e5211beee03402bfc6 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Nov 2026 11:31:07 +0000 Subject: [PATCH] docs: The Dictionary of v4 -- every live word, alphabetical, its stack notation and description; built and published with every release (#157) [skip ci] make dictionary -> build/docs/Dictionary.pdf (20 pages): mkdictionary.py checks docs/reference/v4-dictionary.tsv against the booted system's words first, so a stale dictionary fails the build; then Markdown, pandoc, docs/book/dictionary.tex (the books' preamble, its own title page: version and commit). Quoted FORTH tokens set as code, so their quotes print straight. The nightly's docs stage builds it; publish sends classifier dictionary; the Gitea release attaches it. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2 --- Makefile | 6 ++- docs/book/Makefile | 36 +++++++++++++++- docs/book/dictionary.tex | 42 +++++++++++++++++++ .../plans/2026-11-10-alpha4-documents.md | 6 +-- scripts/nightly.sh | 6 ++- v4/tools/mkdictionary.py | 3 ++ 6 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 docs/book/dictionary.tex diff --git a/Makefile b/Makefile index b1a7db49..6cd81994 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ BOARD_DIR := $(if $(TARGET),$(BOARD_DIR_$(TARGET))) SUBMAKE := $(MAKE) --no-print-directory .DEFAULT_GOAL := all -.PHONY: all boot_image boot_images write_stick docs fabric clean clean-docs kernel boards help help-hosted sbom sbom-board \ +.PHONY: all boot_image boot_images write_stick docs fabric dictionary clean clean-docs kernel boards help help-hosted sbom sbom-board \ qemu qemu-esp qemu-gdb init # ARCH given on the command line and no TARGET: `clean` is the kernel's for that @@ -207,6 +207,10 @@ docs: fabric: @$(SUBMAKE) -f docs/book/Makefile fabric +# dictionary -- The Dictionary of v4 (#157): build/docs/Dictionary.pdf +dictionary: + @$(SUBMAKE) -f docs/book/Makefile dictionary + clean-docs: rm -rf build/docs diff --git a/docs/book/Makefile b/docs/book/Makefile index cc6c3d12..82b00b45 100644 --- a/docs/book/Makefile +++ b/docs/book/Makefile @@ -63,9 +63,18 @@ FABRIC_DIR := $(OUT)/fabric FABRIC_PDF := $(OUT)/BookOfFabric.pdf FABRIC_FRAGS := $(foreach n,fabric-0 fabric-1 fabric-2 fabric-3 fabric-3-5 fabric-3-6 fabric-3-7 fabric-4,$(GEN)/$(n).tex) -.PHONY: all fabric tools FORCE +# The Dictionary of v4 (#157): every live word, alphabetical, with its stack +# notation and description -- `make dictionary` -> build/docs/Dictionary.pdf. +# Its names are the booted system's (v4/tools/mkdictionary.py); the check +# refuses a table that has fallen behind them. +DICT_DIR := $(OUT)/dictionary +DICT_PDF := $(OUT)/Dictionary.pdf +DICT_TSV := docs/reference/v4-dictionary.tsv + +.PHONY: all fabric dictionary tools FORCE all: $(PDF) fabric: $(FABRIC_PDF) +dictionary: $(DICT_PDF) tools: @missing=""; \ @@ -113,6 +122,8 @@ $(VAR_DIR)/meta.tex: FORCE $(meta_cmds) $(FABRIC_DIR)/meta.tex: FORCE $(meta_cmds) +$(DICT_DIR)/meta.tex: FORCE + $(meta_cmds) FORCE: @@ -137,3 +148,26 @@ $(FABRIC_PDF): $(BOOK_DIR)/fabric.tex $(BOOK_DIR)/preamble.tex $(FABRIC_FRAGS) $ echo "Error: LaTeX failed; full log: $(FABRIC_DIR)/fabric.log"; exit 1; } @cp $(FABRIC_DIR)/fabric.pdf $@ @echo " PDF $@" + +# the live word list needs the hosted v4; the check fails the build on a word with no entry, an +# unfinished entry, or an entry for a word the system no longer has +$(GEN)/dictionary-words.md: $(DICT_TSV) v4/tools/mkdictionary.py FORCE | tools + @mkdir -p $(GEN) + @$(MAKE) --no-print-directory -C v4 hosted >/dev/null + @python3 v4/tools/mkdictionary.py check $(DICT_TSV) + @python3 v4/tools/mkdictionary.py md $(DICT_TSV) $@ + +$(GEN)/dictionary-words.tex: $(GEN)/dictionary-words.md $(PANDOC_FILTERS) | tools + @echo " PANDOC $< -> $@" + @$(PANDOC) $(PANDOC_FLAGS) --id-prefix=dictionary- $< -o $@ + +TEXINPUTS_DICT := $(abspath $(DICT_DIR)):$(abspath $(GEN)):$(abspath $(BOOK_DIR)): + +$(DICT_PDF): $(BOOK_DIR)/dictionary.tex $(BOOK_DIR)/preamble.tex $(GEN)/dictionary-words.tex $(GEN)/pandoc-highlighting.tex $(DICT_DIR)/meta.tex | tools + @echo " LATEXMK $(BOOK_DIR)/dictionary.tex -> $@" + @TEXINPUTS=$(TEXINPUTS_DICT) $(LATEXMK) -xelatex -interaction=nonstopmode -halt-on-error \ + -file-line-error -outdir=$(DICT_DIR) $(BOOK_DIR)/dictionary.tex > $(DICT_DIR)/latexmk.log 2>&1 || { \ + grep -A4 -E '^(.*:[0-9]+:|!)' $(DICT_DIR)/dictionary.log | head -40; \ + echo "Error: LaTeX failed; full log: $(DICT_DIR)/dictionary.log"; exit 1; } + @cp $(DICT_DIR)/dictionary.pdf $@ + @echo " PDF $@" diff --git a/docs/book/dictionary.tex b/docs/book/dictionary.tex new file mode 100644 index 00000000..7a98c5c9 --- /dev/null +++ b/docs/book/dictionary.tex @@ -0,0 +1,42 @@ +% docs/book/dictionary.tex -- master file of The Dictionary of v4 (#157): +% every word StarForth v4 boots with, alphabetical, with its stack notation, +% a description and where it is defined (Captain Bob, 2026-11-08: "a +% 'dictionary' document with the word, stack notations and descriptions. +% Alphabetical."; v4's words only). +% +% Built by `make dictionary` (docs/book/Makefile): v4/tools/mkdictionary.py +% checks docs/reference/v4-dictionary.tsv against the live system and writes +% the Markdown that pandoc turns into the fragment input below. +\documentclass[11pt,openany]{book} + +\input{preamble} + +\title{The Dictionary of StarForth v4\\[0.5em]\large Every word, its stack notation, and what it does} +\author{Robert A. James (Captain Bob)} +\date{Version \texttt{\bookversion}\\Built \bookdate{} from commit \texttt{\bookcommit}} + +\begin{document} +\frontmatter +\maketitle + +\chapter{How to read it} +Every word of the dictionary StarForth v4 boots with is here, in +alphabetical order. The names are not typed by hand: they are the booted +system's own list (\texttt{WORDS}, and the kernel's words of the node), and +the build refuses a dictionary that has fallen behind it. + +\textbf{Stack notation.} \texttt{( before -{}- after )}: the values a word +takes from the stack, the top on the right, and what it leaves there. +\texttt{( R: ... )} is the return stack. \texttt{n} a signed number, +\texttt{u} an unsigned one, \texttt{d} and \texttt{ud} double-cell numbers, +\texttt{q} a Q48.16 fixed-point number, \texttt{x} any cell, \texttt{flag} +a truth value (0 false, -1 true), \texttt{c} a character, \texttt{addr} a +cell address, \texttt{baddr} a byte address, \texttt{xt} an execution token. + +\textbf{xxx.} Where a word reads a name or text from the input stream, the +description shows it, as \texttt{' xxx} or \texttt{.\textquotedbl{} text\textquotedbl}. + +\mainmatter +\input{dictionary-words} + +\end{document} diff --git a/docs/v4.0.0/plans/2026-11-10-alpha4-documents.md b/docs/v4.0.0/plans/2026-11-10-alpha4-documents.md index 0fa63526..7f4dbeb2 100644 --- a/docs/v4.0.0/plans/2026-11-10-alpha4-documents.md +++ b/docs/v4.0.0/plans/2026-11-10-alpha4-documents.md @@ -15,9 +15,9 @@ Captain Bob, 2026-11-10: "Do it" -- the rest of alpha.4 that lives in the tree, ## #157 -- the dictionary of v4, and the .com's Documents page - [x] the live word list of the built system (318 words): `v4/tools/mkdictionary.py words` -- the hosted v4's `WORDS` (317) plus the kernel's `sk_v4_words[]` (`MINT-ZUSE`) -- [~] the table in the tree, `docs/reference/v4-dictionary.tsv`: drafted for all 318 (`mkdictionary.py draft`; the source gave a stack comment for 54, a description for 105); the rest written by hand in batches, alphabetical -- next: batch 1 -- [x] the check: `mkdictionary.py check` -- every live word has a finished entry, every entry a live word (fails on all 318 drafts today, as it should); not yet in the build -- [ ] the PDF, alphabetical; `make dictionary`; the nightly's docs stage, classifier `dictionary` +- [x] the table in the tree, `docs/reference/v4-dictionary.tsv`: all 318 entries, written in three alphabetical batches against v4's own definitions (the source gave 54 stacks and 105 descriptions to start from); `check` passes +- [x] the check: `mkdictionary.py check` -- every live word has a finished entry, every entry a live word; run by `make dictionary`, so a stale table fails the build and the nightly +- [x] the PDF, alphabetical: `make dictionary` -> `build/docs/Dictionary.pdf` (20 pages; `docs/book/dictionary.tex`); the nightly's docs stage builds it, `publish` sends classifier `dictionary`, the release attaches it - [ ] the Documents page: canvas artboard, then `site/com` ## #126 -- the Downloads page live diff --git a/scripts/nightly.sh b/scripts/nightly.sh index d1cbb2ce..c1b63dd1 100755 --- a/scripts/nightly.sh +++ b/scripts/nightly.sh @@ -43,6 +43,7 @@ # (make -C docs/formal doxygen), into build/nightly-docs/. # scripts/nightly.sh publish-docs # org.starship:documentation:: classifier book, fabric (The Book of Fabric, #138), +# dictionary (The Dictionary of v4, #157 -- it fails the stage if a live word has no entry), # vol1, vol2, vol3, api (pdf). # # VERSION is -SNAPSHOT, or NIGHTLY_VERSION when set (a release sets it from its @@ -175,9 +176,11 @@ docs) rm -rf "$DOCS"; mkdir -p "$DOCS" make --no-print-directory docs make --no-print-directory fabric + make --no-print-directory dictionary make --no-print-directory -C docs/formal vols doxygen cp build/docs/LithosAnanke.pdf "$DOCS/book.pdf" cp build/docs/BookOfFabric.pdf "$DOCS/fabric.pdf" + cp build/docs/Dictionary.pdf "$DOCS/dictionary.pdf" for v in 1 2 3; do cp "docs/formal/build/vol$v/main.pdf" "$DOCS/vol$v.pdf"; done cp docs/formal/build/doxygen/StarForth-API-Reference.pdf "$DOCS/api.pdf" (cd "$DOCS" && sha256sum ./*.pdf | tee SHA256SUMS) @@ -220,8 +223,9 @@ print(json.dumps(notes.strip() + "\n\n## Checksums (SHA-256)\n\n```\n" + sums.st ;; publish-docs) url=${2:-}; [ -n "$url" ] || usage - need "$DOCS/book.pdf" "$DOCS/fabric.pdf" "$DOCS/vol1.pdf" "$DOCS/vol2.pdf" "$DOCS/vol3.pdf" "$DOCS/api.pdf" + need "$DOCS/book.pdf" "$DOCS/fabric.pdf" "$DOCS/dictionary.pdf" "$DOCS/vol1.pdf" "$DOCS/vol2.pdf" "$DOCS/vol3.pdf" "$DOCS/api.pdf" deploy "$url" documentation "$DOCS/book.pdf" pdf book "$DOCS/fabric.pdf" pdf fabric \ + "$DOCS/dictionary.pdf" pdf dictionary \ "$DOCS/vol1.pdf" pdf vol1 "$DOCS/vol2.pdf" pdf vol2 "$DOCS/vol3.pdf" pdf vol3 \ "$DOCS/api.pdf" pdf api ;; diff --git a/v4/tools/mkdictionary.py b/v4/tools/mkdictionary.py index 7aa3fc6f..1ad21e6d 100644 --- a/v4/tools/mkdictionary.py +++ b/v4/tools/mkdictionary.py @@ -160,6 +160,9 @@ def main(): stack, desc = table.get(w, ("", "")) rel = defs.get(w, ("", "", ""))[0] cell = lambda x: x.replace("|", "\\|") + # a token with a quote in it is FORTH (." text" S" ABORT"): set as code, so its + # quotes print straight, not as typographic ones + desc = re.sub(r'(\S*"\S*)', lambda mm: "`" + mm.group(1) + "`", desc) f.write(f"| `{cell(w)}` | `{cell(stack)}` | {cell(desc)} | `{rel}` |\n") print(f"mkdictionary: {out}, {len(words)} words") return