Skip to content

Let i be the loop variable when it is named as one (#976) - #981

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
fix/sum-index-i
Aug 17, 2026
Merged

Let i be the loop variable when it is named as one (#976)#981
Rafael-SOWNet merged 1 commit into
masterfrom
fix/sum-index-i

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Collaborator

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.

i as the loop variable

sum(i, i, 1, 10) summed nothing. i is the imaginary unit, and that is decided in the lexerNUMBER: ... | '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.

before after
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, 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 every i in the summand stayed the imaginary unit, nothing would substitute, and sum(i, i, 1, 10) would answer 10i — 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:

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

Why this is in MathS, not the grammar

My first attempt was a grammar action. It fixed "sum(i, i, 1, 10)".ToEntity() and left MathS.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 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.

`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>
@Rafael-SOWNet
Rafael-SOWNet merged commit 4b6fbc4 into master Aug 17, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant