diff options
Diffstat (limited to '')
-rw-r--r-- | mdpoly/abc.py | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/mdpoly/abc.py b/mdpoly/abc.py index 35346b8..488d89f 100644 --- a/mdpoly/abc.py +++ b/mdpoly/abc.py @@ -24,31 +24,49 @@ class Expr(ABC): @property def is_leaf(self) -> bool: + """ Whether an expression is a Leaf of the tree. """ return False @property @abstractmethod - def left(self) -> Self: ... + def left(self) -> Self: + """ Left child of node binary tree. """ @left.setter @abstractmethod - def left(self, left: Self) -> None: ... + def left(self, left: Self) -> None: + """ Setter for left child of binary tree. """ + # TODO: If shape is replaced with functools.cached_property + # we will need to update shape here. @property @abstractmethod - def right(self) -> Self: ... + def right(self) -> Self: + """ Right child of node in binary tree. """ @right.setter @abstractmethod - def right(self, right: Self) -> None: ... + def right(self, right: Self) -> None: + """ Setter for right child of binary tree. """ @property @abstractmethod - def algebra(self) -> Algebra: ... + def algebra(self) -> Algebra: + """ Specifies to which algebra belongs the expression. + + This is used to provide nicer error messages and to avoid accidental + mistakes (like adding a scalar and a matrix) which are hard to debug + as expressions are lazily evalated (i.e. without this the exception for + adding a scalar to a matrix does not occurr at the line where the two + are added but rather where :py:meth:`mdpoly.abc.Expr.to_repr` is + called). + """ @property @abstractmethod def shape(self) -> Shape: + # TODO: Test on very large expressions. If there is a performance hit + # change to functools.cached_property. """ Computes the shape of the expression. This method is also used to check if the operation described by *Expr* can be perfomed with *left* and *right*. If the shape cannot be computed because of an algebraic @@ -135,7 +153,15 @@ class Expr(ABC): # --- Operator overloading --- @staticmethod - def _wrap(if_type: type, wrapper_type: type, obj): + def _wrap(if_type: type, wrapper_type: type, obj: Any) -> Expr: + """ Wrap non-expr objects. + + Suppose ``x`` is of type *Expr*, then we would like to be able to do + things like ``x + 1``, so this function can be called in operator + overloadings to for instance wrapp the 1 into a + :py:class:`mdpoly.leaves.Const`. If ``obj`` is already of type *Expr*, + this function does nothing. + """ # Do not wrap if is alreay an expression if isinstance(obj, Expr): return obj @@ -191,16 +217,24 @@ class Leaf(Expr): return True @property - def left(self): ... + def left(self): + """ Overloads left child with function that does nothing. (Leaves do + not have children). """ @left.setter - def left(self, left: Self) -> None: ... + def left(self, left: Self) -> None: + """ Overloads left child setter with function that does nothing. + (Leaves do not have children). """ @property - def right(self): ... + def right(self): + """ Overloads right child with function that does nothing. (Leaves do + not have children). """ @right.setter - def right(self, right: Self) -> None: ... + def right(self, right: Self) -> None: + """ Overloads right child setter with function that does nothing. + (Leaves do not have children). """ class Rel(ABC): |