Let i be the loop variable when it is named as one (#976) - #981
Merged
Conversation
`sum(i, i, 1, 10)` summed nothing. `i` is the imaginary unit, and that is decided in the lexer -- `NUMBER: ... | 'i'` -- so it never reaches the rule that makes variables and cannot be one anywhere in the language. The index arrived as a number, the operator had no variable to bind, and the whole thing stayed unevaluated. #966 documented that as a trap; Happypig375 asked for it not to be one. sum(i, i, 1, 10) unevaluated -> 55 product(i, i, 1, 5) unevaluated -> 120 sum(i ^ 2, i, 1, 4) unevaluated -> 30 Naming i as the index is a statement about the whole operator, so it is honoured through the summand and the bounds and not only in the index position. Doing it there alone would be worse than leaving it alone: the index would become a variable while every i in the summand stayed the imaginary unit, nothing would substitute, and sum(i, i, 1, 10) would answer 10i -- a wrong answer in place of an unevaluated one. And only inside the operator that declares it. These are unchanged, and they are what makes the above a fix rather than a new defect: sum(i * k, k, 1, 3) 6i sum(k + i, k, 1, 2) 3 + 2i sum(i, i, 1, 3) + i 6 + i i * i -1 sqrt(-1) i In MathS.Sum and MathS.Product rather than in the grammar. The first attempt was a grammar action, which fixed `"sum(i, i, 1, 10)".ToEntity()` and left `MathS.Sum("i", "i", 1, 10)` broken -- one library with two answers, since the string conversion is the only thing the parser sees. Putting it at the factory covers both, and leaves the parser untouched, so there is no regeneration and nothing for the grammar-drift check from #965 to catch. The class remark on SummationProductTest taught the trap and now records that it is gone. The test that pinned the old answer is replaced by cases for both halves -- the index being read, and i still being the imaginary unit everywhere else. Suite 7318 passed, 0 failed, 14 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Addresses the first half of #976. The second half is answered in a comment below rather than implemented, with the references you asked me to check.
ias the loop variablesum(i, i, 1, 10)summed nothing.iis the imaginary unit, and that is decided in the lexer —NUMBER: ... | 'i'— so it never reaches the rule that makes variables and cannot be one anywhere in the language. The index arrived as a number, the operator had no variable to bind, and the whole expression stayed unevaluated. #966 documented that as a trap; you asked for it not to be one.sum(i, i, 1, 10)product(i, i, 1, 5)sum(i ^ 2, i, 1, 4)Naming
ias the index is a statement about the whole operator, so it is honoured through the summand and the bounds, not only in the index position. Doing it there alone would have been worse than leaving it broken: the index would become a variable while everyiin the summand stayed the imaginary unit, nothing would substitute, andsum(i, i, 1, 10)would answer10i— a wrong answer replacing an unevaluated one.And only inside the operator that declares it. These are unchanged, and they are what make the above a fix rather than a new defect:
Why this is in
MathS, not the grammarMy first attempt was a grammar action. It fixed
"sum(i, i, 1, 10)".ToEntity()and leftMathS.Sum("i", "i", 1, 10)broken — one library with two answers, since the implicit string conversion is the only thing that goes through the parser. Putting it at the factory covers both paths, and leaves the parser completely untouched, so there is no regeneration and nothing for #965's grammar-drift check to catch.Tests
The class remark on
SummationProductTesttaught the trap and now records that it is gone. The test that pinned the old answer is replaced by cases for both halves — the index being read, andistill being the imaginary unit everywhere else.Suite 7318 passed, 0 failed, 14 skipped.