Skip to content

Commit 86b0915

Browse files
committed
Use defmacro-kwargs from Hyrule.
1 parent ade127f commit 86b0915

File tree

4 files changed

+6
-164
lines changed

4 files changed

+6
-164
lines changed

simalq/macros.hy

+1-103
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(require
2-
hyrule [unless])
2+
hyrule [unless defmacro-kwargs])
33

44

55
(defmacro defmeth [#* args]
@@ -46,108 +46,6 @@
4646
~@dynadoc))
4747

4848

49-
(defmacro defmacro-kwargs [mname params #* body]
50-
(setv [ps p-rest p-kwargs] (parse-params params))
51-
(setv g (hy.gensym))
52-
`(defmacro ~mname [#* ~g]
53-
(setv ~g (hy.I.simalq/macros.match-params ~g '~params))
54-
~@(gfor
55-
name [#* (.keys ps) #* (if p-rest [p-rest] []) #* (if p-kwargs [p-kwargs] [])]
56-
`(setv ~(hy.models.Symbol name) (get ~g ~name)))
57-
~@body))
58-
59-
(defn match-params [args params]
60-
"Match a interable of arguments against a parameter list in the
61-
style of a `defn` lambda list. The parameter-list syntax here is
62-
somewhat restricted: annotations are forbiddden, `/` and `*` aren't
63-
recognized, and nothing is allowed after `#* args` other than `#**
64-
kwargs`.
65-
66-
Return a dictionary of parameters and their values."
67-
68-
(setv [ps p-rest p-kwargs] (parse-params params))
69-
70-
; Loop over `args`.
71-
(setv args (list args) collected-rest [] collected-kwargs {} i-pos 0)
72-
(while args
73-
(setv x (.pop args 0))
74-
(cond
75-
76-
(and
77-
(isinstance x hy.models.Expression)
78-
x
79-
(isinstance (get x 0) hy.models.Symbol)
80-
(in (hy.mangle (get x 0)) ["unpack_iterable" "unpack_mapping"]))
81-
; Unpacking would require evaluating the elements of `args`, which we
82-
; want to avoid.
83-
(raise (TypeError "unpacking is not allowed in `args`"))
84-
85-
(isinstance x hy.models.Keyword) (do
86-
; A keyword argument
87-
(setv x (hy.mangle x.name))
88-
(when (or
89-
(in x collected-kwargs)
90-
(and (in x ps) (is-not (get ps x "value") None)))
91-
(raise (TypeError (+ "keyword argument repeated: " x))))
92-
(setv v (.pop args 0))
93-
(cond
94-
(in x ps)
95-
(setv (get ps x "value") v)
96-
p-kwargs
97-
(setv (get collected-kwargs x) v)
98-
True
99-
(raise (TypeError f"unexpected keyword argument '{x}'"))))
100-
101-
True (do
102-
; A positional argument
103-
(cond
104-
(< i-pos (len ps)) (do
105-
(setv [k d] (get (list (.items ps)) i-pos))
106-
(if (is (get d "value") None)
107-
(setv (get d "value") x)
108-
(raise (TypeError f"got multiple values for argument '{k}'"))))
109-
p-rest
110-
(.append collected-rest x)
111-
True
112-
(raise (TypeError f"takes {(len ps)} positional arguments but more were given")))
113-
(+= i-pos 1))))
114-
115-
; Return the result.
116-
(dict
117-
#** (dfor
118-
[p d] (.items ps)
119-
p (cond
120-
(is-not (get d "value") None)
121-
(get d "value")
122-
(is-not (get d "default") None)
123-
(get d "default")
124-
True
125-
(raise (TypeError f"missing a required positional argument: '{p}'"))))
126-
#** (if p-rest {p-rest (tuple collected-rest)} {})
127-
#** (if p-kwargs {p-kwargs collected-kwargs} {})))
128-
129-
(eval-and-compile (defn parse-params [params]
130-
"A subroutine for `defmacro-kwargs` and `match-params`."
131-
(import
132-
funcparserlib.parser [maybe many]
133-
hy.model-patterns [SYM FORM sym brackets pexpr])
134-
135-
(setv msym (>> SYM hy.mangle))
136-
(defn pvalue [root wanted]
137-
(>> (pexpr (+ (sym root) wanted)) (fn [x] (get x 0))))
138-
(setv [ps p-rest p-kwargs] (.parse
139-
(+
140-
(many (| msym (brackets msym FORM)))
141-
(maybe (pvalue "unpack-iterable" msym))
142-
(maybe (pvalue "unpack-mapping" msym)))
143-
params))
144-
(setv ps (dfor
145-
p ps
146-
:setv [k dv] (if (isinstance p hy.models.List) p [p None])
147-
k (dict :value None :default dv)))
148-
[ps p-rest p-kwargs]))
149-
150-
15149
(defmacro-kwargs defdataclass [class-name superclasses #* args #** kwargs]
15250
#[[Syntactic sugar for common uses of data classes. Code like
15351

simalq/tile/__init__.hy

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
;; --------------------------------------------------------------
44

55
(require
6-
hyrule [unless]
7-
simalq.macros [field-defaults defmeth defmacro-kwargs])
6+
hyrule [unless defmacro-kwargs]
7+
simalq.macros [field-defaults defmeth])
88
(import
99
copy [deepcopy]
1010
re

simalq/tile/monster.hy

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
;; --------------------------------------------------------------
44

55
(require
6-
hyrule [unless do-n list-n]
7-
simalq.macros [field-defaults pop-integer-part defmeth defmacro-kwargs]
6+
hyrule [unless do-n list-n defmacro-kwargs]
7+
simalq.macros [field-defaults pop-integer-part defmeth]
88
simalq.tile [deftile])
99
(import
1010
re

tests/test_util.hy

+1-57
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,13 @@
22

33

44
(require
5-
simalq.macros [pop-integer-part defmacro-kwargs])
5+
simalq.macros [pop-integer-part])
66
(import
77
fractions [Fraction :as f/]
8-
simalq.macros [match-params]
98
simalq.util [mixed-number]
109
pytest)
1110

1211

13-
14-
(defn test-match-params []
15-
16-
(defn f [args]
17-
(match-params args '[a b [c "default-c"] #* rest #** kw]))
18-
(assert (=
19-
(f [1 2])
20-
(dict :a 1 :b 2 :c '"default-c" :rest #() :kw {})))
21-
(assert (=
22-
(f '[1 2])
23-
(dict :a '1 :b '2 :c '"default-c" :rest #() :kw {})))
24-
(assert (=
25-
(f '[1 2 3 4 (+ 4 1)])
26-
(dict :a '1 :b '2 :c '3 :rest #('4 '(+ 4 1)) :kw {})))
27-
(assert (=
28-
(f '[:a 1 :b 2 :c 3 :extra 4])
29-
(dict :a '1 :b '2 :c '3 :rest #() :kw {"extra" '4})))
30-
(assert (=
31-
(f '[:b 2 1])
32-
(dict :a '1 :b '2 :c '"default-c" :rest #() :kw {})))
33-
(assert (=
34-
(f '[:b 2 :extra "foo" :a 1])
35-
(dict :a '1 :b '2 :c '"default-c" :rest #() :kw {"extra" '"foo"})))
36-
(assert (=
37-
(f '[1 2 3 4 5 6 7 :x 10 :y 11])
38-
(dict :a '1 :b '2 :c '3 :rest #('4 '5 '6 '7) :kw {"x" '10 "y" '11})))
39-
40-
; Mangling
41-
(assert (=
42-
(match-params
43-
'[1 :⬢ ☤ :⚘ 3 :☘ 4]
44-
'[a-b ⬢ #** ✈])
45-
(dict
46-
:a_b '1
47-
:hyx_Xblack_hexagonX '☤
48-
:hyx_XairplaneX {"hyx_XflowerX" '3 "hyx_XshamrockX" '4})))
49-
50-
; Unpacking
51-
(with [(pytest.raises TypeError :match "^unpacking is not allowed in `args`$")]
52-
(f '[1 2 3 #* [1 2]]))
53-
(with [(pytest.raises TypeError :match "^unpacking is not allowed in `args`$")]
54-
(f '[1 2 3 #** {"qq" 1 "xx" 2}])))
55-
56-
57-
(defn test-defmacro-kwargs []
58-
(defmacro-kwargs m [a b [c "default-c"] #* rest #** kw]
59-
[a b c rest kw])
60-
(assert (=
61-
(m 1 2)
62-
[1 2 "default-c" #() {}]))
63-
(assert (=
64-
(m :b "bb" :a "aa" :foo "hello")
65-
["aa" "bb" "default-c" #() {"foo" "hello"}])))
66-
67-
6812
(defn test-pop-integer-part []
6913
(setv x (f/ 1 3))
7014
(assert (= (pop-integer-part x) 0))

0 commit comments

Comments
 (0)