1
2 #### command sub $(echo hi)
3 var x = $(echo hi)
4 var y = $(echo '')
5 # Make sure we can operate on these values
6 echo x=${x:-default} y=${y:-default}
7 ## STDOUT:
8 x=hi y=default
9 ## END
10
11 #### shell array %(a 'b c')
12 shopt -s parse_at
13 var x = %(a 'b c')
14 var empty = %()
15 argv.py / @x @empty /
16
17 ## STDOUT:
18 ['/', 'a', 'b c', '/']
19 ## END
20
21 #### empty array and simple_word_eval (regression test)
22 shopt -s parse_at simple_word_eval
23 var empty = :| |
24 echo len=$[len(empty)]
25 argv.py / @empty /
26
27 ## STDOUT:
28 len=0
29 ['/', '/']
30 ## END
31
32 #### Empty array and assignment builtin (regression)
33 # Bug happens with shell arrays too
34 empty=()
35 declare z=1 "${empty[@]}"
36 echo z=$z
37 ## STDOUT:
38 z=1
39 ## END
40
41 #### Shell arrays support tilde detection, static globbing, brace detection
42 shopt -s parse_at simple_word_eval
43 touch {foo,bar}.py
44 HOME=/home/bob
45 no_dynamic_glob='*.py'
46
47 var x = %(~/src *.py {andy,bob}@example.com $no_dynamic_glob)
48 argv.py @x
49 ## STDOUT:
50 ['/home/bob/src', 'bar.py', 'foo.py', 'andy@example.com', 'bob@example.com', '*.py']
51 ## END
52
53 #### Set $HOME using 'var' (i.e. Oil string var in word evaluator)
54 var HOME = "foo"
55 echo $HOME
56 echo ~
57 ## STDOUT:
58 foo
59 foo
60 ## END
61
62 #### Use shell var in Oil expression
63 x='abc'
64 var length = len(x) # length in BYTES, unlike ${#x}
65 echo $length
66 ## STDOUT:
67 3
68 ## END
69
70 #### Length doesn't apply to BashArray
71 x=(a b c)
72 x[10]=A
73 x[20]=B
74
75 # shell style: length is 5
76 echo shell=${#x[@]}
77
78 # Length could be 20, but we may change the representation to Dict[int, str]
79 echo ysh=$[len(x)]
80
81 ## status: 3
82 ## STDOUT:
83 shell=5
84 ## END
85
86 #### $[len(x)] inside strings
87 var s = "abc"
88 echo -$[len(s)]-
89
90 # This already has a meaning ...
91 #echo "-$len(x)-"
92 #echo "-${len}(x)-"
93
94 ## STDOUT:
95 -3-
96 ## END
97
98 #### Func with multiple args in multiple contexts
99 shopt --set ysh:upgrade # needed for math.ysh
100
101 source --builtin math.ysh
102
103 var x = max(1+2, 3+4)
104 echo $x $[max(1+2, 3+4)]
105
106 ## STDOUT:
107 7 7
108 ## END
109
110
111 #### Trailing Comma in Param list
112 shopt --set ysh:upgrade # needed for math.ysh
113
114 source --builtin math.ysh
115
116 var x = max(1+2, 3+4,)
117 echo $x $[max(1+2, 3+4,)]
118
119 ## STDOUT:
120 7 7
121 ## END
122
123 #### nested expr contexts
124 var s = "123"
125
126 # lex_mode_e.ShCommand -> Expr -> ShCommand -> Expr
127 var x = $(echo $'len\n' $[len(s)])
128 echo $x
129 ## STDOUT:
130 len 3
131 ## END
132
133
134 # TODO:
135 # - test keyword args
136 # - test splatting *args, **kwargs
137 # - Multiline parsing
138 #
139 # var x = max(
140 # 1+2,
141 # 3+4,
142 # )
143 # echo $x $max(
144 # 1+2,
145 # 3+4,
146 # )
147
148 #### YSH var used with shell arithmetic
149 var w = "3"
150 echo lt=$(( w < 4 ))
151 echo gt=$(( w > 4 ))
152
153 var z = 3
154 echo lt=$(( z < 4 ))
155 echo gt=$(( z > 4 ))
156 ## STDOUT:
157 lt=1
158 gt=0
159 lt=1
160 gt=0
161 ## END
162
163 #### Parse { var x = 42 }
164 shopt -s oil:upgrade
165 g() { var x = 42 }
166
167 var x = 1
168 f() { var x = 42; setvar x = 43 }
169 f
170 echo x=$x
171 ## STDOUT:
172 x=1
173 ## END
174
175 #### double quoted
176 var foo = "bar"
177 var x = "-$foo-${foo}-${undef:-default}-"
178 echo $x
179 ## STDOUT:
180 -bar-bar-default-
181 ## END
182
183 #### double quoted respects strict_array
184 shopt -s strict:all
185 declare -a a=(one two three)
186 var x = "-${a[@]}-"
187 echo $x
188 ## status: 1
189 ## stdout-json: ""
190
191 #### simple var sub $name $0 $1 $? etc.
192 ( exit 42 )
193 var status = $?
194 echo status=$status
195
196 set -- a b c
197 var one = $1
198 var two = $2
199 echo $one $two
200
201 var named = "$one" # equivalent to 'one'
202 echo named=$named
203
204 ## STDOUT:
205 status=42
206 a b
207 named=a
208 ## END
209
210 #### braced var sub ${x:-default}
211
212 # without double quotes
213
214 var b = ${foo:-default}
215 echo $b
216 var c = ${bar:-"-$b-"}
217 echo $c
218
219 var d = "${bar:-"-$c-"}" # another one
220 echo $d
221
222 ## STDOUT:
223 default
224 -default-
225 --default--
226 ## END
227
228 #### braced var sub respects strict_array
229 set -- a b c
230 var x = ${undef:-"$@"}
231 echo $x
232 shopt -s strict_array
233 setvar x = ${undef:-"$@"}
234 echo $x
235 ## status: 1
236 ## STDOUT:
237 a b c
238 ## END
239
240
241 #### null / true / false
242 shopt -s oil:upgrade
243 var n = null
244 if (n) {
245 echo yes
246 } else {
247 echo no
248 }
249 var t = true
250 if (t) {
251 echo yes
252 } else {
253 echo no
254 }
255 var f = false
256 if (f) {
257 echo yes
258 } else {
259 echo no
260 }
261 ## STDOUT:
262 no
263 yes
264 no
265 ## END
266
267 #### Integer literals
268 var d = 123
269 var b = 0b11
270 var o = 0o123
271 var h = 0xff
272 echo $d $b $o $h
273 ## STDOUT:
274 123 3 83 255
275 ## END
276
277 #### Integer literals with underscores
278 const dec = 65_536
279 const bin = 0b0001_0101
280 const oct = 0o001_755
281 const hex = 0x0001_000f
282
283 echo SHELL
284 echo $dec
285 echo $bin
286 echo $oct
287 echo $hex
288 const x = 1_1 + 0b1_1 + 0o1_1 + 0x1_1
289 echo sum $x
290
291 # This works under Python 3.6, but the continuous build has earlier versions
292 if false; then
293 echo ---
294 echo PYTHON
295
296 python3 -c '
297 print(65_536)
298 print(0b0001_0101)
299 print(0o001_755)
300 print(0x0001_000f)
301
302 # Weird syntax
303 print("sum", 1_1 + 0b1_1 + 0o1_1 + 0x1_1)
304 '
305 fi
306
307 ## STDOUT:
308 SHELL
309 65536
310 21
311 1005
312 65551
313 sum 40
314 ## END
315
316 #### Backslash char literal (is an integer)
317 const newline = \n
318 const backslash = \\
319 const sq = \'
320 const dq = \"
321 echo "$newline $backslash $sq $dq"
322 ## STDOUT:
323 10 92 39 34
324 ## END
325
326 #### \u{3bc} is char literal
327 shopt -s oil:all
328
329 var mu = \u{3bc}
330 if (mu === 0x3bc) { # this is the same!
331 echo 'yes'
332 }
333 echo "mu $mu"
334 ## STDOUT:
335 yes
336 mu 956
337 ## END
338
339 #### Bitwise logical
340 var a = 0b0101 & 0b0011
341 echo $a
342 var b = 0b0101 | 0b0011
343 echo $b
344 var c = 0b0101 ^ 0b0011
345 echo $c
346 var d = ~b
347 echo $d
348 ## STDOUT:
349 1
350 7
351 6
352 -8
353 ## END
354
355 #### Shift operators
356 var a = 1 << 4
357 echo $a
358 var b = 16 >> 4
359 echo $b
360 ## STDOUT:
361 16
362 1
363 ## END
364
365 #### Exponentiation with **
366 var x = 2**3
367 echo $x
368
369 var y = 2.0 ** 3.0 # NOT SUPPORTED
370 echo 'should not get here'
371
372 ## status: 3
373 ## STDOUT:
374 8
375 ## END
376
377 #### Two Kinds of Division
378 var x = 5/2
379 echo $x
380 var y = 5 // 2
381 echo $y
382 ## STDOUT:
383 2.5
384 2
385 ## END
386
387 #### mod operator
388 = 5 % 3
389 = -5 % 3
390 ## STDOUT:
391 (Int) 2
392 (Int) 1
393 ## END
394
395 #### multiline strings, list, tuple syntax for list, etc.
396 var dq = "
397 dq
398 2
399 "
400 echo dq=$[len(dq)]
401
402 var sq = '
403 sq
404 2
405 '
406 echo sq=$[len(sq)]
407
408 var mylist = [
409 1,
410 2,
411 3,
412 ]
413 echo mylist=$[len(mylist)]
414
415 var mytuple = (1,
416 2, 3)
417 echo mytuple=$[len(mytuple)]
418
419 ## STDOUT:
420 dq=6
421 sq=6
422 mylist=3
423 mytuple=3
424 ## END
425
426 #### multiline dict
427
428 # Note: a pair has to be all on one line. We could relax that but there isn't
429 # a strong reason to now.
430
431 var mydict = { a:1,
432 b: 2,
433 }
434 echo mydict=$[len(mydict)]
435 ## STDOUT:
436 mydict=2
437 ## END
438
439 #### multiline array and command sub (only here docs disallowed)
440 var array = %(
441 one
442 two
443 three
444 )
445 echo array=$[len(array)]
446
447 var comsub = $(
448 echo hi
449 echo bye
450 )
451 echo comsub=$[len(comsub)]
452
453 ## STDOUT:
454 array=3
455 comsub=6
456 ## END
457
458 #### obj->method()
459 var s = 'hi'
460
461 # TODO: This does a bound method thing we probably don't want
462 var s2 = s->upper()
463 echo $s2
464 ## STDOUT:
465 HI
466 ## END
467
468 #### obj->method does NOT give you a bound method
469 var s = 'hi'
470 var method = s->upper
471 echo $method
472 ## status: 3
473 ## stdout-json: ""
474
475 #### d.key
476 var d = {name: 'andy'}
477 var x = d.name
478 echo $x
479 ## STDOUT:
480 andy
481 ## END
482
483 #### a ++ b for string/list concatenation
484 shopt -s parse_brace
485
486 var i = 'abc'
487 var j = 'de'
488 var k = i ++ j
489 echo string $k
490
491
492 var a = [1, 2]
493 var b = [3]
494 var c = a ++ b
495 echo list len=$[len(c)]
496
497 echo ---
498
499 try {
500 = 'ab' ++ 3
501 }
502 echo Str Int $_status
503
504 try {
505 = [1, 2] ++ 3
506 }
507 echo List Int $_status
508
509 try {
510 = 3 ++ 'ab'
511 }
512 echo Int Str $_status
513
514 ## STDOUT:
515 string abcde
516 list len=3
517 ---
518 Str Int 3
519 List Int 3
520 Int Str 3
521 ## END
522
523 #### s ~~ glob and s !~~ glob
524 shopt -s oil:all
525
526 if ('foo.py' ~~ '*.py') {
527 echo yes
528 }
529 if ('foo.py' !~~ '*.sh') {
530 echo no
531 }
532 ## STDOUT:
533 yes
534 no
535 ## END
536
537 #### Type Errors
538 shopt --set parse_brace
539
540 # TODO: It might be nice to get a message
541 try {
542 var x = {} + []
543 }
544 echo $_status
545
546 try {
547 setvar x = {} + 3
548 }
549 echo $_status
550
551 try {
552 = 'foo' ++ 3
553 }
554 echo $_status
555
556 try {
557 = 'foo' ++ 3
558 }
559 echo $_status
560
561 ## STDOUT:
562 3
563 3
564 3
565 3
566 ## END
567
568
569 #### can't use ++ on integers
570 var x = 12 ++ 3
571 echo $x
572 ## status: 3
573 ## STDOUT:
574 ## END
575
576 #### can't do mystr ++ mylist
577 = ["s"] + "t"
578 ## status: 3
579 ## STDOUT:
580 ## END
581
582
583 #### expression literals
584 var e = ^[1 + 2]
585
586 echo type=$[type(e)]
587 echo eval=$[evalExpr(e)]
588 ## STDOUT:
589 type=Expr
590 eval=3
591 ## END
592
593 #### expression literals, evaluation failure
594 var e = ^[1 / 0]
595 call evalExpr(e)
596 ## status: 3
597 ## STDOUT:
598 ## END
599
600 #### expression literals, lazy evaluation
601 var x = 0
602 var e = ^[x]
603
604 setvar x = 1
605 echo result=$[evalExpr(e)]
606 ## STDOUT:
607 result=1
608 ## END
609
610 #### expression literals, sugar for strings
611 var x = 0
612 var e = ^"x is $x"
613
614 setvar x = 1
615 echo result=$[evalExpr(e)]
616 ## STDOUT:
617 result=x is 1
618 ## END