Skip to content

Commit f81d7ac

Browse files
Record what the last three fixes taught (#707)
Three additions, each from something that went wrong and was caught: Check the convention against the other systems rather than reasoning about it from memory. mod took the sign of the dividend until review pointed out that no mathematician means that by mod, and SymPy, Mathematica and Maxima all disagreed with it. Say "no answer" with null, not with an unevaluated node of the expression you were asked about. The latter looks honest and is a cycle that overflows the stack, which kills the process rather than raising anything catchable. Stringize has a contract -- parsing what it prints gives back what it printed -- and four node kinds broke it silently, one of them turning 64 into 512. Latexise is under no such obligation. Points at the new syntax reference, which is where what the parser accepts is now written down.
1 parent d825b03 commit f81d7ac

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

‎AGENTS.md‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ the library is wrong — even where the library's way is defensible in isolation
1717
thing; the inverse of `sinh` is an *area*, not an arc, so it is `arsinh` (#687). Follow the notation
1818
of the people who use the subject, not the notation that was easiest to parse.
1919

20+
When you have to choose a convention, **check what the other systems answer** — SymPy,
21+
Mathematica, Maxima — and match the mathematics rather than the language you are writing in.
22+
`mod` takes the sign of the divisor because that is what a mathematician means by mod and what
23+
all three of those give; C's `%` truncates, but C's `%` is an operation on machine integers.
24+
Check it, do not reason about it from memory: this exact case was got wrong first time round.
25+
2026
**Consistency is the point.** [#497](https://github.com/asc-community/AngouriMath/issues/497), the
2127
2.0 paper, names inconsistency as the central defect: *"one may find it inconsistent in a lot of
2228
places in API, behaviour, and internal structure of code."* A rule that fires for `sin` but not
@@ -41,6 +47,26 @@ does not exist. Returning an unevaluated node is honest.
4147
So, in order of preference: right answer > no answer > slow answer > wrong answer. A wrong answer is
4248
worse than a hang, because a hang is visible.
4349

50+
Say "no answer" by returning **`null`**, not by handing back an unevaluated node of the expression
51+
you were asked about. `Limitf(this, ...)` looks like the honest answer and is in fact a cycle: the
52+
caller evaluates it to compare, evaluating computes the limit, and computing arrives back where it
53+
started. That overflows the stack, which kills the process rather than raising anything catchable.
54+
`null` reads the same to the caller and terminates.
55+
56+
## Output has a contract too
57+
58+
**Parsing what `Stringize` prints must give back the expression it printed.** Anything else makes
59+
the printed form a lie, and a silent one, since a wrong reading is usually still a valid
60+
expression: `(2^3)^2` printed as `2^3^2` is 512 where the expression is 64, and a piecewise
61+
printed with `if` came back as a product with `if` read as an undeclared variable. If a node's
62+
usual notation is not in the grammar, print the function call the parser does have.
63+
`StringizeRoundTripTest` is where that is enforced; add to it when you add a node.
64+
65+
`Latexise` is under no such obligation — nothing parses LaTeX.
66+
67+
The syntax the parser accepts is written down in `Sources/AngouriMath/Docs/Usage/Syntax.md`.
68+
Keep it true when you change the grammar.
69+
4470
## Verify the mathematics, not the string
4571

4672
Never assert on printed form unless the printed form *is* the bug. Assert the property:

0 commit comments

Comments
 (0)