Skip to content

Commit d726679

Browse files
authored
feat: fn meta evaluates (#11)
1 parent 980e364 commit d726679

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

src/uclj/core.clj

+15-9
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,13 @@
162162
fn*
163163
(let [[fname & bodies] (parsed-fn expanded)
164164
&env (if fname (add-env &env fname) &env)]
165-
(concat '[fn*]
165+
(with-meta
166+
(concat '[fn*]
166167
(when fname [fname])
167168
(for [[args & bodies] bodies
168169
:let [&env (reduce add-env &env args)]]
169-
(list* args (map (partial iter &env) bodies)))))
170+
(list* args (map (partial iter &env) bodies))))
171+
(meta exp)))
170172

171173
;; else
172174
(map (partial iter &env) expanded))
@@ -316,9 +318,8 @@
316318
;; else
317319
(let [butlast-body (doall (butlast bodies))
318320
last-body (last bodies)]
319-
(gen-eval-node
320-
(do (doseq [x butlast-body] (evalme x &b))
321-
(evalme last-body &b))))))))
321+
(gen-eval-node (do (doseq [x butlast-body] (evalme x &b))
322+
(evalme last-body &b))))))))
322323

323324
(defmethod seq->eval-node 'letfn* seq-eval-letfn [iden->idx recur-indices [_ bindings & bodies :as form]]
324325
(let [promises (for [[k f] (partition 2 bindings)
@@ -398,8 +399,10 @@
398399
(::fn-sym-introduced (meta def)))
399400
(range))
400401
recur-indices (mapv iden->idx (::symbol-loop (meta def)))]]
401-
[arity (->eval-node iden->idx recur-indices (list* 'do bodies))]))]
402-
(make-fn-body fname symbol-used arity->body-node arity->symbols-introduced iden->idx vararg-arity)))
402+
[arity (->eval-node iden->idx recur-indices (list* 'do bodies))]))
403+
meta-node (->eval-node iden->idx nil (::meta-exp (meta form)))]
404+
(cond-> (make-fn-body fname symbol-used arity->body-node arity->symbols-introduced iden->idx vararg-arity)
405+
meta-node (-> (evalme &b) (with-meta (evalme meta-node &b)) (gen-eval-node)))))
403406

404407
(def ^:const max-let-bindings 32)
405408

@@ -707,10 +710,13 @@
707710
::fn-sym-introduced (-> symbol-loop ;; arguments + let vars
708711
(into (set (mapcat (comp ::symbol-introduced meta) bodies))))
709712
::symbol-loop symbol-loop
710-
#_(set (keys new-acc-1))}))]
713+
#_(set (keys new-acc-1))}))
714+
meta-map (-> (meta fn-expression) (dissoc :line :column :file) (not-empty))
715+
meta-exp (enhance-code sym->iden meta-map)]
711716
(with-meta (if fname (list* 'fn* fname fbodies) (list* 'fn* fbodies))
712717
;; symbol-introduced is nil because it is a new closure!
713-
{::symbol-used (set (mapcat (comp ::symbol-used meta) fbodies))})))
718+
{::meta-exp meta-exp
719+
::symbol-used (set (mapcat (comp ::symbol-used meta) fbodies))})))
714720

715721
(defmethod enhance-code 'try [sym->iden [_ & xs]]
716722
(let [bodies (remove (fn [x] (and (seq? x) ('#{finally catch} (first x)))) xs)

test/uclj/core_test.clj

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
(testing "Function name is used"
4747
(is (fn? (evaluator '((fn f [] f))))))
4848

49+
(testing "Meta is evaluated on fn"
50+
(is (= {:a 1} (meta (evaluator '(do ^{:a (inc 0)} (fn []))))))
51+
(is (= "1" (evaluator '(with-out-str ^{:a (print 1)} (fn ^{:b (print 2)} x []))))))
52+
4953
(testing "Recur with single arg"
5054
(is (= :b (evaluator '((fn [a] (if (pos? a) (recur (dec a)) :b)) 4)))))
5155

0 commit comments

Comments
 (0)