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

956 lines, 644 significant
1#!/usr/bin/env bash
2#
3# Usage:
4# test/spec.sh <function name>
5
6set -o nounset
7set -o pipefail
8set -o errexit
9shopt -s strict:all 2>/dev/null || true # dogfood for OSH
10
11REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
12
13source test/common.sh
14source test/spec-common.sh
15source devtools/run-task.sh
16
17if test -z "${IN_NIX_SHELL:-}"; then
18 source build/dev-shell.sh # to run 'dash', etc.
19fi
20
21# TODO: Just use 'dash bash' and $PATH
22readonly DASH=dash
23readonly BASH=bash
24readonly MKSH=mksh
25readonly ZSH=zsh
26readonly BUSYBOX_ASH=ash
27
28# ash and dash are similar, so not including ash by default. zsh is not quite
29# POSIX.
30readonly REF_SHELLS=($DASH $BASH $MKSH)
31
32check-survey-shells() {
33 ### Make sure bash, zsh, OSH, etc. exist
34
35 # Note: yash isn't here, but it is used in a couple tests
36
37 test/spec-runner.sh shell-sanity-check "${REF_SHELLS[@]}" $ZSH $BUSYBOX_ASH $OSH_LIST
38}
39
40# TODO: remove this stub after we hollow out this file
41
42run-file() { test/spec-py.sh run-file "$@"; }
43
44#
45# Misc
46#
47
48# Really what I want is enter(func) and exit(func), and filter by regex?
49trace-var-sub() {
50 local out=_tmp/coverage
51 mkdir -p $out
52
53 # This creates *.cover files, with line counts.
54 #python -m trace --count -C $out \
55
56 # This prints trace with line numbers to stdout.
57 #python -m trace --trace -C $out \
58 PYTHONPATH=. python -m trace --trackcalls -C $out \
59 test/sh_spec.py spec/var-sub.test.sh $DASH $BASH "$@"
60
61 ls -l $out
62 head $out/*.cover
63}
64
65#
66# Individual tests.
67#
68# We configure the shells they run on and the number of allowed failures (to
69# prevent regressions.)
70#
71
72interactive-parse() {
73 run-file interactive-parse "$@"
74}
75
76smoke() {
77 run-file smoke "$@"
78}
79
80interactive() {
81 run-file interactive "$@"
82}
83
84prompt() {
85 run-file prompt "$@"
86}
87
88bugs() {
89 run-file bugs "$@"
90}
91
92TODO-deprecate() {
93 run-file TODO-deprecate "$@"
94}
95
96blog1() {
97 sh-spec spec/blog1.test.sh \
98 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
99}
100
101blog2() {
102 sh-spec spec/blog2.test.sh \
103 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
104}
105
106blog-other1() {
107 sh-spec spec/blog-other1.test.sh \
108 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
109}
110
111alias() {
112 run-file alias "$@"
113}
114
115comments() {
116 sh-spec spec/comments.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
117}
118
119word-split() {
120 run-file word-split "$@"
121}
122
123word-eval() {
124 sh-spec spec/word-eval.test.sh \
125 ${REF_SHELLS[@]} $OSH_LIST "$@"
126}
127
128# These cases apply to many shells.
129assign() {
130 run-file assign "$@"
131}
132
133# These cases apply to a few shells.
134assign-extended() {
135 sh-spec spec/assign-extended.test.sh \
136 $BASH $MKSH $OSH_LIST "$@"
137}
138
139# Corner cases that OSH doesn't handle
140assign-deferred() {
141 sh-spec spec/assign-deferred.test.sh \
142 $BASH $MKSH "$@"
143}
144
145# These test associative arrays
146assign-dialects() {
147 run-file assign-dialects "$@"
148}
149
150background() {
151 run-file background "$@"
152}
153
154subshell() {
155 sh-spec spec/subshell.test.sh \
156 ${REF_SHELLS[@]} $OSH_LIST "$@"
157}
158
159quote() {
160 sh-spec spec/quote.test.sh \
161 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
162}
163
164loop() {
165 sh-spec spec/loop.test.sh \
166 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
167}
168
169case_() {
170 run-file case_ "$@"
171}
172
173if_() {
174 sh-spec spec/if_.test.sh \
175 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
176}
177
178builtins() {
179 run-file builtins "$@"
180}
181
182builtin-eval-source() {
183 sh-spec spec/builtin-eval-source.test.sh \
184 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
185}
186
187builtin-io() {
188 run-file builtin-io "$@"
189}
190
191nul-bytes() {
192 run-file nul-bytes "$@"
193}
194
195# Special bash printf things like -v and %q. Portable stuff goes in builtin-io.
196builtin-printf() {
197 run-file builtin-printf "$@"
198}
199
200builtins2() {
201 run-file builtins2 "$@"
202}
203
204builtin-history() {
205 run-file builtin-history "$@"
206}
207
208# dash and mksh don't implement 'dirs'
209builtin-dirs() {
210 sh-spec spec/builtin-dirs.test.sh \
211 $BASH $ZSH $OSH_LIST "$@"
212}
213
214builtin-vars() {
215 run-file builtin-vars "$@"
216}
217
218builtin-getopts() {
219 run-file builtin-getopts "$@"
220}
221
222builtin-bracket() {
223 run-file builtin-bracket "$@"
224}
225
226builtin-trap() {
227 sh-spec spec/builtin-trap.test.sh \
228 ${REF_SHELLS[@]} $OSH_LIST "$@"
229}
230
231builtin-trap-bash() {
232 run-file builtin-trap-bash "$@"
233}
234
235# Bash implements type -t, but no other shell does. For Nix.
236# zsh/mksh/dash don't have the 'help' builtin.
237builtin-bash() {
238 run-file builtin-bash "$@"
239}
240
241builtin-type() {
242 run-file builtin-type "$@"
243}
244
245builtin-type-bash() {
246 run-file builtin-type-bash "$@"
247}
248
249vars-bash() {
250 run-file vars-bash "$@"
251}
252
253vars-special() {
254 run-file vars-special "$@"
255}
256
257builtin-completion() {
258 run-file builtin-completion "$@"
259}
260
261builtin-special() {
262 sh-spec spec/builtin-special.test.sh --oils-failures-allowed 4 \
263 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
264}
265
266builtin-times() {
267 sh-spec spec/builtin-times.test.sh $BASH $ZSH $OSH_LIST "$@"
268}
269
270command-parsing() {
271 sh-spec spec/command-parsing.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
272}
273
274func-parsing() {
275 sh-spec spec/func-parsing.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
276}
277
278sh-func() {
279 sh-spec spec/sh-func.test.sh --oils-failures-allowed 1 \
280 ${REF_SHELLS[@]} $OSH_LIST "$@"
281}
282
283glob() {
284 # Note: can't pass because it assumes 'bin' exists, etc.
285 sh-spec spec/glob.test.sh --oils-failures-allowed 3 \
286 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
287}
288
289globignore() {
290 run-file globignore "$@"
291}
292
293arith() {
294 run-file arith "$@"
295}
296
297command-sub() {
298 sh-spec spec/command-sub.test.sh \
299 ${REF_SHELLS[@]} $OSH_LIST "$@"
300}
301
302command_() {
303 sh-spec spec/command_.test.sh \
304 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
305}
306
307pipeline() {
308 sh-spec spec/pipeline.test.sh \
309 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
310}
311
312explore-parsing() {
313 sh-spec spec/explore-parsing.test.sh \
314 ${REF_SHELLS[@]} $OSH_LIST "$@"
315}
316
317parse-errors() {
318 sh-spec spec/parse-errors.test.sh --oils-failures-allowed 3 \
319 ${REF_SHELLS[@]} $OSH_LIST "$@"
320}
321
322here-doc() {
323 # NOTE: The last two tests, 31 and 32, have different behavior on my Ubuntu
324 # and Debian machines.
325 # - On Ubuntu, read_from_fd.py fails with Errno 9 -- bad file descriptor.
326 # - On Debian, the whole process hangs.
327 # Is this due to Python 3.2 vs 3.4? Either way osh doesn't implement the
328 # functionality, so it's probably best to just implement it.
329 sh-spec spec/here-doc.test.sh --range 0-31 \
330 ${REF_SHELLS[@]} $OSH_LIST "$@"
331}
332
333redirect() {
334 sh-spec spec/redirect.test.sh --oils-failures-allowed 2 \
335 ${REF_SHELLS[@]} $OSH_LIST "$@"
336}
337
338redirect-multi() {
339 run-file redirect-multi "$@"
340}
341
342posix() {
343 sh-spec spec/posix.test.sh \
344 ${REF_SHELLS[@]} $OSH_LIST "$@"
345}
346
347introspect() {
348 run-file introspect "$@"
349}
350
351tilde() {
352 sh-spec spec/tilde.test.sh \
353 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
354}
355
356var-op-test() {
357 sh-spec spec/var-op-test.test.sh \
358 ${REF_SHELLS[@]} $OSH_LIST "$@"
359}
360
361var-op-len() {
362 sh-spec spec/var-op-len.test.sh \
363 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
364}
365
366var-op-patsub() {
367 # 1 unicode failure, and [^]] which is a parsing divergence
368 sh-spec spec/var-op-patsub.test.sh --oils-failures-allowed 2 \
369 $BASH $MKSH $ZSH $OSH_LIST "$@"
370 # TODO: can add $BUSYBOX_ASH
371}
372
373var-op-slice() {
374 # dash doesn't support any of these operations
375 sh-spec spec/var-op-slice.test.sh --oils-failures-allowed 1 \
376 $BASH $MKSH $ZSH $OSH_LIST "$@"
377}
378
379var-op-bash() {
380 run-file var-op-bash "$@"
381}
382
383var-op-strip() {
384 sh-spec spec/var-op-strip.test.sh \
385 ${REF_SHELLS[@]} $ZSH $BUSYBOX_ASH $OSH_LIST "$@"
386}
387
388var-sub() {
389 # NOTE: ZSH has interesting behavior, like echo hi > "$@" can write to TWO
390 # FILES! But ultimately we don't really care, so I disabled it.
391 sh-spec spec/var-sub.test.sh \
392 ${REF_SHELLS[@]} $OSH_LIST "$@"
393}
394
395var-num() {
396 run-file var-num "$@"
397}
398
399var-sub-quote() {
400 sh-spec spec/var-sub-quote.test.sh \
401 ${REF_SHELLS[@]} $OSH_LIST "$@"
402}
403
404sh-usage() {
405 run-file sh-usage "$@"
406}
407
408sh-options() {
409 run-file sh-options "$@"
410}
411
412xtrace() {
413 sh-spec spec/xtrace.test.sh --oils-failures-allowed 1 \
414 ${REF_SHELLS[@]} $OSH_LIST "$@"
415}
416
417strict-options() {
418 sh-spec spec/strict-options.test.sh \
419 ${REF_SHELLS[@]} $OSH_LIST "$@"
420}
421
422exit-status() {
423 run-file exit-status "$@"
424}
425
426errexit() {
427 sh-spec spec/errexit.test.sh \
428 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
429}
430
431errexit-osh() {
432 run-file errexit-osh "$@"
433}
434
435fatal-errors() {
436 sh-spec spec/fatal-errors.test.sh \
437 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
438}
439
440#
441# Non-POSIX extensions: arrays, brace expansion, [[, ((, etc.
442#
443
444# There as many non-POSIX arithmetic contexts.
445arith-context() {
446 sh-spec spec/arith-context.test.sh \
447 $BASH $MKSH $ZSH $OSH_LIST "$@"
448}
449
450array() {
451 sh-spec spec/array.test.sh \
452 $BASH $MKSH $OSH_LIST "$@"
453}
454
455array-compat() {
456 run-file array-compat "$@"
457}
458
459type-compat() {
460 run-file type-compat "$@"
461}
462
463# += is not POSIX and not in dash.
464append() {
465 run-file append "$@"
466}
467
468# associative array -- mksh and zsh implement different associative arrays.
469assoc() {
470 run-file assoc "$@"
471}
472
473# ZSH also has associative arrays
474assoc-zsh() {
475 sh-spec spec/assoc-zsh.test.sh $ZSH "$@"
476}
477
478dbracket() {
479 run-file dbracket "$@"
480}
481
482dparen() {
483 sh-spec spec/dparen.test.sh --oils-failures-allowed 1 \
484 $BASH $MKSH $ZSH $OSH_LIST "$@"
485}
486
487brace-expansion() {
488 run-file brace-expansion "$@"
489}
490
491regex() {
492 sh-spec spec/regex.test.sh --oils-failures-allowed 2 \
493 $BASH $ZSH $OSH_LIST "$@"
494}
495
496process-sub() {
497 # mksh and dash don't support it
498 sh-spec spec/process-sub.test.sh \
499 $BASH $ZSH $OSH_LIST "$@"
500}
501
502# This does file system globbing
503extglob-files() {
504 sh-spec spec/extglob-files.test.sh --oils-failures-allowed 1 \
505 $BASH $MKSH $OSH_LIST "$@"
506}
507
508# This does string matching.
509extglob-match() {
510 sh-spec spec/extglob-match.test.sh \
511 $BASH $MKSH $OSH_LIST "$@"
512}
513
514nocasematch-match() {
515 run-file nocasematch-match "$@"
516}
517
518# ${!var} syntax -- oil should replace this with associative arrays.
519# mksh has completely different behavior for this syntax. Not worth testing.
520var-ref() {
521 run-file var-ref "$@"
522}
523
524# declare / local -n
525# there is one divergence when combining -n and ${!ref}
526nameref() {
527 sh-spec spec/nameref.test.sh --oils-failures-allowed 7 \
528 $BASH $MKSH $OSH_LIST "$@"
529}
530
531let() {
532 sh-spec spec/let.test.sh $BASH $MKSH $ZSH "$@"
533}
534
535for-expr() {
536 sh-spec spec/for-expr.test.sh \
537 $BASH $ZSH $OSH_LIST "$@"
538}
539
540empty-bodies() {
541 sh-spec spec/empty-bodies.test.sh "${REF_SHELLS[@]}" $ZSH $OSH_LIST "$@"
542}
543
544# TODO: This is for the ANTLR grammars, in the oil-sketch repo.
545# osh has infinite loop?
546shell-grammar() {
547 sh-spec spec/shell-grammar.test.sh $BASH $MKSH $ZSH "$@"
548}
549
550serialize() {
551 run-file serialize "$@"
552}
553
554#
555# Smoosh
556#
557
558readonly SMOOSH_REPO=~/git/languages/smoosh
559
560sh-spec-smoosh-env() {
561 local test_file=$1
562 shift
563
564 # - smoosh tests use $TEST_SHELL instead of $SH
565 # - cd $TMP to avoid littering repo
566 # - pass -o posix
567 # - timeout of 1 second
568 # - Some tests in smoosh use $HOME and $LOGNAME
569
570 sh-spec $test_file \
571 --sh-env-var-name TEST_SHELL \
572 --posix \
573 --env-pair "TEST_UTIL=$SMOOSH_REPO/tests/util" \
574 --env-pair "LOGNAME=$LOGNAME" \
575 --env-pair "HOME=$HOME" \
576 --timeout 1 \
577 --oils-bin-dir $REPO_ROOT/bin \
578 --compare-shells \
579 "$@"
580}
581
582# For speed, only run with one copy of OSH.
583readonly smoosh_osh_list=$OSH_CPYTHON
584
585smoosh() {
586 ### Run case smoosh from the console
587
588 # TODO: Use --oils-bin-dir
589 # our_shells, etc.
590
591 sh-spec-smoosh-env _tmp/smoosh.test.sh \
592 ${REF_SHELLS[@]} $smoosh_osh_list \
593 "$@"
594}
595
596smoosh-hang() {
597 ### Run case smoosh-hang from the console
598
599 # Need the smoosh timeout tool to run correctly.
600 sh-spec-smoosh-env _tmp/smoosh-hang.test.sh \
601 --timeout-bin "$SMOOSH_REPO/tests/util/timeout" \
602 --timeout 1 \
603 "$@"
604}
605
606_one-html() {
607 local spec_name=$1
608 shift
609
610 local out_dir=_tmp/spec/smoosh
611 local tmp_dir=_tmp/src-smoosh
612 mkdir -p $out_dir $out_dir
613
614 doctools/src_tree.py smoosh-file \
615 _tmp/$spec_name.test.sh \
616 $out_dir/$spec_name.test.html
617
618 local out=$out_dir/${spec_name}.html
619 set +o errexit
620 # Shell function is smoosh or smoosh-hang
621 time $spec_name --format html "$@" > $out
622 set -o errexit
623
624 echo
625 echo "Wrote $out"
626
627 # NOTE: This IGNORES the exit status.
628}
629
630# TODO:
631# - Put these tests in the CI
632# - Import smoosh spec tests into the repo, with 'test/smoosh.sh'
633
634smoosh-html() {
635 ### Run by devtools/release.sh
636 _one-html smoosh "$@"
637}
638
639smoosh-hang-html() {
640 ### Run by devtools/release.sh
641 _one-html smoosh-hang "$@"
642}
643
644html-demo() {
645 ### Test for --format html
646
647 local out=_tmp/spec/demo.html
648 builtin-special --format html "$@" > $out
649
650 echo
651 echo "Wrote $out"
652}
653
654#
655# Hay is part of the YSH suite
656#
657
658hay() {
659 run-file hay "$@"
660}
661
662hay-isolation() {
663 run-file hay-isolation "$@"
664}
665
666hay-meta() {
667 run-file hay-meta "$@"
668}
669
670#
671# YSH
672#
673
674ysh-convert() {
675 run-file ysh-convert "$@"
676}
677
678ysh-completion() {
679 run-file ysh-completion "$@"
680}
681
682ysh-stdlib() {
683 run-file ysh-stdlib "$@"
684}
685
686ysh-stdlib-2() {
687 run-file ysh-stdlib-2 "$@"
688}
689
690ysh-stdlib-args() {
691 run-file ysh-stdlib-args "$@"
692}
693
694ysh-stdlib-testing() {
695 run-file ysh-stdlib-testing "$@"
696}
697
698ysh-source() {
699 run-file ysh-source "$@"
700}
701
702ysh-usage() {
703 run-file ysh-usage "$@"
704}
705
706ysh-unicode() {
707 run-file ysh-unicode "$@"
708}
709
710ysh-bin() {
711 run-file ysh-bin "$@"
712}
713
714ysh-dict() {
715 run-file ysh-dict "$@"
716}
717
718ysh-list() {
719 run-file ysh-list "$@"
720}
721
722ysh-place() {
723 run-file ysh-place "$@"
724}
725
726ysh-prompt() {
727 run-file ysh-prompt "$@"
728}
729
730ysh-assign() {
731 run-file ysh-assign "$@"
732}
733
734ysh-augmented() {
735 run-file ysh-augmented "$@"
736}
737
738ysh-blocks() {
739 run-file ysh-blocks "$@"
740}
741
742ysh-bugs() {
743 run-file ysh-bugs "$@"
744}
745
746ysh-builtins() {
747 run-file ysh-builtins "$@"
748}
749
750ysh-builtin-module() {
751 run-file ysh-builtin-module "$@"
752}
753
754ysh-builtin-eval() {
755 run-file ysh-builtin-eval "$@"
756}
757
758# Related to errexit-oil
759ysh-builtin-error() {
760 run-file ysh-builtin-error "$@"
761}
762
763ysh-builtin-meta() {
764 run-file ysh-builtin-meta "$@"
765}
766
767ysh-builtin-process() {
768 run-file ysh-builtin-process "$@"
769}
770
771ysh-builtin-shopt() {
772 run-file ysh-builtin-shopt "$@"
773}
774
775ysh-case() {
776 run-file ysh-case "$@"
777}
778
779ysh-command-sub() {
780 run-file ysh-command-sub "$@"
781}
782
783ysh-demo() {
784 run-file ysh-demo "$@"
785}
786
787ysh-expr() {
788 run-file ysh-expr "$@"
789}
790
791ysh-int-float() {
792 run-file ysh-int-float "$@"
793}
794
795ysh-expr-bool() {
796 run-file ysh-expr-bool "$@"
797}
798
799ysh-expr-arith() {
800 run-file ysh-expr-arith "$@"
801}
802
803ysh-expr-compare() {
804 run-file ysh-expr-compare "$@"
805}
806
807ysh-expr-sub() {
808 run-file ysh-expr-sub "$@"
809}
810
811ysh-for() {
812 run-file ysh-for "$@"
813}
814
815ysh-methods() {
816 run-file ysh-methods "$@"
817}
818
819ysh-func() {
820 run-file ysh-func "$@"
821}
822
823ysh-func-builtin() {
824 run-file ysh-func-builtin "$@"
825}
826
827ysh-funcs-external() {
828 run-file ysh-funcs-external "$@"
829}
830
831ysh-interactive() {
832 run-file ysh-interactive "$@"
833}
834
835ysh-json() {
836 run-file ysh-json "$@"
837}
838
839ysh-keywords() {
840 run-file ysh-keywords "$@"
841}
842
843ysh-multiline() {
844 run-file ysh-multiline "$@"
845}
846
847ysh-options() {
848 run-file ysh-options "$@"
849}
850
851ysh-options-assign() {
852 run-file ysh-options-assign "$@"
853}
854
855ysh-proc() {
856 run-file ysh-proc "$@"
857}
858
859ysh-regex() {
860 run-file ysh-regex "$@"
861}
862
863ysh-regex-api() {
864 run-file ysh-regex-api "$@"
865}
866
867ysh-reserved() {
868 run-file ysh-reserved "$@"
869}
870
871ysh-scope() {
872 run-file ysh-scope "$@"
873}
874
875ysh-slice-range() {
876 run-file ysh-slice-range "$@"
877}
878
879ysh-string() {
880 run-file ysh-string "$@"
881}
882
883ysh-special-vars() {
884 run-file ysh-special-vars "$@"
885}
886
887ysh-tuple() {
888 run-file ysh-tuple "$@"
889}
890
891ysh-var-sub() {
892 run-file ysh-var-sub "$@"
893}
894
895ysh-with-sh() {
896 run-file ysh-with-sh "$@"
897}
898
899ysh-word-eval() {
900 run-file ysh-word-eval "$@"
901}
902
903ysh-xtrace() {
904 run-file ysh-xtrace "$@"
905}
906
907ysh-user-feedback() {
908 run-file ysh-user-feedback "$@"
909}
910
911ysh-builtin-ctx() {
912 run-file ysh-builtin-ctx "$@"
913}
914
915ysh-builtin-error() {
916 run-file ysh-builtin-error "$@"
917}
918
919ysh-builtin-help() {
920 run-file ysh-builtin-help "$@"
921}
922
923ysh-dev() {
924 run-file ysh-dev "$@"
925}
926
927
928#
929# More OSH
930#
931
932nix-idioms() {
933 run-file nix-idioms "$@"
934}
935
936ble-idioms() {
937 sh-spec spec/ble-idioms.test.sh \
938 $BASH $ZSH $MKSH $BUSYBOX_ASH $OSH_LIST "$@"
939}
940
941ble-features() {
942 sh-spec spec/ble-features.test.sh \
943 $BASH $ZSH $MKSH $BUSYBOX_ASH $DASH yash $OSH_LIST "$@"
944}
945
946toysh() {
947 sh-spec spec/toysh.test.sh --oils-failures-allowed 3 \
948 $BASH $MKSH $OSH_LIST "$@"
949}
950
951toysh-posix() {
952 sh-spec spec/toysh-posix.test.sh --oils-failures-allowed 3 \
953 ${REF_SHELLS[@]} $ZSH yash $OSH_LIST "$@"
954}
955
956run-task "$@"