diff options
| author | Jouke Witteveen <j.witteveen@gmail.com> | 2025-07-24 14:17:55 +0200 |
|---|---|---|
| committer | Jussi Pakkanen <jussi.pakkanen@mailbox.org> | 2025-11-28 12:41:01 +0200 |
| commit | 0fb9c5a6839205cc32c2632dd20f723f00dc165b (patch) | |
| tree | 0dab116976dbf400ed9f95860ac683435466d321 | |
| parent | 5e399434f2c3bb791f0c16f01fa85680c3f90fb7 (diff) | |
| download | meson-0fb9c5a6839205cc32c2632dd20f723f00dc165b.tar.gz | |
interpreter: Add a slice() method to arrays
This can come in handy for instance when a custom target creates both
headers and sources. Slicing the output of a `to_list()` call provides
convenient access to just the headers or just the sources.
| -rw-r--r-- | docs/markdown/snippets/array-slice.md | 3 | ||||
| -rw-r--r-- | docs/yaml/elementary/array.yml | 27 | ||||
| -rw-r--r-- | mesonbuild/interpreter/primitives/array.py | 14 | ||||
| -rw-r--r-- | test cases/common/56 array methods/meson.build | 10 |
4 files changed, 54 insertions, 0 deletions
diff --git a/docs/markdown/snippets/array-slice.md b/docs/markdown/snippets/array-slice.md new file mode 100644 index 000000000..8b503bce9 --- /dev/null +++ b/docs/markdown/snippets/array-slice.md @@ -0,0 +1,3 @@ +## Array `.slice()` method + +Arrays now have a `.slice()` method which allows for subsetting of arrays. diff --git a/docs/yaml/elementary/array.yml b/docs/yaml/elementary/array.yml index 7d0480a04..7183d1aff 100644 --- a/docs/yaml/elementary/array.yml +++ b/docs/yaml/elementary/array.yml @@ -37,6 +37,33 @@ methods: type: any description: Fallback value that is returned if the index is out of range. +- name: slice + returns: array[any] + since: 1.10.0 + description: | + Return a selection of the elements of the array starting at index `start` + and continuing with `step` size jumps until `stop`. Negative indices count + from the back of the array. The step size cannot be zero, but may be + negative. If it is negative, `start` and `stop` default to the end and + beginning of the array, respectively. If `step` is positive, `start` + defaults to 0 and `stop` defaults to the length of the array. Either both + or none of `start` and `stop` must be provided to prevent ambiguity. + + optargs: + start: + type: int + description: The lower bound of the slice + + stop: + type: int + description: The upper bound of the slice + + kwargs: + step: + type: int + default: 1 + description: The step size + - name: length returns: int description: Returns the current size of the array. diff --git a/mesonbuild/interpreter/primitives/array.py b/mesonbuild/interpreter/primitives/array.py index d0a244179..86c1ce207 100644 --- a/mesonbuild/interpreter/primitives/array.py +++ b/mesonbuild/interpreter/primitives/array.py @@ -7,12 +7,14 @@ import typing as T from ...interpreterbase import ( InterpreterObject, IterableObject, + KwargInfo, MesonOperator, ObjectHolder, typed_operator, noKwargs, noPosargs, noArgsFlattening, + typed_kwargs, typed_pos_args, FeatureNew, @@ -80,6 +82,18 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject): return args[1] return self.held_object[index] + @FeatureNew('array.slice', '1.10.0') + @typed_kwargs('array.slice', KwargInfo('step', int, default=1)) + @typed_pos_args('array.slice', optargs=[int, int]) + @InterpreterObject.method('slice') + def slice_method(self, args: T.Tuple[T.Optional[int], T.Optional[int]], kwargs: T.Dict[str, int]) -> TYPE_var: + start, stop = args + if start is not None and stop is None: + raise InvalidArguments('Providing only one positional slice argument is ambiguous.') + if kwargs['step'] == 0: + raise InvalidArguments('Slice step cannot be zero.') + return self.held_object[start:stop:kwargs['step']] + @typed_operator(MesonOperator.PLUS, object) @InterpreterObject.operator(MesonOperator.PLUS) def op_plus(self, other: TYPE_var) -> T.List[TYPE_var]: diff --git a/test cases/common/56 array methods/meson.build b/test cases/common/56 array methods/meson.build index 3707775ec..3cc1067b9 100644 --- a/test cases/common/56 array methods/meson.build +++ b/test cases/common/56 array methods/meson.build @@ -69,6 +69,16 @@ if not combined.contains('ghi') error('Combined claims not to contain ghi.') endif +# test array slicing +assert(['a', 'b', 'c'].slice() == ['a', 'b', 'c']) +assert(['a', 'b', 'c'].slice(step : 2) == ['a', 'c']) +assert(['a', 'b', 'c'].slice(step : -1) == ['c', 'b', 'a']) +assert(['a', 'b', 'c'].slice(step : -2) == ['c', 'a']) +assert(['a', 'b', 'c'].slice(1, 2) == ['b']) +assert(['a', 'b', 'c'].slice(2, -2) == []) +assert(['a', 'b', 'c'].slice(-9876543, 2) == ['a', 'b']) +assert(['a', 'b', 'c', 'd', 'e'].slice(1, 12, step : 2) == ['b', 'd']) + # test array flattening x = ['a', ['b'], [[[[[[['c'], 'd']]], 'e']]]] assert(x.length() == 3) |
