请在2024 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面以获取有关此功能的一些更多信息。

0
ClojureScript
在我们项目(一个 ClojureScript 调试器)中,我们希望将 cljs 表达式或一系列表达式转换为 JavaScript,以便在 JavaScript 控制台中执行。

我们希望得到类似于 closure/compile-form-seq (https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L308) 的东西。

但是,我们需要在一个环境参数中提供命名空间、需要的部分和局部变量,如下所示:

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


此代码似乎完成了我们所希望的功能。

(defn compile-form-seq
    "将一系列表达式编译为一个 JavaScript 原始字符串。"...
    [forms env]
    (env/ensure)
    (compiler/with-core-cljs nil)
      (fn []
        (with-out-str)
            (doseq [form forms]
              (compiler/emit (analyzer/analyze env form)))))))


我不确定为什么需要 env/ensure。

您能否修补 compile-form-seq 以提供所需的接口,或者建议我们应该做什么。

谢谢
Stu

4 个答案

0

评论者:mikethompson

为了澄清:
1. 当我们的调试器处于断点时,
2. 用户可以在 repl 中输入一个表达式,
3. 作为响应,我们的调试器必须将用户输入的表达式编译为 JavaScript(然后执行它,显示结果),
4. 考虑到任何局部绑定(-----这是关键点)。<----

为了满足第4点,我们的工具提取当前调用框架中的所有“局部变量”,然后将所有这些局部绑定提供给 env/locals,这样编译器就不会在它们前面添加命名空间。

例如,如果调用堆栈中存在对 'x' 的本地绑定,并且用户的重新输入表达式涉及到 'x',那么我们希望编译器不要对符号 'x' 进行更改,也不在它前面添加某些命名空间。在最终的 JavaScript 中,它必须仍然是 'x',而不是 'some.namespace.x'。

我们实现这一目标的方法是在编译时将 'x' 放入 env/locals 中 - 并且一切正常。但是,由于最近的变更,这已经变得更具挑战性。因此,这张工单请求一种传递 env 的方法。

0

评论者:thheller

您可以将用户表达式包装在一个 fn 中,这样就可以跳过对 locals 的操作。REPL 实际上对 1、2、... 执行相同的技巧。

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

0

评论者:dnolen

这看起来像是可以添加到 {{cljs.compiler.api}} 命名空间中的有用功能。

0
参考: https://clojure.atlassian.net/browse/CLJS-1059(由 stumitchell 报告)
...