diff --git a/mapytex/calculus/API/expression.py b/mapytex/calculus/API/expression.py index 335555d..b44953c 100644 --- a/mapytex/calculus/API/expression.py +++ b/mapytex/calculus/API/expression.py @@ -10,7 +10,7 @@ Expression """ -from ..core import Tree, compute +from ..core import Tree, compute, typing from .renders import renders class Expression(object): @@ -104,9 +104,11 @@ class Expression(object): """ try: - t = self._tree.apply_on_last_level(compute) + t = self._tree.apply_on_last_level(compute, typing) except AttributeError: return self + except NotImplementedError: + return self else: e = Expression(t, ancestor=self) return e.simplify() diff --git a/mapytex/calculus/core/__init__.py b/mapytex/calculus/core/__init__.py index 4f8c550..4028601 100644 --- a/mapytex/calculus/core/__init__.py +++ b/mapytex/calculus/core/__init__.py @@ -37,10 +37,8 @@ Abstracts tools for calculs manipulations >>> print(t.apply_on_last_level(compute, typing)) + > / - | > * - | | > 2 - | | > 4 - | > 4 + | > 2 + | > 1 > / | > 3 | > 4 diff --git a/mapytex/calculus/core/compute/divide.py b/mapytex/calculus/core/compute/divide.py index ec9afb7..7a81b44 100644 --- a/mapytex/calculus/core/compute/divide.py +++ b/mapytex/calculus/core/compute/divide.py @@ -10,6 +10,7 @@ Divide MO """ +from decimal import Decimal from multipledispatch import Dispatcher from ..tree import Tree from ..MO.mo import MO, MOnumber @@ -66,12 +67,22 @@ def divide_filter(left, right): def monumber_monumber(left, right): """ Divide 2 monumbers and return a MOFraction + >>> a = MOnumber(4) + >>> b = MOnumber(6.2) + >>> monumber_monumber(a, b) + Decimal('0.6451612903225806266768278939') >>> a = MOnumber(4) >>> b = MOnumber(6) >>> monumber_monumber(a, b) - + Traceback (most recent call last): + ... + NotImplementedError: Can't divide 2 int. Need to create a Fraction instead """ - return MOFraction(left, right) + if type(left.value) in [float, Decimal] or \ + type(right.value) in [float, Decimal]: + return left / right + else: + raise NotImplementedError("Can't divide 2 int. Need to create a Fraction instead") @divide.register(MOnumber, MOFraction) @special_case(divide_filter) diff --git a/mapytex/calculus/core/tree.py b/mapytex/calculus/core/tree.py index 8e6d116..e84df16 100644 --- a/mapytex/calculus/core/tree.py +++ b/mapytex/calculus/core/tree.py @@ -294,10 +294,13 @@ class Tree(object): return Tree(self.node, left_applied, right_applied) - def apply_on_last_level(self, function): + def apply_on_last_level(self, + function, + type_function = lambda n,l,r: Tree(n,l,r)): """ Apply the function on last level of the tree before leaf - :param function: (op, a, a) -> b + :param function: (op, a, a) -> b function to apply on last level + :param type_function: (op, a, a) -> b typing function to apply on subtree which raise a TypeError. The return value will be concidered as an leaf :returns: b if it is a 1 level Tree, Tree otherwise @@ -325,22 +328,38 @@ class Tree(object): >>> print(ttt) 14 """ + left_is_leaf = 0 right_is_leaf = 0 try: - left_applied = self.left_value.apply_on_last_level(function) + left_applied = self.left_value.\ + apply_on_last_level(function, type_function) + except NotImplementedError: + # TODO: overload __getitem__ to ease unpacking |dim. sept. 23 19:17:50 CEST 2018 + left_is_leaf = 1 + left_tree = self.left_value + left_applied = type_function(left_tree.node, + left_tree.left_value, + left_tree.right_value) except AttributeError: left_applied = self.left_value left_is_leaf = 1 try: - right_applied = self.right_value.apply_on_last_level(function) + right_applied = self.right_value.\ + apply_on_last_level(function, type_function) + except NotImplementedError: + right_is_leaf = 1 + right_tree = self.right_value + right_applied = type_function(right_tree.node, + right_tree.left_value, + right_tree.right_value) except AttributeError: right_applied = self.right_value right_is_leaf = 1 if left_is_leaf and right_is_leaf: - return function(self.node, self.left_value, self.right_value) + return function(self.node, left_applied, right_applied) else: return Tree(self.node, left_applied, right_applied) diff --git a/mapytex/calculus/core/typing/__init__.py b/mapytex/calculus/core/typing/__init__.py new file mode 100644 index 0000000..cd3eac4 --- /dev/null +++ b/mapytex/calculus/core/typing/__init__.py @@ -0,0 +1,44 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# vim:fenc=utf-8 +# +# Copyright © 2017 lafrite +# +# Distributed under terms of the MIT license. + +""" +Computing with MO +""" + +from .exceptions import TypingError +# from .add import add +# from .minus import minus +# from .multiply import multiply +from .divide import divide + +OPERATIONS = { + # "+": add, + # "-": minus, + # "*": multiply, + "/": divide, + } + +def typing(node, left_v, right_v): + """ + Typing a try base on his root node + + :example: + + >>> from ..MO.mo import MOnumber + """ + try: + operation = OPERATIONS[node] + except KeyError: + raise TypingError(f"Unknown operation ({node})") + return operation(left_v, right_v) + + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del diff --git a/mapytex/calculus/core/typing/divide.py b/mapytex/calculus/core/typing/divide.py new file mode 100644 index 0000000..c0d4567 --- /dev/null +++ b/mapytex/calculus/core/typing/divide.py @@ -0,0 +1,43 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# vim:fenc=utf-8 +# +# Copyright © 2017 lafrite +# +# Distributed under terms of the MIT license. + +""" +Typing trees with a divide root +""" + +from multipledispatch import Dispatcher +from ..MO.mo import MO, MOnumber +from ..MO.fraction import MOFraction + +divide_doc = """ Typing trees a divide root + +:param left: left MO +:param right: right MO +:returns: Tree or MO + +""" + +divide = Dispatcher("divide", doc=divide_doc) + +@divide.register(MOnumber, MOnumber) +def monumber_monumber(left, right): + """ A divide tree with 2 MOnumbers is a MOFraction + + >>> a = MOnumber(4) + >>> b = MOnumber(6) + >>> monumber_monumber(a, b) + + + """ + return MOFraction(left, right) + + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del diff --git a/mapytex/calculus/core/typing/exceptions.py b/mapytex/calculus/core/typing/exceptions.py new file mode 100644 index 0000000..64efc60 --- /dev/null +++ b/mapytex/calculus/core/typing/exceptions.py @@ -0,0 +1,19 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# vim:fenc=utf-8 +# +# Copyright © 2017 lafrite +# +# Distributed under terms of the MIT license. + +""" +Exceptions for typing trees +""" + +class TypingError(Exception): + pass + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del