diff options
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/ast/interpreter.py | 1 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 26 | ||||
-rw-r--r-- | mesonbuild/interpreterbase.py | 16 |
3 files changed, 40 insertions, 3 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 98d141d..71c7f47 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -128,6 +128,7 @@ class AstInterpreter(interpreterbase.InterpreterBase): 'subdir_done': self.func_do_nothing, 'alias_target': self.func_do_nothing, 'summary': self.func_do_nothing, + 'range': self.func_do_nothing, }) def func_do_nothing(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> bool: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index d554cce..364cf70 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -30,7 +30,7 @@ from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, str from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler, disablerIfNotFound from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs -from .interpreterbase import ObjectHolder, MesonVersionString +from .interpreterbase import ObjectHolder, MesonVersionString, RangeHolder from .interpreterbase import TYPE_var, TYPE_nkwargs from .modules import ModuleReturnValue, ModuleObject, ModuleState from .cmake import CMakeInterpreter @@ -2509,7 +2509,8 @@ class Interpreter(InterpreterBase): 'static_library': self.func_static_lib, 'both_libraries': self.func_both_lib, 'test': self.func_test, - 'vcs_tag': self.func_vcs_tag + 'vcs_tag': self.func_vcs_tag, + 'range': self.func_range, }) if 'MESON_UNIT_TEST' in os.environ: self.funcs.update({'exception': self.func_exception}) @@ -5033,3 +5034,24 @@ This will become a hard error in the future.''', location=self.current_node) raise InvalidCode('Is_disabler takes one argument.') varname = args[0] return isinstance(varname, Disabler) + + @noKwargs + @FeatureNew('range', '0.58.0') + @typed_pos_args('range', int, optargs=[int, int]) + def func_range(self, node, args: T.Tuple[int, T.Optional[int], T.Optional[int]], kwargs: T.Dict[str, T.Any]) -> RangeHolder: + start, stop, step = args + # Just like Python's range, we allow range(stop), range(start, stop), or + # range(start, stop, step) + if stop is None: + stop = start + start = 0 + if step is None: + step = 1 + # This is more strict than Python's range() + if start < 0: + raise InterpreterException('start cannot be negative') + if stop < start: + raise InterpreterException('stop cannot be less than start') + if step < 1: + raise InterpreterException('step must be >=1') + return RangeHolder(start, stop, step) diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 1764713..a364510 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -70,6 +70,20 @@ class ObjectHolder(T.Generic[TV_InterpreterObject]): class MesonVersionString(str): pass +class RangeHolder(InterpreterObject): + def __init__(self, start: int, stop: int, step: int) -> None: + super().__init__() + self.range = range(start, stop, step) + + def __iter__(self) -> T.Iterator[int]: + return iter(self.range) + + def __getitem__(self, key: int) -> int: + return self.range[key] + + def __len__(self) -> int: + return len(self.range) + # Decorators for method calls. def check_stringlist(a: T.Any, msg: str = 'Arguments must be strings.') -> None: @@ -950,7 +964,7 @@ The result of this is undefined and will become a hard error in a future Meson r assert(isinstance(node, mparser.ForeachClauseNode)) items = self.evaluate_statement(node.items) - if isinstance(items, list): + if isinstance(items, (list, RangeHolder)): if len(node.varnames) != 1: raise InvalidArguments('Foreach on array does not unpack') varname = node.varnames[0] |