| 50 | } |
| 51 | |
| 52 | func TestOptimize_sum_range_with_predicate(t *testing.T) { |
| 53 | tests := []struct { |
| 54 | expr string |
| 55 | want int |
| 56 | }{ |
| 57 | // # (identity) - same as sum(m..n) |
| 58 | {`sum(1..10, #)`, 55}, |
| 59 | {`sum(1..100, #)`, 5050}, |
| 60 | |
| 61 | // # * k (multiply by constant) |
| 62 | {`sum(1..10, # * 2)`, 110}, // 2 * 55 |
| 63 | {`sum(1..100, # * 2)`, 10100}, // 2 * 5050 |
| 64 | {`sum(1..10, # * 0)`, 0}, |
| 65 | {`sum(1..10, # * 1)`, 55}, |
| 66 | |
| 67 | // k * # (multiply by constant, reversed) |
| 68 | {`sum(1..10, 2 * #)`, 110}, |
| 69 | {`sum(1..100, 3 * #)`, 15150}, // 3 * 5050 |
| 70 | |
| 71 | // # + k (add constant to each element) |
| 72 | {`sum(1..10, # + 1)`, 65}, // 55 + 10*1 |
| 73 | {`sum(1..100, # + 1)`, 5150}, // 5050 + 100*1 |
| 74 | {`sum(1..10, # + 0)`, 55}, |
| 75 | {`sum(1..10, # + 10)`, 155}, // 55 + 10*10 |
| 76 | |
| 77 | // k + # (add constant, reversed) |
| 78 | {`sum(1..10, 1 + #)`, 65}, |
| 79 | {`sum(1..100, 5 + #)`, 5550}, // 5050 + 100*5 |
| 80 | |
| 81 | // # - k (subtract constant from each element) |
| 82 | {`sum(1..10, # - 1)`, 45}, // 55 - 10*1 |
| 83 | {`sum(1..100, # - 1)`, 4950}, // 5050 - 100*1 |
| 84 | {`sum(1..10, # - 0)`, 55}, |
| 85 | |
| 86 | // k - # (constant minus each element) |
| 87 | {`sum(1..10, 10 - #)`, 45}, // 10*10 - 55 |
| 88 | {`sum(1..10, 0 - #)`, -55}, // 10*0 - 55 |
| 89 | } |
| 90 | |
| 91 | for _, tt := range tests { |
| 92 | t.Run(tt.expr, func(t *testing.T) { |
| 93 | program, err := expr.Compile(tt.expr) |
| 94 | require.NoError(t, err) |
| 95 | |
| 96 | output, err := expr.Run(program, nil) |
| 97 | require.NoError(t, err) |
| 98 | assert.Equal(t, tt.want, output) |
| 99 | }) |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | func TestOptimize_sum_range_with_predicate_ast(t *testing.T) { |
| 104 | // Verify that sum(1..10, # * 2) is optimized to a constant |