#pragma once #include "irrt_utils.hpp" #include "irrt_typedefs.hpp" namespace { // A proper slice in IRRT, all negative indices have be resolved to absolute values. template struct Slice { T start; T stop; T step; }; template T resolve_index_in_length(T length, T index) { nac3_assert(length >= 0); if (index < 0) { // Remember that index is negative, so do a plus here return max(length + index, 0); } else { return min(length, index); } } // NOTE: using a bitfield for the `*_defined` is better, at the // cost of a more annoying implementation in nac3core inkwell template struct UserSlice { uint8_t start_defined; T start; uint8_t stop_defined; T stop; uint8_t step_defined; T step; // Like Python's `slice(start, stop, step).indices(length)` Slice indices(T length) { // NOTE: This function implements Python's `slice.indices` *FAITHFULLY*. // SEE: https://github.com/python/cpython/blob/f62161837e68c1c77961435f1b954412dd5c2b65/Objects/sliceobject.c#L546 nac3_assert(length >= 0); nac3_assert(!step_defined || step != 0); // step_defined -> step != 0; step cannot be zero if specified by user Slice result; result.step = step_defined ? step : 1; bool step_is_negative = result.step < 0; if (start_defined) { result.start = resolve_index_in_length(length, start); } else { result.start = step_is_negative ? length - 1 : 0; } if (stop_defined) { result.stop = resolve_index_in_length(length, stop); } else { result.stop = step_is_negative ? -1 : length; } return result; } }; }