Skip to content

fix: add the start argument of sum(xs, start) - #60

Merged
ylluminate merged 1 commit into
vlang:masterfrom
ylluminate:fix-sum-start
Nov 13, 2026
Merged

ylluminate merged 1 commit into
vlang:masterfrom
ylluminate:fix-sum-start

Conversation

@ylluminate

Copy link
Copy Markdown
Contributor

sum(xs, 10) with xs = [1, 2, 3] printed 6 instead of 16, because visit_sum emitted arrays.sum(xs) or { 0 } and never read the start.

The start is now used when it's made only of names, constants and operators, as the second positional argument or as start=, in two ways. When py2v infers the start as an int or i64 and the elements as int, it emits (arrays.sum(xs) or { 0 }) + 10, since the order doesn't matter for ints. When a float is involved (the start is an f64, or it's an int or i64 over elements inferred as f64), it emits a fold seeded with the start, arrays.fold(fs, f64(10), |acc, x| acc + x), which adds in the order Python does, start first: sum([-1.0, -1e16], 2.0) rounds to something else when the start is added to a finished total. So with fs = [1.5, 2.5], sum(fs, 10) gives 14.0, sum(xs, 0.5) gives 6.5 and sum(xs, 0.0) gives 6.0. A start with a leading minus is typed by its operand, so sum(xs, -1) is handled.

Any other start is still dropped, as on master: one that py2v infers as another type or not at all (a u8 or an f32, for example); an integer start over elements py2v doesn't infer as int or f64, such as a generator expression or a list comprehension; and one with anything else in it, such as a call (sum(xs, len(ys))) or an index (sum(xs, ys[0])). Calls are left out on purpose: when the call changes the list, the emitted code doesn't see what Python sees (with a grow that appends -100 to xs and returns 100, sum(xs, grow(xs)) is 6 in Python and came out as 106 when I let calls through).

A sum of floats still adds one value at a time where Python compensates for rounding: ten 0.1 sum to 0.9999999999999999 on master and here, with no start or with a 0.0 start, where Python prints 1.0. And one start that is handled still prints the wrong thing: an int start over an empty float list, sum(ef, 10) with ef: list[float] = [], prints 10.0 where Python prints 10.

Adding the start can also uncover other things py2v gets wrong that the dropped start used to hide. These were found so far; each one turns a program that is right on master into one that is not:

  • A float start over an int list makes the total a float, and py2v treats it as an int in several places: %, // and ** on it no longer build (r = sum(xs, 0.5) and then r // 2; r = sum(fs) and then r // 2 fails the same way on master), neither does assigning it to a variable that held an int (t = 0 and then t += sum(xs, 0.5)) or returning it from a function annotated -> int, and '%d' % sum(xs, 0.5) prints 6.5 where Python prints 6.
  • A total of negative zero loses its sign with a -0.0 start (fs = [-1.5 * 0], then sum(fs, -0.0) prints 0.0), because py2v emits -0.0 as -0.
  • A start that names a module-level variable (base = 0 at the top, sum(xs, base) in main) no longer builds, because py2v declares module-level variables inside fn main() where other functions can't see them.
  • py2v types a list by its first element, so xs = [1, 1e16] counts as ints while V holds floats, and sum(xs, -2) adds the start after the float total: it prints 9.999999999999998e+15 where Python and master print 1e+16.

Test plan

  • tests/cases/sum_start.py with its expected V covers the handled forms: int and float starts over int and float lists, a variable start, range(), start=, a negative start and base - step. v tests/run_tests.vsh: 173 passed, 0 failed (172 before, plus the new case).
  • 540 generated programs (9 iterables x 20 starts x 3 uses) and 13 handwritten ones compared with CPython's output, built with plain v run (V ec510e2, Python 3.15.2, macOS arm64): 324 that were wrong now match, and none that matched before stops matching. Of the generated programs whose V changed, the 36 that are still wrong are the empty float list described above.

@ylluminate
ylluminate merged commit 44a519b into vlang:master Nov 13, 2026
2 checks passed
@ylluminate
ylluminate deleted the fix-sum-start branch November 13, 2026 08:44
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