(defn analyze-symbol
[sym env]
(let [mform (macroexpand-1 sym env)] ;; t.a.j/macroexpand-1 macroexpands Class/Field into (. Class Field)
(if (= mform sym)
(merge (if-let [{:keys [mutable children] :as local-binding} (-> env :locals sym)] ;; locals shadow globals
(merge (dissoc local-binding :init) ;; avoids useless passes later
{:op :local
:assignable? (boolean mutable)
:children (vec (remove #{:init} children))})
(if-let [var (let [v (resolve-sym sym env)]
(and (var? v) v))]
(let [m (meta var)]
{:op :var
:assignable? (dynamic? var m) ;; we cannot statically determine if a Var is in a thread-local context
:var var ;; so checking whether it's dynamic or not is the most we can do
:meta m})
(if-let [maybe-class (namespace sym)] ;; e.g. js/foo.bar or Long/MAX_VALUE
(let [maybe-class (symbol maybe-class)]
{:op :maybe-host-form
:class maybe-class
:field (symbol (name sym))})
{:op :maybe-class ;; e.g. java.lang.Integer or Long
:class mform})))
{:env env
:form mform})
(-> (analyze-form mform env)
(update-in [:raw-forms] (fnil conj ()) sym)))))