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