git » blacktide.git » master » tree

[master] / src / com / tailrecursion / blacktide / compiler / passes / invariants.clj

(ns ^:typed.clojure com.tailrecursion.blacktide.compiler.passes.invariants
  "Remove loop parameters that only forward an outer lexical value. Their
  initializers remain in place, and recur keeps exactly the retained parameters."
  (:require [clojure.set :as set]
            [com.tailrecursion.nanopass :as np]
            [com.tailrecursion.blacktide.compiler.languages :as l]
            [typed.clojure :as-alias t]))

(np/defpass assigned {:from [l/Joined Expr] :to (t/Set t/Sym)}
  [node]
  :bind (conj (assigned (:body node)) (:target (:binding node)))
  :join (into (assigned (:body node)) (:targets node))
  :branch (set/union (assigned (:yes node)) (assigned (:no node)))
  :switch (into #{} (mapcat assigned) (:arms node))
  ;; Inner bindings are private; only enclosing join targets export changes.
  :loop #{}
  :recur #{} :return #{} :throw #{})

(np/defpass expression {:from [l/Joined Expr] :to [l/Joined Expr] :args [(t/Set t/Sym)]}
  [invariants node]
  :loop (let [invariants (set/difference (set (:slots node)) (assigned (:body node)))]
          (assoc node :slots (filterv #(not (contains? invariants %)) (:slots node))
                      :body (expression invariants (:body node))))
  :recur (assoc node :slots (filterv #(not (contains? invariants %)) (:slots node))))