Reset exit status on assignment.

* gash/eval.scm (eval-word): Add 'on-command-substitution' keyword.
(eval-sh): On '<sh-set!>' reset the exit status unless a command
substitution has occurred.
* tests/assignments.org: Add tests.
This commit is contained in:
Timothy Sample 2019-10-12 09:34:32 -04:00
parent 9d98405821
commit 7fee72f5c7
2 changed files with 61 additions and 6 deletions

View File

@ -33,8 +33,10 @@
;;; ;;;
;;; Code: ;;; Code:
(define* (eval-word word #:key (output 'fields) (rhs-tildes? #f)) (define* (eval-word word #:key (output 'fields) (rhs-tildes? #f)
(on-command-substitution noop))
(parameterize ((eval-cmd-sub (lambda (exps) (parameterize ((eval-cmd-sub (lambda (exps)
(on-command-substitution)
(sh:substitute-command (sh:substitute-command
(lambda () (lambda ()
(for-each eval-sh exps)))))) (for-each eval-sh exps))))))
@ -124,11 +126,15 @@
(('<sh-pipeline> cmd*s ..1) (('<sh-pipeline> cmd*s ..1)
(apply sh:pipeline (map exp->thunk cmd*s))) (apply sh:pipeline (map exp->thunk cmd*s)))
(('<sh-set!> (names words) ..1) (('<sh-set!> (names words) ..1)
(for-each (lambda (name word) (let* ((command-substitution? #f)
(setvar! name (eval-word word (thunk (lambda () (set! command-substitution? #t))))
#:output 'string (for-each (lambda (name word)
#:rhs-tildes? #t))) (setvar! name (eval-word word
names words)) #:output 'string
#:rhs-tildes? #t
#:on-command-substitution thunk)))
names words)
(unless command-substitution? (set-status! 0))))
(('<sh-subshell> . sub-exps) (('<sh-subshell> . sub-exps)
(sh:subshell (exps->thunk sub-exps))) (sh:subshell (exps->thunk sub-exps)))
(('<sh-while> test-exp sub-exps ..1) (('<sh-while> test-exp sub-exps ..1)

View File

@ -106,3 +106,52 @@
#+begin_example #+begin_example
bin:gash bin:gash
#+end_example #+end_example
* Assignments reset exit status
:script:
#+begin_src sh
set +e
false
x=foobar
#+end_src
* Assigning exit status works
:script:
#+begin_src sh
set +e
false
x=$?
echo $x
#+end_src
:stdout:
#+begin_example
1
#+end_example
* Assignments use command substitutions for exit status
:script:
#+begin_src sh
set +e
x=$(false)
echo $?
x=$(true)
echo $?
#+end_src
:stdout:
#+begin_example
1
0
#+end_example
* Assignments update exit status on the fly
:script:
#+begin_src sh
set +e
false
x=$? y=$(true) z=$?
echo $x $z
#+end_src
:stdout:
#+begin_example
1 0
#+end_example