Fix(steps): Typing steps are bypassed

Useless steps where complex objects were built are not shown. I create
a typing function which is called when compute raise
NotImplementedError.
This commit is contained in:
Bertrand Benjamin 2018-09-24 17:21:50 +02:00
parent 0e479323dd
commit a557fa3981
7 changed files with 149 additions and 13 deletions

View File

@ -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):
<Exp: 2 + 12>
"""
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()

View File

@ -37,10 +37,8 @@ Abstracts tools for calculs manipulations
>>> print(t.apply_on_last_level(compute, typing))
+
> /
| > *
| | > 2
| | > 4
| > 4
| > 2
| > 1
> /
| > 3
| > 4

View File

@ -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)
<MOFraction 4 / 6>
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)

View File

@ -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)

View File

@ -0,0 +1,44 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 lafrite <lafrite@Poivre>
#
# 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

View File

@ -0,0 +1,43 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 lafrite <lafrite@Poivre>
#
# 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)
<MOFraction 4 / 6>
"""
return MOFraction(left, right)
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del

View File

@ -0,0 +1,19 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 lafrite <lafrite@Poivre>
#
# 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