1 | ## oils_failures_allowed: 0
|
2 |
|
3 | # Hay Metaprogramming
|
4 |
|
5 | #### Conditional Inside Blocks
|
6 | shopt --set ysh:all
|
7 |
|
8 | hay define Rule
|
9 |
|
10 | const DEBUG = true
|
11 |
|
12 | Rule one {
|
13 | if (DEBUG) {
|
14 | deps = 'foo'
|
15 | } else {
|
16 | deps = 'bar'
|
17 | }
|
18 | }
|
19 |
|
20 | json write (_hay()) | jq '.children[0]' > actual.txt
|
21 |
|
22 | diff -u - actual.txt <<EOF
|
23 | {
|
24 | "type": "Rule",
|
25 | "args": [
|
26 | "one"
|
27 | ],
|
28 | "children": [],
|
29 | "attrs": {
|
30 | "deps": "foo"
|
31 | }
|
32 | }
|
33 | EOF
|
34 |
|
35 | ## STDOUT:
|
36 | ## END
|
37 |
|
38 |
|
39 | #### Conditional Outside Block
|
40 | shopt --set ysh:all
|
41 |
|
42 | hay define Rule
|
43 |
|
44 | const DEBUG = true
|
45 |
|
46 | if (DEBUG) {
|
47 | Rule two {
|
48 | deps = 'spam'
|
49 | }
|
50 | } else {
|
51 | Rule two {
|
52 | deps = 'bar'
|
53 | }
|
54 | }
|
55 |
|
56 | json write (_hay()) | jq '.children[0].attrs' > actual.txt
|
57 |
|
58 | diff -u - actual.txt <<EOF
|
59 | {
|
60 | "deps": "spam"
|
61 | }
|
62 | EOF
|
63 |
|
64 | ## STDOUT:
|
65 | ## END
|
66 |
|
67 |
|
68 | #### Iteration Inside Block
|
69 | shopt --set ysh:all
|
70 |
|
71 | hay define Rule
|
72 |
|
73 | Rule foo {
|
74 | var d = {}
|
75 | # private var with _
|
76 | for name_ in spam eggs ham {
|
77 | setvar d[name_] = true
|
78 | }
|
79 | }
|
80 |
|
81 | json write (_hay()) | jq '.children[0].attrs' > actual.txt
|
82 |
|
83 | # For loop name leaks! Might want to make it "name_" instead!
|
84 |
|
85 | #cat actual.txt
|
86 |
|
87 | diff -u - actual.txt <<EOF
|
88 | {
|
89 | "d": {
|
90 | "spam": true,
|
91 | "eggs": true,
|
92 | "ham": true
|
93 | }
|
94 | }
|
95 | EOF
|
96 |
|
97 |
|
98 | ## STDOUT:
|
99 | ## END
|
100 |
|
101 |
|
102 | #### Iteration Outside Block
|
103 | shopt --set ysh:all
|
104 |
|
105 | hay define Rule
|
106 |
|
107 | for name in spam eggs ham {
|
108 | Rule $name {
|
109 | path = "/usr/bin/$name"
|
110 | }
|
111 | }
|
112 |
|
113 | json write (_hay()) | jq '.children[].attrs' > actual.txt
|
114 |
|
115 | diff -u - actual.txt <<EOF
|
116 | {
|
117 | "path": "/usr/bin/spam"
|
118 | }
|
119 | {
|
120 | "path": "/usr/bin/eggs"
|
121 | }
|
122 | {
|
123 | "path": "/usr/bin/ham"
|
124 | }
|
125 | EOF
|
126 |
|
127 | ## STDOUT:
|
128 | ## END
|
129 |
|
130 |
|
131 | #### Iteration outside Hay node - example from Samuel
|
132 |
|
133 | shopt --set ysh:all
|
134 |
|
135 | hay define task
|
136 |
|
137 | # BUG with hay eval!
|
138 | hay eval :result {
|
139 | var all_hellos = [ "You", "lovely", "people", "Chuck Norris" ]
|
140 | for hello in (all_hellos) {
|
141 | task "Say $hello" {
|
142 | var extend = "Say Hello"
|
143 | var overrides = {
|
144 | WORD: hello
|
145 | }
|
146 | }
|
147 | }
|
148 | }
|
149 |
|
150 | json write (result) | jq '.children[].attrs' > actual.txt
|
151 |
|
152 | #json write (_hay()) | jq '.children[].attrs' > actual.txt
|
153 |
|
154 | diff -u - actual.txt <<EOF
|
155 | {
|
156 | "extend": "Say Hello",
|
157 | "overrides": {
|
158 | "WORD": "You"
|
159 | }
|
160 | }
|
161 | {
|
162 | "extend": "Say Hello",
|
163 | "overrides": {
|
164 | "WORD": "lovely"
|
165 | }
|
166 | }
|
167 | {
|
168 | "extend": "Say Hello",
|
169 | "overrides": {
|
170 | "WORD": "people"
|
171 | }
|
172 | }
|
173 | {
|
174 | "extend": "Say Hello",
|
175 | "overrides": {
|
176 | "WORD": "Chuck Norris"
|
177 | }
|
178 | }
|
179 | EOF
|
180 | echo status=$?
|
181 |
|
182 | ## STDOUT:
|
183 | status=0
|
184 | ## END
|
185 |
|
186 | #### Proc Inside Block
|
187 | shopt --set ysh:all
|
188 |
|
189 | hay define rule # lower case allowed
|
190 |
|
191 | proc p(name; out) {
|
192 | echo 'p'
|
193 | call out->setValue(name)
|
194 | }
|
195 |
|
196 | rule hello {
|
197 | var eggs = ''
|
198 | var bar = ''
|
199 |
|
200 | p spam (&eggs)
|
201 | p foo (&bar)
|
202 | }
|
203 |
|
204 | json write (_hay()) | jq '.children[0].attrs' > actual.txt
|
205 |
|
206 | diff -u - actual.txt <<EOF
|
207 | {
|
208 | "eggs": "spam",
|
209 | "bar": "foo"
|
210 | }
|
211 | EOF
|
212 |
|
213 | ## STDOUT:
|
214 | p
|
215 | p
|
216 | ## END
|
217 |
|
218 |
|
219 |
|
220 | #### Proc That Defines Block
|
221 | shopt --set ysh:all
|
222 |
|
223 | hay define Rule
|
224 |
|
225 | proc myrule(name) {
|
226 | Rule $name {
|
227 | path = "/usr/bin/$name"
|
228 | }
|
229 | }
|
230 |
|
231 | myrule spam
|
232 | myrule eggs
|
233 | myrule ham
|
234 |
|
235 | json write (_hay()) | jq '.children[].attrs' > actual.txt
|
236 |
|
237 | diff -u - actual.txt <<EOF
|
238 | {
|
239 | "path": "/usr/bin/spam"
|
240 | }
|
241 | {
|
242 | "path": "/usr/bin/eggs"
|
243 | }
|
244 | {
|
245 | "path": "/usr/bin/ham"
|
246 | }
|
247 | EOF
|
248 |
|
249 | ## STDOUT:
|
250 | ## END
|
251 |
|
252 | #### Param scope issue (from Zulip, 2025-02)
|
253 | shopt --set ysh:all
|
254 |
|
255 | hay define Service
|
256 |
|
257 | setvar variant = 'local'
|
258 |
|
259 | proc gen_service(; ; variant=null) {
|
260 |
|
261 | pp test_ (variant)
|
262 |
|
263 | Service auth.example.com { # node taking a block
|
264 | pp test_ (variant)
|
265 | if (variant === 'local') { # condition
|
266 | port = 8001
|
267 | } else {
|
268 | port = 80
|
269 | }
|
270 | }
|
271 | }
|
272 |
|
273 | gen_service (variant='remote')
|
274 | const result = _hay()
|
275 | json write (result)
|
276 |
|
277 | ## STDOUT:
|
278 | (Str) "remote"
|
279 | (Str) "remote"
|
280 | {
|
281 | "source": null,
|
282 | "children": [
|
283 | {
|
284 | "type": "Service",
|
285 | "args": [
|
286 | "auth.example.com"
|
287 | ],
|
288 | "children": [],
|
289 | "attrs": {
|
290 | "port": 80
|
291 | }
|
292 | }
|
293 | ]
|
294 | }
|
295 | ## END
|
296 |
|
297 |
|
298 | #### Hay node with exression block arg now allowed - Node (; ; ^(var x = 1))
|
299 | shopt --set ysh:all
|
300 |
|
301 | hay define Foo
|
302 |
|
303 | Foo (; ; ^(echo hi))
|
304 |
|
305 | ## status: 1
|
306 | ## STDOUT:
|
307 | ## END
|