Adding automatic gensym macro
Adding to the manual gensym for macros are 2 new macros, but very literal from the CL in letoverlambda. The first is the (with-gensyms ...) macro that can generate a small set of syms for a macro. Works something like: (defmacro adder2 [A B] (with-gensyms [a b] `(let [[~a ~A] [~b ~B]] (+ ~a ~b)))) and ~a and ~b will be replaced with (gensym "a") and (gensym "b") respectively. Then the final macro is a new defmacro that will automatically replace symbols prefaced with "g!" with a new gensym based on the rest of the symbol. So in this final version of 'nif': (defmacro/g! nif4 (expr pos zero neg) `(let [[~g!result ~expr]] (cond [(pos? ~g!result) ~pos] [(zero? ~g!result) ~zero] [(neg? ~g!result) ~neg]))) all uses of ~g!result will be replaced with (gensym "result").
This commit is contained in:
parent
f5d88bb108
commit
c80e3c75a0
@ -88,6 +88,19 @@
|
|||||||
(if (pred val)
|
(if (pred val)
|
||||||
(yield val)))))
|
(yield val)))))
|
||||||
|
|
||||||
|
(defn flatten [coll]
|
||||||
|
"Return a single flat list expanding all members of coll"
|
||||||
|
(if (and (iterable? coll) (not (string? coll)))
|
||||||
|
(_flatten coll [])
|
||||||
|
(raise (TypeError (.format "{0!r} is not a collection" coll)))))
|
||||||
|
|
||||||
|
(defn _flatten [coll result]
|
||||||
|
(if (and (iterable? coll) (not (string? coll)))
|
||||||
|
(do (foreach [b coll]
|
||||||
|
(_flatten b result)))
|
||||||
|
(.append result coll))
|
||||||
|
result)
|
||||||
|
|
||||||
(defn float? [x]
|
(defn float? [x]
|
||||||
"Return True if x is float"
|
"Return True if x is float"
|
||||||
(isinstance x float))
|
(isinstance x float))
|
||||||
@ -237,8 +250,8 @@
|
|||||||
(_numeric_check n)
|
(_numeric_check n)
|
||||||
(= n 0))
|
(= n 0))
|
||||||
|
|
||||||
(def *exports* '[cycle dec distinct drop drop-while empty? even? filter float?
|
(def *exports* '[cycle dec distinct drop drop-while empty? even? filter flatten
|
||||||
gensym
|
float? gensym
|
||||||
inc instance? integer integer? iterable? iterate iterator? neg?
|
inc instance? integer integer? iterable? iterate iterator? neg?
|
||||||
none? nth numeric? odd? pos? remove repeat repeatedly second
|
none? nth numeric? odd? pos? remove repeat repeatedly second
|
||||||
string string? take take-nth take-while zero?])
|
string string? take take-nth take-while zero?])
|
||||||
|
@ -116,3 +116,13 @@
|
|||||||
(let [[x (gensym)]]
|
(let [[x (gensym)]]
|
||||||
`(foreach [~x ~iterable]
|
`(foreach [~x ~iterable]
|
||||||
(yield ~x))))
|
(yield ~x))))
|
||||||
|
|
||||||
|
(defmacro with-gensyms [args &rest body]
|
||||||
|
`(let ~(HyList (map (fn [x] `[~x (gensym '~x)]) args))
|
||||||
|
~@body))
|
||||||
|
|
||||||
|
(defmacro defmacro/g! [name args &rest body]
|
||||||
|
(let [[syms (list (distinct (filter (fn [x] (.startswith x "g!")) (flatten body))))]]
|
||||||
|
`(defmacro ~name [~@args]
|
||||||
|
(let ~(HyList (map (fn [x] `[~x (gensym (slice '~x 2))]) syms))
|
||||||
|
~@body))))
|
||||||
|
@ -133,6 +133,26 @@
|
|||||||
(setv res (list (filter none? [1 2 None 3 4 None 4 6])))
|
(setv res (list (filter none? [1 2 None 3 4 None 4 6])))
|
||||||
(assert-equal res [None None]))
|
(assert-equal res [None None]))
|
||||||
|
|
||||||
|
(defn test-flatten []
|
||||||
|
"NATIVE: testing the flatten function"
|
||||||
|
(setv res (flatten [1 2 [3 4] 5]))
|
||||||
|
(assert-equal res [1 2 3 4 5])
|
||||||
|
(setv res (flatten ["foo" (, 1 2) [1 [2 3] 4] "bar"]))
|
||||||
|
(assert-equal res ["foo" 1 2 1 2 3 4 "bar"])
|
||||||
|
(setv res (flatten [1]))
|
||||||
|
(assert-equal res [1])
|
||||||
|
(setv res (flatten []))
|
||||||
|
(assert-equal res [])
|
||||||
|
(setv res (flatten (, 1)))
|
||||||
|
(assert-equal res [1])
|
||||||
|
;; test with None
|
||||||
|
(setv res (flatten (, 1 (, None 3))))
|
||||||
|
(assert-equal res [1 None 3])
|
||||||
|
(try (flatten "foo")
|
||||||
|
(catch [e [TypeError]] (assert (in "not a collection" (str e)))))
|
||||||
|
(try (flatten 12.34)
|
||||||
|
(catch [e [TypeError]] (assert (in "not a collection" (str e))))))
|
||||||
|
|
||||||
(defn test-float? []
|
(defn test-float? []
|
||||||
"NATIVE: testing the float? function"
|
"NATIVE: testing the float? function"
|
||||||
(assert-true (float? 4.2))
|
(assert-true (float? 4.2))
|
||||||
|
@ -131,3 +131,48 @@
|
|||||||
(assert (in ":G_" s2))
|
(assert (in ":G_" s2))
|
||||||
;; but make sure the two don't match each other
|
;; but make sure the two don't match each other
|
||||||
(assert (not (= s1 s2))))
|
(assert (not (= s1 s2))))
|
||||||
|
|
||||||
|
(defn test-with-gensym []
|
||||||
|
(import ast)
|
||||||
|
(import [astor.codegen [to_source]])
|
||||||
|
(import [hy.importer [import_buffer_to_ast]])
|
||||||
|
(setv macro1 "(defmacro nif [expr pos zero neg]
|
||||||
|
(with-gensyms [a]
|
||||||
|
`(let [[~a ~expr]]
|
||||||
|
(cond [(pos? ~a) ~pos]
|
||||||
|
[(zero? ~a) ~zero]
|
||||||
|
[(neg? ~a) ~neg]))))
|
||||||
|
|
||||||
|
(print (nif (inc -1) 1 0 -1))
|
||||||
|
")
|
||||||
|
;; expand the macro twice, should use a different
|
||||||
|
;; gensym each time
|
||||||
|
(setv _ast1 (import_buffer_to_ast macro1 "foo"))
|
||||||
|
(setv _ast2 (import_buffer_to_ast macro1 "foo"))
|
||||||
|
(setv s1 (to_source _ast1))
|
||||||
|
(setv s2 (to_source _ast2))
|
||||||
|
(assert (in ":a_" s1))
|
||||||
|
(assert (in ":a_" s2))
|
||||||
|
(assert (not (= s1 s2))))
|
||||||
|
|
||||||
|
(defn test-defmacro-g! []
|
||||||
|
(import ast)
|
||||||
|
(import [astor.codegen [to_source]])
|
||||||
|
(import [hy.importer [import_buffer_to_ast]])
|
||||||
|
(setv macro1 "(defmacro/g! nif [expr pos zero neg]
|
||||||
|
`(let [[~g!res ~expr]]
|
||||||
|
(cond [(pos? ~g!res) ~pos]
|
||||||
|
[(zero? ~g!res) ~zero]
|
||||||
|
[(neg? ~g!res) ~neg])))
|
||||||
|
|
||||||
|
(print (nif (inc -1) 1 0 -1))
|
||||||
|
")
|
||||||
|
;; expand the macro twice, should use a different
|
||||||
|
;; gensym each time
|
||||||
|
(setv _ast1 (import_buffer_to_ast macro1 "foo"))
|
||||||
|
(setv _ast2 (import_buffer_to_ast macro1 "foo"))
|
||||||
|
(setv s1 (to_source _ast1))
|
||||||
|
(setv s2 (to_source _ast2))
|
||||||
|
(assert (in ":res_" s1))
|
||||||
|
(assert (in ":res_" s2))
|
||||||
|
(assert (not (= s1 s2))))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user