Skip to content

Instantly share code, notes, and snippets.

@sgrove
Last active December 20, 2015 01:39
Show Gist options
  • Save sgrove/6050286 to your computer and use it in GitHub Desktop.
Save sgrove/6050286 to your computer and use it in GitHub Desktop.
Adding symbol location to source maps for fn params and let bindings

Right now fn params are compiled out in compiler.clj via e.g. (emit-fn-method ...) using:

(emitln "(function " (munge name) "(" (comma-sep (map munge params)) "){")

comma-sep just munges the names, interposes ',', and emitss the result, losing any metadata.

If instead in the analyzer when building the fn params, we attached extra keys to give a param the same shape as a :var, then the compiler can simply call (emit param) and have it treated as a var.

(in cljs.analyzer/analyze-fn-method):

[locals params] (reduce (fn [[locals params] name]
                              (let [param {:name name
                                           :line (get-line name env)
                                           :column (get-col name env)
                                           :tag (-> name meta :tag)
                                           :shadow (when locals (locals name))
                                           ;; Give the fn params the same shape
                                           ;; as a :var, so it gets routed
                                           ;; correctly in the compiler
                                           :op :var
                                           :env (merge (select-keys env [:context])
                                                       {:line (get-line name env)
                                                        :column (get-col name env)})
                                           :info {:name name}
                                           :just-munge? true}]
                                [(assoc locals name param) (conj params param)]))
                            [locals []] param-names)

The compiler can simply use emit now on the params an have their output tracked into source maps:

  (doseq [{:keys [init] :as binding} bindings]
    (emits "var ")
    (emit binding) ; Binding will be treated as a var
    (emits " = " init ";"))

The same additions to the bes in cljs.analyzer/analyze-let can cause the same for let bindings.

All these changes are implemented and working in this branch (note that it relies on the clojure.tools patch to be applied from http://dev.clojure.org/jira/browse/CLJS-540)

@brandonbloom
Copy link

Upon very, very brief reflection of this, it seems mostly sensible. I'd have to find some more time later to study the patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment