This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-09
Channels
- # aleph (16)
- # bangalore-clj (1)
- # beginners (57)
- # cider (4)
- # clara (1)
- # cljs-dev (25)
- # cljsrn (12)
- # clojure (76)
- # clojure-dusseldorf (2)
- # clojure-italy (41)
- # clojure-russia (4)
- # clojure-spec (3)
- # clojure-uk (122)
- # clojurescript (101)
- # cursive (8)
- # data-science (30)
- # datomic (2)
- # emacs (2)
- # figwheel (10)
- # fulcro (53)
- # garden (5)
- # gorilla (6)
- # hoplon (1)
- # jobs (1)
- # juxt (14)
- # leiningen (12)
- # om (1)
- # om-next (1)
- # onyx (21)
- # pedestal (40)
- # perun (5)
- # portkey (2)
- # re-frame (16)
- # reagent (1)
- # ring-swagger (3)
- # rum (6)
- # shadow-cljs (239)
- # spacemacs (10)
- # specter (9)
- # uncomplicate (2)
- # unrepl (1)
- # vim (13)
- # yada (16)
@mhuebert I don’t think it will be possible to compile cljs.js
with the bootstrap build
I think I found the problem, the “host” loads cells.cell, the bootstrap then incorrectly assumes that the cells.cell$macros are loaded as well
Now I have to look.. the repl-specials namespace is what is pulling that in. Maybe it is unnecessary
:source-paths ["src"
"test"
"checkouts/re_view/src"
"checkouts/re_view_hiccup/src"
"checkouts/re_view_routing/src"
"checkouts/re_view_prosemirror/src"
"checkouts/re_db/src"
"checkouts/cljs_live/src"
"checkouts/shapes"
"checkouts/friendly"
"../../lark/cells/src"
"../../lark/commands/src"
"../../lark/structure/src"
"../../lark/editors/src"
"../../lark/tree/src"]
I currently have the compiler state and the eval functions all in maria.eval. I could potentially move the compiler state into another namespace
adding the :excludes option really is not a big deal, afaict it only needs to ignore macros anyways
Haha. I was having trouble getting figwheel to reload in changes in checkouts and so tried putting that all in source paths
just want to make sure that we don’t accidentally break everything by running bootstrap inside bootstrap
for checkouts
you don’t really need to add the :source-paths
, lein
will pick them up
Yeah. Let me try a little refactoring to allow Maria.user access to compiler state without cljs.js
“I was having trouble getting figwheel to reload in changes in checkouts and so tried putting that all in source paths”
you can also set :lein {:profile "+cljs"}
which will then use the :cljs
profile when launching
so you can create a :cljs
profile in project.clj
and put some dependencies there is needed
so i thought i did, but what if I just put compiler-state into a different namespace.
so maria.live.state
will just define a blank atom, then maria.eval
will reset the atom to (empty-env) and use it
right so being able to exclude cljs.js
allows us to enable eval
in self-host, because we can expose a namespace that references cljs.js
without following it
if :lein true
is set, can i still have :source-paths
that are only in shadow-cljs.edn
(ns shadow-eval.user
(:require re-view-hiccup.core
[cells.cell :refer [cell defcell]]
[cells.lib :as cell :refer [interval timeout fetch geo-location with-view wait]]
[shapes.core :as shapes :refer [listen
circle square rectangle triangle path text image
position opacity rotate scale
colorize stroke no-stroke fill no-fill
color-names rgb hsl rescale
layer beside above
fish ; for functional geometry demo
;; are these internal only? -jar
assure-shape-seq shape-bounds bounds shape->vector]]
[re-view.core]
[cljs.js]))
yeah, if there is a namespace that you know isn’t wanted in self-host, it might be useful to essentially pretend it doesn’t exist as far as dependencies go.
the :bootstrap
build still needs to compile everything to ensure everything is correct
(:require-macros [cljs.core.async.macros :as m])
this compiled with the proper :exclude
😉
its a .clj
file https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/env/macros.clj
required by https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/js.clj
so it tries to load cljs.env.macros
as CLJS, which it can’t find since its a .clj
file
to me this is a bit mind bending:
Even though the macros are defined in ClojureScript, they are defined in *.clj files. You can, if you wish, also define macros in *.cljc files, but when they are processed, the :cljs branch of reader conditionals will be used.
we have started a conversation about macros in maria: https://github.com/mhuebert/maria/issues/151
so if we exclude cljs.js
, does it serve any purpose to include transitive macro dependencies of it?
right. i think if they are, then you could include them as a direct dependency in the user namespace
you can use it just fine inside maria, just everything eval’d by the user can’t use them directly
that way you don’t have to specifically exclude all the transitive macro deps of cljs.js in addition to excluding cljs.js
well I only exclude those dependencies from https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/js.clj
I do not ignore those deps https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/js.cljs
dunno the whole cljs.js
namespace seems a bit hacky, it shouldn’t even attempt things like requiring cljs.core$macros
or the cljs.core
analyzer data
dumping the cljs.core analzyer data into the code just seems like a bad idea to begin with
ok, so with current, Maria can now compile and eval with a shadow-cljs build 🙂.
of the basic tests I run (https://www.maria.cloud/gist/8d7dd5bb0294b9623af0bc7c607f46d2?eval=true), only one fails, and that is (require '[cljs.js :as cljs])
. I forgot that I even do that.
I’ve tried putting cljs.env.macros
into the :exclude
but it still throws The required namespace "cljs.env.macros" is not available, it was required by "cljs/js$macros.cljc".
on compile. I’m guessing this relates to your comment above:
> it tries to load cljs.env.macros
as CLJS, which it can’t find since its a .clj
file
when compiling a macro namespace I treat :require
as a CLJS require, ie. it looks for .clj(s|c) files
btw @mhuebert one thing you might want to consider for maria: do the read yourself to split user input properly
I am thinking about that namespace dance. It would be nice if evaluating defmacro in a non-macros namespace would put that into :macros in the analyser state, and then 'get-expander' would also look in cljs namespaces for macros. Since defmacro isn't currently used for anything at all in cljs namespaces AFAIK, this wouldn't conflict with any existing code, only enable better macros in self-host
This is just thinking aloud, how crazy is it to think of shadow-cljs supporting compiling cljs namespaces that use defmacro? I have no idea how your builds work. The current way of doing things is complicated and an understandable but unfortunate artifact of decisions made years ago
We definitely can't reasonably teach macros in Maria without doing this somehow, so incompatibility with existing clojurescript seems inevitable
I can’t really add support for that to shadow-cljs itself since its the JVM compiler, I avoid everything self-hosted when I can.
adding support for your use-case is different since its still just a normal CLJS compile that just adds a few things on top
but adding defmacro
to self-hosted really should not be that hard, you just can’t use the default compile-str
or other *-str
fns
in theory it is easy to just eval defmacro
forms in the JVM instead of generating JS
macros are allowed to use functions normally, but they wouldn’t exist if there is only special case handling for defmacro
https://dev.clojure.org/jira/browse/CLJS-948 is the best I could come up with
So the only way to get real clojure-style macros is to eval them in a JS environment
(in-ns 'cljs.core)
(defn get-expander* [sym env]
(when-not (or (some? (gets env :locals sym)) ; locals hide macros
(and (excluded? env sym) (not (used? env sym))))
(let [nstr (namespace sym)]
(cond
(some? nstr)
(let [ns (get-expander-ns env nstr)]
(when (some? ns)
(.findInternedVar ^clojure.lang.Namespace ns (symbol (name sym)))))
(some? (gets env :ns :rename-macros sym))
(let [qualified-symbol (gets env :ns :rename-macros sym)
nsym (symbol (namespace qualified-symbol))
sym (symbol (name qualified-symbol))]
(.findInternedVar ^clojure.lang.Namespace (find-macros-ns nsym) sym))
:else
(let [cur-ns (gets env :ns :name)]
(or (when (get-in @env/*compiler* [::namespaces cur-ns :defs sym :macro])
(.findInternedVar (find-ns cur-ns) sym))
(let [nsym (gets env :ns :use-macros sym)]
(if (and (some? nsym) (symbol? nsym))
(.findInternedVar ^clojure.lang.Namespace
(find-macros-ns nsym) sym)
(.findInternedVar ^clojure.lang.Namespace
(find-macros-ns CLJS_CORE_MACROS_SYM) sym)))))))))
(in-ns 'maria.user)
I just hacked the get-expander*
fn :else
case to also check in the current ns for macros
you can also Command-P > ‘Print to console’, it will spit the whole gist to the console as a string
I tried something like this yesterday but didn’t figure out get-expander*
well enough to work
and because these are in the same namespace, macros can reference other things in the same namespace from within syntax quote, and it just works
with the shadow bootstrap build, is :dump-core
disabled? ie. avoids spitting the cljs core compiler state into cljs.js?
what if you just (doc cljs.js/eval-str)
without the require
? I’m currently only excluding the cljs.js
macro ns from compilation
so you could have it referred into precompiled namespaces, but not (require ...)
it or put it in an (ns ..)
form
i think that would be useful, ensure that we can still use precompiled namespaces even if they have unfriendly macro deps?
then all of the self-host-related code that i’m aware of us using with Maria will work
next step will be for me to sort out the javascript deps + externs for the outer frame (an :advanced build, eval
happens in a iframe isolated from auth tokens etc.) but that should be more straightforward 🙂
@mhuebert master
should have a fix for the macro deps, didn’t test it but should work 😛
might be useful to emit all excludes into the index itself but just pretending that it doesn’t require the macro should be fine
@mhuebert btw I wanted to build a UI for shadow-cljs
for quite some time now. I might steal some ideas from Maria for the quick-start mode 😉
let users start playing with code immediately and then have some kind of UI widget guide them through generating a proper build config
@thheller I’ve pulled from master and attempted to (require '[cljs.js :as cljs])
, still getting the same:
ns cljs.js$macros not available
Could not require cljs.js
did you try in https://github.com/mhuebert/shadow-eval? it works in my simple example but that doesn’t have to mean much.
i have to crash and have some meetings tomorrow so i won’t get back to this till later
ok, I’ll try to reproduce. might just be related to too much version mockery and bad AOT artifacts
you have cljs.js directly in entries as well as in exclude, i only have it as a transitive dep of another entry. shouldn’t make a difference i don’t think
yeah :exclude
should correctly be called :exclude-macros
as its only for excluding macros