Merge branch 'master' into pr/213

This commit is contained in:
Paul Tagliamonte 2013-07-04 21:25:58 -04:00
commit 2e909d5357
9 changed files with 68 additions and 28 deletions

View File

@ -8,7 +8,7 @@ python:
# command to install dependencies # command to install dependencies
install: install:
- pip install -r requirements.txt --use-mirrors - 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 == '2.7' ]]; then pip install astor --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi - if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi
- python setup.py -q install - python setup.py -q install

View File

@ -116,9 +116,6 @@ no arguments to re-raise the last Exception.
try try
--- ---
.. TODO::
Document the else / finally syntax.
the `try` form is used to start a `try` / `catch` block. The form is used the `try` form is used to start a `try` / `catch` block. The form is used
as follows as follows
@ -126,7 +123,12 @@ as follows
(try (try
(error-prone-function) (error-prone-function)
(catch [e SomeException] (err "It sucks!"))) (catch [e ZeroDivisionError] (print "Division by zero"))
(else (print "no errors"))
(finally (print "all done")))
`try` must contain at least one `catch` block, and may optionally have an `try` must contain at least one `catch` block, and may optionally have an
`else` or `finally` block. `else` or `finally` block. If an error is raised with a matching catch
block during execution of `error-prone-function` then that catch block will
be executed. If no errors are raised the `else` block is executed. Regardless
if an error was raised or not, the `finally` block is executed as last.

View File

@ -36,14 +36,14 @@ from hy.models.list import HyList
from hy.models.dict import HyDict from hy.models.dict import HyDict
import hy.importer import hy.importer
from hy.core import process
from hy.util import str_type
from hy.macros import require from hy.macros import require
from hy.util import str_type
from hy.core import process
import codecs
import traceback import traceback
import importlib
import codecs
import ast import ast
import sys import sys
@ -61,6 +61,17 @@ def compile_time_ns(module_name):
return ns 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): class HyCompileError(HyError):
def __init__(self, exception, traceback=None): def __init__(self, exception, traceback=None):
self.exception = exception self.exception = exception
@ -339,6 +350,9 @@ class HyASTCompiler(object):
self.anon_var_count = 0 self.anon_var_count = 0
self.imports = defaultdict(set) self.imports = defaultdict(set)
self.module_name = module_name 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): def get_anon_var(self):
self.anon_var_count += 1 self.anon_var_count += 1
@ -1432,6 +1446,10 @@ class HyASTCompiler(object):
ret = self.compile_atom(fn, expression) ret = self.compile_atom(fn, expression)
if ret: if ret:
return ret return ret
if fn in _stdlib:
self.imports[_stdlib[fn]].add(fn)
if fn.startswith("."): if fn.startswith("."):
# (.split "test test") -> "test test".split() # (.split "test test") -> "test test".split()

View File

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

View File

@ -137,21 +137,6 @@ def let_macro(variables, *body):
return HyExpression([expr + list(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") @macro("when")
def when_macro(test, *body): def when_macro(test, *body):
return HyExpression([ 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

@ -1,3 +1,4 @@
astor
tox tox
nose nose
flake8 flake8

View File

@ -385,9 +385,9 @@
(defn test-drop [] (defn test-drop []
"NATIVE: test drop" "NATIVE: test drop"
(assert (= (drop 0 [2 3]) [2 3])) (assert (= (list (drop 0 [2 3])) [2 3]))
(assert (= (drop 1 [2 3]) [3])) (assert (= (list (drop 1 [2 3])) [3]))
(assert (= (drop 2 [2 3]) []))) (assert (= (list (drop 2 [2 3])) [])))
(defn test-rest [] (defn test-rest []
@ -741,6 +741,13 @@
(assert (= "test" (:foo {:foo "test"})))) (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 [] (defn test-break-breaking []
"NATIVE: test checking if break actually breaks" "NATIVE: test checking if break actually breaks"
(defn holy-grail [] (for [x (range 10)] (if (= x 5) (break))) x) (defn holy-grail [] (for [x (range 10)] (if (= x 5) (break))) x)

View File

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