-
-
Notifications
You must be signed in to change notification settings - Fork 45
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
Allow specifying macros as argument to compileString
#500
Comments
It sounds like this is a solution proposal rather than a problem statement. The current solution that is proposed, how would that play with macros from libraries? |
Fair, it's taking into account some things you already told me about the macro API. As to how it considers dependencies: it wouldn't. Much like compileString doesn't really consider dependencies. I'm thinking of this as a low level extension mechanism through which other tools can provide macro implementations (from wherever). Very open to other ideas as well, I guess what I'm suggesting is more about a "no assumptions" API to provide macros. Hope that makes sense! |
I don't think it will be very convenient if users would have to add library macros manually in the plugin configuration though |
That's not what I'm suggesting. |
That's only one piece of the puzzle though. The other maybe harder piece would be: where would the plugin get the information from? I guess another approach could be to still have a squint.edn such that |
The plugin could also look in This is far out of course but I'm not seeing this API as something that end users would use but rather build tools that work on top of squint (like the Vite plugin).
|
I am trying to use squint to compile user code using |
@nasser Currently it only works on the CLJ/CLJS side, but it could be made to work on the JS side as well. Demo in JVM Clojure: user=> (sq/compile-string "(dude/foo 1)" {:macros {'dude {'foo (fn [form env x] `(do (js/console.log ~x) ~x))}}})
"import * as squint_core from 'squint-cljs/core.js';\nconsole.log(1);\n1;\n" Squint doesn't support "inline" Note that scittle (based on SCI = Clojure interpreter) does support inline macros without any problems since how it works is closer to how JVM Clojure works: https://babashka.org/scittle/ |
oh very cool! thanks for the background! yeah i am less interested in the inline could you point me in the direction of what to change to expose the |
yes: squint/src/squint/compiler.cljc Lines 550 to 557 in 1aa8a67
|
awesome i am on it. one thing -- do macros referenced this way always need to be fully qualified? i.e. in your example is there a way i could say |
@nasser Before we proceed, one more question. How would you write macros in pure JS or squint? Macros typically deal with CLJS data structures with symbols and keywords. Squint doesn't have the concept of keywords and/or symbols. This is why macros run in SCI when using squint with the command line. |
Cherry does have runtime keywords and symbols btw. |
thats a good question. is there a way i could use cherry to compile or run the macros? |
No, since cherry is advanced compiled in a different build than squint and their symbol/keyword/data-structure stuff isn't interchangeable. It's way easier to use squint from ClojureScript, mix in your macros, then compile that to a final artifact and use that instead. |
you're totally right, and given that i don't need macros beyond the few built-in ones in my system i think that's the path of least resistance. exposing my own (ns eighth-floor.core
(:require [squint.compiler :as sq]))
(defn genstr [s]
(-> (js/Math.random) (.toString 32) (.replace "0." (str s "."))))
(aset js/globalThis "$CYCLES" #js {})
(def default-opts
{:macros
{'<> (fn [form env x]
(let [name (genstr "cycle")]
`(do
(when-not (aget js/globalThis.$CYCLES ~name)
(aset js/globalThis.$CYCLES ~name (cycle ~x)))
(aget js/globalThis.$CYCLES ~name))))}})
(defn compile-string
([s] (compile-string s nil))
([s opts]
(sq/compile-string s (-> opts
sq/clj-ize-opts
(merge default-opts))))) means i can do this from JS import { compileString } from './lib/eighth-floor.js';
const compiled = compileString("(fn [] (+ 1 (<> 10 (str [1 2 3 4]))))", { 'elide-imports': true, context: 'expr' });
console.log(compiled)
// (function () {
// return (1) + ((() => {
// if (squint_core.truth_(globalThis.$CYCLES["cycle.fggh95bnobo"])) {
// } else {
// squint_core.aset(globalThis.$CYCLES, "cycle.fggh95bnobo", squint_core.cycle(10))};
// return globalThis.$CYCLES["cycle.fggh95bnobo"];
// })());
// }); which is exactly what i need! thanks for your guidance @borkdude. no PR coming from me in that case, especially given your point that it is not clear how to run the macros from the JS API side. |
Excellent, thank you! And also thank you for letting me think through this issue more, in hindsight it doesn't make that much sense to allow this to be done from the JS side, so I'll close this. |
Btw, @nasser, I'm curious what you're creating :) |
porting https://8fl.live/ to the browser 👀 |
nice! |
To upvote this issue, give it a thumbs up. See this list for the most upvoted issues.
Is your feature request related to a problem? Please describe.
Currently macros rely on a "classpath style" construct via
squint.edn
. For tools like Vite and general flexibility it would be nice to be able to provide macros to thecompileString
function.Describe the solution you'd like
Document (and implement if not already) an extra input to
compileString
that takes macros. This could be plain JS functions.The text was updated successfully, but these errors were encountered: