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

697 lines, 384 significant
1
2#### command sub $(echo hi)
3var x = $(echo hi)
4var y = $(echo '')
5# Make sure we can operate on these values
6echo x=${x:-default} y=${y:-default}
7## STDOUT:
8x=hi y=default
9## END
10
11#### shell array %(a 'b c')
12shopt -s parse_at
13var x = %(a 'b c')
14var empty = %()
15argv.py / @x @empty /
16
17## STDOUT:
18['/', 'a', 'b c', '/']
19## END
20
21#### empty array and simple_word_eval (regression test)
22shopt -s parse_at simple_word_eval
23var empty = :| |
24echo len=$[len(empty)]
25argv.py / @empty /
26
27## STDOUT:
28len=0
29['/', '/']
30## END
31
32#### Empty array and assignment builtin (regression)
33# Bug happens with shell arrays too
34empty=()
35declare z=1 "${empty[@]}"
36echo z=$z
37## STDOUT:
38z=1
39## END
40
41#### Shell arrays support tilde detection, static globbing, brace detection
42shopt -s parse_at simple_word_eval
43touch {foo,bar}.py
44HOME=/home/bob
45no_dynamic_glob='*.py'
46
47var x = %(~/src *.py {andy,bob}@example.com $no_dynamic_glob)
48argv.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)
54var HOME = "foo"
55echo $HOME
56echo ~
57## STDOUT:
58foo
59foo
60## END
61
62#### Use shell var in Oil expression
63x='abc'
64var length = len(x) # length in BYTES, unlike ${#x}
65echo $length
66## STDOUT:
673
68## END
69
70#### Length doesn't apply to BashArray
71x=(a b c)
72x[10]=A
73x[20]=B
74
75# shell style: length is 5
76echo shell=${#x[@]}
77
78# Length could be 20, but we may change the representation to Dict[int, str]
79echo ysh=$[len(x)]
80
81## status: 3
82## STDOUT:
83shell=5
84## END
85
86#### $[len(x)] inside strings
87var s = "abc"
88echo -$[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
99shopt --set ysh:upgrade # needed for math.ysh
100
101source $LIB_YSH/math.ysh
102
103var x = max(1+2, 3+4)
104echo $x $[max(1+2, 3+4)]
105
106## STDOUT:
1077 7
108## END
109
110
111#### Trailing Comma in Param list
112shopt --set ysh:upgrade # needed for math.ysh
113
114source $LIB_YSH/math.ysh
115
116var x = max(1+2, 3+4,)
117echo $x $[max(1+2, 3+4,)]
118
119## STDOUT:
1207 7
121## END
122
123#### nested expr contexts
124var s = "123"
125
126# lex_mode_e.ShCommand -> Expr -> ShCommand -> Expr
127var x = $(echo $'len\n' $[len(s)])
128echo $x
129## STDOUT:
130len 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
149var w = "3"
150echo lt=$(( w < 4 ))
151echo gt=$(( w > 4 ))
152
153var z = 3
154echo lt=$(( z < 4 ))
155echo gt=$(( z > 4 ))
156## STDOUT:
157lt=1
158gt=0
159lt=1
160gt=0
161## END
162
163#### Parse { var x = 42 }
164shopt -s oil:upgrade
165g() { var x = 42 }
166
167var x = 1
168f() { var x = 42; setvar x = 43 }
169f
170echo x=$x
171## STDOUT:
172x=1
173## END
174
175#### double quoted
176var foo = "bar"
177var x = "-$foo-${foo}-${undef:-default}-"
178echo $x
179## STDOUT:
180-bar-bar-default-
181## END
182
183#### double quoted respects strict_array
184shopt -s strict:all
185declare -a a=(one two three)
186var x = "-${a[@]}-"
187echo $x
188## status: 1
189## stdout-json: ""
190
191#### simple var sub $name $0 $1 $? etc.
192( exit 42 )
193var status = $?
194echo status=$status
195
196set -- a b c
197var one = $1
198var two = $2
199echo $one $two
200
201var named = "$one" # equivalent to 'one'
202echo named=$named
203
204## STDOUT:
205status=42
206a b
207named=a
208## END
209
210#### braced var sub ${x:-default}
211
212# without double quotes
213
214var b = ${foo:-default}
215echo $b
216var c = ${bar:-"-$b-"}
217echo $c
218
219var d = "${bar:-"-$c-"}" # another one
220echo $d
221
222## STDOUT:
223default
224-default-
225--default--
226## END
227
228#### braced var sub respects strict_array
229set -- a b c
230var x = ${undef:-"$@"}
231echo $x
232shopt -s strict_array
233setvar x = ${undef:-"$@"}
234echo $x
235## status: 1
236## STDOUT:
237a b c
238## END
239
240
241#### null / true / false
242shopt -s oil:upgrade
243var n = null
244if (n) {
245 echo yes
246} else {
247 echo no
248}
249var t = true
250if (t) {
251 echo yes
252} else {
253 echo no
254}
255var f = false
256if (f) {
257 echo yes
258} else {
259 echo no
260}
261## STDOUT:
262no
263yes
264no
265## END
266
267#### Integer literals
268var d = 123
269var b = 0b11
270var o = 0o123
271var h = 0xff
272echo $d $b $o $h
273## STDOUT:
274123 3 83 255
275## END
276
277#### Integer literals with underscores
278const dec = 65_536
279const bin = 0b0001_0101
280const oct = 0o001_755
281const hex = 0x0001_000f
282
283echo SHELL
284echo $dec
285echo $bin
286echo $oct
287echo $hex
288const x = 1_1 + 0b1_1 + 0o1_1 + 0x1_1
289echo sum $x
290
291# This works under Python 3.6, but the continuous build has earlier versions
292if 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 '
305fi
306
307## STDOUT:
308SHELL
30965536
31021
3111005
31265551
313sum 40
314## END
315
316#### Exponentiation with **
317var x = 2**3
318echo $x
319
320var y = 2.0 ** 3.0 # NOT SUPPORTED
321echo 'should not get here'
322
323## status: 3
324## STDOUT:
3258
326## END
327
328#### Float Division
329pp test_ (5/2)
330pp test_ (-5/2)
331pp test_ (5/-2)
332pp test_ (-5/-2)
333
334echo ---
335
336var x = 9
337setvar x /= 2
338pp test_ (x)
339
340var x = -9
341setvar x /= 2
342pp test_ (x)
343
344var x = 9
345setvar x /= -2
346pp test_ (x)
347
348var x = -9
349setvar x /= -2
350pp test_ (x)
351
352
353## STDOUT:
354(Float) 2.5
355(Float) -2.5
356(Float) -2.5
357(Float) 2.5
358---
359(Float) 4.5
360(Float) -4.5
361(Float) -4.5
362(Float) 4.5
363## END
364
365#### Integer Division (rounds toward zero)
366pp test_ (5//2)
367pp test_ (-5//2)
368pp test_ (5//-2)
369pp test_ (-5//-2)
370
371echo ---
372
373var x = 9
374setvar x //= 2
375pp test_ (x)
376
377var x = -9
378setvar x //= 2
379pp test_ (x)
380
381var x = 9
382setvar x //= -2
383pp test_ (x)
384
385var x = -9
386setvar x //= -2
387pp test_ (x)
388
389## STDOUT:
390(Int) 2
391(Int) -2
392(Int) -2
393(Int) 2
394---
395(Int) 4
396(Int) -4
397(Int) -4
398(Int) 4
399## END
400
401#### % operator is remainder
402pp test_ ( 5 % 3)
403pp test_ (-5 % 3)
404
405# negative divisor illegal (tested in test/ysh-runtime-errors.sh)
406#pp test_ ( 5 % -3)
407#pp test_ (-5 % -3)
408
409var z = 10
410setvar z %= 3
411pp test_ (z)
412
413var z = -10
414setvar z %= 3
415pp test_ (z)
416
417## STDOUT:
418(Int) 2
419(Int) -2
420(Int) 1
421(Int) -1
422## END
423
424#### Bitwise logical
425var a = 0b0101 & 0b0011
426echo $a
427var b = 0b0101 | 0b0011
428echo $b
429var c = 0b0101 ^ 0b0011
430echo $c
431var d = ~b
432echo $d
433## STDOUT:
4341
4357
4366
437-8
438## END
439
440#### Shift operators
441var a = 1 << 4
442echo $a
443var b = 16 >> 4
444echo $b
445## STDOUT:
44616
4471
448## END
449
450#### multiline strings, list, tuple syntax for list, etc.
451var dq = "
452dq
4532
454"
455echo dq=$[len(dq)]
456
457var sq = '
458sq
4592
460'
461echo sq=$[len(sq)]
462
463var mylist = [
464 1,
465 2,
466 3,
467]
468echo mylist=$[len(mylist)]
469
470var mytuple = (1,
471 2, 3)
472echo mytuple=$[len(mytuple)]
473
474## STDOUT:
475dq=6
476sq=6
477mylist=3
478mytuple=3
479## END
480
481#### multiline dict
482
483# Note: a pair has to be all on one line. We could relax that but there isn't
484# a strong reason to now.
485
486var mydict = { a:1,
487 b: 2,
488}
489echo mydict=$[len(mydict)]
490## STDOUT:
491mydict=2
492## END
493
494#### multiline array and command sub (only here docs disallowed)
495var array = %(
496 one
497 two
498 three
499)
500echo array=$[len(array)]
501
502var comsub = $(
503echo hi
504echo bye
505)
506echo comsub=$[len(comsub)]
507
508## STDOUT:
509array=3
510comsub=6
511## END
512
513#### obj->method()
514var s = 'hi'
515
516# TODO: This does a bound method thing we probably don't want
517var s2 = s=>upper()
518echo $s2
519## STDOUT:
520HI
521## END
522
523#### obj->method does NOT give you a bound method
524var s = 'hi'
525var method = s->upper
526echo $method
527## status: 3
528## stdout-json: ""
529
530#### d.key
531var d = {name: 'andy'}
532var x = d.name
533echo $x
534## STDOUT:
535andy
536## END
537
538#### a ++ b for string/list concatenation
539shopt -s parse_brace
540
541var i = 'abc'
542var j = 'de'
543var k = i ++ j
544echo string $k
545
546
547var a = [1, 2]
548var b = [3]
549var c = a ++ b
550echo list len=$[len(c)]
551
552echo ---
553
554try {
555 = 'ab' ++ 3
556}
557echo Str Int $_status
558
559try {
560 = [1, 2] ++ 3
561}
562echo List Int $_status
563
564try {
565 = 3 ++ 'ab'
566}
567echo Int Str $_status
568
569## STDOUT:
570string abcde
571list len=3
572---
573Str Int 3
574List Int 3
575Int Str 3
576## END
577
578#### s ~~ glob and s !~~ glob
579shopt -s oil:all
580
581if ('foo.py' ~~ '*.py') {
582 echo yes
583}
584if ('foo.py' !~~ '*.sh') {
585 echo no
586}
587## STDOUT:
588yes
589no
590## END
591
592#### Type Errors
593shopt --set parse_brace
594
595# TODO: It might be nice to get a message
596try {
597 var x = {} + []
598}
599echo $_status
600
601try {
602 setvar x = {} + 3
603}
604echo $_status
605
606try {
607 = 'foo' ++ 3
608}
609echo $_status
610
611try {
612 = 'foo' ++ 3
613}
614echo $_status
615
616## STDOUT:
6173
6183
6193
6203
621## END
622
623
624#### can't use ++ on integers
625var x = 12 ++ 3
626echo $x
627## status: 3
628## STDOUT:
629## END
630
631#### can't do mystr ++ mylist
632= ["s"] + "t"
633## status: 3
634## STDOUT:
635## END
636
637
638#### expression literals
639var e = ^[1 + 2]
640
641echo type=$[type(e)]
642echo $[evalExpr(e)]
643
644var e = ^[2 < 1]
645echo $[evalExpr(e)]
646
647var x = 42
648var e = ^[42 === x and true]
649echo $[evalExpr(e)]
650
651var mylist = ^[3, 4]
652pp test_ (evalExpr(mylist))
653
654## STDOUT:
655type=Expr
6563
657false
658true
659(List) [3,4]
660## END
661
662#### No list comprehension in ^[]
663
664var mylist = ^[x for x in y]
665pp test_ (evalExpr(mylist))
666
667## status: 2
668## STDOUT:
669## END
670
671
672#### expression literals, evaluation failure
673var e = ^[1 / 0]
674call evalExpr(e)
675## status: 3
676## STDOUT:
677## END
678
679#### expression literals, lazy evaluation
680var x = 0
681var e = ^[x]
682
683setvar x = 1
684echo result=$[evalExpr(e)]
685## STDOUT:
686result=1
687## END
688
689#### expression literals, sugar for strings
690var x = 0
691var e = ^"x is $x"
692
693setvar x = 1
694echo result=$[evalExpr(e)]
695## STDOUT:
696result=x is 1
697## END