1 ## our_shell: ysh
2 ## oils_failures_allowed: 2
3
4 # dynamically generate procs
5
6 #### myproc.docString()
7
8 source $[ENV.REPO_ROOT]/spec/testdata/doc-comments.sh
9
10 pp test_ (myproc.docComment())
11 pp test_ (getVar('proc-none').docComment())
12
13 var f = get(__sh_function__, 'f')
14 pp test_ (f.docComment())
15
16 var g = get(__sh_function__, 'g')
17 pp test_ (g.docComment())
18
19 #pp proc
20
21 ## STDOUT:
22 (Str) "YSH-style proc"
23 (Null) null
24 (Str) "doc ' comment with \" quotes"
25 (Null) null
26 ## END
27
28 #### Mutate __sh_function__
29
30 f() { echo sh-func; }
31 f
32
33 setvar __sh_function__.f = 42
34
35 f
36
37 ## STDOUT:
38 sh-func
39 ## END
40
41
42 #### with eval builtin command, in global scope
43
44 for param in a b {
45 eval """
46 proc echo_$param(prefix) {
47 echo \$prefix $param
48 }
49 """
50 # We need to "escape" the for loop scope
51 call setVar("echo_$param", getVar("echo_$param"), global=true)
52 }
53
54 echo_a prefix
55 echo_b prefix
56
57 ## STDOUT:
58 prefix a
59 prefix b
60 ## END
61
62 #### with eval builtin command, in local scope
63
64 proc p {
65 for param in a b {
66 eval """
67 proc echo_$param(prefix) {
68 echo \$prefix $param
69 }
70 """
71 # We need to "escape" the for loop scope
72 call setVar("echo_$param", getVar("echo_$param"), global=true)
73 }
74
75 # calling globals
76 echo_a prefix
77 echo_b prefix
78 }
79
80 p
81
82 # the global is available
83 echo_a prefix
84
85 ## STDOUT:
86 prefix a
87 prefix b
88 prefix a
89 ## END
90
91 #### with eval builtin command, reeturning Dict
92
93 func genProcs() {
94 var result = {}
95 for param in a b {
96 eval """
97 proc echo_$param(prefix) {
98 echo \$prefix $param
99 }
100 """
101 setvar result["echo_$param"] = getVar("echo_$param")
102 }
103 return (result)
104 }
105
106 var procs = genProcs()
107
108 # bind to global scope
109 for name in (procs) {
110 call setVar("my_$name", procs[name], global=true)
111 }
112
113 my_echo_a prefix
114 my_echo_b prefix
115
116 ## STDOUT:
117 prefix a
118 prefix b
119 ## END
120
121 #### with parseCommand() then io->eval(), in local scope
122
123 proc p {
124 var result = {}
125 for param in a b {
126 var s = """
127 proc echo_$param (prefix) {
128 echo \$prefix $param
129 }
130 """
131 var cmd = parseCommand(s)
132 #pp test_ (cmd)
133 #pp asdl_ (cmd)
134
135 # note: this creates its own frame, unlike 'eval'
136 # call io->eval(cmd)
137
138 var d = io->eval(cmd, to_dict=true)
139
140 # bind my_echo_a globally
141 call setVar("my_echo_$param", d["echo_$param"], global=true)
142 }
143
144 #= dict(vm.getFrame(0))
145
146 my_echo_a in-proc
147 my_echo_b in-proc
148 }
149
150 p
151
152 my_echo_a global
153 my_echo_b global
154
155 ## STDOUT:
156 in-proc a
157 in-proc b
158 global a
159 global b
160 ## END
161
162 #### with parseCommand() then io->eval(cmd, vars={out_dict: {}})
163
164 # This could take the place of evalToDict()? But evalToDict() is useful in
165 # Hay?
166
167 func genProcs() {
168 var vars = {out_dict: {}}
169 for param in a b {
170 var s = """
171 proc echo_$param(prefix) {
172 echo \$prefix $param
173 }
174 setvar out_dict.echo_$param = echo_$param
175 """
176 var cmd = parseCommand(s)
177 call io->eval(cmd, vars=vars)
178 }
179 return (vars.out_dict)
180 }
181
182 var procs = genProcs()
183
184 var my_echo_a = procs.echo_a
185 var my_echo_b = procs.echo_b
186
187 my_echo_a prefix
188 my_echo_b prefix
189
190 ## STDOUT:
191 prefix a
192 prefix b
193 ## END
194
195 #### with evalToDict()
196
197 func genProcs() {
198 var result = {}
199 for param in a b {
200 var s = """
201 # This is defined locally
202 proc echo_$param(prefix) {
203 echo \$prefix $param
204 }
205 if false {
206 = echo_$param
207 var a = 42
208 pp frame_vars_
209 }
210 """
211 var cmd = parseCommand(s)
212
213 var d = io->evalToDict(cmd)
214
215 # accumulate
216 setvar result["echo_$param"] = d["echo_$param"]
217 }
218 return (result)
219 }
220
221 var procs = genProcs()
222
223 var my_echo_a = procs.echo_a
224 var my_echo_b = procs.echo_b
225
226 my_echo_a prefix
227 my_echo_b prefix
228
229 ## STDOUT:
230 prefix a
231 prefix b
232 ## END
233
234
235 #### with runtime REFLECTION via __invoke__ - no parsing
236
237 # self is the first typed arg
238 proc p (prefix; self) {
239 echo $prefix $[self.param]
240 }
241
242 # p is invoked with "self", which has self.param
243 var methods = Object(null, {__invoke__: p})
244
245 var procs = {}
246 for param in a b {
247 setvar procs["echo_$param"] = Object(methods, {param: param})
248 }
249
250 var my_echo_a = procs.echo_a
251 var my_echo_b = procs.echo_b
252
253 if false {
254 = my_echo_a
255 = my_echo_b
256 type -t my_echo_a
257 type -t my_echo_b
258 }
259
260 # Maybe show an error if this is not value.Obj?
261 my_echo_a prefix
262 my_echo_b prefix
263
264 ## STDOUT:
265 prefix a
266 prefix b
267 ## END