Require capitalizing NaN and Inf like so
This commit is contained in:
parent
a746ccb42c
commit
bb91b57dca
1
NEWS
1
NEWS
@ -8,6 +8,7 @@ Changes from 0.13.0
|
|||||||
* The compiler now automatically promotes values to Hy model objects
|
* The compiler now automatically promotes values to Hy model objects
|
||||||
as necessary, so you can write ``(eval `(+ 1 ~n))`` instead of
|
as necessary, so you can write ``(eval `(+ 1 ~n))`` instead of
|
||||||
``(eval `(+ 1 ~(HyInteger n)))``
|
``(eval `(+ 1 ~(HyInteger n)))``
|
||||||
|
* Literal `Inf`s and `NaN`s must now be capitalized like that
|
||||||
|
|
||||||
[ Bug Fixes ]
|
[ Bug Fixes ]
|
||||||
* Numeric literals are no longer parsed as symbols when followed by a dot
|
* Numeric literals are no longer parsed as symbols when followed by a dot
|
||||||
|
@ -52,6 +52,9 @@ digits.
|
|||||||
|
|
||||||
(print 10,000,000,000 10_000_000_000)
|
(print 10,000,000,000 10_000_000_000)
|
||||||
|
|
||||||
|
Unlike Python, Hy provides literal forms for NaN and infinity: `NaN`, `Inf`,
|
||||||
|
and `-Inf`.
|
||||||
|
|
||||||
string literals
|
string literals
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
31
hy/models.py
31
hy/models.py
@ -3,6 +3,7 @@
|
|||||||
# license. See the LICENSE.
|
# license. See the LICENSE.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from math import isnan, isinf
|
||||||
from hy._compat import PY3, str_type, bytes_type, long_type, string_types
|
from hy._compat import PY3, str_type, bytes_type, long_type, string_types
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
@ -142,15 +143,24 @@ if not PY3: # do not add long on python3
|
|||||||
_wrappers[long_type] = HyInteger
|
_wrappers[long_type] = HyInteger
|
||||||
|
|
||||||
|
|
||||||
|
def check_inf_nan_cap(arg, value):
|
||||||
|
if isinstance(arg, string_types):
|
||||||
|
if isinf(value) and "Inf" not in arg:
|
||||||
|
raise ValueError('Inf must be capitalized as "Inf"')
|
||||||
|
if isnan(value) and "NaN" not in arg:
|
||||||
|
raise ValueError('NaN must be capitalized as "NaN"')
|
||||||
|
|
||||||
|
|
||||||
class HyFloat(HyObject, float):
|
class HyFloat(HyObject, float):
|
||||||
"""
|
"""
|
||||||
Internal representation of a Hy Float. May raise a ValueError as if
|
Internal representation of a Hy Float. May raise a ValueError as if
|
||||||
float(foo) was called, given HyFloat(foo).
|
float(foo) was called, given HyFloat(foo).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(cls, number, *args, **kwargs):
|
def __new__(cls, num, *args, **kwargs):
|
||||||
number = float(strip_digit_separators(number))
|
value = super(HyFloat, cls).__new__(cls, strip_digit_separators(num))
|
||||||
return super(HyFloat, cls).__new__(cls, number)
|
check_inf_nan_cap(num, value)
|
||||||
|
return value
|
||||||
|
|
||||||
_wrappers[float] = HyFloat
|
_wrappers[float] = HyFloat
|
||||||
|
|
||||||
@ -161,9 +171,18 @@ class HyComplex(HyObject, complex):
|
|||||||
complex(foo) was called, given HyComplex(foo).
|
complex(foo) was called, given HyComplex(foo).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(cls, number, *args, **kwargs):
|
def __new__(cls, num, *args, **kwargs):
|
||||||
number = complex(strip_digit_separators(number))
|
value = super(HyComplex, cls).__new__(cls, strip_digit_separators(num))
|
||||||
return super(HyComplex, cls).__new__(cls, number)
|
if isinstance(num, string_types):
|
||||||
|
p1, _, p2 = num.lstrip("+-").replace("-", "+").partition("+")
|
||||||
|
if p2:
|
||||||
|
check_inf_nan_cap(p1, value.real)
|
||||||
|
check_inf_nan_cap(p2, value.imag)
|
||||||
|
elif "j" in p1:
|
||||||
|
check_inf_nan_cap(p1, value.imag)
|
||||||
|
else:
|
||||||
|
check_inf_nan_cap(p1, value.real)
|
||||||
|
return value
|
||||||
|
|
||||||
_wrappers[complex] = HyComplex
|
_wrappers[complex] = HyComplex
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# This file is part of Hy, which is free software licensed under the Expat
|
# This file is part of Hy, which is free software licensed under the Expat
|
||||||
# license. See the LICENSE.
|
# license. See the LICENSE.
|
||||||
|
|
||||||
|
from math import isnan
|
||||||
from hy.models import (HyExpression, HyInteger, HyFloat, HyComplex, HySymbol,
|
from hy.models import (HyExpression, HyInteger, HyFloat, HyComplex, HySymbol,
|
||||||
HyString, HyDict, HyList, HySet, HyCons)
|
HyString, HyDict, HyList, HySet, HyCons)
|
||||||
from hy.lex import LexException, PrematureEndOfInput, tokenize
|
from hy.lex import LexException, PrematureEndOfInput, tokenize
|
||||||
@ -91,6 +92,22 @@ def test_lex_expression_float():
|
|||||||
assert objs == [HyExpression([HySymbol("foo"), HyFloat(1.e7)])]
|
assert objs == [HyExpression([HySymbol("foo"), HyFloat(1.e7)])]
|
||||||
|
|
||||||
|
|
||||||
|
def test_lex_nan_and_inf():
|
||||||
|
|
||||||
|
assert isnan(tokenize("NaN")[0])
|
||||||
|
assert tokenize("Nan") == [HySymbol("Nan")]
|
||||||
|
assert tokenize("nan") == [HySymbol("nan")]
|
||||||
|
assert tokenize("NAN") == [HySymbol("NAN")]
|
||||||
|
|
||||||
|
assert tokenize("Inf") == [HyFloat(float("inf"))]
|
||||||
|
assert tokenize("inf") == [HySymbol("inf")]
|
||||||
|
assert tokenize("INF") == [HySymbol("INF")]
|
||||||
|
|
||||||
|
assert tokenize("-Inf") == [HyFloat(float("-inf"))]
|
||||||
|
assert tokenize("-inf") == [HySymbol("_inf")]
|
||||||
|
assert tokenize("-INF") == [HySymbol("_INF")]
|
||||||
|
|
||||||
|
|
||||||
def test_lex_expression_complex():
|
def test_lex_expression_complex():
|
||||||
""" Make sure expressions can produce complex """
|
""" Make sure expressions can produce complex """
|
||||||
|
|
||||||
@ -102,6 +119,11 @@ def test_lex_expression_complex():
|
|||||||
assert t("-0.5j") == f(HyComplex(-0.5j))
|
assert t("-0.5j") == f(HyComplex(-0.5j))
|
||||||
assert t("1.e7j") == f(HyComplex(1e7j))
|
assert t("1.e7j") == f(HyComplex(1e7j))
|
||||||
assert t("j") == f(HySymbol("j"))
|
assert t("j") == f(HySymbol("j"))
|
||||||
|
assert isnan(t("NaNj")[0][1].imag)
|
||||||
|
assert t("nanj") == f(HySymbol("nanj"))
|
||||||
|
assert t("Inf+Infj") == f(HyComplex(complex(float("inf"), float("inf"))))
|
||||||
|
assert t("Inf-Infj") == f(HyComplex(complex(float("inf"), float("-inf"))))
|
||||||
|
assert t("Inf-INFj") == f(HySymbol("Inf_INFj"))
|
||||||
|
|
||||||
|
|
||||||
def test_lex_digit_separators():
|
def test_lex_digit_separators():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user