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