added for and with macros
Fixed up anaphoric.hy and added the tests too native_tests/__init__.py added __init__.hy
This commit is contained in:
parent
f189f0a457
commit
d82636958b
@ -441,52 +441,36 @@ first / car
|
|||||||
|
|
||||||
|
|
||||||
for
|
for
|
||||||
---
|
|
||||||
|
|
||||||
`for` macro is used to build nested `foreach` loops. The macro takes two
|
|
||||||
parameters, first being a vector specifying collections to iterate over and
|
|
||||||
variables to bind. The second parameter is a statement which is executed during
|
|
||||||
each loop:
|
|
||||||
|
|
||||||
.. code-block:: clj
|
|
||||||
|
|
||||||
(for [x iter y iter] stmt)
|
|
||||||
|
|
||||||
(foreach [x iter]
|
|
||||||
(foreach [y iter] stmt))
|
|
||||||
|
|
||||||
|
|
||||||
foreach
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||
`foreach` is used to call a function for each element in a list or vector.
|
`for` is used to call a function for each element in a list or vector.
|
||||||
Results are discarded and None is returned instead. Example code iterates over
|
Results are discarded and None is returned instead. Example code iterates over
|
||||||
collection and calls side-effect to each element in the collection:
|
collection and calls side-effect to each element in the collection:
|
||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
;; assuming that (side-effect) is a function that takes a single parameter
|
;; assuming that (side-effect) is a function that takes a single parameter
|
||||||
(foreach [element collection] (side-effect element))
|
(for [[element collection]] (side-effect element))
|
||||||
|
|
||||||
;; foreach can have an optional else block
|
;; for can have an optional else block
|
||||||
(foreach [element collection] (side-effect element)
|
(for [[element collection]] (side-effect element)
|
||||||
(else (side-effect-2)))
|
(else (side-effect-2)))
|
||||||
|
|
||||||
The optional `else` block is executed only if the `foreach` loop terminates
|
The optional `else` block is executed only if the `for` loop terminates
|
||||||
normally. If the execution is halted with `break`, the `else` does not execute.
|
normally. If the execution is halted with `break`, the `else` does not execute.
|
||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
=> (foreach [element [1 2 3]] (if (< element 3)
|
=> (for [[element [1 2 3]]] (if (< element 3)
|
||||||
... (print element)
|
... (print element)
|
||||||
... (break))
|
... (break))
|
||||||
... (else (print "loop finished")))
|
... (else (print "loop finished")))
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
|
|
||||||
=> (foreach [element [1 2 3]] (if (< element 4)
|
=> (for [[element [1 2 3]]] (if (< element 4)
|
||||||
... (print element)
|
... (print element)
|
||||||
... (break))
|
... (break))
|
||||||
... (else (print "loop finished")))
|
... (else (print "loop finished")))
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
@ -635,7 +619,7 @@ function is defined and passed to another function for filtering output.
|
|||||||
... {:name "Dave" :age 5}])
|
... {:name "Dave" :age 5}])
|
||||||
|
|
||||||
=> (defn display-people [people filter]
|
=> (defn display-people [people filter]
|
||||||
... (foreach [person people] (if (filter person) (print (:name person)))))
|
... (for [[person people]] (if (filter person) (print (:name person)))))
|
||||||
|
|
||||||
=> (display-people people (fn [person] (< (:age person) 25)))
|
=> (display-people people (fn [person] (< (:age person) 25)))
|
||||||
Alice
|
Alice
|
||||||
@ -949,16 +933,18 @@ context to an argument or ignore it completely, as shown below:
|
|||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
(with [arg (expr)] block)
|
(with [[arg (expr)]] block)
|
||||||
|
|
||||||
(with [(expr)] block)
|
(with [[(expr)]] block)
|
||||||
|
|
||||||
|
(with [[arg (expr)] [(expr)]] block)
|
||||||
|
|
||||||
The following example will open file `NEWS` and print its content on screen. The
|
The following example will open file `NEWS` and print its content on screen. The
|
||||||
file is automatically closed after it has been processed.
|
file is automatically closed after it has been processed.
|
||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
(with [f (open "NEWS")] (print (.read f)))
|
(with [[f (open "NEWS")]] (print (.read f)))
|
||||||
|
|
||||||
|
|
||||||
with-decorator
|
with-decorator
|
||||||
@ -996,7 +982,7 @@ infinite series without consuming infinite amount of memory.
|
|||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
=> (defn multiply [bases coefficients]
|
=> (defn multiply [bases coefficients]
|
||||||
... (foreach [(, base coefficient) (zip bases coefficients)]
|
... (for [[(, base coefficient) (zip bases coefficients)]]
|
||||||
... (yield (* base coefficient))))
|
... (yield (* base coefficient))))
|
||||||
|
|
||||||
=> (multiply (range 5) (range 5))
|
=> (multiply (range 5) (range 5))
|
||||||
|
@ -1177,14 +1177,18 @@ class HyASTCompiler(object):
|
|||||||
fn.stmts[-1].decorator_list = decorators
|
fn.stmts[-1].decorator_list = decorators
|
||||||
return ret + fn
|
return ret + fn
|
||||||
|
|
||||||
@builds("with")
|
@builds("with*")
|
||||||
@checkargs(min=2)
|
@checkargs(min=2)
|
||||||
def compile_with_expression(self, expr):
|
def compile_with_expression(self, expr):
|
||||||
expr.pop(0) # with
|
expr.pop(0) # with*
|
||||||
|
|
||||||
args = expr.pop(0)
|
args = expr.pop(0)
|
||||||
if len(args) > 2 or len(args) < 1:
|
if not isinstance(args, HyList):
|
||||||
raise HyTypeError(expr, "with needs [arg (expr)] or [(expr)]")
|
raise HyTypeError(expr,
|
||||||
|
"with expects a list, received `{0}'".format(
|
||||||
|
type(args).__name__))
|
||||||
|
if len(args) < 1:
|
||||||
|
raise HyTypeError(expr, "with needs [[arg (expr)]] or [[(expr)]]]")
|
||||||
|
|
||||||
args.reverse()
|
args.reverse()
|
||||||
ctx = self.compile(args.pop(0))
|
ctx = self.compile(args.pop(0))
|
||||||
@ -1623,23 +1627,36 @@ class HyASTCompiler(object):
|
|||||||
result += ld_name
|
result += ld_name
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@builds("foreach")
|
@builds("for*")
|
||||||
@checkargs(min=1)
|
@checkargs(min=1)
|
||||||
def compile_for_expression(self, expression):
|
def compile_for_expression(self, expression):
|
||||||
expression.pop(0) # for
|
expression.pop(0) # for
|
||||||
target_name, iterable = expression.pop(0)
|
|
||||||
|
args = expression.pop(0)
|
||||||
|
|
||||||
|
if not isinstance(args, HyList):
|
||||||
|
raise HyTypeError(expression,
|
||||||
|
"for expects a list, received `{0}'".format(
|
||||||
|
type(args).__name__))
|
||||||
|
|
||||||
|
try:
|
||||||
|
target_name, iterable = args
|
||||||
|
except ValueError:
|
||||||
|
raise HyTypeError(expression,
|
||||||
|
"for requires two forms in the list")
|
||||||
|
|
||||||
target = self._storeize(self.compile(target_name))
|
target = self._storeize(self.compile(target_name))
|
||||||
|
|
||||||
ret = Result()
|
ret = Result()
|
||||||
|
|
||||||
orel = Result()
|
orel = Result()
|
||||||
# (foreach [] body (else …))
|
# (for* [] body (else …))
|
||||||
if expression and expression[-1][0] == HySymbol("else"):
|
if expression and expression[-1][0] == HySymbol("else"):
|
||||||
else_expr = expression.pop()
|
else_expr = expression.pop()
|
||||||
if len(else_expr) > 2:
|
if len(else_expr) > 2:
|
||||||
raise HyTypeError(
|
raise HyTypeError(
|
||||||
else_expr,
|
else_expr,
|
||||||
"`else' statement in `foreach' is too long")
|
"`else' statement in `for' is too long")
|
||||||
elif len(else_expr) == 2:
|
elif len(else_expr) == 2:
|
||||||
orel += self.compile(else_expr[1])
|
orel += self.compile(else_expr[1])
|
||||||
orel += orel.expr_as_stmt()
|
orel += orel.expr_as_stmt()
|
||||||
|
@ -31,14 +31,14 @@
|
|||||||
|
|
||||||
(defmacro ap-each [lst &rest body]
|
(defmacro ap-each [lst &rest body]
|
||||||
"Evaluate the body form for each element in the list."
|
"Evaluate the body form for each element in the list."
|
||||||
`(foreach [it ~lst] ~@body))
|
`(for [[it ~lst]] ~@body))
|
||||||
|
|
||||||
|
|
||||||
(defmacro ap-each-while [lst form &rest body]
|
(defmacro ap-each-while [lst form &rest body]
|
||||||
"Evalutate the body form for each element in the list while the
|
"Evalutate the body form for each element in the list while the
|
||||||
predicate form evaluates to True."
|
predicate form evaluates to True."
|
||||||
`(let [[p (lambda [it] ~form)]]
|
`(let [[p (lambda [it] ~form)]]
|
||||||
(foreach [it ~lst]
|
(for [[it ~lst]]
|
||||||
(if (p it)
|
(if (p it)
|
||||||
~@body
|
~@body
|
||||||
(break)))))
|
(break)))))
|
||||||
@ -47,7 +47,7 @@
|
|||||||
(defmacro ap-map [form lst]
|
(defmacro ap-map [form lst]
|
||||||
"Yield elements evaluated in the form for each element in the list."
|
"Yield elements evaluated in the form for each element in the list."
|
||||||
`(let [[f (lambda [it] ~form)]]
|
`(let [[f (lambda [it] ~form)]]
|
||||||
(foreach [v ~lst]
|
(for [[v ~lst]]
|
||||||
(yield (f v)))))
|
(yield (f v)))))
|
||||||
|
|
||||||
|
|
||||||
@ -55,7 +55,7 @@
|
|||||||
"Yield elements evaluated for each element in the list when the
|
"Yield elements evaluated for each element in the list when the
|
||||||
predicate function returns True."
|
predicate function returns True."
|
||||||
`(let [[f (lambda [it] ~rep)]]
|
`(let [[f (lambda [it] ~rep)]]
|
||||||
(foreach [it ~lst]
|
(for [[it ~lst]]
|
||||||
(if (~predfn it)
|
(if (~predfn it)
|
||||||
(yield (f it))
|
(yield (f it))
|
||||||
(yield it)))))
|
(yield it)))))
|
||||||
@ -64,7 +64,7 @@
|
|||||||
(defmacro ap-filter [form lst]
|
(defmacro ap-filter [form lst]
|
||||||
"Yield elements returned when the predicate form evaluates to True."
|
"Yield elements returned when the predicate form evaluates to True."
|
||||||
`(let [[pred (lambda [it] ~form)]]
|
`(let [[pred (lambda [it] ~form)]]
|
||||||
(foreach [val ~lst]
|
(for [[val ~lst]]
|
||||||
(if (pred val)
|
(if (pred val)
|
||||||
(yield val)))))
|
(yield val)))))
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
(defmacro defmacro-alias [names lambda-list &rest body]
|
(defmacro defmacro-alias [names lambda-list &rest body]
|
||||||
"define one macro with several names"
|
"define one macro with several names"
|
||||||
(setv ret `(do))
|
(setv ret `(do))
|
||||||
(foreach [name names]
|
(for* [name names]
|
||||||
(.append ret
|
(.append ret
|
||||||
`(defmacro ~name ~lambda-list ~@body)))
|
`(defmacro ~name ~lambda-list ~@body)))
|
||||||
ret)
|
ret)
|
||||||
@ -52,7 +52,7 @@
|
|||||||
(setv macroed_variables [])
|
(setv macroed_variables [])
|
||||||
(if (not (isinstance variables HyList))
|
(if (not (isinstance variables HyList))
|
||||||
(macro-error variables "let lexical context must be a list"))
|
(macro-error variables "let lexical context must be a list"))
|
||||||
(foreach [variable variables]
|
(for* [variable variables]
|
||||||
(if (isinstance variable HyList)
|
(if (isinstance variable HyList)
|
||||||
(do
|
(do
|
||||||
(if (!= (len variable) 2)
|
(if (!= (len variable) 2)
|
||||||
|
@ -33,11 +33,11 @@
|
|||||||
(defn cycle [coll]
|
(defn cycle [coll]
|
||||||
"Yield an infinite repetition of the items in coll"
|
"Yield an infinite repetition of the items in coll"
|
||||||
(setv seen [])
|
(setv seen [])
|
||||||
(foreach [x coll]
|
(for* [x coll]
|
||||||
(yield x)
|
(yield x)
|
||||||
(.append seen x))
|
(.append seen x))
|
||||||
(while seen
|
(while seen
|
||||||
(foreach [x seen]
|
(for* [x seen]
|
||||||
(yield x))))
|
(yield x))))
|
||||||
|
|
||||||
(defn dec [n]
|
(defn dec [n]
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"Return a generator from the original collection with duplicates
|
"Return a generator from the original collection with duplicates
|
||||||
removed"
|
removed"
|
||||||
(let [[seen []] [citer (iter coll)]]
|
(let [[seen []] [citer (iter coll)]]
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(if (not_in val seen)
|
(if (not_in val seen)
|
||||||
(do
|
(do
|
||||||
(yield val)
|
(yield val)
|
||||||
@ -58,7 +58,7 @@
|
|||||||
(defn drop [count coll]
|
(defn drop [count coll]
|
||||||
"Drop `count` elements from `coll` and yield back the rest"
|
"Drop `count` elements from `coll` and yield back the rest"
|
||||||
(let [[citer (iter coll)]]
|
(let [[citer (iter coll)]]
|
||||||
(try (foreach [i (range count)]
|
(try (for* [i (range count)]
|
||||||
(next citer))
|
(next citer))
|
||||||
(catch [StopIteration]))
|
(catch [StopIteration]))
|
||||||
citer))
|
citer))
|
||||||
@ -66,10 +66,10 @@
|
|||||||
(defn drop-while [pred coll]
|
(defn drop-while [pred coll]
|
||||||
"Drop all elements of `coll` until `pred` is False"
|
"Drop all elements of `coll` until `pred` is False"
|
||||||
(let [[citer (iter coll)]]
|
(let [[citer (iter coll)]]
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(if (not (pred val))
|
(if (not (pred val))
|
||||||
(do (yield val) (break))))
|
(do (yield val) (break))))
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(yield val))))
|
(yield val))))
|
||||||
|
|
||||||
(defn empty? [coll]
|
(defn empty? [coll]
|
||||||
@ -84,7 +84,7 @@
|
|||||||
(defn filter [pred coll]
|
(defn filter [pred coll]
|
||||||
"Return all elements from `coll` that pass `pred`"
|
"Return all elements from `coll` that pass `pred`"
|
||||||
(let [[citer (iter coll)]]
|
(let [[citer (iter coll)]]
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(if (pred val)
|
(if (pred val)
|
||||||
(yield val)))))
|
(yield val)))))
|
||||||
|
|
||||||
@ -96,7 +96,7 @@
|
|||||||
|
|
||||||
(defn _flatten [coll result]
|
(defn _flatten [coll result]
|
||||||
(if (and (iterable? coll) (not (string? coll)))
|
(if (and (iterable? coll) (not (string? coll)))
|
||||||
(do (foreach [b coll]
|
(do (for* [b coll]
|
||||||
(_flatten b result)))
|
(_flatten b result)))
|
||||||
(.append result coll))
|
(.append result coll))
|
||||||
result)
|
result)
|
||||||
@ -187,7 +187,7 @@
|
|||||||
(defn remove [pred coll]
|
(defn remove [pred coll]
|
||||||
"Return coll with elements removed that pass `pred`"
|
"Return coll with elements removed that pass `pred`"
|
||||||
(let [[citer (iter coll)]]
|
(let [[citer (iter coll)]]
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(if (not (pred val))
|
(if (not (pred val))
|
||||||
(yield val)))))
|
(yield val)))))
|
||||||
|
|
||||||
@ -195,7 +195,7 @@
|
|||||||
"Yield x forever or optionally n times"
|
"Yield x forever or optionally n times"
|
||||||
(if (none? n)
|
(if (none? n)
|
||||||
(setv dispatch (fn [] (while true (yield x))))
|
(setv dispatch (fn [] (while true (yield x))))
|
||||||
(setv dispatch (fn [] (foreach [_ (range n)] (yield x)))))
|
(setv dispatch (fn [] (for* [_ (range n)] (yield x)))))
|
||||||
(dispatch))
|
(dispatch))
|
||||||
|
|
||||||
(defn repeatedly [func]
|
(defn repeatedly [func]
|
||||||
@ -223,7 +223,7 @@
|
|||||||
"Take `count` elements from `coll`, or the whole set if the total
|
"Take `count` elements from `coll`, or the whole set if the total
|
||||||
number of entries in `coll` is less than `count`."
|
number of entries in `coll` is less than `count`."
|
||||||
(let [[citer (iter coll)]]
|
(let [[citer (iter coll)]]
|
||||||
(foreach [_ (range count)]
|
(for* [_ (range count)]
|
||||||
(yield (next citer)))))
|
(yield (next citer)))))
|
||||||
|
|
||||||
(defn take-nth [n coll]
|
(defn take-nth [n coll]
|
||||||
@ -231,16 +231,16 @@
|
|||||||
raises ValueError for (not (pos? n))"
|
raises ValueError for (not (pos? n))"
|
||||||
(if (pos? n)
|
(if (pos? n)
|
||||||
(let [[citer (iter coll)] [skip (dec n)]]
|
(let [[citer (iter coll)] [skip (dec n)]]
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(yield val)
|
(yield val)
|
||||||
(foreach [_ (range skip)]
|
(for* [_ (range skip)]
|
||||||
(next citer))))
|
(next citer))))
|
||||||
(raise (ValueError "n must be positive"))))
|
(raise (ValueError "n must be positive"))))
|
||||||
|
|
||||||
(defn take-while [pred coll]
|
(defn take-while [pred coll]
|
||||||
"Take all elements while `pred` is true"
|
"Take all elements while `pred` is true"
|
||||||
(let [[citer (iter coll)]]
|
(let [[citer (iter coll)]]
|
||||||
(foreach [val citer]
|
(for* [val citer]
|
||||||
(if (pred val)
|
(if (pred val)
|
||||||
(yield val)
|
(yield val)
|
||||||
(break)))))
|
(break)))))
|
||||||
|
@ -26,17 +26,24 @@
|
|||||||
;;; They are automatically required in every module, except inside hy.core
|
;;; They are automatically required in every module, except inside hy.core
|
||||||
|
|
||||||
(defmacro for [args &rest body]
|
(defmacro for [args &rest body]
|
||||||
"shorthand for nested foreach loops:
|
"shorthand for nested for loops:
|
||||||
(for [x foo y bar] baz) ->
|
(for [[x foo] [y bar]] baz) ->
|
||||||
(foreach [x foo]
|
(for* [x foo]
|
||||||
(foreach [y bar]
|
(for* [y bar]
|
||||||
baz))"
|
baz))"
|
||||||
;; TODO: that signature sucks.
|
|
||||||
;; (for [[x foo] [y bar]] baz) would be more consistent
|
|
||||||
(if (% (len args) 2)
|
|
||||||
(macro-error args "for needs an even number of elements in its first argument"))
|
|
||||||
(if args
|
(if args
|
||||||
`(foreach [~(.pop args 0) ~(.pop args 0)] (for ~args ~@body))
|
`(for* ~(.pop args 0) (for ~args ~@body))
|
||||||
|
`(do ~@body)))
|
||||||
|
|
||||||
|
|
||||||
|
(defmacro with [args &rest body]
|
||||||
|
"shorthand for nested for* loops:
|
||||||
|
(with [[x foo] [y bar]] baz) ->
|
||||||
|
(with* [x foo]
|
||||||
|
(with* [y bar]
|
||||||
|
baz))"
|
||||||
|
(if args
|
||||||
|
`(with* ~(.pop args 0) (with ~args ~@body))
|
||||||
`(do ~@body)))
|
`(do ~@body)))
|
||||||
|
|
||||||
|
|
||||||
@ -71,7 +78,7 @@
|
|||||||
(setv root (check-branch branch))
|
(setv root (check-branch branch))
|
||||||
(setv latest-branch root)
|
(setv latest-branch root)
|
||||||
|
|
||||||
(foreach [branch branches]
|
(for* [branch branches]
|
||||||
(setv cur-branch (check-branch branch))
|
(setv cur-branch (check-branch branch))
|
||||||
(.append latest-branch cur-branch)
|
(.append latest-branch cur-branch)
|
||||||
(setv latest-branch cur-branch))
|
(setv latest-branch cur-branch))
|
||||||
@ -81,7 +88,7 @@
|
|||||||
(defmacro -> [head &rest rest]
|
(defmacro -> [head &rest rest]
|
||||||
;; TODO: fix the docstring by someone who understands this
|
;; TODO: fix the docstring by someone who understands this
|
||||||
(setv ret head)
|
(setv ret head)
|
||||||
(foreach [node rest]
|
(for* [node rest]
|
||||||
(if (not (isinstance node HyExpression))
|
(if (not (isinstance node HyExpression))
|
||||||
(setv node `(~node)))
|
(setv node `(~node)))
|
||||||
(.insert node 1 ret)
|
(.insert node 1 ret)
|
||||||
@ -92,7 +99,7 @@
|
|||||||
(defmacro ->> [head &rest rest]
|
(defmacro ->> [head &rest rest]
|
||||||
;; TODO: fix the docstring by someone who understands this
|
;; TODO: fix the docstring by someone who understands this
|
||||||
(setv ret head)
|
(setv ret head)
|
||||||
(foreach [node rest]
|
(for* [node rest]
|
||||||
(if (not (isinstance node HyExpression))
|
(if (not (isinstance node HyExpression))
|
||||||
(setv node `(~node)))
|
(setv node `(~node)))
|
||||||
(.append node ret)
|
(.append node ret)
|
||||||
@ -113,7 +120,7 @@
|
|||||||
(defmacro yield-from [iterable]
|
(defmacro yield-from [iterable]
|
||||||
"Yield all the items from iterable"
|
"Yield all the items from iterable"
|
||||||
(let [[x (gensym)]]
|
(let [[x (gensym)]]
|
||||||
`(foreach [~x ~iterable]
|
`(for* [~x ~iterable]
|
||||||
(yield ~x))))
|
(yield ~x))))
|
||||||
|
|
||||||
(defmacro with-gensyms [args &rest body]
|
(defmacro with-gensyms [args &rest body]
|
||||||
|
@ -12,4 +12,5 @@ from .native_tests.when import * # noqa
|
|||||||
from .native_tests.with_decorator import * # noqa
|
from .native_tests.with_decorator import * # noqa
|
||||||
from .native_tests.core import * # noqa
|
from .native_tests.core import * # noqa
|
||||||
from .native_tests.reader_macros import * # noqa
|
from .native_tests.reader_macros import * # noqa
|
||||||
|
from .native_tests.with_test import * # noqa
|
||||||
from .native_tests.contrib.anaphoric import * # noqa
|
from .native_tests.contrib.anaphoric import * # noqa
|
||||||
|
@ -295,9 +295,9 @@ def test_ast_bad_assoc():
|
|||||||
|
|
||||||
def test_ast_bad_with():
|
def test_ast_bad_with():
|
||||||
"Make sure AST can't compile invalid with"
|
"Make sure AST can't compile invalid with"
|
||||||
cant_compile("(with)")
|
cant_compile("(with*)")
|
||||||
cant_compile("(with [])")
|
cant_compile("(with* [])")
|
||||||
cant_compile("(with [] (pass))")
|
cant_compile("(with* [] (pass))")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_valid_while():
|
def test_ast_valid_while():
|
||||||
@ -305,14 +305,14 @@ def test_ast_valid_while():
|
|||||||
can_compile("(while foo bar)")
|
can_compile("(while foo bar)")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_valid_foreach():
|
def test_ast_valid_for():
|
||||||
"Make sure AST can compile valid foreach"
|
"Make sure AST can compile valid for"
|
||||||
can_compile("(foreach [a 2])")
|
can_compile("(for [[a 2]])")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_invalid_foreach():
|
def test_ast_invalid_for():
|
||||||
"Make sure AST can't compile invalid foreach"
|
"Make sure AST can't compile invalid for"
|
||||||
cant_compile("(foreach [a 1] (else 1 2))")
|
cant_compile("(for* [a 1] (else 1 2))")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_expression_basics():
|
def test_ast_expression_basics():
|
||||||
|
@ -31,12 +31,12 @@
|
|||||||
(defn test-for-loop []
|
(defn test-for-loop []
|
||||||
"NATIVE: test for loops?"
|
"NATIVE: test for loops?"
|
||||||
(setv count 0)
|
(setv count 0)
|
||||||
(for [x [1 2 3 4 5]]
|
(for [[x [1 2 3 4 5]]]
|
||||||
(setv count (+ count x)))
|
(setv count (+ count x)))
|
||||||
(assert (= count 15))
|
(assert (= count 15))
|
||||||
(setv count 0)
|
(setv count 0)
|
||||||
(for [x [1 2 3 4 5]
|
(for [[x [1 2 3 4 5]]
|
||||||
y [1 2 3 4 5]]
|
[y [1 2 3 4 5]]]
|
||||||
(setv count (+ count x y)))
|
(setv count (+ count x y)))
|
||||||
(assert (= count 150)))
|
(assert (= count 150)))
|
||||||
|
|
||||||
@ -394,9 +394,9 @@
|
|||||||
|
|
||||||
(defn test-yield []
|
(defn test-yield []
|
||||||
"NATIVE: test yielding"
|
"NATIVE: test yielding"
|
||||||
(defn gen [] (for [x [1 2 3 4]] (yield x)))
|
(defn gen [] (for [[x [1 2 3 4]]] (yield x)))
|
||||||
(setv ret 0)
|
(setv ret 0)
|
||||||
(for [y (gen)] (setv ret (+ ret y)))
|
(for [[y (gen)]] (setv ret (+ ret y)))
|
||||||
(assert (= ret 10)))
|
(assert (= ret 10)))
|
||||||
|
|
||||||
|
|
||||||
@ -439,37 +439,37 @@
|
|||||||
|
|
||||||
(defn test-context []
|
(defn test-context []
|
||||||
"NATIVE: test with"
|
"NATIVE: test with"
|
||||||
(with [fd (open "README.md" "r")] (assert fd))
|
(with [[fd (open "README.md" "r")]] (assert fd))
|
||||||
(with [(open "README.md" "r")] (do)))
|
(with [[(open "README.md" "r")]] (do)))
|
||||||
|
|
||||||
|
|
||||||
(defn test-with-return []
|
(defn test-with-return []
|
||||||
"NATIVE: test that with returns stuff"
|
"NATIVE: test that with returns stuff"
|
||||||
(defn read-file [filename]
|
(defn read-file [filename]
|
||||||
(with [fd (open filename "r")] (.read fd)))
|
(with [[fd (open filename "r")]] (.read fd)))
|
||||||
(assert (!= 0 (len (read-file "README.md")))))
|
(assert (!= 0 (len (read-file "README.md")))))
|
||||||
|
|
||||||
|
|
||||||
(defn test-for-doodle []
|
(defn test-for-doodle []
|
||||||
"NATIVE: test for-do"
|
"NATIVE: test for-do"
|
||||||
(do (do (do (do (do (do (do (do (do (setv (, x y) (, 0 0)))))))))))
|
(do (do (do (do (do (do (do (do (do (setv (, x y) (, 0 0)))))))))))
|
||||||
(foreach [- [1 2]]
|
(for [[- [1 2]]]
|
||||||
(do
|
(do
|
||||||
(setv x (+ x 1))
|
(setv x (+ x 1))
|
||||||
(setv y (+ y 1))))
|
(setv y (+ y 1))))
|
||||||
(assert (= y x 2)))
|
(assert (= y x 2)))
|
||||||
|
|
||||||
|
|
||||||
(defn test-foreach-else []
|
(defn test-for-else []
|
||||||
"NATIVE: test foreach else"
|
"NATIVE: test for else"
|
||||||
(let [[x 0]]
|
(let [[x 0]]
|
||||||
(foreach [a [1 2]]
|
(for* [a [1 2]]
|
||||||
(setv x (+ x a))
|
(setv x (+ x a))
|
||||||
(else (setv x (+ x 50))))
|
(else (setv x (+ x 50))))
|
||||||
(assert (= x 53)))
|
(assert (= x 53)))
|
||||||
|
|
||||||
(let [[x 0]]
|
(let [[x 0]]
|
||||||
(foreach [a [1 2]]
|
(for* [a [1 2]]
|
||||||
(setv x (+ x a))
|
(setv x (+ x a))
|
||||||
(else))
|
(else))
|
||||||
(assert (= x 3))))
|
(assert (= x 3))))
|
||||||
@ -636,7 +636,7 @@
|
|||||||
|
|
||||||
(defn test-nested-if []
|
(defn test-nested-if []
|
||||||
"NATIVE: test nested if"
|
"NATIVE: test nested if"
|
||||||
(for [x (range 10)]
|
(for [[x (range 10)]]
|
||||||
(if (in "foo" "foobar")
|
(if (in "foo" "foobar")
|
||||||
(do
|
(do
|
||||||
(if true true true))
|
(if true true true))
|
||||||
@ -800,14 +800,14 @@
|
|||||||
|
|
||||||
(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)
|
||||||
(assert (= (holy-grail) 5)))
|
(assert (= (holy-grail) 5)))
|
||||||
|
|
||||||
|
|
||||||
(defn test-continue-continuation []
|
(defn test-continue-continuation []
|
||||||
"NATIVE: test checking if continue actually continues"
|
"NATIVE: test checking if continue actually continues"
|
||||||
(setv y [])
|
(setv y [])
|
||||||
(for [x (range 10)]
|
(for [[x (range 10)]]
|
||||||
(if (!= x 5)
|
(if (!= x 5)
|
||||||
(continue))
|
(continue))
|
||||||
(.append y x))
|
(.append y x))
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
(defn test-midtree-yield-in-for []
|
(defn test-midtree-yield-in-for []
|
||||||
"NATIVE: test yielding in a for with a return"
|
"NATIVE: test yielding in a for with a return"
|
||||||
(defn kruft-in-for []
|
(defn kruft-in-for []
|
||||||
(for [i (range 5)]
|
(for* [i (range 5)]
|
||||||
(yield i))
|
(yield i))
|
||||||
(+ 1 2)))
|
(+ 1 2)))
|
||||||
|
|
||||||
@ -72,7 +72,7 @@
|
|||||||
(defn test-multi-yield []
|
(defn test-multi-yield []
|
||||||
"NATIVE: testing multiple yields"
|
"NATIVE: testing multiple yields"
|
||||||
(defn multi-yield []
|
(defn multi-yield []
|
||||||
(for [i (range 3)]
|
(for* [i (range 3)]
|
||||||
(yield i))
|
(yield i))
|
||||||
(yield "a")
|
(yield "a")
|
||||||
(yield "end"))
|
(yield "end"))
|
||||||
@ -97,7 +97,7 @@
|
|||||||
(defn test-yield-from []
|
(defn test-yield-from []
|
||||||
"NATIVE: testing yield from"
|
"NATIVE: testing yield from"
|
||||||
(defn yield-from-test []
|
(defn yield-from-test []
|
||||||
(for [i (range 3)]
|
(for* [i (range 3)]
|
||||||
(yield i))
|
(yield i))
|
||||||
(yield-from [1 2 3]))
|
(yield-from [1 2 3]))
|
||||||
(assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
|
(assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
|
||||||
|
44
tests/native_tests/with_test.hy
Normal file
44
tests/native_tests/with_test.hy
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
(defclass WithTest [object]
|
||||||
|
[(--init--
|
||||||
|
(fn [self val]
|
||||||
|
(setv self.val val)
|
||||||
|
None))
|
||||||
|
|
||||||
|
(--enter--
|
||||||
|
(fn [self]
|
||||||
|
self.val))
|
||||||
|
|
||||||
|
(--exit--
|
||||||
|
(fn [self type value traceback]
|
||||||
|
(setv self.val None)))])
|
||||||
|
|
||||||
|
(defn test-single-with []
|
||||||
|
"NATIVE: test a single with"
|
||||||
|
(with [[t (WithTest 1)]]
|
||||||
|
(assert (= t 1))))
|
||||||
|
|
||||||
|
(defn test-two-with []
|
||||||
|
"NATIVE: test two withs"
|
||||||
|
(with [[t1 (WithTest 1)]
|
||||||
|
[t2 (WithTest 2)]]
|
||||||
|
(assert (= t1 1))
|
||||||
|
(assert (= t2 2))))
|
||||||
|
|
||||||
|
(defn test-thrice-with []
|
||||||
|
"NATIVE: test three withs"
|
||||||
|
(with [[t1 (WithTest 1)]
|
||||||
|
[t2 (WithTest 2)]
|
||||||
|
[t3 (WithTest 3)]]
|
||||||
|
(assert (= t1 1))
|
||||||
|
(assert (= t2 2))
|
||||||
|
(assert (= t3 3))))
|
||||||
|
|
||||||
|
(defn test-quince-with []
|
||||||
|
"NATIVE: test four withs, one with no args"
|
||||||
|
(with [[t1 (WithTest 1)]
|
||||||
|
[t2 (WithTest 2)]
|
||||||
|
[t3 (WithTest 3)]
|
||||||
|
[(WithTest 4)]]
|
||||||
|
(assert (= t1 1))
|
||||||
|
(assert (= t2 2))
|
||||||
|
(assert (= t3 3))))
|
Loading…
Reference in New Issue
Block a user