1 # Oil Functions
2
3 #### Open proc (any number of args)
4 shopt --set parse_proc
5
6 proc f {
7 var x = 42
8 return $x
9 }
10 # this gets called with 3 args then?
11 f a b c
12 echo status=$?
13 ## STDOUT:
14 status=42
15 ## END
16
17 #### Closed proc with no args, passed too many
18 shopt --set parse_proc
19
20 proc f() {
21 return 42
22 }
23 f
24 echo status=$?
25
26 f a b
27 echo status=$? # status 2 because it's a usage error
28
29 ## STDOUT:
30 status=42
31 status=2
32 ## END
33
34 #### Open proc has "$@"
35 shopt -s oil:all
36 proc foo {
37 write ARGV "$@"
38 }
39 builtin set -- a b c
40 foo x y z
41 ## STDOUT:
42 ARGV
43 x
44 y
45 z
46 ## END
47
48 #### Closed proc doesn't have "$@"
49 shopt -s oil:all
50 proc foo(d, e, f) {
51 write params $d $e $f
52 write ARGV "$@"
53 }
54 builtin set -- a b c
55 foo x y z
56 ## STDOUT:
57 params
58 x
59 y
60 z
61 ARGV
62 ## END
63
64
65 #### Proc with default args
66 shopt --set parse_proc
67
68 proc f(x='foo') {
69 echo x=$x
70 }
71 f
72 ## STDOUT:
73 x=foo
74 ## END
75
76 #### Proc with explicit args
77 shopt --set parse_proc
78
79 # doesn't require oil:all
80 proc f(x, y, z) {
81 echo $x $y $z
82 var ret = 42
83 return $ret
84 }
85 # this gets called with 3 args then?
86 f a b c
87 echo status=$?
88 ## STDOUT:
89 a b c
90 status=42
91 ## END
92
93 #### Proc with varargs
94
95 # TODO: opts goes with this
96 # var opt = grep_opts.parse(ARGV)
97 #
98 # func(**opt) # Assumes keyword args match?
99 # parse :grep_opts :opt @ARGV
100
101 shopt -s oil:all
102
103 proc f(...names) {
104 write names: @names
105 }
106 # this gets called with 3 args then?
107 f a b c
108 echo status=$?
109 ## STDOUT:
110 names:
111 a
112 b
113 c
114 status=0
115 ## END
116
117 #### varargs 2
118 shopt -s oil:all
119
120 proc f(first, ...rest) { # @ means "the rest of the arguments"
121 write --sep ' ' -- $first
122 write --sep ' ' -- @rest # @ means "splice this array"
123 }
124 f a b c
125 ## STDOUT:
126 a
127 b c
128 ## END
129
130 #### Proc name-with-hyphen
131 shopt --set parse_proc
132
133 proc name-with-hyphen {
134 echo "$@"
135 }
136 name-with-hyphen x y z
137 ## STDOUT:
138 x y z
139 ## END
140
141 #### Proc with block arg
142 shopt --set parse_proc
143
144 # TODO: Test more of this
145 proc f(x, y; block) {
146 echo F
147 }
148 f a b
149
150 # With varargs and block
151 shopt --set parse_proc
152
153 proc g(x, y, ...rest; block = null) {
154 echo G
155 }
156 g a b c d
157 ## STDOUT:
158 F
159 G
160 ## END
161
162 #### proc returning wrong type
163 shopt --set parse_proc
164
165 # this should print an error message
166 proc f {
167 var a = %(one two)
168 return $a
169 }
170 f
171 ## status: 1
172 ## STDOUT:
173 ## END
174
175 #### proc returning invalid string
176 shopt --set parse_proc
177
178 # this should print an error message
179 proc f {
180 var s = 'not an integer status'
181 return $s
182 }
183 f
184 ## status: 1
185 ## STDOUT:
186 ## END
187
188 #### Out param / setref
189 shopt --set parse_proc
190
191 proc f(input, out Ref) { # : means accept a string "reference"
192 #pp cell __out
193 setref out = "PREFIX-$input"
194 }
195
196 var myvar = 'value'
197 echo myvar=$myvar
198 f zzz :myvar # : means that it's the name of a variable
199 echo myvar=$myvar
200
201 ## STDOUT:
202 myvar=value
203 myvar=PREFIX-zzz
204 ## END
205
206 #### Pass out param through 2 levels of proc
207
208 shopt --set parse_proc
209
210 proc p(s, out Ref) {
211 setref out = "PREFIX-$s" # only goes up ONE level
212 }
213
214 proc p2(s, out Ref) {
215 # SILLY MANUAL idiom, because setref only looks up one level (scope_e.Parent)
216
217 var tmp = null # can be null
218 p $s :tmp
219 setref out = tmp
220
221 # TODO: test
222 # p (s, :tmp)
223 # p (s, 'tmp')
224 #
225 # I think there's no reason they shouldn't work
226 # You strip : in command mode, but in expr mode it's a string
227
228 echo tmp=$tmp
229 }
230
231 var top = 'top'
232 p2 zzz :top
233 echo top=$top
234
235 ## STDOUT:
236 tmp=PREFIX-zzz
237 top=PREFIX-zzz
238 ## END
239
240
241 #### 'return' doesn't accept expressions
242 proc p {
243 return 1 + 2
244 }
245 p
246 ## status: 2
247 ## STDOUT:
248 ## END
249
250 #### procs are in same namespace as shell functions
251 shopt --set parse_proc
252
253 myfunc() {
254 echo hi
255 }
256
257 proc myproc {
258 echo hi
259 }
260
261 declare -F
262 ## STDOUT:
263 declare -f myfunc
264 declare -f myproc
265 ## END
266
267
268 #### Nested proc is disallowed at parse time
269 shopt --set parse_proc
270
271 # NOTE: we can disallow this in Oil statically ...
272 proc f {
273 proc g {
274 echo 'G'
275 }
276 g
277 }
278 f
279 g
280 ## status: 2
281 ## stdout-json: ""
282
283 #### Procs defined inside compound statements (with redefine_proc)
284
285 shopt --set oil:upgrade
286 shopt --set redefine_proc
287
288 for x in 1 2 {
289 proc p {
290 echo 'loop'
291 }
292 }
293 p
294
295 {
296 proc p {
297 echo 'brace'
298 }
299 }
300 p
301
302 ## STDOUT:
303 loop
304 brace
305 ## END
306