diff --git a/docs/language/internals.rst b/docs/language/internals.rst index 0a1f948..7d8e4a2 100644 --- a/docs/language/internals.rst +++ b/docs/language/internals.rst @@ -44,7 +44,7 @@ Hy parser. HyList ~~~~~~ -``hy.models.list.HyList`` is the base class of "iterable" Hy models. Its +``hy.models.HyList`` is the base class of "iterable" Hy models. Its basic use is to represent bracketed ``[]`` lists, which, when used as a top-level expression, translate to Python list literals in the compilation phase. @@ -58,7 +58,7 @@ objects in a macro, for instance. HyExpression ~~~~~~~~~~~~ -``hy.models.expression.HyExpression`` inherits :ref:`HyList` for +``hy.models.HyExpression`` inherits :ref:`HyList` for parenthesized ``()`` expressions. The compilation result of those expressions depends on the first element of the list: the compiler dispatches expressions between compiler special-forms, user-defined @@ -69,7 +69,7 @@ macros, and regular Python function calls. HyDict ~~~~~~ -``hy.models.dict.HyDict`` inherits :ref:`HyList` for curly-bracketed ``{}`` +``hy.models.HyDict`` inherits :ref:`HyList` for curly-bracketed ``{}`` expressions, which compile down to a Python dictionary literal. The decision of using a list instead of a dict as the base class for @@ -101,7 +101,7 @@ the following order: HyString ~~~~~~~~ -``hy.models.string.HyString`` is the base class of string-equivalent Hy +``hy.models.HyString`` is the base class of string-equivalent Hy models. It also represents double-quoted string literals, ``""``, which compile down to unicode string literals in Python. ``HyStrings`` inherit unicode objects in Python 2, and string objects in Python 3 (and are @@ -118,12 +118,12 @@ strings. Numeric Models ~~~~~~~~~~~~~~ -``hy.models.integer.HyInteger`` represents integer literals (using the +``hy.models.HyInteger`` represents integer literals (using the ``long`` type on Python 2, and ``int`` on Python 3). -``hy.models.float.HyFloat`` represents floating-point literals. +``hy.models.HyFloat`` represents floating-point literals. -``hy.models.complex.HyComplex`` represents complex literals. +``hy.models.HyComplex`` represents complex literals. Numeric models are parsed using the corresponding Python routine, and valid numeric python literals will be turned into their Hy counterpart. @@ -133,7 +133,7 @@ valid numeric python literals will be turned into their Hy counterpart. HySymbol ~~~~~~~~ -``hy.models.symbol.HySymbol`` is the model used to represent symbols +``hy.models.HySymbol`` is the model used to represent symbols in the Hy language. It inherits :ref:`HyString`. ``HySymbol`` objects are mangled in the parsing phase, to help Python @@ -153,7 +153,7 @@ source code. Such a mechanism is used by :ref:`gensym` to generate HyKeyword ~~~~~~~~~ -``hy.models.keyword.HyKeyword`` represents keywords in Hy. Keywords are +``hy.models.HyKeyword`` represents keywords in Hy. Keywords are symbols starting with a ``:``. The class inherits :ref:`HyString`. To distinguish :ref:`HyKeywords ` from :ref:`HySymbols @@ -166,7 +166,7 @@ literal before storage. Cons Cells ========== -``hy.models.cons.HyCons`` is a representation of Python-friendly `cons +``hy.models.HyCons`` is a representation of Python-friendly `cons cells`_. Cons cells are especially useful to mimic features of "usual" LISP variants such as Scheme or Common Lisp. diff --git a/hy/__init__.py b/hy/__init__.py index 4d5ef77..8714fd7 100644 --- a/hy/__init__.py +++ b/hy/__init__.py @@ -26,17 +26,7 @@ except ImportError: __version__ = 'unknown' -from hy.models.expression import HyExpression # NOQA -from hy.models.integer import HyInteger # NOQA -from hy.models.keyword import HyKeyword # NOQA -from hy.models.complex import HyComplex # NOQA -from hy.models.string import HyString # NOQA -from hy.models.symbol import HySymbol # NOQA -from hy.models.float import HyFloat # NOQA -from hy.models.dict import HyDict # NOQA -from hy.models.list import HyList # NOQA -from hy.models.set import HySet # NOQA -from hy.models.cons import HyCons # NOQA +from hy.models import HyExpression, HyInteger, HyKeyword, HyComplex, HyString, HySymbol, HyFloat, HyDict, HyList, HySet, HyCons # NOQA import hy.importer # NOQA diff --git a/hy/cmdline.py b/hy/cmdline.py index 8ef5d4b..3638f6e 100644 --- a/hy/cmdline.py +++ b/hy/cmdline.py @@ -48,9 +48,7 @@ from hy.completer import Completer from hy.errors import HyIOError from hy.macros import macro, require -from hy.models.expression import HyExpression -from hy.models.string import HyString -from hy.models.symbol import HySymbol +from hy.models import HyExpression, HyString, HySymbol from hy._compat import builtins, PY3 diff --git a/hy/compiler.py b/hy/compiler.py index 46a2deb..e441caf 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -24,18 +24,8 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -from hy.models.expression import HyExpression -from hy.models.keyword import HyKeyword -from hy.models.integer import HyInteger -from hy.models.complex import HyComplex -from hy.models.string import HyString -from hy.models.symbol import HySymbol -from hy.models.float import HyFloat -from hy.models.list import HyList -from hy.models.set import HySet -from hy.models.dict import HyDict -from hy.models.cons import HyCons - +from hy.models import (HyExpression, HyKeyword, HyInteger, HyComplex, HyString, + HySymbol, HyFloat, HyList, HySet, HyDict, HyCons) from hy.errors import HyCompileError, HyTypeError from hy.lex.parser import hy_symbol_mangle diff --git a/hy/contrib/multi.hy b/hy/contrib/multi.hy index d79ae2e..62dbf14 100644 --- a/hy/contrib/multi.hy +++ b/hy/contrib/multi.hy @@ -21,9 +21,7 @@ ;; DEALINGS IN THE SOFTWARE. (import [collections [defaultdict]] - [hy.models.expression [HyExpression]] - [hy.models.list [HyList]] - [hy.models.string [HyString]]) + [hy [HyExpression HyList HyString]]) (defclass MultiDispatch [object] [ diff --git a/hy/core/language.hy b/hy/core/language.hy index af20799..d9405cd 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -33,9 +33,7 @@ (import [StringIO [StringIO]]) (import [io [StringIO]])) (import [hy._compat [long-type]]) ; long for python2, int for python3 -(import [hy.models.cons [HyCons]] - [hy.models.symbol [HySymbol]] - [hy.models.keyword [HyKeyword *keyword-prefix*]]) +(import [hy.models [HyCons HySymbol HyKeyword *keyword-prefix*]]) (import [hy.lex [LexException PrematureEndOfInput tokenize]]) (import [hy.compiler [HyASTCompiler]]) diff --git a/hy/core/macros.hy b/hy/core/macros.hy index 7046296..6d32c42 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -26,8 +26,7 @@ ;;; They are automatically required in every module, except inside hy.core -(import [hy.models.list [HyList]] - [hy.models.symbol [HySymbol]] +(import [hy.models [HyList HySymbol]] [hy._compat [PY33 PY34]]) (defmacro as-> [head name &rest rest] diff --git a/hy/lex/parser.py b/hy/lex/parser.py index c790d13..30dd4f5 100644 --- a/hy/lex/parser.py +++ b/hy/lex/parser.py @@ -23,18 +23,8 @@ from functools import wraps from rply import ParserGenerator -from hy.models.complex import HyComplex -from hy.models.cons import HyCons -from hy.models.dict import HyDict -from hy.models.expression import HyExpression -from hy.models.float import HyFloat -from hy.models.integer import HyInteger -from hy.models.keyword import HyKeyword -from hy.models.list import HyList -from hy.models.set import HySet -from hy.models.string import HyString -from hy.models.symbol import HySymbol - +from hy.models import (HyComplex, HyCons, HyDict, HyExpression, HyFloat, + HyInteger, HyKeyword, HyList, HySet, HyString, HySymbol) from .lexer import lexer from .exceptions import LexException, PrematureEndOfInput diff --git a/hy/macros.py b/hy/macros.py index 02b1330..3ddeada 100644 --- a/hy/macros.py +++ b/hy/macros.py @@ -19,9 +19,7 @@ # DEALINGS IN THE SOFTWARE. from inspect import getargspec, formatargspec -from hy.models import replace_hy_obj, wrap_value -from hy.models.expression import HyExpression -from hy.models.string import HyString +from hy.models import replace_hy_obj, wrap_value, HyExpression, HyString from hy.errors import HyTypeError, HyMacroExpansionError diff --git a/hy/models.py b/hy/models.py new file mode 100644 index 0000000..fcfeca8 --- /dev/null +++ b/hy/models.py @@ -0,0 +1,331 @@ +# Copyright (c) 2013 Paul Tagliamonte +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from __future__ import unicode_literals +from hy._compat import PY3, str_type, long_type, string_types + + +class HyObject(object): + """ + Generic Hy Object model. This is helpful to inject things into all the + Hy lexing Objects at once. + """ + + def replace(self, other): + if isinstance(other, HyObject): + for attr in ["start_line", "end_line", + "start_column", "end_column"]: + if not hasattr(self, attr) and hasattr(other, attr): + setattr(self, attr, getattr(other, attr)) + else: + raise TypeError("Can't replace a non Hy object with a Hy object") + + return self + + +_wrappers = {} + + +def wrap_value(x): + """Wrap `x` into the corresponding Hy type. + + This allows replace_hy_obj to convert a non Hy object to a Hy object. + + This also allows a macro to return an unquoted expression transparently. + + """ + + wrapper = _wrappers.get(type(x)) + if wrapper is None: + return x + else: + return wrapper(x) + + +def replace_hy_obj(obj, other): + + if isinstance(obj, HyObject): + return obj.replace(other) + + wrapped_obj = wrap_value(obj) + + if isinstance(wrapped_obj, HyObject): + return wrapped_obj.replace(other) + else: + raise TypeError("Don't know how to wrap a %s object to a HyObject" + % type(obj)) + + +class HyString(HyObject, str_type): + """ + Generic Hy String object. Helpful to store string literals from Hy + scripts. It's either a ``str`` or a ``unicode``, depending on the + Python version. + """ + pass + +_wrappers[str_type] = HyString + + +class HySymbol(HyString): + """ + Hy Symbol. Basically a String. + """ + + def __init__(self, string): + self += string + +_wrappers[bool] = lambda x: HySymbol("True") if x else HySymbol("False") +_wrappers[type(None)] = lambda foo: HySymbol("None") + + +KEYWORD_PREFIX = "\uFDD0" + + +class HyKeyword(HyObject, str_type): + """Generic Hy Keyword object. It's either a ``str`` or a ``unicode``, + depending on the Python version. + """ + + def __new__(cls, value): + if not value.startswith(KEYWORD_PREFIX): + value = KEYWORD_PREFIX + value + + obj = str_type.__new__(cls, value) + return obj + + +class HyInteger(HyObject, long_type): + """ + Internal representation of a Hy Integer. May raise a ValueError as if + int(foo) was called, given HyInteger(foo). On python 2.x long will + be used instead + """ + + def __new__(cls, number, *args, **kwargs): + if isinstance(number, string_types): + number = number.replace("_", "").replace(",", "") + bases = {"0x": 16, "0o": 8, "0b": 2} + for leader, base in bases.items(): + if number.startswith(leader): + # We've got a string, known leader, set base. + number = long_type(number, base=base) + break + else: + # We've got a string, no known leader; base 10. + number = long_type(number, base=10) + else: + # We've got a non-string; convert straight. + number = long_type(number) + return super(HyInteger, cls).__new__(cls, number) + + +_wrappers[int] = HyInteger +if not PY3: # do not add long on python3 + _wrappers[long_type] = HyInteger + + +class HyFloat(HyObject, float): + """ + Internal representation of a Hy Float. May raise a ValueError as if + float(foo) was called, given HyFloat(foo). + """ + + def __new__(cls, number, *args, **kwargs): + if isinstance(number, string_types): + number = number.replace("_", "").replace(",", "") + number = float(number) + return super(HyFloat, cls).__new__(cls, number) + +_wrappers[float] = HyFloat + + +class HyComplex(HyObject, complex): + """ + Internal representation of a Hy Complex. May raise a ValueError as if + complex(foo) was called, given HyComplex(foo). + """ + + def __new__(cls, number, *args, **kwargs): + if isinstance(number, string_types): + number = number.replace("_", "").replace(",", "") + number = complex(number) + return super(HyComplex, cls).__new__(cls, number) + +_wrappers[complex] = HyComplex + + +class HyList(HyObject, list): + """ + Hy List. Basically just a list. + """ + + def replace(self, other): + for x in self: + replace_hy_obj(x, other) + + HyObject.replace(self, other) + return self + + def __add__(self, other): + return self.__class__(super(HyList, self).__add__(other)) + + def __getslice__(self, start, end): + return self.__class__(super(HyList, self).__getslice__(start, end)) + + def __getitem__(self, item): + ret = super(HyList, self).__getitem__(item) + + if isinstance(item, slice): + return self.__class__(ret) + + return ret + + def __repr__(self): + return "[%s]" % (" ".join([repr(x) for x in self])) + +_wrappers[list] = lambda l: HyList(wrap_value(x) for x in l) +_wrappers[tuple] = lambda t: HyList(wrap_value(x) for x in t) + + +class HyDict(HyList): + """ + HyDict (just a representation of a dict) + """ + + def __repr__(self): + return "{%s}" % (" ".join([repr(x) for x in self])) + + def keys(self): + return self[0::2] + + def values(self): + return self[1::2] + + def items(self): + return list(zip(self.keys(), self.values())) + +_wrappers[dict] = lambda d: HyDict(wrap_value(x) for x in sum(d.items(), ())) + + +class HyExpression(HyList): + """ + Hy S-Expression. Basically just a list. + """ + + def __repr__(self): + return "(%s)" % (" ".join([repr(x) for x in self])) + +_wrappers[HyExpression] = lambda e: HyExpression(wrap_value(x) for x in e) + + +class HySet(HyList): + """ + Hy set (just a representation of a set) + """ + + def __repr__(self): + return "#{%s}" % (" ".join([repr(x) for x in self])) + +_wrappers[set] = lambda s: HySet(wrap_value(x) for x in s) + + +class HyCons(HyObject): + """ + HyCons: a cons object. + + Building a HyCons of something and a HyList really builds a HyList + """ + + __slots__ = ["car", "cdr"] + + def __new__(cls, car, cdr): + if isinstance(cdr, list): + + # Keep unquotes in the cdr of conses + if type(cdr) == HyExpression: + if len(cdr) > 0 and type(cdr[0]) == HySymbol: + if cdr[0] in ("unquote", "unquote_splice"): + return super(HyCons, cls).__new__(cls) + + return cdr.__class__([wrap_value(car)] + cdr) + + elif cdr is None: + return HyExpression([wrap_value(car)]) + + else: + return super(HyCons, cls).__new__(cls) + + def __init__(self, car, cdr): + self.car = wrap_value(car) + self.cdr = wrap_value(cdr) + + def __getitem__(self, n): + if n == 0: + return self.car + if n == slice(1, None): + return self.cdr + + raise IndexError( + "Can only get the car ([0]) or the cdr ([1:]) of a HyCons") + + def __setitem__(self, n, new): + if n == 0: + self.car = new + return + if n == slice(1, None): + self.cdr = new + return + + raise IndexError( + "Can only set the car ([0]) or the cdr ([1:]) of a HyCons") + + def __iter__(self): + yield self.car + try: + iterator = (i for i in self.cdr) + except TypeError: + if self.cdr is not None: + yield self.cdr + raise TypeError("Iteration on malformed cons") + else: + for i in iterator: + yield i + + def replace(self, other): + if self.car is not None: + replace_hy_obj(self.car, other) + if self.cdr is not None: + replace_hy_obj(self.cdr, other) + + HyObject.replace(self, other) + + def __repr__(self): + if isinstance(self.cdr, self.__class__): + return "(%s %s)" % (repr(self.car), repr(self.cdr)[1:-1]) + else: + return "(%s . %s)" % (repr(self.car), repr(self.cdr)) + + def __eq__(self, other): + return ( + isinstance(other, self.__class__) and + self.car == other.car and + self.cdr == other.cdr + ) diff --git a/hy/models/__init__.py b/hy/models/__init__.py deleted file mode 100644 index f2818c3..0000000 --- a/hy/models/__init__.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - - -class HyObject(object): - """ - Generic Hy Object model. This is helpful to inject things into all the - Hy lexing Objects at once. - """ - - def replace(self, other): - if isinstance(other, HyObject): - for attr in ["start_line", "end_line", - "start_column", "end_column"]: - if not hasattr(self, attr) and hasattr(other, attr): - setattr(self, attr, getattr(other, attr)) - else: - raise TypeError("Can't replace a non Hy object with a Hy object") - - return self - -_wrappers = {} - - -def wrap_value(x): - """Wrap `x` into the corresponding Hy type. - - This allows replace_hy_obj to convert a non Hy object to a Hy object. - - This also allows a macro to return an unquoted expression transparently. - - """ - - wrapper = _wrappers.get(type(x)) - if wrapper is None: - return x - else: - return wrapper(x) - - -def replace_hy_obj(obj, other): - - if isinstance(obj, HyObject): - return obj.replace(other) - - wrapped_obj = wrap_value(obj) - - if isinstance(wrapped_obj, HyObject): - return wrapped_obj.replace(other) - else: - raise TypeError("Don't know how to wrap a %s object to a HyObject" - % type(obj)) diff --git a/hy/models/complex.py b/hy/models/complex.py deleted file mode 100644 index d45ce6f..0000000 --- a/hy/models/complex.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import HyObject, _wrappers -from hy._compat import string_types - - -class HyComplex(HyObject, complex): - """ - Internal representation of a Hy Complex. May raise a ValueError as if - complex(foo) was called, given HyComplex(foo). - """ - - def __new__(cls, number, *args, **kwargs): - if isinstance(number, string_types): - number = number.replace("_", "").replace(",", "") - number = complex(number) - return super(HyComplex, cls).__new__(cls, number) - -_wrappers[complex] = HyComplex diff --git a/hy/models/cons.py b/hy/models/cons.py deleted file mode 100644 index 6c2fdc0..0000000 --- a/hy/models/cons.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2013 Nicolas Dandrimont -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import HyObject, replace_hy_obj, wrap_value -from hy.models.expression import HyExpression -from hy.models.symbol import HySymbol - - -class HyCons(HyObject): - """ - HyCons: a cons object. - - Building a HyCons of something and a HyList really builds a HyList - """ - - __slots__ = ["car", "cdr"] - - def __new__(cls, car, cdr): - if isinstance(cdr, list): - - # Keep unquotes in the cdr of conses - if type(cdr) == HyExpression: - if len(cdr) > 0 and type(cdr[0]) == HySymbol: - if cdr[0] in ("unquote", "unquote_splice"): - return super(HyCons, cls).__new__(cls) - - return cdr.__class__([wrap_value(car)] + cdr) - - elif cdr is None: - return HyExpression([wrap_value(car)]) - - else: - return super(HyCons, cls).__new__(cls) - - def __init__(self, car, cdr): - self.car = wrap_value(car) - self.cdr = wrap_value(cdr) - - def __getitem__(self, n): - if n == 0: - return self.car - if n == slice(1, None): - return self.cdr - - raise IndexError( - "Can only get the car ([0]) or the cdr ([1:]) of a HyCons") - - def __setitem__(self, n, new): - if n == 0: - self.car = new - return - if n == slice(1, None): - self.cdr = new - return - - raise IndexError( - "Can only set the car ([0]) or the cdr ([1:]) of a HyCons") - - def __iter__(self): - yield self.car - try: - iterator = (i for i in self.cdr) - except TypeError: - if self.cdr is not None: - yield self.cdr - raise TypeError("Iteration on malformed cons") - else: - for i in iterator: - yield i - - def replace(self, other): - if self.car is not None: - replace_hy_obj(self.car, other) - if self.cdr is not None: - replace_hy_obj(self.cdr, other) - - HyObject.replace(self, other) - - def __repr__(self): - if isinstance(self.cdr, self.__class__): - return "(%s %s)" % (repr(self.car), repr(self.cdr)[1:-1]) - else: - return "(%s . %s)" % (repr(self.car), repr(self.cdr)) - - def __eq__(self, other): - return ( - isinstance(other, self.__class__) and - self.car == other.car and - self.cdr == other.cdr - ) diff --git a/hy/models/dict.py b/hy/models/dict.py deleted file mode 100644 index bb02afc..0000000 --- a/hy/models/dict.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import _wrappers, wrap_value -from hy.models.list import HyList - - -class HyDict(HyList): - """ - HyDict (just a representation of a dict) - """ - - def __repr__(self): - return "{%s}" % (" ".join([repr(x) for x in self])) - - def keys(self): - return self[0::2] - - def values(self): - return self[1::2] - - def items(self): - return list(zip(self.keys(), self.values())) - -_wrappers[dict] = lambda d: HyDict(wrap_value(x) for x in sum(d.items(), ())) diff --git a/hy/models/expression.py b/hy/models/expression.py deleted file mode 100644 index 6e8b041..0000000 --- a/hy/models/expression.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import _wrappers, wrap_value -from hy.models.list import HyList - - -class HyExpression(HyList): - """ - Hy S-Expression. Basically just a list. - """ - - def __repr__(self): - return "(%s)" % (" ".join([repr(x) for x in self])) - -_wrappers[HyExpression] = lambda e: HyExpression(wrap_value(x) for x in e) diff --git a/hy/models/float.py b/hy/models/float.py deleted file mode 100644 index 4669ff2..0000000 --- a/hy/models/float.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import HyObject, _wrappers -from hy._compat import string_types - - -class HyFloat(HyObject, float): - """ - Internal representation of a Hy Float. May raise a ValueError as if - float(foo) was called, given HyFloat(foo). - """ - - def __new__(cls, number, *args, **kwargs): - if isinstance(number, string_types): - number = number.replace("_", "").replace(",", "") - number = float(number) - return super(HyFloat, cls).__new__(cls, number) - -_wrappers[float] = HyFloat diff --git a/hy/models/integer.py b/hy/models/integer.py deleted file mode 100644 index e780b26..0000000 --- a/hy/models/integer.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import HyObject, _wrappers -from hy._compat import long_type, string_types - -import sys - - -class HyInteger(HyObject, long_type): - """ - Internal representation of a Hy Integer. May raise a ValueError as if - int(foo) was called, given HyInteger(foo). On python 2.x long will - be used instead - """ - - def __new__(cls, number, *args, **kwargs): - if isinstance(number, string_types): - number = number.replace("_", "").replace(",", "") - bases = {"0x": 16, "0o": 8, "0b": 2} - for leader, base in bases.items(): - if number.startswith(leader): - # We've got a string, known leader, set base. - number = long_type(number, base=base) - break - else: - # We've got a string, no known leader; base 10. - number = long_type(number, base=10) - else: - # We've got a non-string; convert straight. - number = long_type(number) - return super(HyInteger, cls).__new__(cls, number) - - -_wrappers[int] = HyInteger - -if sys.version_info[0] < 3: # do not add long on python3 - _wrappers[long_type] = HyInteger diff --git a/hy/models/keyword.py b/hy/models/keyword.py deleted file mode 100644 index 32b2306..0000000 --- a/hy/models/keyword.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2013 Gergely Nagy -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from __future__ import unicode_literals -from hy.models import HyObject -from hy._compat import str_type - - -KEYWORD_PREFIX = "\uFDD0" - - -class HyKeyword(HyObject, str_type): - """Generic Hy Keyword object. It's either a ``str`` or a ``unicode``, - depending on the Python version. - """ - - def __new__(cls, value): - if not value.startswith(KEYWORD_PREFIX): - value = KEYWORD_PREFIX + value - - obj = str_type.__new__(cls, value) - return obj diff --git a/hy/models/list.py b/hy/models/list.py deleted file mode 100644 index 54c8a85..0000000 --- a/hy/models/list.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import HyObject, replace_hy_obj, _wrappers, wrap_value - - -class HyList(HyObject, list): - """ - Hy List. Basically just a list. - """ - - def replace(self, other): - for x in self: - replace_hy_obj(x, other) - - HyObject.replace(self, other) - return self - - def __add__(self, other): - return self.__class__(super(HyList, self).__add__(other)) - - def __getslice__(self, start, end): - return self.__class__(super(HyList, self).__getslice__(start, end)) - - def __getitem__(self, item): - ret = super(HyList, self).__getitem__(item) - - if isinstance(item, slice): - return self.__class__(ret) - - return ret - - def __repr__(self): - return "[%s]" % (" ".join([repr(x) for x in self])) - -_wrappers[list] = lambda l: HyList(wrap_value(x) for x in l) -_wrappers[tuple] = lambda t: HyList(wrap_value(x) for x in t) diff --git a/hy/models/set.py b/hy/models/set.py deleted file mode 100644 index fda7b52..0000000 --- a/hy/models/set.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import _wrappers, wrap_value -from hy.models.list import HyList - - -class HySet(HyList): - """ - Hy set (just a representation of a set) - """ - - def __repr__(self): - return "#{%s}" % (" ".join([repr(x) for x in self])) - -_wrappers[set] = lambda s: HySet(wrap_value(x) for x in s) diff --git a/hy/models/string.py b/hy/models/string.py deleted file mode 100644 index 2e406cb..0000000 --- a/hy/models/string.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import HyObject, _wrappers -from hy._compat import str_type - - -class HyString(HyObject, str_type): - """ - Generic Hy String object. Helpful to store string literals from Hy - scripts. It's either a ``str`` or a ``unicode``, depending on the - Python version. - """ - pass - -_wrappers[str_type] = HyString diff --git a/hy/models/symbol.py b/hy/models/symbol.py deleted file mode 100644 index 8d767c7..0000000 --- a/hy/models/symbol.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2013 Paul Tagliamonte -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models import _wrappers -from hy.models.string import HyString - - -class HySymbol(HyString): - """ - Hy Symbol. Basically a String. - """ - - def __init__(self, string): - self += string - -_wrappers[bool] = lambda x: HySymbol("True") if x else HySymbol("False") -_wrappers[type(None)] = lambda foo: HySymbol("None") diff --git a/tests/compilers/test_compiler.py b/tests/compilers/test_compiler.py index 35e92ba..f2765d7 100644 --- a/tests/compilers/test_compiler.py +++ b/tests/compilers/test_compiler.py @@ -23,10 +23,7 @@ import ast import sys from hy import compiler -from hy.models.expression import HyExpression -from hy.models.list import HyList -from hy.models.symbol import HySymbol -from hy.models.integer import HyInteger +from hy.models import HyExpression, HyList, HySymbol, HyInteger from hy._compat import PY33 if sys.version_info[0] <= 2 and sys.version_info[1] <= 6: diff --git a/tests/lex/test_lex.py b/tests/lex/test_lex.py index 881eef2..9691888 100644 --- a/tests/lex/test_lex.py +++ b/tests/lex/test_lex.py @@ -19,17 +19,8 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -from hy.models.expression import HyExpression -from hy.models.integer import HyInteger -from hy.models.float import HyFloat -from hy.models.complex import HyComplex -from hy.models.symbol import HySymbol -from hy.models.string import HyString -from hy.models.dict import HyDict -from hy.models.list import HyList -from hy.models.set import HySet -from hy.models.cons import HyCons - +from hy.models import (HyExpression, HyInteger, HyFloat, HyComplex, HySymbol, + HyString, HyDict, HyList, HySet, HyCons) from hy.lex import LexException, PrematureEndOfInput, tokenize diff --git a/tests/macros/test_macro_processor.py b/tests/macros/test_macro_processor.py index 9cb17c2..4d999bb 100644 --- a/tests/macros/test_macro_processor.py +++ b/tests/macros/test_macro_processor.py @@ -2,10 +2,7 @@ from hy.macros import macro, macroexpand from hy.lex import tokenize -from hy.models.string import HyString -from hy.models.list import HyList -from hy.models.symbol import HySymbol -from hy.models.expression import HyExpression +from hy.models import HyString, HyList, HySymbol, HyExpression from hy.errors import HyMacroExpansionError from hy.compiler import HyASTCompiler diff --git a/tests/models/__init__.py b/tests/models/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/models/test_cons.py b/tests/models/test_cons.py deleted file mode 100644 index 51b3b10..0000000 --- a/tests/models/test_cons.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2013 Nicolas Dandrimont -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -from hy.models.cons import HyCons - - -def test_cons_slicing(): - """Check that cons slicing works as expected""" - cons = HyCons("car", "cdr") - assert cons[0] == "car" - assert cons[1:] == "cdr" - try: - cons[:] - assert True is False - except IndexError: - pass - - try: - cons[1] - assert True is False - except IndexError: - pass - - -def test_cons_replacing(): - """Check that assigning to a cons works as expected""" - cons = HyCons("foo", "bar") - cons[0] = "car" - - assert cons == HyCons("car", "bar") - - cons[1:] = "cdr" - assert cons == HyCons("car", "cdr") - - try: - cons[:] = "foo" - assert True is False - except IndexError: - pass diff --git a/tests/models/test_dict.py b/tests/models/test_dict.py deleted file mode 100644 index cf3b2fd..0000000 --- a/tests/models/test_dict.py +++ /dev/null @@ -1,16 +0,0 @@ -from hy.models.dict import HyDict - - -hydict = HyDict(["a", 1, "b", 2, "c", 3]) - - -def test_dict_items(): - assert hydict.items() == [("a", 1), ("b", 2), ("c", 3)] - - -def test_dict_keys(): - assert hydict.keys() == ["a", "b", "c"] - - -def test_dict_values(): - assert hydict.values() == [1, 2, 3] diff --git a/tests/models/test_list.py b/tests/models/test_list.py deleted file mode 100644 index cc49c70..0000000 --- a/tests/models/test_list.py +++ /dev/null @@ -1,22 +0,0 @@ -from hy.models.list import HyList - - -def test_list_add(): - """Check that adding two HyLists generates a HyList""" - a = HyList([1, 2, 3]) - b = HyList([3, 4, 5]) - c = a + b - assert c == [1, 2, 3, 3, 4, 5] - assert c.__class__ == HyList - - -def test_list_slice(): - """Check that slicing a HyList produces a HyList""" - a = HyList([1, 2, 3, 4]) - sl1 = a[1:] - sl5 = a[5:] - - assert type(sl1) == HyList - assert sl1 == HyList([2, 3, 4]) - assert type(sl5) == HyList - assert sl5 == HyList([]) diff --git a/tests/models/test_replace_hy_obj.py b/tests/models/test_replace_hy_obj.py deleted file mode 100644 index 540749f..0000000 --- a/tests/models/test_replace_hy_obj.py +++ /dev/null @@ -1,26 +0,0 @@ -from hy._compat import long_type, str_type -from hy.models.string import HyString -from hy.models.integer import HyInteger -from hy.models.list import HyList - -from hy.models import replace_hy_obj - - -def test_replace_long_type(): - """ Test replacing integers.""" - replaced = replace_hy_obj(long_type(0), HyInteger(13)) - assert replaced == HyInteger(0) - - -def test_replace_string_type(): - """Test replacing python string""" - replaced = replace_hy_obj(str_type("foo"), HyString("bar")) - assert replaced == HyString("foo") - - -def test_replace_tuple(): - """ Test replacing tuples.""" - replaced = replace_hy_obj((long_type(0), ), HyInteger(13)) - assert type(replaced) == HyList - assert type(replaced[0]) == HyInteger - assert replaced == HyList([HyInteger(0)]) diff --git a/tests/models/test_set.py b/tests/models/test_set.py deleted file mode 100644 index 0462c2c..0000000 --- a/tests/models/test_set.py +++ /dev/null @@ -1,8 +0,0 @@ -from hy.models.set import HySet - - -hyset = HySet([3, 1, 2, 2]) - - -def test_set(): - assert hyset == [3, 1, 2, 2] diff --git a/tests/models/test_wrap_value.py b/tests/models/test_wrap_value.py deleted file mode 100644 index 140adbb..0000000 --- a/tests/models/test_wrap_value.py +++ /dev/null @@ -1,28 +0,0 @@ -from hy._compat import long_type -from hy.models.integer import HyInteger -from hy.models.list import HyList -from hy.models.expression import HyExpression - -from hy.models import wrap_value - - -def test_wrap_long_type(): - """ Test conversion of integers.""" - wrapped = wrap_value(long_type(0)) - assert type(wrapped) == HyInteger - - -def test_wrap_tuple(): - """ Test conversion of tuples.""" - wrapped = wrap_value((HyInteger(0),)) - assert type(wrapped) == HyList - assert type(wrapped[0]) == HyInteger - assert wrapped == HyList([HyInteger(0)]) - - -def test_wrap_nested_expr(): - """ Test conversion of HyExpressions with embedded non-HyObjects.""" - wrapped = wrap_value(HyExpression([long_type(0)])) - assert type(wrapped) == HyExpression - assert type(wrapped[0]) == HyInteger - assert wrapped == HyExpression([HyInteger(0)]) diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index a24a401..52fbb1e 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -241,7 +241,7 @@ (defn test-gensym [] "NATIVE: testing the gensym function" - (import [hy.models.symbol [HySymbol]]) + (import [hy.models [HySymbol]]) (setv s1 (gensym)) (assert (isinstance s1 HySymbol)) (assert (= 0 (.find s1 ":G_"))) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index b5f8d43..6057b01 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -1363,7 +1363,7 @@ (if-python2 (import [StringIO [StringIO]]) (import [io [StringIO]])) - (import [hy.models.expression [HyExpression]]) + (import [hy.models [HyExpression]]) (def stdin-buffer (StringIO "(+ 2 2)\n(- 2 2)")) (assert (= (eval (read stdin-buffer)) 4)) diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..390f017 --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,123 @@ +from hy._compat import long_type, str_type +from hy.models import (wrap_value, replace_hy_obj, HyString, HyInteger, HyList, + HyDict, HySet, HyExpression, HyCons) + + +def test_wrap_long_type(): + """ Test conversion of integers.""" + wrapped = wrap_value(long_type(0)) + assert type(wrapped) == HyInteger + + +def test_wrap_tuple(): + """ Test conversion of tuples.""" + wrapped = wrap_value((HyInteger(0),)) + assert type(wrapped) == HyList + assert type(wrapped[0]) == HyInteger + assert wrapped == HyList([HyInteger(0)]) + + +def test_wrap_nested_expr(): + """ Test conversion of HyExpressions with embedded non-HyObjects.""" + wrapped = wrap_value(HyExpression([long_type(0)])) + assert type(wrapped) == HyExpression + assert type(wrapped[0]) == HyInteger + assert wrapped == HyExpression([HyInteger(0)]) + + +def test_replace_long_type(): + """ Test replacing integers.""" + replaced = replace_hy_obj(long_type(0), HyInteger(13)) + assert replaced == HyInteger(0) + + +def test_replace_string_type(): + """Test replacing python string""" + replaced = replace_hy_obj(str_type("foo"), HyString("bar")) + assert replaced == HyString("foo") + + +def test_replace_tuple(): + """ Test replacing tuples.""" + replaced = replace_hy_obj((long_type(0), ), HyInteger(13)) + assert type(replaced) == HyList + assert type(replaced[0]) == HyInteger + assert replaced == HyList([HyInteger(0)]) + + +def test_list_add(): + """Check that adding two HyLists generates a HyList""" + a = HyList([1, 2, 3]) + b = HyList([3, 4, 5]) + c = a + b + assert c == [1, 2, 3, 3, 4, 5] + assert c.__class__ == HyList + + +def test_list_slice(): + """Check that slicing a HyList produces a HyList""" + a = HyList([1, 2, 3, 4]) + sl1 = a[1:] + sl5 = a[5:] + + assert type(sl1) == HyList + assert sl1 == HyList([2, 3, 4]) + assert type(sl5) == HyList + assert sl5 == HyList([]) + + +hydict = HyDict(["a", 1, "b", 2, "c", 3]) + + +def test_dict_items(): + assert hydict.items() == [("a", 1), ("b", 2), ("c", 3)] + + +def test_dict_keys(): + assert hydict.keys() == ["a", "b", "c"] + + +def test_dict_values(): + assert hydict.values() == [1, 2, 3] + + +hyset = HySet([3, 1, 2, 2]) + + +def test_set(): + assert hyset == [3, 1, 2, 2] + + +def test_cons_slicing(): + """Check that cons slicing works as expected""" + cons = HyCons("car", "cdr") + assert cons[0] == "car" + assert cons[1:] == "cdr" + try: + cons[:] + assert True is False + except IndexError: + pass + + try: + cons[1] + assert True is False + except IndexError: + pass + + +def test_cons_replacing(): + """Check that assigning to a cons works as expected""" + cons = HyCons("foo", "bar") + cons[0] = "car" + + assert cons == HyCons("car", "bar") + + cons[1:] = "cdr" + assert cons == HyCons("car", "cdr") + + try: + cons[:] = "foo" + assert True is False + except IndexError: + pass