Feat: tokenify for everything!

This commit is contained in:
Bertrand Benjamin 2019-07-17 09:25:12 +02:00
parent a32b684b6b
commit d75fd4c4cf
2 changed files with 117 additions and 33 deletions

View File

@ -10,52 +10,84 @@
Tokens represents MathObject at API level Tokens represents MathObject at API level
""" """
from ...core.MO import MO, MOnumber, MOstr from ...core.MO import MO, MOnumber, MOstr, moify
from ...core.MO.fraction import MOFraction from ...core.MO.fraction import MOFraction
from ...core.MO.monomial import MOstrPower, MOMonomial from ...core.MO.monomial import MOstrPower, MOMonomial
from ...core.MO.polynomial import MOpolynomial from ...core.MO.polynomial import MOpolynomial
from decimal import Decimal as _Decimal from decimal import Decimal as _Decimal
from .token import Token
__all__ = ["factory"] __all__ = ["factory"]
def tokenify(mo, name="", ancestor=None):
""" Transform a MO or a python builtin to the appropriate token
def factory(exp, name="", ancestor=None): :param mo: the thing to turn into a Token
""" Transform a Expression with on MathObject (from core) to a appropriate token (from API) :param name: a virtual name of the toke
:param ancestor: its ancestor
:example: :example:
>>> from ..expression import Expression >>> a = MOnumber(2)
>>> a = Expression(MOnumber(2)) >>> tokenify(a)
>>> factory(a)
<Integer 2> <Integer 2>
>>> a = Expression(MOnumber(2.5)) >>> tokenify(2)
>>> factory(a) <Integer 2>
<Decimal 2.5> >>> tokenify("x")
>>> a = Expression(MOFraction(2, 5))
>>> factory(a)
<Fraction 2 / 5>
>>> a = Expression(MOstr('x'))
>>> factory(a)
<Linear x> <Linear x>
>>> a = Expression(MOstrPower('x', 2)) >>> tokenify(_Decimal("2.2"))
>>> factory(a) <Decimal 2.2>
>>> tokenify("2.2")
<Decimal 2.2>
>>> tokenify(2.2)
<Decimal 2.20000000000000017763568394002504646778106689453125>
tokenify is idempotent on "mo" parameter
>>> a = MOnumber(2)
>>> ta = tokenify(a)
>>> ta == tokenify(ta)
True
"""
if isinstance(mo, MO):
return _tokenify(mo, name, ancestor)
elif isinstance(mo, Token):
return _tokenify(mo._mo, name, ancestor)
return _tokenify(moify(mo), name, ancestor)
def _tokenify(mo, name="", ancestor=None):
""" Transform a MO (from core) to the appropriate token (from API)
:example:
>>> a = MOnumber(2)
>>> _tokenify(a)
<Integer 2>
>>> a = MOnumber(2.5)
>>> _tokenify(a)
<Decimal 2.5>
>>> a = MOFraction(2, 5)
>>> _tokenify(a)
<Fraction 2 / 5>
>>> a = MOstr('x')
>>> _tokenify(a)
<Linear x>
>>> a = MOstrPower('x', 2)
>>> _tokenify(a)
<Quadratic x^2> <Quadratic x^2>
>>> a = Expression(MOstrPower('x', 3)) >>> a = MOstrPower('x', 3)
>>> factory(a) >>> _tokenify(a)
<Polynomial x^3> <Polynomial x^3>
>>> a = Expression(MOMonomial(3, 'x', 1)) >>> a = MOMonomial(3, 'x', 1)
>>> factory(a) >>> _tokenify(a)
<Linear 3x> <Linear 3x>
>>> a = Expression(MOMonomial(3, 'x', 2)) >>> a = MOMonomial(3, 'x', 2)
>>> factory(a) >>> _tokenify(a)
<Quadratic 3x^2> <Quadratic 3x^2>
>>> a = Expression(MOMonomial(3, 'x', 3)) >>> a = MOMonomial(3, 'x', 3)
>>> factory(a) >>> _tokenify(a)
<Polynomial 3x^3> <Polynomial 3x^3>
""" """
mo = exp._tree
if not isinstance(mo, MO):
raise TypeError(f"Can't build Token from not computed Expression (got {mo})")
if isinstance(mo, MOnumber): if isinstance(mo, MOnumber):
if isinstance(mo.value, int): if isinstance(mo.value, int):
from .number import Integer from .number import Integer
@ -104,6 +136,47 @@ def factory(exp, name="", ancestor=None):
raise TypeError(f"{type(mo)} is unknown MathObject") raise TypeError(f"{type(mo)} is unknown MathObject")
def factory(exp, name="", ancestor=None):
""" Transform a Expression with on single MathObject (from core) to a appropriate token (from API)
:example:
>>> from ..expression import Expression
>>> a = Expression(MOnumber(2))
>>> factory(a)
<Integer 2>
>>> a = Expression(MOnumber(2.5))
>>> factory(a)
<Decimal 2.5>
>>> a = Expression(MOFraction(2, 5))
>>> factory(a)
<Fraction 2 / 5>
>>> a = Expression(MOstr('x'))
>>> factory(a)
<Linear x>
>>> a = Expression(MOstrPower('x', 2))
>>> factory(a)
<Quadratic x^2>
>>> a = Expression(MOstrPower('x', 3))
>>> factory(a)
<Polynomial x^3>
>>> a = Expression(MOMonomial(3, 'x', 1))
>>> factory(a)
<Linear 3x>
>>> a = Expression(MOMonomial(3, 'x', 2))
>>> factory(a)
<Quadratic 3x^2>
>>> a = Expression(MOMonomial(3, 'x', 3))
>>> factory(a)
<Polynomial 3x^3>
"""
mo = exp._tree
if not isinstance(mo, MO):
raise TypeError(f"Can't build Token from not computed Expression (got {mo})")
return _tokenify(mo, name, ancestor)
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4: # vim:set autoindent expandtab tabstop=4 shiftwidth=4:

