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 emits
s 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)
Upon very, very brief reflection of this, it seems mostly sensible. I'd have to find some more time later to study the patch.