|
1 | 1 | (require
|
2 |
| - hyrule [unless]) |
| 2 | + hyrule [unless defmacro-kwargs]) |
3 | 3 |
|
4 | 4 |
|
5 | 5 | (defmacro defmeth [#* args]
|
|
46 | 46 | ~@dynadoc))
|
47 | 47 |
|
48 | 48 |
|
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 |
| - |
151 | 49 | (defmacro-kwargs defdataclass [class-name superclasses #* args #** kwargs]
|
152 | 50 | #[[Syntactic sugar for common uses of data classes. Code like
|
153 | 51 |
|
|
0 commit comments