Check the memory map against itself, not only against the code
The CosmOS README's Data row gave the system 0x0000-0x3FFF and a loaded application 0x2000 and above: two columns of one row that cannot both be true. Program was doubled to 0x3FFF when CosmOS outgrew its first map and that number was copied into the Data row as well, where the answer is 0x1FFF. docs.sh measured both segments against the CosmOS column and passed the table anyway, because it never read the column beside it. A number checked against the code and not against the number next to it is still unchecked, so it now reads both and compares them - and compares two further copies of the same fact that had gone stale on their own: the minimal application in the README, still based where applications lived before the doubling, and the map cosmos.asm opens with, which somebody reading the system reads before they read the README. Each of the three checks was confirmed by breaking the fact and watching it fail; the first reproduces exactly the text this commit removes. While in that header, the command list said five commands and CosmOS has eleven and a search path besides, and "dump is next" outlived the monitor.
This commit is contained in:
+55
-3
@@ -467,9 +467,12 @@ for name, text in (("the Programming Manual", pm), ("the Assembler Manual", am),
|
||||
# That is why this reads the numbers out of the table rather than being told them: the
|
||||
# table is the specification, and a table nothing checks is the thing that goes stale.
|
||||
readme = open("Programs/CosmOS/README.md").read()
|
||||
row = re.compile(r"\|\s*(Program|Data) Memory\s*\|\s*`0x0000` through `0x([0-9A-Fa-f]{4})`")
|
||||
limits = {kind: int(top, 16) + 1 for kind, top in row.findall(readme)}
|
||||
if len(limits) != 2:
|
||||
row = re.compile(r"\|\s*(Program|Data) Memory\s*\|\s*`0x0000` through `0x([0-9A-Fa-f]{4})`"
|
||||
r"\s*\|\s*`0x([0-9A-Fa-f]{4})` and above\s*\|")
|
||||
table = {kind: (int(top, 16) + 1, int(base, 16)) for kind, top, base in row.findall(readme)}
|
||||
limits = {kind: room for kind, (room, base) in table.items()}
|
||||
bases = {kind: base for kind, (room, base) in table.items()}
|
||||
if len(table) != 2:
|
||||
problems.append("the CosmOS README no longer states a memory map this can check")
|
||||
else:
|
||||
built = subprocess.run(["./Assembler", "-I", "Programs/CosmOS/Source",
|
||||
@@ -487,6 +490,55 @@ else:
|
||||
" reaches into the %d bytes an application is loaded at, and loading"
|
||||
" one will overwrite it" % (kind, used, room, used - room))
|
||||
|
||||
# ---- And the table against itself ----
|
||||
#
|
||||
# The check above reads the CosmOS column and never the one beside it, so it passed a
|
||||
# Data row that gave the system 0x0000-0x3FFF and an application 0x2000 and above -
|
||||
# two halves of one sentence contradicting each other in print. A number checked
|
||||
# against the code and not against the number next to it is still unchecked.
|
||||
for kind in ("Program", "Data"):
|
||||
room, base = table[kind]
|
||||
if base != room:
|
||||
problems.append(
|
||||
"the CosmOS README gives the system %s Memory up to 0x%04X and puts an"
|
||||
" application at 0x%04X - the two columns of that row disagree"
|
||||
% (kind, room - 1, base))
|
||||
|
||||
# ---- And the example under it ----
|
||||
#
|
||||
# The minimal application in the same section is what somebody copies, so it is the
|
||||
# part of the map most worth being right. It went stale across the doubling while the
|
||||
# table above it was corrected.
|
||||
example = re.search(r"```asm\n(.*?)```", readme, re.S)
|
||||
if not example:
|
||||
problems.append("the CosmOS README no longer shows a minimal application")
|
||||
else:
|
||||
shown = dict(zip(("Program", "Data"),
|
||||
re.findall(r"#Base 0x([0-9A-Fa-f]{4})", example.group(1))))
|
||||
for kind in ("Program", "Data"):
|
||||
if kind not in shown:
|
||||
problems.append("the minimal CosmOS application shows no %s #Base" % kind)
|
||||
elif int(shown[kind], 16) != bases[kind]:
|
||||
problems.append(
|
||||
"the minimal CosmOS application is based at 0x%s in %s Memory and the"
|
||||
" map above it says 0x%04X" % (shown[kind].upper(), kind, bases[kind]))
|
||||
|
||||
# ---- And the copy in the source ----
|
||||
#
|
||||
# cosmos.asm opens with the same map in its own words, because somebody reading the
|
||||
# system reads that before they read the README. Three copies of one fact, so all
|
||||
# three are compared.
|
||||
header = open("Programs/CosmOS/Source/cosmos.asm").read()[:4096]
|
||||
stated = dict(re.findall(
|
||||
r"(Program|Data) Memory\s+0x0000 - 0x([0-9A-Fa-f]{4})\s+the system", header))
|
||||
for kind in ("Program", "Data"):
|
||||
if kind not in stated:
|
||||
problems.append("cosmos.asm no longer opens with a %s Memory map" % kind)
|
||||
elif int(stated[kind], 16) + 1 != limits[kind]:
|
||||
problems.append(
|
||||
"cosmos.asm says the system keeps below 0x%s in %s Memory and the CosmOS"
|
||||
" README says 0x%04X" % (stated[kind].upper(), kind, limits[kind] - 1))
|
||||
|
||||
if problems:
|
||||
print("The manuals and the code disagree:")
|
||||
for p in problems:
|
||||
|
||||
Reference in New Issue
Block a user