Merge branch 'pr/829'
This commit is contained in:
commit
144ee3b2f0
@ -198,6 +198,8 @@ Hy. Let's experiment with this in the hy interpreter::
|
|||||||
{'dog': 'bark', 'cat': 'meow'}
|
{'dog': 'bark', 'cat': 'meow'}
|
||||||
=> (, 1 2 3)
|
=> (, 1 2 3)
|
||||||
(1, 2, 3)
|
(1, 2, 3)
|
||||||
|
=> #{3 1 2}
|
||||||
|
{1, 2, 3}
|
||||||
|
|
||||||
If you are familiar with other Lisps, you may be interested that Hy
|
If you are familiar with other Lisps, you may be interested that Hy
|
||||||
supports the Common Lisp method of quoting:
|
supports the Common Lisp method of quoting:
|
||||||
|
@ -31,6 +31,7 @@ from hy.models.symbol import HySymbol # NOQA
|
|||||||
from hy.models.float import HyFloat # NOQA
|
from hy.models.float import HyFloat # NOQA
|
||||||
from hy.models.dict import HyDict # NOQA
|
from hy.models.dict import HyDict # NOQA
|
||||||
from hy.models.list import HyList # 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.cons import HyCons # NOQA
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ from hy.models.string import HyString
|
|||||||
from hy.models.symbol import HySymbol
|
from hy.models.symbol import HySymbol
|
||||||
from hy.models.float import HyFloat
|
from hy.models.float import HyFloat
|
||||||
from hy.models.list import HyList
|
from hy.models.list import HyList
|
||||||
|
from hy.models.set import HySet
|
||||||
from hy.models.dict import HyDict
|
from hy.models.dict import HyDict
|
||||||
from hy.models.cons import HyCons
|
from hy.models.cons import HyCons
|
||||||
|
|
||||||
@ -628,7 +629,7 @@ class HyASTCompiler(object):
|
|||||||
name = form.__class__.__name__
|
name = form.__class__.__name__
|
||||||
imports = set([name])
|
imports = set([name])
|
||||||
|
|
||||||
if isinstance(form, (HyList, HyDict)):
|
if isinstance(form, (HyList, HyDict, HySet)):
|
||||||
if not form:
|
if not form:
|
||||||
contents = HyList()
|
contents = HyList()
|
||||||
else:
|
else:
|
||||||
@ -1974,6 +1975,31 @@ class HyASTCompiler(object):
|
|||||||
col_offset=expression.start_column)
|
col_offset=expression.start_column)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@builds(HySet)
|
||||||
|
def compile_set(self, expression):
|
||||||
|
elts, ret, _ = self._compile_collect(expression)
|
||||||
|
if PY27:
|
||||||
|
ret += ast.Set(elts=elts,
|
||||||
|
ctx=ast.Load(),
|
||||||
|
lineno=expression.start_line,
|
||||||
|
col_offset=expression.start_column)
|
||||||
|
else:
|
||||||
|
ret += ast.Call(func=ast.Name(id='set',
|
||||||
|
ctx=ast.Load(),
|
||||||
|
lineno=expression.start_line,
|
||||||
|
col_offset=expression.start_column),
|
||||||
|
args=[
|
||||||
|
ast.List(elts=elts,
|
||||||
|
ctx=ast.Load(),
|
||||||
|
lineno=expression.start_line,
|
||||||
|
col_offset=expression.start_column)],
|
||||||
|
keywords=[],
|
||||||
|
starargs=None,
|
||||||
|
kwargs=None,
|
||||||
|
lineno=expression.start_line,
|
||||||
|
col_offset=expression.start_column)
|
||||||
|
return ret
|
||||||
|
|
||||||
@builds("lambda")
|
@builds("lambda")
|
||||||
@builds("fn")
|
@builds("fn")
|
||||||
@checkargs(min=1)
|
@checkargs(min=1)
|
||||||
|
@ -35,12 +35,13 @@ lg.add('LBRACKET', r'\[')
|
|||||||
lg.add('RBRACKET', r'\]')
|
lg.add('RBRACKET', r'\]')
|
||||||
lg.add('LCURLY', r'\{')
|
lg.add('LCURLY', r'\{')
|
||||||
lg.add('RCURLY', r'\}')
|
lg.add('RCURLY', r'\}')
|
||||||
|
lg.add('HLCURLY', r'#\{')
|
||||||
lg.add('QUOTE', r'\'%s' % end_quote)
|
lg.add('QUOTE', r'\'%s' % end_quote)
|
||||||
lg.add('QUASIQUOTE', r'`%s' % end_quote)
|
lg.add('QUASIQUOTE', r'`%s' % end_quote)
|
||||||
lg.add('UNQUOTESPLICE', r'~@%s' % end_quote)
|
lg.add('UNQUOTESPLICE', r'~@%s' % end_quote)
|
||||||
lg.add('UNQUOTE', r'~%s' % end_quote)
|
lg.add('UNQUOTE', r'~%s' % end_quote)
|
||||||
lg.add('HASHBANG', r'#!.*[^\r\n]')
|
lg.add('HASHBANG', r'#!.*[^\r\n]')
|
||||||
lg.add('HASHREADER', r'#.')
|
lg.add('HASHREADER', r'#[^{]')
|
||||||
|
|
||||||
# A regexp which matches incomplete strings, used to support
|
# A regexp which matches incomplete strings, used to support
|
||||||
# multi-line strings in the interpreter
|
# multi-line strings in the interpreter
|
||||||
|
@ -31,6 +31,7 @@ from hy.models.float import HyFloat
|
|||||||
from hy.models.integer import HyInteger
|
from hy.models.integer import HyInteger
|
||||||
from hy.models.keyword import HyKeyword
|
from hy.models.keyword import HyKeyword
|
||||||
from hy.models.list import HyList
|
from hy.models.list import HyList
|
||||||
|
from hy.models.set import HySet
|
||||||
from hy.models.string import HyString
|
from hy.models.string import HyString
|
||||||
from hy.models.symbol import HySymbol
|
from hy.models.symbol import HySymbol
|
||||||
|
|
||||||
@ -152,6 +153,7 @@ def list_contents_single(p):
|
|||||||
@pg.production("term : paren")
|
@pg.production("term : paren")
|
||||||
@pg.production("term : dict")
|
@pg.production("term : dict")
|
||||||
@pg.production("term : list")
|
@pg.production("term : list")
|
||||||
|
@pg.production("term : set")
|
||||||
@pg.production("term : string")
|
@pg.production("term : string")
|
||||||
def term(p):
|
def term(p):
|
||||||
return p[0]
|
return p[0]
|
||||||
@ -190,6 +192,18 @@ def hash_reader(p):
|
|||||||
return HyExpression([HySymbol("dispatch_reader_macro"), str_object, expr])
|
return HyExpression([HySymbol("dispatch_reader_macro"), str_object, expr])
|
||||||
|
|
||||||
|
|
||||||
|
@pg.production("set : HLCURLY list_contents RCURLY")
|
||||||
|
@set_boundaries
|
||||||
|
def t_set(p):
|
||||||
|
return HySet(p[1])
|
||||||
|
|
||||||
|
|
||||||
|
@pg.production("set : HLCURLY RCURLY")
|
||||||
|
@set_boundaries
|
||||||
|
def empty_set(p):
|
||||||
|
return HySet([])
|
||||||
|
|
||||||
|
|
||||||
@pg.production("dict : LCURLY list_contents RCURLY")
|
@pg.production("dict : LCURLY list_contents RCURLY")
|
||||||
@set_boundaries
|
@set_boundaries
|
||||||
def t_dict(p):
|
def t_dict(p):
|
||||||
|
36
hy/models/set.py
Normal file
36
hy/models/set.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# 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.list import HyList
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
|
||||||
|
class HySet(HyList):
|
||||||
|
"""
|
||||||
|
Hy set (actually a list that pretends to be a set)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, items):
|
||||||
|
items = sorted(items)
|
||||||
|
items = list(reduce(lambda r, v: v in r and r or r+[v], items, []))
|
||||||
|
super(HySet, self).__init__(items)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "#{%s}" % (" ".join([repr(x) for x in self]))
|
@ -27,6 +27,7 @@ from hy.models.symbol import HySymbol
|
|||||||
from hy.models.string import HyString
|
from hy.models.string import HyString
|
||||||
from hy.models.dict import HyDict
|
from hy.models.dict import HyDict
|
||||||
from hy.models.list import HyList
|
from hy.models.list import HyList
|
||||||
|
from hy.models.set import HySet
|
||||||
from hy.models.cons import HyCons
|
from hy.models.cons import HyCons
|
||||||
|
|
||||||
from hy.lex import LexException, PrematureEndOfInput, tokenize
|
from hy.lex import LexException, PrematureEndOfInput, tokenize
|
||||||
@ -202,6 +203,21 @@ def test_dicts():
|
|||||||
])]
|
])]
|
||||||
|
|
||||||
|
|
||||||
|
def test_sets():
|
||||||
|
""" Ensure that we can tokenize a set. """
|
||||||
|
objs = tokenize("#{1 2}")
|
||||||
|
assert objs == [HySet([HyInteger(1), HyInteger(2)])]
|
||||||
|
objs = tokenize("(bar #{foo bar baz})")
|
||||||
|
assert objs == [HyExpression([HySymbol("bar"),
|
||||||
|
HySet(["foo", "bar", "baz"])])]
|
||||||
|
|
||||||
|
objs = tokenize("#{(foo bar) (baz quux)}")
|
||||||
|
assert objs == [HySet([
|
||||||
|
HyExpression([HySymbol("foo"), HySymbol("bar")]),
|
||||||
|
HyExpression([HySymbol("baz"), HySymbol("quux")])
|
||||||
|
])]
|
||||||
|
|
||||||
|
|
||||||
def test_nospace():
|
def test_nospace():
|
||||||
""" Ensure we can tokenize without spaces if we have to """
|
""" Ensure we can tokenize without spaces if we have to """
|
||||||
entry = tokenize("(foo(one two))")[0]
|
entry = tokenize("(foo(one two))")[0]
|
||||||
|
8
tests/models/test_set.py
Normal file
8
tests/models/test_set.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from hy.models.set import HySet
|
||||||
|
|
||||||
|
|
||||||
|
hyset = HySet([3, 1, 2, 2])
|
||||||
|
|
||||||
|
|
||||||
|
def test_set():
|
||||||
|
assert hyset == [1, 2, 3]
|
@ -23,6 +23,12 @@
|
|||||||
(assert (= {1 2 3 4} {1 (+ 1 1) 3 (+ 2 2)})))
|
(assert (= {1 2 3 4} {1 (+ 1 1) 3 (+ 2 2)})))
|
||||||
|
|
||||||
|
|
||||||
|
(defn test-sets []
|
||||||
|
"NATIVE: test sets work right"
|
||||||
|
(assert (= #{1 2 3 4} (| #{1 2} #{3 4})))
|
||||||
|
(assert (= #{} (set))))
|
||||||
|
|
||||||
|
|
||||||
(defn test-setv-get []
|
(defn test-setv-get []
|
||||||
"NATIVE: test setv works on a get expression"
|
"NATIVE: test setv works on a get expression"
|
||||||
(setv foo [0 1 2])
|
(setv foo [0 1 2])
|
||||||
|
Loading…
Reference in New Issue
Block a user