aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/ast/interpreter.py1
-rw-r--r--mesonbuild/interpreter.py26
-rw-r--r--mesonbuild/interpreterbase.py16
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]