diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2025-01-27 12:48:07 +0100 |
|---|---|---|
| committer | Jussi Pakkanen <jussi.pakkanen@mailbox.org> | 2025-06-17 12:29:56 +0300 |
| commit | 9b3932abb3bcdd2dc5957e65a5097983efaab0f0 (patch) | |
| tree | 78924c3529af4f33fb24e6cf64f170f049ffbd0c /mesonbuild/interpreter | |
| parent | 2f47d0b4b15e27aa62f439c4b65282771149cc7c (diff) | |
| download | meson-9b3932abb3bcdd2dc5957e65a5097983efaab0f0.tar.gz | |
interpreter: make methods per-class for primitives
Do not call update() and Enum.__hash__ a gazillion times; operators
are the same for every instance of the class. In order to access
the class, just mark the methods using a decorator and build
METHODS later using __init_subclass__.
Non-primitive objects are not converted yet to keep the patch small.
They are created a lot less than other objects, especially strings
and booleans.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'mesonbuild/interpreter')
| -rw-r--r-- | mesonbuild/interpreter/primitives/array.py | 13 | ||||
| -rw-r--r-- | mesonbuild/interpreter/primitives/boolean.py | 11 | ||||
| -rw-r--r-- | mesonbuild/interpreter/primitives/dict.py | 13 | ||||
| -rw-r--r-- | mesonbuild/interpreter/primitives/integer.py | 13 | ||||
| -rw-r--r-- | mesonbuild/interpreter/primitives/string.py | 38 |
5 files changed, 27 insertions, 61 deletions
diff --git a/mesonbuild/interpreter/primitives/array.py b/mesonbuild/interpreter/primitives/array.py index 0a116c3e4..ff520a280 100644 --- a/mesonbuild/interpreter/primitives/array.py +++ b/mesonbuild/interpreter/primitives/array.py @@ -23,8 +23,6 @@ from ...interpreterbase import ( from ...mparser import PlusAssignmentNode if T.TYPE_CHECKING: - # Object holders need the actual interpreter - from ...interpreter import Interpreter from ...interpreterbase import TYPE_kwargs class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject): @@ -36,14 +34,6 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject): MesonOperator.NOT_IN: (object, lambda obj, x: x not in obj.held_object), } - def __init__(self, obj: T.List[TYPE_var], interpreter: 'Interpreter') -> None: - super().__init__(obj, interpreter) - self.methods.update({ - 'contains': self.contains_method, - 'length': self.length_method, - 'get': self.get_method, - }) - def display_name(self) -> str: return 'array' @@ -59,6 +49,7 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject): @noArgsFlattening @noKwargs @typed_pos_args('array.contains', object) + @InterpreterObject.method('contains') def contains_method(self, args: T.Tuple[object], kwargs: TYPE_kwargs) -> bool: def check_contains(el: T.List[TYPE_var]) -> bool: for element in el: @@ -73,12 +64,14 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject): @noKwargs @noPosargs + @InterpreterObject.method('length') def length_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: return len(self.held_object) @noArgsFlattening @noKwargs @typed_pos_args('array.get', int, optargs=[object]) + @InterpreterObject.method('get') def get_method(self, args: T.Tuple[int, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var: index = args[0] if index < -len(self.held_object) or index >= len(self.held_object): diff --git a/mesonbuild/interpreter/primitives/boolean.py b/mesonbuild/interpreter/primitives/boolean.py index 48e7aedb2..eb01b9ff2 100644 --- a/mesonbuild/interpreter/primitives/boolean.py +++ b/mesonbuild/interpreter/primitives/boolean.py @@ -16,8 +16,6 @@ from ...interpreterbase import ( import typing as T if T.TYPE_CHECKING: - # Object holders need the actual interpreter - from ...interpreter import Interpreter from ...interpreterbase import TYPE_var, TYPE_kwargs class BooleanHolder(ObjectHolder[bool]): @@ -28,23 +26,18 @@ class BooleanHolder(ObjectHolder[bool]): MesonOperator.NOT_EQUALS: (bool, lambda obj, x: obj.held_object != x), } - def __init__(self, obj: bool, interpreter: 'Interpreter') -> None: - super().__init__(obj, interpreter) - self.methods.update({ - 'to_int': self.to_int_method, - 'to_string': self.to_string_method, - }) - def display_name(self) -> str: return 'bool' @noKwargs @noPosargs + @InterpreterObject.method('to_int') def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: return 1 if self.held_object else 0 @noKwargs @typed_pos_args('bool.to_string', optargs=[str, str]) + @InterpreterObject.method('to_string') def to_string_method(self, args: T.Tuple[T.Optional[str], T.Optional[str]], kwargs: TYPE_kwargs) -> str: true_str = args[0] or 'true' false_str = args[1] or 'false' diff --git a/mesonbuild/interpreter/primitives/dict.py b/mesonbuild/interpreter/primitives/dict.py index ffc1af27a..d641fa88f 100644 --- a/mesonbuild/interpreter/primitives/dict.py +++ b/mesonbuild/interpreter/primitives/dict.py @@ -21,8 +21,6 @@ from ...interpreterbase import ( ) if T.TYPE_CHECKING: - # Object holders need the actual interpreter - from ...interpreter import Interpreter from ...interpreterbase import TYPE_kwargs class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject): @@ -38,14 +36,6 @@ class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject): MesonOperator.NOT_IN: (str, lambda obj, x: x not in obj.held_object), } - def __init__(self, obj: T.Dict[str, TYPE_var], interpreter: 'Interpreter') -> None: - super().__init__(obj, interpreter) - self.methods.update({ - 'has_key': self.has_key_method, - 'keys': self.keys_method, - 'get': self.get_method, - }) - def display_name(self) -> str: return 'dict' @@ -60,17 +50,20 @@ class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject): @noKwargs @typed_pos_args('dict.has_key', str) + @InterpreterObject.method('has_key') def has_key_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: return args[0] in self.held_object @noKwargs @noPosargs + @InterpreterObject.method('keys') def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: return sorted(self.held_object) @noArgsFlattening @noKwargs @typed_pos_args('dict.get', str, optargs=[object]) + @InterpreterObject.method('get') def get_method(self, args: T.Tuple[str, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var: if args[0] in self.held_object: return self.held_object[args[0]] diff --git a/mesonbuild/interpreter/primitives/integer.py b/mesonbuild/interpreter/primitives/integer.py index 17abca3c7..c59ea6e22 100644 --- a/mesonbuild/interpreter/primitives/integer.py +++ b/mesonbuild/interpreter/primitives/integer.py @@ -11,8 +11,6 @@ from ...interpreterbase import ( import typing as T if T.TYPE_CHECKING: - # Object holders need the actual interpreter - from ...interpreter import Interpreter from ...interpreterbase import TYPE_var, TYPE_kwargs class IntegerHolder(ObjectHolder[int]): @@ -33,14 +31,6 @@ class IntegerHolder(ObjectHolder[int]): MesonOperator.LESS_EQUALS: (int, lambda obj, x: obj.held_object <= x), } - def __init__(self, obj: int, interpreter: 'Interpreter') -> None: - super().__init__(obj, interpreter) - self.methods.update({ - 'is_even': self.is_even_method, - 'is_odd': self.is_odd_method, - 'to_string': self.to_string_method, - }) - def display_name(self) -> str: return 'int' @@ -53,11 +43,13 @@ class IntegerHolder(ObjectHolder[int]): @noKwargs @noPosargs + @InterpreterObject.method('is_even') def is_even_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: return self.held_object % 2 == 0 @noKwargs @noPosargs + @InterpreterObject.method('is_odd') def is_odd_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: return self.held_object % 2 != 0 @@ -66,6 +58,7 @@ class IntegerHolder(ObjectHolder[int]): KwargInfo('fill', int, default=0, since='1.3.0') ) @noPosargs + @InterpreterObject.method('to_string') def to_string_method(self, args: T.List[TYPE_var], kwargs: T.Dict[str, T.Any]) -> str: return str(self.held_object).zfill(kwargs['fill']) diff --git a/mesonbuild/interpreter/primitives/string.py b/mesonbuild/interpreter/primitives/string.py index 71efa3345..49dd71660 100644 --- a/mesonbuild/interpreter/primitives/string.py +++ b/mesonbuild/interpreter/primitives/string.py @@ -25,8 +25,6 @@ from ...interpreterbase import ( if T.TYPE_CHECKING: - # Object holders need the actual interpreter - from ...interpreter import Interpreter from ...interpreterbase import TYPE_var, TYPE_kwargs class StringHolder(ObjectHolder[str]): @@ -43,47 +41,31 @@ class StringHolder(ObjectHolder[str]): MesonOperator.LESS_EQUALS: (str, lambda obj, x: obj.held_object <= x), } - def __init__(self, obj: str, interpreter: 'Interpreter') -> None: - super().__init__(obj, interpreter) - self.methods.update({ - 'contains': self.contains_method, - 'startswith': self.startswith_method, - 'endswith': self.endswith_method, - 'format': self.format_method, - 'join': self.join_method, - 'replace': self.replace_method, - 'split': self.split_method, - 'splitlines': self.splitlines_method, - 'strip': self.strip_method, - 'substring': self.substring_method, - 'to_int': self.to_int_method, - 'to_lower': self.to_lower_method, - 'to_upper': self.to_upper_method, - 'underscorify': self.underscorify_method, - 'version_compare': self.version_compare_method, - }) - def display_name(self) -> str: return 'str' @noKwargs @typed_pos_args('str.contains', str) + @InterpreterObject.method('contains') def contains_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: return self.held_object.find(args[0]) >= 0 @noKwargs @typed_pos_args('str.startswith', str) + @InterpreterObject.method('startswith') def startswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: return self.held_object.startswith(args[0]) @noKwargs @typed_pos_args('str.endswith', str) + @InterpreterObject.method('endswith') def endswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: return self.held_object.endswith(args[0]) @noArgsFlattening @noKwargs @typed_pos_args('str.format', varargs=object) + @InterpreterObject.method('format') def format_method(self, args: T.Tuple[T.List[TYPE_var]], kwargs: TYPE_kwargs) -> str: arg_strings: T.List[str] = [] for arg in args[0]: @@ -104,27 +86,32 @@ class StringHolder(ObjectHolder[str]): @noKwargs @noPosargs @FeatureNew('str.splitlines', '1.2.0') + @InterpreterObject.method('splitlines') def splitlines_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: return self.held_object.splitlines() @noKwargs @typed_pos_args('str.join', varargs=str) + @InterpreterObject.method('join') def join_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> str: return self.held_object.join(args[0]) @noKwargs @FeatureNew('str.replace', '0.58.0') @typed_pos_args('str.replace', str, str) + @InterpreterObject.method('replace') def replace_method(self, args: T.Tuple[str, str], kwargs: TYPE_kwargs) -> str: return self.held_object.replace(args[0], args[1]) @noKwargs @typed_pos_args('str.split', optargs=[str]) + @InterpreterObject.method('split') def split_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> T.List[str]: return self.held_object.split(args[0]) @noKwargs @typed_pos_args('str.strip', optargs=[str]) + @InterpreterObject.method('strip') def strip_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> str: if args[0]: FeatureNew.single_use('str.strip with a positional argument', '0.43.0', self.subproject, location=self.current_node) @@ -133,6 +120,7 @@ class StringHolder(ObjectHolder[str]): @noKwargs @FeatureNew('str.substring', '0.56.0') @typed_pos_args('str.substring', optargs=[int, int]) + @InterpreterObject.method('substring') def substring_method(self, args: T.Tuple[T.Optional[int], T.Optional[int]], kwargs: TYPE_kwargs) -> str: start = args[0] if args[0] is not None else 0 end = args[1] if args[1] is not None else len(self.held_object) @@ -140,6 +128,7 @@ class StringHolder(ObjectHolder[str]): @noKwargs @noPosargs + @InterpreterObject.method('to_int') def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int: try: return int(self.held_object) @@ -148,20 +137,24 @@ class StringHolder(ObjectHolder[str]): @noKwargs @noPosargs + @InterpreterObject.method('to_lower') def to_lower_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self.held_object.lower() @noKwargs @noPosargs + @InterpreterObject.method('to_upper') def to_upper_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self.held_object.upper() @noKwargs @noPosargs + @InterpreterObject.method('underscorify') def underscorify_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return re.sub(r'[^a-zA-Z0-9]', '_', self.held_object) @noKwargs + @InterpreterObject.method('version_compare') @typed_pos_args('str.version_compare', varargs=str, min_varargs=1) def version_compare_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> bool: if len(args[0]) > 1: @@ -205,6 +198,7 @@ class MesonVersionString(str): class MesonVersionStringHolder(StringHolder): @noKwargs @typed_pos_args('str.version_compare', str) + @InterpreterObject.method('version_compare') def version_compare_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: self.interpreter.tmp_meson_version = args[0] return version_compare(self.held_object, args[0]) |
