OILS / spec / ysh-assign.test.sh View on Github | oilshell.org

423 lines, 219 significant
1# Test var / setvar / etc.
2
3## our_shell: ysh
4## oils_failures_allowed: 2
5
6#### proc static check: const can't be mutated
7proc f {
8 const x = 'local'
9 echo x=$x
10 setvar x = 'mutated'
11 echo x=$x
12}
13## status: 2
14## STDOUT:
15## END
16
17#### top-level dynamic check: const can't be be mutated
18shopt -s ysh:all
19
20const x = 'foo'
21echo x=$x
22const x = 'bar'
23echo x=$x
24## status: 1
25## STDOUT:
26x=foo
27## END
28
29#### top level: var can be redefined by var/const
30var x = "global"
31echo x=$x
32f() {
33 var x = "local"
34 echo x=$x
35}
36f
37var x = "g2"
38echo x=$x
39const x = 'now-const'
40echo x=$x
41const x = 'oops'
42echo x=$x
43## status: 1
44## STDOUT:
45x=global
46x=local
47x=g2
48x=now-const
49## END
50
51#### setvar mutates local
52proc f {
53 var x = 'local'
54 echo x=$x
55 setvar x = 'mutated'
56 echo x=$x
57}
58
59var x = 'global'
60echo x=$x
61f
62echo x=$x
63## STDOUT:
64x=global
65x=local
66x=mutated
67x=global
68## END
69
70#### top level: setvar creates global
71setvar x = 'global'
72echo x=$x
73setvar x = 'g2'
74echo x=$x
75## STDOUT:
76x=global
77x=g2
78## END
79
80#### top level: setvar mutates var
81var x = 1
82setvar x = 42 # this is allowed
83echo $x
84setvar y = 50 # error because it's not declared
85echo $y
86## STDOUT:
8742
8850
89## END
90
91#### proc static check: variable changed by setvar must be declared
92shopt -s ysh:all
93
94var x = 1
95f() {
96 # setting global is OK
97 setglobal x = 'XX'
98 echo x=$x
99
100 # local NOT DECLARED
101 setvar x = 'YY'
102 echo y=$y
103}
104## status: 2
105## STDOUT:
106## END
107
108#### setglobal
109f() {
110 var x = 'local'
111 echo x=$x
112 setglobal x = 'mutated'
113}
114var x = 'global'
115echo x=$x
116f
117echo x=$x
118## STDOUT:
119x=global
120x=local
121x=mutated
122## END
123
124#### setglobal of undeclared var is allowed
125var x = 'XX'
126echo x=$x
127setglobal x = 'xx'
128echo x=$x
129
130# fatal error
131setglobal y = 'YY'
132
133## STDOUT:
134x=XX
135x=xx
136## END
137
138#### var a, b does implicit null init
139
140var x
141var a, b
142
143var c: Int, d: Int
144
145echo $x $a $b $c $d
146
147## STDOUT:
148null null null null null
149## END
150
151#### var x, y = f()
152
153# The syntax consistent with JavaScript would be
154# var x = 1, y = 2;
155
156var x, y = 1, 2
157echo "x=$x y=$y"
158
159func f() {
160 # this syntax would be nice, but is illegal
161 # return (3, 4)
162 return ([3, 4])
163}
164
165var a, b = f()
166echo "a=$a b=$b"
167
168
169## STDOUT:
170x=1 y=2
171a=3 b=4
172## END
173
174#### const x, y = f()
175
176func f() {
177 # this syntax would be nice, but is illegal
178 # return (3, 4)
179 return ([3, 4])
180}
181
182
183const a, b = f()
184echo "a=$a b=$b"
185
186setvar a = 9 # error
187
188## status: 1
189## STDOUT:
190a=3 b=4
191## END
192
193
194#### setvar x, y = 1, 2
195
196# Python doesn't allow you to have annotation on each variable!
197# https://www.python.org/dev/peps/pep-0526/#where-annotations-aren-t-allowed
198var x Int = 3
199var y Int = 4
200echo "x=$x y=$y"
201
202setvar x, y = 1, 9
203echo "x=$x y=$y"
204
205setvar y, x = x, y
206echo "x=$x y=$y"
207
208setvar x, y = x*2, x*3
209echo "x=$x y=$y"
210
211## STDOUT:
212x=3 y=4
213x=1 y=9
214x=9 y=1
215x=18 y=27
216## END
217
218#### setvar to swap List and Dict elements
219var x = [1, 2, 3]
220echo @x
221
222setvar x[0], x[1] = x[1], x[0]
223
224echo @x
225
226var d = {int: 42}
227
228setvar x[0], d.int = d.int, x[0]
229
230echo @x
231json write (d)
232
233## STDOUT:
2341 2 3
2352 1 3
23642 1 3
237{
238 "int": 2
239}
240## END
241
242#### setvar d.key = 42
243shopt -s ysh:all
244
245var d = {}
246setvar d['f2'] = 42
247setvar d.f3 = 43
248
249# Use the opposite thing to retrieve
250var f3 = d['f3']
251var f2 = d.f2
252echo f3=$f3
253echo f2=$f2
254## STDOUT:
255f3=43
256f2=42
257## END
258
259#### setvar mylist[1] = 42
260shopt -s ysh:all
261var mylist = [1,2,3]
262setvar mylist[1] = 42
263
264write --sep ' ' @mylist
265## STDOUT:
2661 42 3
267## END
268
269#### setvar mylist[99] out of range
270shopt -s ysh:all
271var mylist = [4,5,6]
272try {
273 setvar mylist[99] = 42
274}
275echo $[_error.code]
276
277try {
278 setvar mylist[-99] = 42
279}
280echo $[_error.code]
281
282write --sep ' ' @mylist
283
284## STDOUT:
2853
2863
2874 5 6
288## END
289
290#### mixing assignment builtins and YSH assignment
291shopt -s ysh:all parse_equals
292
293proc local-var {
294 local x=1
295 var x = 2
296 echo x=$x
297}
298
299proc readonly-var {
300 readonly x=1
301 var x = 2
302 echo x=$x
303}
304
305try { eval 'local-var' }
306echo status=$_status
307try { eval 'readonly-var' }
308echo status=$_status
309
310## STDOUT:
311x=2
312status=0
313status=1
314## END
315
316#### circular dict - TODO 2023-06 REGRESS
317var d = {name: 'foo'}
318pp test_ (d)
319
320setvar d['name'] = 123
321pp test_ (d)
322
323setvar d['name'] = 'mystr'
324pp test_ (d)
325
326setvar d['name'] = d
327pp test_ (d)
328
329# This used to print ...
330
331## STDOUT:
332(OrderedDict) <'name': 'foo'>
333(OrderedDict) <'name': 123>
334(OrderedDict) <'name': 'mystr'>
335(OrderedDict) <'name': ...>
336## END
337
338#### circular list - TODO 2023-06 REGRESS
339var L = [1,2,3]
340= L
341#setvar L[0] = L
342#= L
343## STDOUT:
344(List) [1, 2, 3]
345(List) [[...], 2, 3]
346## END
347
348
349#### exit code of var, const, setvar with command sub
350
351# NOTE: This feels PROBLEMATIC without command_sub_errexit feels like it should
352# be the last one ...
353
354run() {
355 $REPO_ROOT/bin/osh -O parse_proc -c "$@"
356
357 # Identical
358 # $SH +O ysh:all -O parse_proc -c "$@"
359}
360
361set +o errexit
362
363run '
364var x = $(false)
365echo inside1=$?
366'
367echo outside1=$?
368
369run '
370setvar x = $(false)
371echo inside2=$?
372'
373echo outside2=$?
374
375# Argument list
376run '
377call split( $(false) )
378echo inside3=$?
379'
380echo outside3=$?
381
382# Place expression
383run '
384var d = {}
385setvar d[ $(false) ] = 42
386echo inside4=$?
387'
388echo outside4=$?
389
390## STDOUT:
391outside1=1
392outside2=1
393outside3=1
394outside4=1
395## END
396
397#### setvar obj[INVALID TYPE] =
398
399set +o errexit
400
401$SH -c '
402var d = {}
403setvar d["key"] = 5
404echo "d.key = $[d.key]"
405setvar d[42] = 6
406echo "should not get here"
407'
408echo outside1=$?
409
410$SH -c '
411var L = [42]
412setvar L[0] = 43
413echo "L[0] = $[L[0]]"
414setvar L["key"] = 44
415'
416echo outside2=$?
417
418## STDOUT:
419d.key = 5
420outside1=3
421L[0] = 43
422outside2=3
423## END