1 ## oils_failures_allowed: 1
2 ## our_shell: ysh
3
4 # dynamically generate procs
5
6 #### with eval builtin command, in global scope
7
8 for param in a b {
9 eval """
10 proc echo_$param(prefix) {
11 echo \$prefix $param
12 }
13 """
14 }
15
16 echo_a prefix
17 echo_b prefix
18
19 ## STDOUT:
20 prefix a
21 prefix b
22 ## END
23
24 #### with eval builtin command, in local scope
25
26 proc p {
27 for param in a b {
28 eval """
29 proc echo_$param(prefix) {
30 echo \$prefix $param
31 }
32 """
33 }
34
35 echo_a prefix
36 echo_b prefix
37 }
38
39 p
40
41 echo_a prefix # not available here!
42
43 ## status: 127
44 ## STDOUT:
45 prefix a
46 prefix b
47 ## END
48
49 #### with eval builtin command, making them global with names() and setVar()
50
51 func genProcs() {
52 var result = {}
53 for param in a b {
54 eval """
55 proc echo_$param(prefix) {
56 echo \$prefix $param
57 }
58 """
59 setvar result["echo_$param"] = getVar("echo_$param")
60 }
61
62 echo 'local'
63 echo_a prefix
64 echo_b prefix
65 echo
66
67 return (result)
68 }
69
70 var procs = genProcs()
71
72 # bind to global scope
73 for name in (procs) {
74 call setVar("my_$name", procs[name])
75 }
76
77 echo 'global'
78 my_echo_a prefix
79 my_echo_b prefix
80
81 ## STDOUT:
82 local
83 prefix a
84 prefix b
85
86 global
87 prefix a
88 prefix b
89 ## END
90
91 #### with parseCommand() then io->eval(), in local scope
92
93 proc p {
94 var result = {}
95 for param in a b {
96 var s = """
97 proc echo_$param(prefix) {
98 echo \$prefix $param
99 }
100 """
101 var cmd = parseCommand(s)
102 #pp test_ (cmd)
103 pp asdl_ (cmd)
104
105 # Oh so then echo_a is defined in the front frame
106 # And then the front frame is discarded?
107 #
108 # OK I see
109 #
110 # So you only use evalToDict()?
111 #
112 # Or parseCommand() returns something UNBOUND, so it has the same power
113 # as eval $mystr
114
115 call io->eval(cmd)
116
117 #call io->evalToDict(cmd)
118 #pp (echo_a)
119 echo_a zz
120 }
121
122 echo_a prefix
123 echo_b prefix
124 }
125
126 p
127
128 echo_a not_defined
129
130 ## status: 127
131 ## STDOUT:
132 prefix a
133 prefix b
134 ## END
135
136 #### with parseCommand() then io->eval(cmd, vars={out_dict: {}})
137
138 # This could take the place of evalToDict()? But evalToDict() is useful in
139 # Hay?
140
141 func genProcs() {
142 var vars = {out_dict: {}}
143 for param in a b {
144 var s = """
145 proc echo_$param(prefix) {
146 echo \$prefix $param
147 }
148 setvar out_dict.echo_$param = echo_$param
149 """
150 var cmd = parseCommand(s)
151 call io->eval(cmd, vars=vars)
152 }
153 return (vars.out_dict)
154 }
155
156 var procs = genProcs()
157
158 var my_echo_a = procs.echo_a
159 var my_echo_b = procs.echo_b
160
161 my_echo_a prefix
162 my_echo_b prefix
163
164 ## STDOUT:
165 prefix a
166 prefix b
167 ## END
168
169 #### with evalToDict()
170
171 func genProcs() {
172 var result = {}
173 for param in a b {
174 var s = """
175 # This is defined locally
176 proc echo_$param(prefix) {
177 echo \$prefix $param
178 }
179 if false {
180 = echo_$param
181 var a = 42
182 pp frame_vars_
183 }
184 """
185 var cmd = parseCommand(s)
186
187 var d = io->evalToDict(cmd)
188
189 # accumulate
190 setvar result["echo_$param"] = d["echo_$param"]
191 }
192 return (result)
193 }
194
195 var procs = genProcs()
196
197 var my_echo_a = procs.echo_a
198 var my_echo_b = procs.echo_b
199
200 my_echo_a prefix
201 my_echo_b prefix
202
203 ## STDOUT:
204 prefix a
205 prefix b
206 ## END
207
208
209 #### with runtime REFLECTION via __invoke__ - no parsing
210
211 # self is the first typed arg
212 proc p (prefix; self) {
213 echo $prefix $[self.param]
214 }
215
216 # p is invoked with "self", which has self.param
217 var methods = Object(null, {__invoke__: p})
218
219 var procs = {}
220 for param in a b {
221 setvar procs["echo_$param"] = Object(methods, {param: param})
222 }
223
224 var my_echo_a = procs.echo_a
225 var my_echo_b = procs.echo_b
226
227 if false {
228 = my_echo_a
229 = my_echo_b
230 type -t my_echo_a
231 type -t my_echo_b
232 }
233
234 # Maybe show an error if this is not value.Obj?
235 my_echo_a prefix
236 my_echo_b prefix
237
238 ## STDOUT:
239 prefix a
240 prefix b
241 ## END