summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-01-08 10:50:25 +0100
committerJussi Pakkanen <jussi.pakkanen@mailbox.org>2025-06-17 12:29:56 +0300
commit992a93bcef47972c75464d1878c4c4b0469b1fbf (patch)
treeb6dab1d7e16f05ab96a97cfe5bfafeb25a665019
parent2be42a5423209a88551cf88dd3b49f8e4da50963 (diff)
downloadmeson-992a93bcef47972c75464d1878c4c4b0469b1fbf.tar.gz
interpreter: make operator functions binary
In preparation for moving them to the class, make the operator functions binary. Adjust the lambdas for trivial operators, and store unbound methods for non-trivial ones. Note that this requires adding operators manually for every override, even subclasses. It's decidedly ugly at this temporary stage; later it will result in just an extra @InterpreterObject.operator decorator on the subclasses. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py2
-rw-r--r--mesonbuild/interpreter/primitives/array.py12
-rw-r--r--mesonbuild/interpreter/primitives/boolean.py8
-rw-r--r--mesonbuild/interpreter/primitives/dict.py12
-rw-r--r--mesonbuild/interpreter/primitives/integer.py24
-rw-r--r--mesonbuild/interpreter/primitives/range.py2
-rw-r--r--mesonbuild/interpreter/primitives/string.py34
-rw-r--r--mesonbuild/interpreterbase/baseobjects.py22
8 files changed, 63 insertions, 53 deletions
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index af1322d0e..aeead5013 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -1063,7 +1063,7 @@ class _CustomTargetHolder(ObjectHolder[_CT]):
})
self.operators.update({
- MesonOperator.INDEX: self.op_index,
+ MesonOperator.INDEX: _CustomTargetHolder.op_index,
})
def __repr__(self) -> str:
diff --git a/mesonbuild/interpreter/primitives/array.py b/mesonbuild/interpreter/primitives/array.py
index b42ddeaa4..6582d4b60 100644
--- a/mesonbuild/interpreter/primitives/array.py
+++ b/mesonbuild/interpreter/primitives/array.py
@@ -36,16 +36,16 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
})
self.trivial_operators.update({
- MesonOperator.EQUALS: (list, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (list, lambda x: self.held_object != x),
- MesonOperator.IN: (object, lambda x: x in self.held_object),
- MesonOperator.NOT_IN: (object, lambda x: x not in self.held_object),
+ MesonOperator.EQUALS: (list, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (list, lambda obj, x: obj.held_object != x),
+ MesonOperator.IN: (object, lambda obj, x: x in obj.held_object),
+ MesonOperator.NOT_IN: (object, lambda obj, x: x not in obj.held_object),
})
# Use actual methods for functions that require additional checks
self.operators.update({
- MesonOperator.PLUS: self.op_plus,
- MesonOperator.INDEX: self.op_index,
+ MesonOperator.PLUS: ArrayHolder.op_plus,
+ MesonOperator.INDEX: ArrayHolder.op_index,
})
def display_name(self) -> str:
diff --git a/mesonbuild/interpreter/primitives/boolean.py b/mesonbuild/interpreter/primitives/boolean.py
index 4b49caf45..0695e2dd5 100644
--- a/mesonbuild/interpreter/primitives/boolean.py
+++ b/mesonbuild/interpreter/primitives/boolean.py
@@ -28,10 +28,10 @@ class BooleanHolder(ObjectHolder[bool]):
})
self.trivial_operators.update({
- MesonOperator.BOOL: (None, lambda x: self.held_object),
- MesonOperator.NOT: (None, lambda x: not self.held_object),
- MesonOperator.EQUALS: (bool, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (bool, lambda x: self.held_object != x),
+ MesonOperator.BOOL: (None, lambda obj, x: obj.held_object),
+ MesonOperator.NOT: (None, lambda obj, x: not obj.held_object),
+ MesonOperator.EQUALS: (bool, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (bool, lambda obj, x: obj.held_object != x),
})
def display_name(self) -> str:
diff --git a/mesonbuild/interpreter/primitives/dict.py b/mesonbuild/interpreter/primitives/dict.py
index ab4c15ffa..ed2986da7 100644
--- a/mesonbuild/interpreter/primitives/dict.py
+++ b/mesonbuild/interpreter/primitives/dict.py
@@ -35,18 +35,18 @@ class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject):
self.trivial_operators.update({
# Arithmetic
- MesonOperator.PLUS: (dict, lambda x: {**self.held_object, **x}),
+ MesonOperator.PLUS: (dict, lambda obj, x: {**obj.held_object, **x}),
# Comparison
- MesonOperator.EQUALS: (dict, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (dict, lambda x: self.held_object != x),
- MesonOperator.IN: (str, lambda x: x in self.held_object),
- MesonOperator.NOT_IN: (str, lambda x: x not in self.held_object),
+ MesonOperator.EQUALS: (dict, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (dict, lambda obj, x: obj.held_object != x),
+ MesonOperator.IN: (str, lambda obj, x: x in obj.held_object),
+ MesonOperator.NOT_IN: (str, lambda obj, x: x not in obj.held_object),
})
# Use actual methods for functions that require additional checks
self.operators.update({
- MesonOperator.INDEX: self.op_index,
+ MesonOperator.INDEX: DictHolder.op_index,
})
def display_name(self) -> str:
diff --git a/mesonbuild/interpreter/primitives/integer.py b/mesonbuild/interpreter/primitives/integer.py
index cdf2355f0..2d0915f7b 100644
--- a/mesonbuild/interpreter/primitives/integer.py
+++ b/mesonbuild/interpreter/primitives/integer.py
@@ -25,24 +25,24 @@ class IntegerHolder(ObjectHolder[int]):
self.trivial_operators.update({
# Arithmetic
- MesonOperator.UMINUS: (None, lambda x: -self.held_object),
- MesonOperator.PLUS: (int, lambda x: self.held_object + x),
- MesonOperator.MINUS: (int, lambda x: self.held_object - x),
- MesonOperator.TIMES: (int, lambda x: self.held_object * x),
+ MesonOperator.UMINUS: (None, lambda obj, x: -obj.held_object),
+ MesonOperator.PLUS: (int, lambda obj, x: obj.held_object + x),
+ MesonOperator.MINUS: (int, lambda obj, x: obj.held_object - x),
+ MesonOperator.TIMES: (int, lambda obj, x: obj.held_object * x),
# Comparison
- MesonOperator.EQUALS: (int, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (int, lambda x: self.held_object != x),
- MesonOperator.GREATER: (int, lambda x: self.held_object > x),
- MesonOperator.LESS: (int, lambda x: self.held_object < x),
- MesonOperator.GREATER_EQUALS: (int, lambda x: self.held_object >= x),
- MesonOperator.LESS_EQUALS: (int, lambda x: self.held_object <= x),
+ MesonOperator.EQUALS: (int, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (int, lambda obj, x: obj.held_object != x),
+ MesonOperator.GREATER: (int, lambda obj, x: obj.held_object > x),
+ MesonOperator.LESS: (int, lambda obj, x: obj.held_object < x),
+ MesonOperator.GREATER_EQUALS: (int, lambda obj, x: obj.held_object >= x),
+ MesonOperator.LESS_EQUALS: (int, lambda obj, x: obj.held_object <= x),
})
# Use actual methods for functions that require additional checks
self.operators.update({
- MesonOperator.DIV: self.op_div,
- MesonOperator.MOD: self.op_mod,
+ MesonOperator.DIV: IntegerHolder.op_div,
+ MesonOperator.MOD: IntegerHolder.op_mod,
})
def display_name(self) -> str:
diff --git a/mesonbuild/interpreter/primitives/range.py b/mesonbuild/interpreter/primitives/range.py
index 23d5617b8..432cfe1b2 100644
--- a/mesonbuild/interpreter/primitives/range.py
+++ b/mesonbuild/interpreter/primitives/range.py
@@ -19,7 +19,7 @@ class RangeHolder(MesonInterpreterObject, IterableObject):
super().__init__(subproject=subproject)
self.range = range(start, stop, step)
self.operators.update({
- MesonOperator.INDEX: self.op_index,
+ MesonOperator.INDEX: RangeHolder.op_index,
})
def op_index(self, other: int) -> int:
diff --git a/mesonbuild/interpreter/primitives/string.py b/mesonbuild/interpreter/primitives/string.py
index a224dfac8..3cb78b310 100644
--- a/mesonbuild/interpreter/primitives/string.py
+++ b/mesonbuild/interpreter/primitives/string.py
@@ -51,23 +51,23 @@ class StringHolder(ObjectHolder[str]):
self.trivial_operators.update({
# Arithmetic
- MesonOperator.PLUS: (str, lambda x: self.held_object + x),
+ MesonOperator.PLUS: (str, lambda obj, x: obj.held_object + x),
# Comparison
- MesonOperator.EQUALS: (str, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (str, lambda x: self.held_object != x),
- MesonOperator.GREATER: (str, lambda x: self.held_object > x),
- MesonOperator.LESS: (str, lambda x: self.held_object < x),
- MesonOperator.GREATER_EQUALS: (str, lambda x: self.held_object >= x),
- MesonOperator.LESS_EQUALS: (str, lambda x: self.held_object <= x),
+ MesonOperator.EQUALS: (str, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (str, lambda obj, x: obj.held_object != x),
+ MesonOperator.GREATER: (str, lambda obj, x: obj.held_object > x),
+ MesonOperator.LESS: (str, lambda obj, x: obj.held_object < x),
+ MesonOperator.GREATER_EQUALS: (str, lambda obj, x: obj.held_object >= x),
+ MesonOperator.LESS_EQUALS: (str, lambda obj, x: obj.held_object <= x),
})
# Use actual methods for functions that require additional checks
self.operators.update({
- MesonOperator.DIV: self.op_div,
- MesonOperator.INDEX: self.op_index,
- MesonOperator.IN: self.op_in,
- MesonOperator.NOT_IN: self.op_notin,
+ MesonOperator.DIV: StringHolder.op_div,
+ MesonOperator.INDEX: StringHolder.op_index,
+ MesonOperator.IN: StringHolder.op_in,
+ MesonOperator.NOT_IN: StringHolder.op_notin,
})
def display_name(self) -> str:
@@ -221,6 +221,12 @@ class DependencyVariableString(str):
pass
class DependencyVariableStringHolder(StringHolder):
+ def __init__(self, obj: str, interpreter: Interpreter) -> None:
+ super().__init__(obj, interpreter)
+ self.operators.update({
+ MesonOperator.DIV: DependencyVariableStringHolder.op_div,
+ })
+
def op_div(self, other: str) -> T.Union[str, DependencyVariableString]:
ret = super().op_div(other)
if '..' in other:
@@ -243,6 +249,12 @@ class OptionString(str):
class OptionStringHolder(StringHolder):
held_object: OptionString
+ def __init__(self, obj: str, interpreter: Interpreter) -> None:
+ super().__init__(obj, interpreter)
+ self.operators.update({
+ MesonOperator.DIV: OptionStringHolder.op_div,
+ })
+
def op_div(self, other: str) -> T.Union[str, OptionString]:
ret = super().op_div(other)
name = self._op_div(self.held_object.optname, other)
diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py
index 5ad6f4351..32c36f538 100644
--- a/mesonbuild/interpreterbase/baseobjects.py
+++ b/mesonbuild/interpreterbase/baseobjects.py
@@ -15,16 +15,11 @@ from abc import ABCMeta
from contextlib import AbstractContextManager
if T.TYPE_CHECKING:
- from typing_extensions import Protocol, TypeAlias
+ from typing_extensions import TypeAlias
# Object holders need the actual interpreter
from ..interpreter import Interpreter
- __T = T.TypeVar('__T', bound='TYPE_var', contravariant=True)
-
- class OperatorCall(Protocol[__T]):
- def __call__(self, other: __T) -> 'TYPE_var': ...
-
TV_func = T.TypeVar('TV_func', bound=T.Callable[..., T.Any])
@@ -34,6 +29,8 @@ TYPE_nvar = T.Union[TYPE_var, mparser.BaseNode]
TYPE_kwargs = T.Dict[str, TYPE_var]
TYPE_nkwargs = T.Dict[str, TYPE_nvar]
TYPE_key_resolver = T.Callable[[mparser.BaseNode], str]
+TYPE_op_arg = T.TypeVar('TYPE_op_arg', bound='TYPE_var', contravariant=True)
+TYPE_op_func = T.Callable[[TYPE_op_arg, TYPE_op_arg], TYPE_var]
SubProject = T.NewType('SubProject', str)
@@ -43,12 +40,12 @@ class InterpreterObject:
str,
T.Callable[[T.List[TYPE_var], TYPE_kwargs], TYPE_var]
] = {}
- self.operators: T.Dict[MesonOperator, 'OperatorCall'] = {}
+ self.operators: T.Dict[MesonOperator, TYPE_op_func] = {}
self.trivial_operators: T.Dict[
MesonOperator,
T.Tuple[
T.Union[T.Type, T.Tuple[T.Type, ...]],
- 'OperatorCall'
+ TYPE_op_func
]
] = {}
# Current node set during a method call. This can be used as location
@@ -58,8 +55,8 @@ class InterpreterObject:
# Some default operators supported by all objects
self.operators.update({
- MesonOperator.EQUALS: self.op_equals,
- MesonOperator.NOT_EQUALS: self.op_not_equals,
+ MesonOperator.EQUALS: self.__class__.op_equals,
+ MesonOperator.NOT_EQUALS: self.__class__.op_not_equals,
})
# The type of the object that can be printed to the user
@@ -88,9 +85,10 @@ class InterpreterObject:
raise MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}')
if op[0] is not None and not isinstance(other, op[0]):
raise InvalidArguments(f'The `{operator.value}` operator of {self.display_name()} does not accept objects of type {type(other).__name__} ({other})')
- return op[1](other)
+ return op[1](self, other)
if operator in self.operators:
- return self.operators[operator](other)
+ return self.operators[operator](self, other)
+
raise InvalidCode(f'Object {self} of type {self.display_name()} does not support the `{operator.value}` operator.')
# Default comparison operator support