Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customizable, dependency-free, potentially non-blocking breakpoints #10

Open
vvvvalvalval opened this issue Oct 18, 2017 · 2 comments
Open

Comments

@vvvvalvalval
Copy link
Owner

In order to make breakpoints available to non-blocking execution environments such as ClojureScript, the macro-expansion of sc.api/brk needs to be customized by some green-threading mechanism.

Currently, the most popular / official green threading mechanism would be core.async's go and <!, i.e the macro-expansion of (sc.api/brk expr) would expand to something like:

(let [ch12 (cljs.core.async/chan)]
  (prompt-breakpoint ch12)
  (let [cmd13 (cljs.core.async/<! ch12)]
    (case (:op cmd13)
      :loose expr 
      :loose-with (:value cmd13)
      :loose-with-err (throw (:error cmd13)))
    ))

Of course, for this to work, the (brk ...) call should be placed inside a go block.

I'm reluctant to use this approach, for several reasons:

  • core.async's not that portable, e.g it's currently not supported on self-hosted CLJS
  • it's prescriptive about the green threading mechanism used; core.async's go is currently the most popular, but it may not always be so in the future, and other such as promesa's or manifold's are desirable as well
  • it imposes to distinguish the emission for Clojure and for ClojureScript, which is always a bit hacky.

Another solution would be to let the client register and use their own strategies for green-threading, by registering a hook in brk. Such strategies could be registered for core.async, manifold, promesa, etc. Examples:

clojure.core promise / deliver / deref:

(defn promise-deliver-port 
  []
  (let [p (promise)]
    {:read-port p
     :write-to-port (fn [cmd] (deliver p cmd))}))

(sc.api.breakpoints/register-green-threading-strategy
  :promise-deliver
  {:make-port `promise-deliver-port
   :emit (fn [cmd-sym read-port body]
           `(let [~cmd-sym (deref ~read-port)]
              ~body))})

core.async go / <!

(defn core-async-port
  []
  (let [c (cljs.core.async/chan)]
    {:read-port c
     :write-to-port (fn [cmd] (a/put! c cmd))}))

(sc.api.breakpoints/register-green-threading-strategy
  :core-async-<!
  {:make-port `core-async-port
   :emit (fn [cmd-sym read-port body]
           `(let [~cmd-sym (cljs.core.async/<! ~read-port)]
              ~body))})

Promesa alet / await

(defn promesa-port
  []
  (let [a (atom nil)
        p (p/promise (fn [resolve reject]
                       (reset! a resolve)))]
    {:read-port p
     :write-to-port @a}))

(sc.api.breakpoints/register-green-threading-strategy
  :promesa-alet-await
  {:make-port `core-async-port
   :emit (fn [cmd-sym read-port body]
           `(p/await (p/alet [~cmd-sym (p/await ~read-port)]
                       ~body)))})
@vvvvalvalval
Copy link
Owner Author

Will need a lil more hammock time, in the meantime brk not supported in CLJS.

@vvvvalvalval
Copy link
Owner Author

There's not necessarily a big demand for scope-capture providing non-blocking breakpoints, as it's already provided by Dirac: https://github.com/binaryage/dirac

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

No branches or pull requests

1 participant