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 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 Block) {
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) { # : means accept a string "reference"
192 setref out = "PREFIX-$input"
193 }
194
195 var myvar = 'value'
196 echo myvar=$myvar
197 f zzz :myvar # : means that it's the name of a variable
198 echo myvar=$myvar
199
200 ## STDOUT:
201 myvar=value
202 myvar=PREFIX-zzz
203 ## END
204
205 #### 'return' doesn't accept expressions
206 proc p {
207 return 1 + 2
208 }
209 p
210 ## status: 2
211 ## STDOUT:
212 ## END
213
214 #### procs are in same namespace as shell functions
215 shopt --set parse_proc
216
217 myfunc() {
218 echo hi
219 }
220
221 proc myproc {
222 echo hi
223 }
224
225 declare -F
226 ## STDOUT:
227 declare -f myfunc
228 declare -f myproc
229 ## END
230
231
232 #### Nested proc is disallowed at parse time
233 shopt --set parse_proc
234
235 # NOTE: we can disallow this in Oil statically ...
236 proc f {
237 proc g {
238 echo 'G'
239 }
240 g
241 }
242 f
243 g
244 ## status: 2
245 ## stdout-json: ""
246
247 #### Procs defined inside compound statements (with redefine_proc)
248
249 shopt --set oil:upgrade
250 shopt --set redefine_proc
251
252 for x in 1 2 {
253 proc p {
254 echo 'loop'
255 }
256 }
257 p
258
259 {
260 proc p {
261 echo 'brace'
262 }
263 }
264 p
265
266 ## STDOUT:
267 loop
268 brace
269 ## END
270