View File

@ -91,6 +91,12 @@ class MOnumber(Atom):
>>> MOnumber(Decimal("-23.3")) >>> MOnumber(Decimal("-23.3"))
<MOnumber - 23.3> <MOnumber - 23.3>
Or directly passe a decimal string
>>> MOnumber("23.3")
<MOnumber 23.3>
>>> MOnumber("-23.3")
<MOnumber - 23.3>
MOnumber initialisation is idempotent MOnumber initialisation is idempotent
>>> a = MOnumber(23) >>> a = MOnumber(23)
@ -100,7 +106,7 @@ class MOnumber(Atom):
>>> MOnumber("a") >>> MOnumber("a")
Traceback (most recent call last): Traceback (most recent call last):
... ...
mapytex.calculus.core.MO.exceptions.MOError: ('The value of an MOnumber need to be a int, a float or a Decimal', "(got <class 'str'>)") mapytex.calculus.core.MO.exceptions.MOError: ('The value of an MOnumber need to be a int, a float, a Decimal or a decimal string', "(got <class 'str'>)")
Atoms specific property and methods Atoms specific property and methods
@ -122,10 +128,15 @@ class MOnumber(Atom):
elif isinstance(value, float): elif isinstance(value, float):
Atom.__init__(self, Decimal(value)) Atom.__init__(self, Decimal(value))
else: else:
try:
float(value)
except (ValueError, TypeError):
raise MOError( raise MOError(
"The value of an MOnumber need to be a int, a float or a Decimal", "The value of an MOnumber need to be a int, a float, a Decimal or a decimal string",
f"(got {type(value)})", f"(got {type(value)})",
) )
else:
Atom.__init__(self, Decimal(value))
self._signature = "scalar" self._signature = "scalar"