Fixed lambda capture in presence of let bindings

This commit is contained in:
Basile Pesin 2020-06-15 19:32:29 +02:00
parent fc6d6aa626
commit dd6d3e9008
2 changed files with 27 additions and 2 deletions

View File

@ -1,5 +1,18 @@
(defn my-curry [f] (fn [x] (fn [y] (f x y))))
(defn double-curry [f] (fn [x] (fn [y] (fn [z] (f x y z)))))
(defn make-cb []
((fn []
(let [x "hi"]
(fn [] (IO.println x))))))
(defn make-cb2 []
((fn []
(let [x "hello"
f (fn [] (IO.println x))]
f))))
(defn main []
(do (((my-curry (fn [x y] (Int.+ x y))) 1) 2)))
(do ((make-cb))
((make-cb2))
(((my-curry (fn [x y] (Int.+ x y))) 1) 2)))

View File

@ -326,14 +326,26 @@ collectCapturedVars root = removeDuplicates (map decreaseCaptureLevel (visit roo
else LookupLocal (Capture (n-1))))
(Just dummyInfo) ty
pairBindings :: [XObj] -> [(XObj, XObj)]
pairBindings [] = []
pairBindings (k:v:tl) = (k, v):pairBindings tl
visit xobj =
case obj xobj of
-- don't peek inside lambdas, trust their capture lists:
(Lst [XObj (Fn _ captures) _ _, _, _]) -> Set.toList captures
(Lst [XObj Let _ _, XObj (Arr bindings) _ _, body]) ->
let (bound, bindingsCaptured) = foldl
(\(bound, captured) (XObj sym _ ty, expr) ->
let capt = filter (\x -> Set.notMember x bound) (visit expr) in
(Set.insert (XObj sym (Just dummyInfo) ty) bound, capt++captured))
(Set.empty, []) (pairBindings bindings) in
let bodyCaptured = filter (\x -> Set.notMember x bound) (visit body) in
bindingsCaptured++bodyCaptured
(Lst _) -> visitList xobj
(Arr _) -> visitArray xobj
-- TODO: Static Arrays!
(Sym path (LookupLocal (Capture _))) -> [xobj]
sym@(Sym path (LookupLocal (Capture _))) -> [XObj sym (Just dummyInfo) (ty xobj)]
_ -> []
visitList :: XObj -> [XObj]