From 62280648011de19960f630f5bf4276507f6dcda9 Mon Sep 17 00:00:00 2001 From: Timothy Sample Date: Thu, 1 Aug 2019 09:02:05 -0400 Subject: [PATCH] Fix top-level 'break', 'continue', and 'return'. * gash/environment.scm (sh:break, sh:continue, sh:return): Wrap 'abort-to-prompt' with 'false-if-exception'. * gash/built-ins/break.scm (main): Print warning and continue if 'sh:break' returns. * gash/built-ins/continue.scm (main): Likewise, but for 'sh:continue'. * gash/built-ins/return.scm (main): Likewise, but for 'sh:return'. * tests/functions.org (Top-level return): New test. * tests/spec/oil.scm: Enable previously failing test. --- gash/built-ins/break.scm | 5 ++++- gash/built-ins/continue.scm | 5 ++++- gash/built-ins/return.scm | 6 +++++- gash/environment.scm | 15 +++++++++------ tests/functions.org | 7 +++++++ tests/spec/oil.scm | 1 - 6 files changed, 29 insertions(+), 10 deletions(-) diff --git a/gash/built-ins/break.scm b/gash/built-ins/break.scm index 30fdba8..817a312 100644 --- a/gash/built-ins/break.scm +++ b/gash/built-ins/break.scm @@ -37,7 +37,10 @@ "gash: break: argument must be a positive integer~%") EXIT_FAILURE) (n (set-status! 0) - (sh:break (1- n))))) + (sh:break (1- n)) + (format (current-error-port) + "gash: break: no loop to break from~%") + EXIT_SUCCESS))) (_ (format (current-error-port) "gash: break: too many arguments~%") EXIT_FAILURE))) diff --git a/gash/built-ins/continue.scm b/gash/built-ins/continue.scm index 53b46ba..8dd9141 100644 --- a/gash/built-ins/continue.scm +++ b/gash/built-ins/continue.scm @@ -37,7 +37,10 @@ "gash: continue: argument must be a positive integer~%") EXIT_FAILURE) (n (set-status! 0) - (sh:continue (1- n))))) + (sh:continue (1- n)) + (format (current-error-port) + "gash: continue: no loop to continue from~%") + EXIT_SUCCESS))) (_ (format (current-error-port) "gash: continue: too many arguments~%") EXIT_FAILURE))) diff --git a/gash/built-ins/return.scm b/gash/built-ins/return.scm index 87b55b6..4369820 100644 --- a/gash/built-ins/return.scm +++ b/gash/built-ins/return.scm @@ -36,7 +36,11 @@ (#f (format (current-error-port) "gash: return: argument must be a number from 0 to 255~%") EXIT_FAILURE) - (n (sh:return n)))) + (n (sh:return n) + (format (current-error-port) + (string-append "gash: return: no function " + "or sourced script to return from~%")) + EXIT_SUCCESS))) (_ (format (current-error-port) "gash: return: too many arguments~%") EXIT_FAILURE))) diff --git a/gash/environment.scm b/gash/environment.scm index a8338b8..c545511 100644 --- a/gash/environment.scm +++ b/gash/environment.scm @@ -334,8 +334,9 @@ exit the dynamic extent of @var{thunk}." (define* (sh:continue #:optional (n 0)) "Exit to the closest invocation of @code{call-with-continue}. If -@var{n} is set, exit to the @math{n + 1}th closest invocation." - (abort-to-prompt *continue-tag* n)) +@var{n} is set, exit to the @math{n + 1}th closest invocation. If not +called from within @code{call-with-continue}, return @code{#f}." + (false-if-exception (abort-to-prompt *continue-tag* n))) (define *break-tag* (make-prompt-tag)) @@ -351,8 +352,9 @@ exit the dynamic extent of @var{thunk}." (define* (sh:break #:optional (n 0)) "Exit to the closest invocation of @code{call-with-break}. If -@var{n} is set, exit to the @math{n + 1}th closest invocation." - (abort-to-prompt *break-tag* n)) +@var{n} is set, exit to the @math{n + 1}th closest invocation. If not +called from within @code{call-with-break}, return @code{#f}." + (false-if-exception (abort-to-prompt *break-tag* n))) (define *return-tag* (make-prompt-tag)) @@ -367,8 +369,9 @@ exit the dynamic extent of @var{thunk}." (define* (sh:return #:optional (status (get-status))) "Exit to the closest invocation of @code{call-with-return} setting status to @var{status}. If @var{status} is not set, keep the current -status." - (abort-to-prompt *return-tag* status)) +status. If not called from within @code{call-with-return}, return +@code{#f}." + (false-if-exception (abort-to-prompt *return-tag* status))) (define *atexit* #f) (define *exiting?* #f) diff --git a/tests/functions.org b/tests/functions.org index af9ef71..7248179 100644 --- a/tests/functions.org +++ b/tests/functions.org @@ -83,3 +83,10 @@ foo #+end_src :status: 1 + +* Top-level return +:script: +#+begin_src sh + return +#+end_src +:status: 0 diff --git a/tests/spec/oil.scm b/tests/spec/oil.scm index 8b33057..dc91d65 100644 --- a/tests/spec/oil.scm +++ b/tests/spec/oil.scm @@ -159,7 +159,6 @@ ("while in pipe with subshell" ("\\$\\(\\(i\\+1\\)\\)" "$(expr $i + 1)")) ;; Gash needs to be fixed to pass these tests. - ("continue at top level") ("continue in subshell") ("continue in subshell aborts with errexit") ;; The Oil shell handles this statically. We