Add in a new core language file.

This will let us implement common functions seen in other lisps,
 and allow them to be importable, without explicit imports. The goal
 is to keep this as small as we can; we don't want too much magic.

 I've added `take' and `drop' as examples of what we can do.
This commit is contained in:
Paul Tagliamonte 2013-06-29 11:50:31 -04:00
parent b65c2a4596
commit 86af7eacf1
7 changed files with 60 additions and 23 deletions

View File

@ -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

View File

@ -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()

View File

@ -24,6 +24,10 @@ MACROS = [
"hy.core.bootstrap",
]
STDLIB = [
"hy.core.language"
]
def process(tree, module_name):
load_macros()

View File

@ -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([

22
hy/core/language.hy Normal file
View File

@ -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"])

View File

@ -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)

View File

@ -26,6 +26,7 @@ deps =
nose
setuptools
unittest2
importlib
[testenv:flake8]
deps = flake8