Closed borkdude closed 4 years ago
Having macros would be sweet.
I am experimenting with using sci for closh, so that it could be graalified to a binary with fast startup. But closh heavily depends on macros. I was surprised that when I expand the macros before passing them to sci I was able to get basically all of the tests passing. This is very exciting, you did a really great work on sci :clap:
@dundalek Thanks! Yeah, that would indeed be exciting. I'll look into macros sometime soon.
@dundalek First test is passing: https://github.com/borkdude/sci/blob/b0d05444da98f9026bf519c6f6f08a1ca14ff486/test/sci/core_test.cljc#L383
No templating implemented yet, but (defmacro foo [x] (list 'do x x)) (foo (prn :dude))
should already work. To be continued.
@dundalek Now this also works (in the defmacro
branch):
(defmacro foo [x] (let [y (str x x)] `[~y ~y]))
Can you give me a couple of macros for testing? Since sci doesn't really have user-defined namespaces yet, I'm not resolving symbols to their namespace yet in the templating. I wonder if this is needed for your use case.
Unquote-splicing also works now:
$ lein run '(defmacro foo [x] `(list ~@[x 2 3])) (foo 1)'
(1 2 3)
@borkdude very cool progress
One thing I discovered is that arguments to macros are being evaluated, so example cases like these:
(is (= "bar"
(eval* "(defmacro foo [x] (str x)) (foo bar)")))
(is (= :bar
(eval* "(defmacro foo [x] `(keyword ~(str x)) (foo bar)")))
Give error like:
Execution error (ExceptionInfo) at sci.impl.utils/throw-error-with-location (utils.cljc:51).
Could not resolve symbol: bar [at line 1, column 33]
Thanks. Will notify you when it's fixed.
Should be fixed now.
I should note that it's also possible to bring in predefined macros via metadata:
https://github.com/borkdude/babashka/blob/master/src/babashka/impl/clojure/core.clj#L16
Not sure if that is relevant to your use case, or if you want users to be able to define macros. This feature is not yet documented and may change in the future.
@borkdude I was able to figure out the last remaining issue. The thing was I had a self-referencing macro inside backtick, so it referenced fully qualified variant of itself. I was able to make it work with workaround by adding both unqualified and fully qualified variant to bindings
.
So for my use cases this now works :100:.
@dundalek Would it be better if sci fixed something in this regard, if so could you post a repro? Or is this ready for merge? Do you need a release for closh or do you refer by commit sha?
It is good as is, makes sense to me to merge it in. I use sha in deps.edn so no need to cut a release just for me.
Next step for me is to try to get the whole thing compile with graal into a native image :)
@dundalek OK, I merged and deleted the branch. Please refer to a commit on master from here after.
Do I understand correctly you're not using the user defined macro feature but just pass bindings with :sci/macro
?
If you need any help with GraalVM, just let me know. As a heads up: macroexpand and resolve probably don't work on 1.10.1 without any workarounds but it might on 1.9.0 (YMMV). But there are workarounds. One thing that will definitely fail is eval.
We might get an idea how to implement the templating from looking at: