Skip to content

Commit

Permalink
impl attrs detection in binding
Browse files Browse the repository at this point in the history
  • Loading branch information
onionpancakes committed Feb 19, 2024
1 parent 5ba9cb4 commit 661a524
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
28 changes: 26 additions & 2 deletions src/dev/onionpancakes/chassis/compiler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
(:refer-clojure :exclude [compile])
(:require [dev.onionpancakes.chassis.core :as c]))

;; Examine compiler binding expressions for attrs maps.
(defprotocol AttributesCompilerExpr
(attrs-compiler-expr? [this] "Returns true if clojure.lang.Compiler$Expr is attrs."))

(defprotocol CompilableForm
(attrs? [this] "Returns true if form is attrs. Returns false if it might be attrs.")
(not-attrs? [this] "Returns true if form is not attrs. Returns false if it might be attrs.")
Expand Down Expand Up @@ -89,6 +93,26 @@
(attrs-type? (resolve tag-sym)))
false))

(defn attrs-binding?
[^clojure.lang.Compiler$LocalBinding b]
(attrs-compiler-expr? (.-init b)))

(extend-protocol AttributesCompilerExpr
clojure.lang.Compiler$NilExpr
(attrs-compiler-expr? [_] true)
clojure.lang.Compiler$EmptyExpr
(attrs-compiler-expr? [this]
(attrs-type? (.getJavaClass this)))
clojure.lang.Compiler$ConstantExpr
(attrs-compiler-expr? [this]
;; Class not public for some reason, can't call method.
#_(attrs-type? (.getJavaClass this))
false)
clojure.lang.Compiler$MapExpr
(attrs-compiler-expr? [this] true)
Object
(attrs-compiler-expr? [_] false))

(extend-protocol CompilableForm
dev.onionpancakes.chassis.core.OpeningTag
(attrs? [this] false)
Expand Down Expand Up @@ -160,7 +184,8 @@
(attrs? [this]
(or (attrs-type-hinted? this)
(if-some [entry (find *env* this)]
(attrs-type-hinted? (key entry))
(or (attrs-type-hinted? (key entry))
(attrs-binding? (val entry)))
false)))
(not-attrs? [this] false)
(constant? [_] false)
Expand Down Expand Up @@ -201,7 +226,6 @@

(defn attrs-present-evaluated?
[elem]
{:pre [(attrs-present? elem)]}
(evaluated? (nth elem 1)))

(defn attrs-absent?
Expand Down
15 changes: 13 additions & 2 deletions test/dev/onionpancakes/chassis/tests/test_compiler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,26 @@
(defmethod c/resolve-alias ::ReflectiveAttrsAlias
[_ _ ^java.util.Map attrs content]
(cc/compile [:div.reflective-alias-attrs attrs content]))
;; Type hinted invocation
(cc/compile [:div ^java.util.Map (:foo {:foo {}}) "foobar"])
;; Vetted attrs fns
(cc/compile [:div (assoc {} :foo "bar") "foobar"])
(cc/compile [:div (assoc-in {} [:foo :bar] "bar") "foobar"])
(cc/compile [:div (merge {} {:foo "bar"}) "foobar"])
(cc/compile [:div (select-keys {} [:foo]) "foobar"])
(cc/compile [:div (update-keys {} identity) "foobar"])
(cc/compile [:div (update-vals {} identity) "foobar"])
;; Type hinted invocation
(cc/compile [:div ^java.util.Map (:foo {:foo {}}) "foobar"])
;; LocalBinded attrs literals
(let [attrs nil]
(cc/compile [:div attrs "foobar"]))
(let [attrs {}]
(cc/compile [:div attrs "foobar"]))
;; ConstantExpr not public, can't determine constant attrs case.
#_
(let [attrs {:foo "bar"}]
(cc/compile [:div attrs "foobar"]))
(let [attrs {:foo (identity "bar")}]
(cc/compile [:div attrs "foobar"]))
)

(remove-tap count-ambig-attrs)
Expand Down

0 comments on commit 661a524

Please sign in to comment.