aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mdpoly/abc.py54
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):