Repository navigation
fix: add the start argument of sum(xs, start) - #60
Merged
Merged
Conversation
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.
sum(xs, 10)withxs = [1, 2, 3]printed 6 instead of 16, becausevisit_sumemittedarrays.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 anintori64and the elements asint, it emits(arrays.sum(xs) or { 0 }) + 10, since the order doesn't matter for ints. When a float is involved (the start is anf64, or it's anintori64over elements inferred asf64), 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 withfs = [1.5, 2.5],sum(fs, 10)gives14.0,sum(xs, 0.5)gives6.5andsum(xs, 0.0)gives6.0. A start with a leading minus is typed by its operand, sosum(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
u8or anf32, for example); an integer start over elements py2v doesn't infer asintorf64, 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 agrowthat appends -100 toxsand 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.1sum to0.9999999999999999on master and here, with no start or with a0.0start, where Python prints1.0. And one start that is handled still prints the wrong thing: an int start over an empty float list,sum(ef, 10)withef: list[float] = [], prints10.0where Python prints10.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:
%,//and**on it no longer build (r = sum(xs, 0.5)and thenr // 2;r = sum(fs)and thenr // 2fails the same way on master), neither does assigning it to a variable that held an int (t = 0and thent += sum(xs, 0.5)) or returning it from a function annotated-> int, and'%d' % sum(xs, 0.5)prints6.5where Python prints6.-0.0start (fs = [-1.5 * 0], thensum(fs, -0.0)prints0.0), because py2v emits-0.0as-0.base = 0at the top,sum(xs, base)inmain) no longer builds, because py2v declares module-level variables insidefn main()where other functions can't see them.xs = [1, 1e16]counts as ints while V holds floats, andsum(xs, -2)adds the start after the float total: it prints9.999999999999998e+15where Python and master print1e+16.Test plan
tests/cases/sum_start.pywith its expected V covers the handled forms: int and float starts over int and float lists, a variable start,range(),start=, a negative start andbase - step.v tests/run_tests.vsh: 173 passed, 0 failed (172 before, plus the new case).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.