if (is_stmt<slice_expression>(this->property)) {
auto s = cast_stmt<slice_expression>(this->property);
- value start_val = s->start_expr ? s->start_expr->execute(ctx) : mk_val<value_int>(0);
- value stop_val = s->stop_expr ? s->stop_expr->execute(ctx) : mk_val<value_int>(arr_size);
value step_val = s->step_expr ? s->step_expr->execute(ctx) : mk_val<value_int>(1);
+ value start_val = s->start_expr ? s->start_expr->execute(ctx) : (step_val->as_int() < 0 ? mk_val<value_int>(arr_size - 1) : mk_val<value_int>(0));
+ value stop_val = s->stop_expr ? s->stop_expr->execute(ctx) : (step_val->as_int() < 0 ? mk_val<value_int>(-1) : mk_val<value_int>(arr_size));
// translate to function call: obj.slice(start, stop, step)
JJ_DEBUG("Member expression is a slice: start %s, stop %s, step %s",
stop_val = std::min(stop_val, len);
}
} else {
- start_val = len - 1;
+ start_val = start;
if (start_val < 0) {
- start_val = std::max(len + start_val, (int64_t)-1);
+ start_val = std::max(len + start_val, (int64_t)0);
} else {
start_val = std::min(start_val, len - 1);
}
- stop_val = -1;
+ stop_val = stop;
if (stop_val < -1) {
stop_val = std::max(len + stop_val, (int64_t)-1);
} else {
"('c', 'b', 'a')"
);
+ test_template(t, "string slice negative step",
+ "{{ 'abcdef'[::-2] }}",
+ json::object(),
+ "fdb"
+ );
+
+ test_template(t, "string slice negative start and step",
+ "{{ 'abcdef'[-1:1:-1] }}",
+ json::object(),
+ "fedc"
+ );
+
+ test_template(t, "string slice negative start, stop and step",
+ "{{ 'abcdef'[-1:-5:-1] }}",
+ json::object(),
+ "fedc"
+ );
+
test_template(t, "arithmetic",
"{{ (a + b) * c }}",
{{"a", 2}, {"b", 3}, {"c", 4}},