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

720 lines, 398 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 --builtin 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 --builtin 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#### Backslash char literal (is an integer)
317const newline = \n
318const backslash = \\
319const sq = \'
320const dq = \"
321echo "$newline $backslash $sq $dq"
322## STDOUT:
32310 92 39 34
324## END
325
326#### \u{3bc} is char literal
327shopt -s oil:all
328
329var mu = \u{3bc}
330if (mu === 0x3bc) { # this is the same!
331 echo 'yes'
332}
333echo "mu $mu"
334## STDOUT:
335yes
336mu 956
337## END
338
339#### Exponentiation with **
340var x = 2**3
341echo $x
342
343var y = 2.0 ** 3.0 # NOT SUPPORTED
344echo 'should not get here'
345
346## status: 3
347## STDOUT:
3488
349## END
350
351#### Float Division
352pp line (5/2)
353pp line (-5/2)
354pp line (5/-2)
355pp line (-5/-2)
356
357echo ---
358
359var x = 9
360setvar x /= 2
361pp line (x)
362
363var x = -9
364setvar x /= 2
365pp line (x)
366
367var x = 9
368setvar x /= -2
369pp line (x)
370
371var x = -9
372setvar x /= -2
373pp line (x)
374
375
376## STDOUT:
377(Float) 2.5
378(Float) -2.5
379(Float) -2.5
380(Float) 2.5
381---
382(Float) 4.5
383(Float) -4.5
384(Float) -4.5
385(Float) 4.5
386## END
387
388#### Integer Division (rounds toward zero)
389pp line (5//2)
390pp line (-5//2)
391pp line (5//-2)
392pp line (-5//-2)
393
394echo ---
395
396var x = 9
397setvar x //= 2
398pp line (x)
399
400var x = -9
401setvar x //= 2
402pp line (x)
403
404var x = 9
405setvar x //= -2
406pp line (x)
407
408var x = -9
409setvar x //= -2
410pp line (x)
411
412## STDOUT:
413(Int) 2
414(Int) -2
415(Int) -2
416(Int) 2
417---
418(Int) 4
419(Int) -4
420(Int) -4
421(Int) 4
422## END
423
424#### % operator is remainder
425pp line ( 5 % 3)
426pp line (-5 % 3)
427
428# negative divisor illegal (tested in test/ysh-runtime-errors.sh)
429#pp line ( 5 % -3)
430#pp line (-5 % -3)
431
432var z = 10
433setvar z %= 3
434pp line (z)
435
436var z = -10
437setvar z %= 3
438pp line (z)
439
440## STDOUT:
441(Int) 2
442(Int) -2
443(Int) 1
444(Int) -1
445## END
446
447#### Bitwise logical
448var a = 0b0101 & 0b0011
449echo $a
450var b = 0b0101 | 0b0011
451echo $b
452var c = 0b0101 ^ 0b0011
453echo $c
454var d = ~b
455echo $d
456## STDOUT:
4571
4587
4596
460-8
461## END
462
463#### Shift operators
464var a = 1 << 4
465echo $a
466var b = 16 >> 4
467echo $b
468## STDOUT:
46916
4701
471## END
472
473#### multiline strings, list, tuple syntax for list, etc.
474var dq = "
475dq
4762
477"
478echo dq=$[len(dq)]
479
480var sq = '
481sq
4822
483'
484echo sq=$[len(sq)]
485
486var mylist = [
487 1,
488 2,
489 3,
490]
491echo mylist=$[len(mylist)]
492
493var mytuple = (1,
494 2, 3)
495echo mytuple=$[len(mytuple)]
496
497## STDOUT:
498dq=6
499sq=6
500mylist=3
501mytuple=3
502## END
503
504#### multiline dict
505
506# Note: a pair has to be all on one line. We could relax that but there isn't
507# a strong reason to now.
508
509var mydict = { a:1,
510 b: 2,
511}
512echo mydict=$[len(mydict)]
513## STDOUT:
514mydict=2
515## END
516
517#### multiline array and command sub (only here docs disallowed)
518var array = %(
519 one
520 two
521 three
522)
523echo array=$[len(array)]
524
525var comsub = $(
526echo hi
527echo bye
528)
529echo comsub=$[len(comsub)]
530
531## STDOUT:
532array=3
533comsub=6
534## END
535
536#### obj->method()
537var s = 'hi'
538
539# TODO: This does a bound method thing we probably don't want
540var s2 = s=>upper()
541echo $s2
542## STDOUT:
543HI
544## END
545
546#### obj->method does NOT give you a bound method
547var s = 'hi'
548var method = s->upper
549echo $method
550## status: 3
551## stdout-json: ""
552
553#### d.key
554var d = {name: 'andy'}
555var x = d.name
556echo $x
557## STDOUT:
558andy
559## END
560
561#### a ++ b for string/list concatenation
562shopt -s parse_brace
563
564var i = 'abc'
565var j = 'de'
566var k = i ++ j
567echo string $k
568
569
570var a = [1, 2]
571var b = [3]
572var c = a ++ b
573echo list len=$[len(c)]
574
575echo ---
576
577try {
578 = 'ab' ++ 3
579}
580echo Str Int $_status
581
582try {
583 = [1, 2] ++ 3
584}
585echo List Int $_status
586
587try {
588 = 3 ++ 'ab'
589}
590echo Int Str $_status
591
592## STDOUT:
593string abcde
594list len=3
595---
596Str Int 3
597List Int 3
598Int Str 3
599## END
600
601#### s ~~ glob and s !~~ glob
602shopt -s oil:all
603
604if ('foo.py' ~~ '*.py') {
605 echo yes
606}
607if ('foo.py' !~~ '*.sh') {
608 echo no
609}
610## STDOUT:
611yes
612no
613## END
614
615#### Type Errors
616shopt --set parse_brace
617
618# TODO: It might be nice to get a message
619try {
620 var x = {} + []
621}
622echo $_status
623
624try {
625 setvar x = {} + 3
626}
627echo $_status
628
629try {
630 = 'foo' ++ 3
631}
632echo $_status
633
634try {
635 = 'foo' ++ 3
636}
637echo $_status
638
639## STDOUT:
6403
6413
6423
6433
644## END
645
646
647#### can't use ++ on integers
648var x = 12 ++ 3
649echo $x
650## status: 3
651## STDOUT:
652## END
653
654#### can't do mystr ++ mylist
655= ["s"] + "t"
656## status: 3
657## STDOUT:
658## END
659
660
661#### expression literals
662var e = ^[1 + 2]
663
664echo type=$[type(e)]
665echo $[evalExpr(e)]
666
667var e = ^[2 < 1]
668echo $[evalExpr(e)]
669
670var x = 42
671var e = ^[42 === x and true]
672echo $[evalExpr(e)]
673
674var mylist = ^[3, 4]
675pp line (evalExpr(mylist))
676
677## STDOUT:
678type=Expr
6793
680false
681true
682(List) [3,4]
683## END
684
685#### No list comprehension in ^[]
686
687var mylist = ^[x for x in y]
688pp line (evalExpr(mylist))
689
690## status: 2
691## STDOUT:
692## END
693
694
695#### expression literals, evaluation failure
696var e = ^[1 / 0]
697call evalExpr(e)
698## status: 3
699## STDOUT:
700## END
701
702#### expression literals, lazy evaluation
703var x = 0
704var e = ^[x]
705
706setvar x = 1
707echo result=$[evalExpr(e)]
708## STDOUT:
709result=1
710## END
711
712#### expression literals, sugar for strings
713var x = 0
714var e = ^"x is $x"
715
716setvar x = 1
717echo result=$[evalExpr(e)]
718## STDOUT:
719result=x is 1
720## END