-
Notifications
You must be signed in to change notification settings - Fork 51
/
analyzer.clj
126 lines (98 loc) · 2.73 KB
/
analyzer.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
(ns helix.impl.analyzer
(:require [clojure.walk]
[clojure.zip :as zip]
[clojure.string :as string]
[cljs.env]
[cljs.analyzer.api :as ana]
[ilk.core :as ilk]))
#_(clj->props '{:a 1 :b {:foo bar}
:on-click (fn [e] (js/alert "hi"))})
;;
;; -- Hooks
;;
(defn resolve-local-vars
"Returns a set of symbols found in `body` that also exist in `env`."
[env body]
(let [sym-list (atom #{})]
(clojure.walk/postwalk
(fn w [x]
(if (symbol? x)
(do (swap! sym-list conj x)
x)
x))
body)
(->> @sym-list
(map (:locals env))
(filter (comp not nil?))
(map :name)
vec)))
;; TODO:
;; - Detect custom hooks
;; - Handle re-ordering
;; - Detect hooks used in let-bindings and add left-hand side to signature
;; - ???
(defn- find-all
"Recursively walks a tree structure and finds all elements
that match `pred`. Returns a vector of results."
[pred tree]
(let [results (atom [])]
(clojure.walk/postwalk
(fn walker [x]
(when (pred x)
(swap! results conj x))
x)
tree)
@results))
(defn hook?
[x]
(when (list? x)
(let [fst (first x)]
(and (symbol? fst) (string/starts-with? (name fst) "use")))))
(defn find-hooks
[body]
(find-all hook? body))
(defn seqable-zip [root]
(zip/zipper (every-pred (comp not string?)
(comp not #(and (sequential? %) (string/starts-with?
(name (first %))
"use")))
sequential?)
seq
(fn [_ c] c)
root))
(defn inferred-type [env x]
(cljs.analyzer/infer-tag env (ana/no-warn (ana/analyze env x))))
(comment
(def example '[foo (fn foo [x] "foo")
bar {:a 1}
baz "baz"])
(ilk/inferred-type {:a 1})
(def z (seqable-zip example))
(defn prn-all-nodes [loc]
(if (zip/end? loc)
(zip/root loc)
(do (prn (zip/node loc))
(recur (zip/next loc)))))
(prn-all-nodes z)
(-> z zip/next zip/next
(zip/edit (fn [node] `(use-callback ~node)))
(zip/next)
(zip/next)
(zip/edit (fn [node] `(use-memo ~node)))
(zip/next)
(zip/next)
(zip/root)
#_(zip/node)
(->> (into [])))
(let [forms '[^:meta (fn [x] 1)
(fn [x] 1)]
env cljs.env/*compiler*]
(for [f forms]
(cljs.analyzer/infer-tag env (ana/analyze env f))))
(let [env (ana/empty-env)]
(for [f example]
[(meta f)
(cljs.analyzer/infer-tag env (ana/analyze env f))
f]))
)
;; => (nil cljs.core/IMap)