diff --git a/.travis.yml b/.travis.yml index 4dcaa29..1b8ef6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ python: # command to install dependencies install: - pip install -r requirements.txt --use-mirrors - - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2 astor --use-mirrors; fi + - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install importlib unittest2 astor --use-mirrors; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install astor --use-mirrors; fi - if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi - python setup.py -q install diff --git a/hy/compiler.py b/hy/compiler.py index d92ede3..9259a9b 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -36,14 +36,14 @@ from hy.models.list import HyList from hy.models.dict import HyDict import hy.importer -from hy.core import process - -from hy.util import str_type from hy.macros import require +from hy.util import str_type +from hy.core import process -import codecs import traceback +import importlib +import codecs import ast import sys @@ -61,6 +61,17 @@ def compile_time_ns(module_name): return ns +_stdlib = {} + + +def load_stdlib(): + import hy.core + for module in hy.core.STDLIB: + mod = importlib.import_module(module) + for e in mod.EXPORTS: + _stdlib[e] = module + + class HyCompileError(HyError): def __init__(self, exception, traceback=None): self.exception = exception @@ -339,6 +350,9 @@ class HyASTCompiler(object): self.anon_var_count = 0 self.imports = defaultdict(set) self.module_name = module_name + if not module_name.startswith("hy.core"): + # everything in core needs to be explicit. + load_stdlib() def get_anon_var(self): self.anon_var_count += 1 @@ -1432,6 +1446,10 @@ class HyASTCompiler(object): ret = self.compile_atom(fn, expression) if ret: return ret + + if fn in _stdlib: + self.imports[_stdlib[fn]].add(fn) + if fn.startswith("."): # (.split "test test") -> "test test".split() diff --git a/hy/core/__init__.py b/hy/core/__init__.py index df38a3d..2c29df6 100644 --- a/hy/core/__init__.py +++ b/hy/core/__init__.py @@ -24,6 +24,10 @@ MACROS = [ "hy.core.bootstrap", ] +STDLIB = [ + "hy.core.language" +] + def process(tree, module_name): load_macros() diff --git a/hy/core/bootstrap.py b/hy/core/bootstrap.py index 5cf4106..6b9171f 100644 --- a/hy/core/bootstrap.py +++ b/hy/core/bootstrap.py @@ -137,21 +137,6 @@ def let_macro(variables, *body): return HyExpression([expr + list(body)]) -@macro("take") -def take_macro(n, lst): - return HyExpression([HySymbol('slice'), - lst, - HyInteger(0), - HyInteger(n)]) - - -@macro("drop") -def drop_macro(n, lst): - return HyExpression([HySymbol('slice'), - lst, - HyInteger(n)]) - - @macro("when") def when_macro(test, *body): return HyExpression([ diff --git a/hy/core/language.hy b/hy/core/language.hy new file mode 100644 index 0000000..1401db5 --- /dev/null +++ b/hy/core/language.hy @@ -0,0 +1,22 @@ +;;;; This contains some of the core Hy functions used +;;;; to make functional programming slightly easier. +;;;; + + +(defn take [count what] + "Take `count` elements from `what`, or the whole set if the total + number of entries in `what` is less than `count`." + (setv what (iter what)) + (for [i (range count)] + (yield (next what)))) + + +(defn drop [count coll] + "Drop `count` elements from `coll` and return the iter" + (let [ [citer (iter coll)] ] + (for [i (range count)] + (next citer)) + citer)) + + +(def *exports* ["take" "drop"]) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 03c62b0..d8f3825 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -385,9 +385,9 @@ (defn test-drop [] "NATIVE: test drop" - (assert (= (drop 0 [2 3]) [2 3])) - (assert (= (drop 1 [2 3]) [3])) - (assert (= (drop 2 [2 3]) []))) + (assert (= (list (drop 0 [2 3])) [2 3])) + (assert (= (list (drop 1 [2 3])) [3])) + (assert (= (list (drop 2 [2 3])) []))) (defn test-rest [] @@ -741,6 +741,13 @@ (assert (= "test" (:foo {:foo "test"})))) +(defn test-take [] + "NATIVE: test the take operator" + (assert (= [1 2 3] (list (take 3 [1 2 3])))) + (assert (= [1 2 3] (list (take 4 [1 2 3])))) + (assert (= [1 2] (list (take 2 [1 2 4]))))) + + (defn test-break-breaking [] "NATIVE: test checking if break actually breaks" (defn holy-grail [] (for [x (range 10)] (if (= x 5) (break))) x) diff --git a/tox.ini b/tox.ini index 1fb410a..dc99df8 100644 --- a/tox.ini +++ b/tox.ini @@ -26,6 +26,7 @@ deps = nose setuptools unittest2 + importlib [testenv:flake8] deps = flake8