From c2147d2282310379363a759761dfb6b53802990f Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Wed, 7 Oct 2026 02:21:37 +0200 Subject: [PATCH] Answer prose round 1 and product-owner round 1: CheckIdentifier's doc counts a bound name, FuncCall and the grammar doc say PathRead and identifiers, the Layout's list.go, name.go and data-import rows read on one pass, the locality row says a postort with no street is dropped, geo.py's docs name what they take, well_cased says what it drops, and item 61 names the next steps to share --- README.md | 8 ++++---- data-import/geo-se.py | 4 +++- data-import/geo.py | 9 +++++---- datatype.go | 4 ++-- internal/grammar/format.go | 4 ++-- internal/grammar/identifier.go | 7 +++---- path.go | 8 ++++---- todo.md | 2 +- 8 files changed, 24 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 6c86fd2..1435e08 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ neighbouring one. |-------|----------|----------|--------| | `region` | län, by code or name | state, by USPS abbreviation or name; `code` is the FIPS code | population | | `municipality` | kommun, by code or name | county, by FIPS code or name | population | -| `locality` | postort, by name; [`geo-se.py`](data-import/geo-se.py)'s `localities` picks which ship | incorporated place of 25,000 people or more with a postal code of its own, by GEOID or name; Hawaii has none | tätort population, the kommun's where the postort names it, else 200; place population | +| `locality` | postort, by name; [`geo-se.py`](data-import/geo-se.py)'s `localities` picks the candidates, and one with no street is dropped | incorporated place of 25,000 people or more with a postal code of its own, by GEOID or name; Hawaii has none | tätort population, the kommun's where the postort names it, else 200; place population | | `postal-code` | postnummer with street delivery, by code | ZCTA, by code | one; address ranges | | `street` | gatunamn, the ten with most road segments per postort | street name, the ten with most address ranges per place | segments; address ranges | @@ -960,12 +960,12 @@ Where the project is heading; the sections before Audience document what ships t ``` doc.go the package doc, and the vocabulary the package is written in fejkdata.go Generator, New, options, List -list.go the paths List advertises, every one a node reaches a direct descent at a time +list.go the paths List advertises: direct descents only shipped.go the embedded data set, and loading a shipped category on the first call reaching it shippedindex.go the index of shipped categories, generated from data/ node.go the node model and JSON -> node compilation table.go tables: their options, format and cells, the link to the parent beside them, and how a path passes and draws a table -name.go names: {x as n} bindings, the scopes they live in, the reads they answer, and what each resolves to at load: its target, its reads and the keys they address +name.go names: {x as n} bindings, the scopes they live in, the reads they answer, and each binding's target and the keys its reads address namefence.go the load fences over names pick.go a render's named picks: the frame of each name scope rendering, the memo a pick keeps, and the reads kept under it env.go renderEnv: what a render reads names and rows through, the stack of frames it renders in, and the frames a read opens and finds @@ -994,7 +994,7 @@ internal/invariant/ the one phrase every package panics with when an invariant b internal/proven/ what a proof knows of a value, and the bounds a calc takes from its operands internal/rows/ a table's rows: the TSV, the options proved over it, the links between tables, row selection and draws, and the pin set one path or one named pick fixes data/ shipped data (JSON, and a TSV per table), embedded at build: locale folders, geo, misc -data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md) +data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md), and the modules they share docs/ the decision log, the register research behind the shipped data, and the survey of other libraries release-tooling/ the release CI publishes from the changelog heading testdata/ the pinned shipped shape (see Versioning) diff --git a/data-import/geo-se.py b/data-import/geo-se.py index c3780e2..c5f1b57 100644 --- a/data-import/geo-se.py +++ b/data-import/geo-se.py @@ -137,6 +137,8 @@ def population_of(name, municipality, tatorter, municipalities, population): def well_cased(name): + """Whether each word of name is capitalised: GeoNames also spells some postorter, such as STOCKHOLM and örebro, in + capitals or lower case.""" return all(part[:1].isupper() and (len(part) == 1 or not part.isupper()) for part in re.split(r"[ -]", name)) @@ -155,7 +157,7 @@ def localities(codes, tatorter, municipalities, population): continue lat, lon = point out[name] = {"name": name, "municipality": municipality, "population": population_of(name, municipality, tatorter, municipalities, population), "lat": f"{lat:.4f}", "lon": f"{lon:.4f}", "codes": kept} - print(f"municipality by {dict(how)}; {len(by_locality) - len(out)} postorter dropped", file=sys.stderr) + print(f"municipality by {dict(how)}; {len(by_locality) - len(out)} postorter dropped before streets", file=sys.stderr) return out diff --git a/data-import/geo.py b/data-import/geo.py index fc25f92..14c153d 100644 --- a/data-import/geo.py +++ b/data-import/geo.py @@ -10,7 +10,8 @@ CACHE = Path(__file__).resolve().parent / "cache" def parser(doc, country, **own): - """The options every country's import takes and the script's own, keyed by name with "_" for "-", in name order.""" + """A parser for the options every country's import takes, plus the script's own: each keyword names one option, with + "_" standing for "-".""" options = {"cache": {"default": str(CACHE)}, "out": {"default": str(DATA / country)}, "streets_per_locality": {"type": int, "default": 10}, **own} p = argparse.ArgumentParser(description=doc.splitlines()[0]) for name in sorted(options): @@ -63,8 +64,8 @@ class Nearest: def top_streets(count, per_locality, column): - """Per locality, the per_locality street names counted most in count, keyed (locality, name), ties by name; each - row holds its count in column.""" + """count maps (locality, street name) to a count. Per locality, the per_locality names counted most, ties broken by + name, each row holding its count under column.""" of = collections.defaultdict(list) for (locality, name), n in count.items(): of[locality].append((n, name)) @@ -72,7 +73,7 @@ def top_streets(count, per_locality, column): def with_streets(places, named): - """The places named holds streets for; each other one is logged as dropped.""" + """The places that named holds streets for; logs each other place as dropped.""" for key, place in places.items(): if key not in named: label = key if key == place["name"] else f"{key} {place['name']}" diff --git a/datatype.go b/datatype.go index fcd549f..39cb605 100644 --- a/datatype.go +++ b/datatype.go @@ -161,8 +161,8 @@ func disagreement(a *template, da DataType, b *template, db DataType) error { return message(c) } -// clash is two items of one column holding different datatypes: fix, the item to fix, beside -// other, which holds want; held says what each holds. +// clash is two items of one column holding different datatypes: other holds want; held says +// what each holds. type clash struct { fix, other *template want DataType diff --git a/internal/grammar/format.go b/internal/grammar/format.go index cee6da0..2306795 100644 --- a/internal/grammar/format.go +++ b/internal/grammar/format.go @@ -1,5 +1,5 @@ // Package grammar is how the template language is written: format tokens, paths and -// their selectors, reference sigils, names, calc expressions, and whether an argument is a +// their selectors, reference sigils, identifiers, calc expressions, and whether an argument is a // template or a path. It reads strings only. package grammar @@ -122,7 +122,7 @@ func ParseFormat(format string) ([]Token, error) { } // FuncCall splits a "{token}" body shaped name(args) into its parts; ok is false -// for a name-read body. A '(' without a trailing ')' yields ok=false. +// for a PathRead body. A '(' without a trailing ')' yields ok=false. func FuncCall(body string) (name string, args []string, ok bool) { lp := indexOutside(body, '(') if lp < 0 || !strings.HasSuffix(body, ")") { diff --git a/internal/grammar/identifier.go b/internal/grammar/identifier.go index 48cfb53..dc2c5ae 100644 --- a/internal/grammar/identifier.go +++ b/internal/grammar/identifier.go @@ -8,14 +8,13 @@ import ( // reservedInIdentifier is what an identifier may not contain: a dot // separates the segments of a path, '|' the arms of a token, '(' opens a function // call, braces delimit the token, '/' starts a reference, and brackets and a quote -// open a JSON value. An identifier carrying one is rejected where it is authored rather -// than where it would be unreachable. +// open a JSON value. An identifier carrying one is rejected where it is authored. const reservedInIdentifier = ".|({}/[]\"" var reservedList = strings.Join(strings.Split(reservedInIdentifier, ""), " ") -// CheckIdentifier rejects an identifier, the name of a folder, category, field or column, that the -// dot path, {token} and JSON grammars cannot spell, or a struct tag cannot read. +// An identifier names a folder, category, field, column or bound name. CheckIdentifier rejects one +// that the dot path, {token} and JSON grammars cannot spell, or that a struct tag cannot read. func CheckIdentifier(name string) error { if name == "" { return fmt.Errorf("%q is empty, which is not a path segment, so List never offers it", name) diff --git a/path.go b/path.go index 46c46a3..9e70a19 100644 --- a/path.go +++ b/path.go @@ -65,10 +65,10 @@ const ( stepParent // up to the table's parent, at the row its own row links to ) -// compiledPath is a path proved to reach a node whichever way the draws go: every variant of a -// choice carries the rest of it, and is walked, a selector names a row inside the -// rows selected before it, and no level read carries a repeat. It holds the steps -// a draw takes, and every leaf the path may render; level names the head in its errors. +// compiledPath walks a path and proves it reaches a node whichever way the draws go: every +// variant of a choice carries the rest of it, and is walked, a selector names a row inside the +// rows selected before it, and no level read carries a repeat. Once run, it holds the steps a +// draw takes, and every leaf the path may render; level names the head in its errors. type compiledPath struct { pins pinSet level string diff --git a/todo.md b/todo.md index c53dd5d..fc6839d 100644 --- a/todo.md +++ b/todo.md @@ -171,7 +171,7 @@ Needs item 77. Ten streets per place crowds 500 Stockholm customers onto ten str ### 61. Add a locale, with its `geo/` tree, for each of the ten most-spoken languages and each Nordic country. -Pick the ten from a published ranking of languages by total speakers, such as Ethnologue's, each in the country where it has the most speakers, and record the ranking in the decision that names them. The Nordic ones are sv_SE (shipped), nb_NO, da_DK, fi_FI and is_IS. Each locale carries goal 2.2's categories, and its `address` reads its country's `geo/` tree by reference. `rows.Pins` holds eight pins inline, sized for a five-deep geo tree; a deeper tree needs more to keep a render off the heap. +Pick the ten from a published ranking of languages by total speakers, such as Ethnologue's, each in the country where it has the most speakers, and record the ranking in the decision that names them. The Nordic ones are sv_SE (shipped), nb_NO, da_DK, fi_FI and is_IS. A second country reading GeoNames' postal codes moves `geonames()` from `geo-se.py`, and the nearest-centroid street assignment in its `streets()`, into `geo.py`. Each locale carries goal 2.2's categories, and its `address` reads its country's `geo/` tree by reference. `rows.Pins` holds eight pins inline, sized for a five-deep geo tree; a deeper tree needs more to keep a render off the heap. ### 16. Add the remaining locale categories: company, phone, finance, vehicle, words.