Merge pull request #1224 from Kodiologist/refactor-models
Refactor hy.models
This commit is contained in:
commit
92d5d6b42c
@ -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 <HyKeyword>` 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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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] [
|
||||
|
||||
|
@ -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]])
|
||||
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
|
||||
(import [hy.compiler [HyASTCompiler]])
|
||||
|
||||
@ -458,7 +456,7 @@
|
||||
(defn keyword [value]
|
||||
"Create a keyword from the given value. Strings numbers and even objects
|
||||
with the __name__ magic will work"
|
||||
(if (and (string? value) (value.startswith *keyword-prefix*))
|
||||
(if (and (string? value) (value.startswith HyKeyword.PREFIX))
|
||||
(hyify value)
|
||||
(if (string? value)
|
||||
(HyKeyword (+ ":" (hyify value)))
|
||||
@ -469,7 +467,7 @@
|
||||
(defn name [value]
|
||||
"Convert the given value to a string. Keyword special character will be stripped.
|
||||
String will be used as is. Even objects with the __name__ magic will work"
|
||||
(if (and (string? value) (value.startswith *keyword-prefix*))
|
||||
(if (and (string? value) (value.startswith HyKeyword.PREFIX))
|
||||
(hyify (cut value 2))
|
||||
(if (string? value)
|
||||
(hyify value)
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
332
hy/models.py
Normal file
332
hy/models.py
Normal file
@ -0,0 +1,332 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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")
|
||||
|
||||
|
||||
class HyKeyword(HyObject, str_type):
|
||||
"""Generic Hy Keyword object. It's either a ``str`` or a ``unicode``,
|
||||
depending on the Python version.
|
||||
"""
|
||||
|
||||
PREFIX = "\uFDD0"
|
||||
|
||||
def __new__(cls, value):
|
||||
if not value.startswith(cls.PREFIX):
|
||||
value = cls.PREFIX + value
|
||||
|
||||
obj = str_type.__new__(cls, value)
|
||||
return obj
|
||||
|
||||
|
||||
def strip_digit_separators(number):
|
||||
return (number.replace("_", "").replace(",", "")
|
||||
if isinstance(number, string_types)
|
||||
else number)
|
||||
|
||||
|
||||
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 = strip_digit_separators(number)
|
||||
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):
|
||||
number = float(strip_digit_separators(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):
|
||||
number = complex(strip_digit_separators(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
|
||||
)
|
@ -1,69 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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))
|
@ -1,37 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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
|
@ -1,107 +0,0 @@
|
||||
# Copyright (c) 2013 Nicolas Dandrimont <nicolas.dandrimont@crans.org>
|
||||
#
|
||||
# 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
|
||||
)
|
@ -1,42 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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(), ()))
|
@ -1,33 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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)
|
@ -1,37 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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
|
@ -1,55 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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
|
@ -1,39 +0,0 @@
|
||||
# Copyright (c) 2013 Gergely Nagy <algernon@madhouse-project.org>
|
||||
#
|
||||
# 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
|
@ -1,54 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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)
|
@ -1,33 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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)
|
@ -1,33 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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
|
@ -1,34 +0,0 @@
|
||||
# Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
|
||||
#
|
||||
# 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")
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,56 +0,0 @@
|
||||
# Copyright (c) 2013 Nicolas Dandrimont <nicolas.dandrimont@crans.org>
|
||||
#
|
||||
# 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
|
@ -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]
|
@ -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([])
|
@ -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)])
|
@ -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]
|
@ -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)])
|
@ -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_")))
|
||||
|
@ -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))
|
||||
|
123
tests/test_models.py
Normal file
123
tests/test_models.py
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user