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