Welcome! Please see the About page for a little more info on how this works.

0 votes
in ClojureScript by
In our project (a clojurescript debugger) we want to convert cljs forms or a sequence of forms into javascript so that they can be executed in the javascript console.

We would like something similar to closure/compile-form-seq (https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L308)

However, we need to supply, the namespace requires and locals in an env like this

{:ns {:name "test.core" :requires {(quote gstring) (quote goog.string)}} :locals {}}

This code seems to do what we want.

(defn compile-form-seq
    \"Compile a sequence of forms to a JavaScript source string.\"
    [forms env]
    (compiler/with-core-cljs nil
      (fn []
            (doseq [form forms]
              (compiler/emit (analyzer/analyze env form))))))))

I am not sure why I need env/ensure.

Would you be able to patch compile-form-seq to provide the needed interface, or suggest what we should be doing.


4 Answers

0 votes

Comment made by: mikethompson

Just to be clear:
1. when our debugger is at a breakpoint,
2. the user can type in an expression at the repl
3. in response, our debugger has to compile the user-typed-in expression to javascript (and then execute it, showing a result)
4. taking into account any local bindings. <---- this is the key bit.

To satisfy point 4, our tool extracts all the 'locals' from the current call-frame, and then supplies all these local bindings in env/locals, so the compiler doesn't stick a namespace on the front of them.

For example, if there was a local binding for 'x' in the callstack, and the user's repl-entered-expression involves 'x', then we want the compiler to leave the symbol 'x' alone and to not put some namespace on the front of it. In the final javascript, it must still be 'x', not 'some.namespace.x'

Our method to achieve this is to put 'x' into env/locals when compiling -- and it all works. Except, with the recent changes this has become more of a challenge. Hence this ticket asking for a way to pass in env.

0 votes

Comment made by: thheller

You could wrap the user expression in an fn, that would allow you to skip messing with the locals. The REPL basically does the same trick for 1,2,...

(fn [x] ~user-expression-here)

0 votes

Comment made by: dnolen

Seems like something useful to add to a {{cljs.compiler.api}} namespace.

0 votes
Reference: https://clojure.atlassian.net/browse/CLJS-1059 (reported by stumitchell)