support (nonlocal) in let

This commit is contained in:
gilch 2017-09-18 13:50:41 -06:00
parent 34038ff433
commit ba898aa8d8
3 changed files with 61 additions and 27 deletions

View File

@ -161,7 +161,7 @@ as can nested let forms.
;; else expand if applicable
(if (and (in form bound-symbols)
(not-in form protected-symbols))
`(get ~g!let ~(name form))
(HySymbol (+ g!let "::" form))
form))]
;; We have to treat special forms differently.
;; Quotation should suppress symbol expansion,
@ -232,15 +232,10 @@ as can nested let forms.
[True form]))
(expand-symbols #{}
`(do
(setv ~g!let {}
~@bindings)
(setv ~@bindings)
~@body)))
#_[special cases for let
;; this means we can't use a list for our let scope
;; we're using a dict instead.
'del',
;; Symbols containing a dot should be converted to this form.
;; attrs should not get expanded,
;; but [] lookups should.

View File

@ -135,8 +135,8 @@
(do
foo
(assert False))
(except [ke LookupError]
(setv error ke)))
(except [ne NameError]
(setv error ne)))
(setv foo 16)
(assert (= foo 16))
(setv [foo bar baz] [1 2 3])
@ -153,6 +153,14 @@
(if done (break))))
(assert (= x 1)))
(defn test-let-continue []
(let [foo []]
(for [x (range 10)]
(let [odd (odd? x)]
(if odd (continue))
(.append foo x)))
(assert (= foo [0 2 4 6 8]))))
(defn test-let-yield []
(defn grind []
(yield 0)
@ -231,16 +239,15 @@
&rest 12]
(defn foo [a b &rest xs]
(-= a 1)
(-= c 1)
(setv xs (list xs))
(.append xs 42)
(, &rest a b c xs))
(assert (= xs 6))
(assert (= a 88))
(assert (= (foo 1 2 3 4)
(, 12 0 2 63 [3 4 42])))
(, 12 0 2 64 [3 4 42])))
(assert (= xs 6))
(assert (= c 63))
(assert (= c 64))
(assert (= a 88))))
(defn test-let-kwargs []
@ -275,12 +282,17 @@
(, 10 20 30)))
(assert (= (, a b d)
(, 1 6 2)))))
;; TODO
;; test-let-continue
;; test-let-closure
;; test-let-global
(defn test-let-closure []
(let [count [0]]
(defn +count [&optional [x 1]]
(+= (get count 0) x)
(get count 0)))
;; let bindings can still exist outside of a let body
(assert (= 1 (+count)))
(assert (= 2 (+count)))
(assert (= 42 (+count 40))))
;; TODO
;;; Python 3 only
;; test-let-nonlocal
;; test-let-kwonly
;; test-let-global

View File

@ -8,8 +8,8 @@
(defn test-exception-cause []
(try (raise ValueError :from NameError)
(except [e [ValueError]]
(assert (= (type (. e __cause__)) NameError)))))
(except [e [ValueError]]
(assert (= (type (. e __cause__)) NameError)))))
(defn test-kwonly []
@ -21,8 +21,8 @@
;; keyword-only without default ...
(defn kwonly-foo-no-default [&kwonly foo] foo)
(setv attempt-to-omit-default (try
(kwonly-foo-no-default)
(except [e [Exception]] e)))
(kwonly-foo-no-default)
(except [e [Exception]] e)))
;; works
(assert (= (kwonly-foo-no-default :foo "quux") "quux"))
;; raises TypeError with appropriate message if not supplied
@ -64,9 +64,36 @@
(assert 0))
(defn yield-from-test []
(for* [i (range 3)]
(yield i))
(yield i))
(try
(yield-from (yield-from-subgenerator-test))
(except [e AssertionError]
(yield 4))))
(yield-from (yield-from-subgenerator-test))
(except [e AssertionError]
(yield 4))))
(assert (= (list (yield-from-test)) [0 1 2 1 2 3 4])))
(require [hy.contrib.walk [let]])
(defn test-let-nonlocal []
(let [a 88
c 64]
(defn foo [a b]
(nonlocal c)
(-= a 1)
(-= c 1)
(, a b c))
(assert (= a 88))
(assert (= (foo 1 2)
(, 0 2 63)))
(assert (= c 63))
(assert (= a 88))))
(defn test-let-optional []
(let [a 1
b 6
d 2]
(defn foo [&kwonly [a a] b [c d]]
(, a b c))
(assert (= (foo :b "b")
(, 1 "b" 2)))
(assert (= (foo :b 20 :a 10 :c 30)
(, 10 20 30)))))