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 ;; else expand if applicable
(if (and (in form bound-symbols) (if (and (in form bound-symbols)
(not-in form protected-symbols)) (not-in form protected-symbols))
`(get ~g!let ~(name form)) (HySymbol (+ g!let "::" form))
form))] form))]
;; We have to treat special forms differently. ;; We have to treat special forms differently.
;; Quotation should suppress symbol expansion, ;; Quotation should suppress symbol expansion,
@ -232,15 +232,10 @@ as can nested let forms.
[True form])) [True form]))
(expand-symbols #{} (expand-symbols #{}
`(do `(do
(setv ~g!let {} (setv ~@bindings)
~@bindings)
~@body))) ~@body)))
#_[special cases for let #_[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. ;; Symbols containing a dot should be converted to this form.
;; attrs should not get expanded, ;; attrs should not get expanded,
;; but [] lookups should. ;; but [] lookups should.

View File

@ -135,8 +135,8 @@
(do (do
foo foo
(assert False)) (assert False))
(except [ke LookupError] (except [ne NameError]
(setv error ke))) (setv error ne)))
(setv foo 16) (setv foo 16)
(assert (= foo 16)) (assert (= foo 16))
(setv [foo bar baz] [1 2 3]) (setv [foo bar baz] [1 2 3])
@ -153,6 +153,14 @@
(if done (break)))) (if done (break))))
(assert (= x 1))) (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 test-let-yield []
(defn grind [] (defn grind []
(yield 0) (yield 0)
@ -231,16 +239,15 @@
&rest 12] &rest 12]
(defn foo [a b &rest xs] (defn foo [a b &rest xs]
(-= a 1) (-= a 1)
(-= c 1)
(setv xs (list xs)) (setv xs (list xs))
(.append xs 42) (.append xs 42)
(, &rest a b c xs)) (, &rest a b c xs))
(assert (= xs 6)) (assert (= xs 6))
(assert (= a 88)) (assert (= a 88))
(assert (= (foo 1 2 3 4) (assert (= (foo 1 2 3 4)
(, 12 0 2 63 [3 4 42]))) (, 12 0 2 64 [3 4 42])))
(assert (= xs 6)) (assert (= xs 6))
(assert (= c 63)) (assert (= c 64))
(assert (= a 88)))) (assert (= a 88))))
(defn test-let-kwargs [] (defn test-let-kwargs []
@ -275,12 +282,17 @@
(, 10 20 30))) (, 10 20 30)))
(assert (= (, a b d) (assert (= (, a b d)
(, 1 6 2))))) (, 1 6 2)))))
;; TODO
;; test-let-continue (defn test-let-closure []
;; test-let-closure (let [count [0]]
;; test-let-global (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 ;; TODO
;;; Python 3 only ;; test-let-global
;; test-let-nonlocal
;; test-let-kwonly

View File

@ -8,8 +8,8 @@
(defn test-exception-cause [] (defn test-exception-cause []
(try (raise ValueError :from NameError) (try (raise ValueError :from NameError)
(except [e [ValueError]] (except [e [ValueError]]
(assert (= (type (. e __cause__)) NameError))))) (assert (= (type (. e __cause__)) NameError)))))
(defn test-kwonly [] (defn test-kwonly []
@ -21,8 +21,8 @@
;; keyword-only without default ... ;; keyword-only without default ...
(defn kwonly-foo-no-default [&kwonly foo] foo) (defn kwonly-foo-no-default [&kwonly foo] foo)
(setv attempt-to-omit-default (try (setv attempt-to-omit-default (try
(kwonly-foo-no-default) (kwonly-foo-no-default)
(except [e [Exception]] e))) (except [e [Exception]] e)))
;; works ;; works
(assert (= (kwonly-foo-no-default :foo "quux") "quux")) (assert (= (kwonly-foo-no-default :foo "quux") "quux"))
;; raises TypeError with appropriate message if not supplied ;; raises TypeError with appropriate message if not supplied
@ -64,9 +64,36 @@
(assert 0)) (assert 0))
(defn yield-from-test [] (defn yield-from-test []
(for* [i (range 3)] (for* [i (range 3)]
(yield i)) (yield i))
(try (try
(yield-from (yield-from-subgenerator-test)) (yield-from (yield-from-subgenerator-test))
(except [e AssertionError] (except [e AssertionError]
(yield 4)))) (yield 4))))
(assert (= (list (yield-from-test)) [0 1 2 1 2 3 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)))))