From 1690fee4466aa0473e619afa1f74847ef485a5ec Mon Sep 17 00:00:00 2001 From: bakpakin Date: Fri, 8 Jun 2018 15:58:23 -0400 Subject: [PATCH] Add failure on top level error. --- src/compiler/boot.dst | 16 +++++++++----- src/core/os.c | 49 +++++++++++++++++++++-------------------- src/mainclient/init.dst | 5 ++++- test/suite0.dst | 2 +- test/suite1.dst | 2 +- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index 1a10f9aa..e6c5f014 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -1092,21 +1092,26 @@ returned from compiling and running the file." (def cache @{}) (def loading @{}) - (fn [path] + (fn [path args] (when (get loading path) (error (string "circular dependency: module " path " is loading"))) + (def { + :exit exit-on-error + } args) (def check (get cache path)) (if check check (do (def newenv (make-env)) (put cache path newenv) (put loading path true) - (def f (find-mod path)) (if f (do # Normal dst module (defn chunks [buf] (file.read f 1024 buf)) - (run-context newenv chunks identity default-error-handler) + (run-context newenv chunks identity + (if exit-on-error + (fn [a b c] (default-error-handler a b c) (os.exit 1)) + default-error-handler)) (file.close f) (put loading path nil) newenv) @@ -1118,11 +1123,12 @@ returned from compiling and running the file." ((native n))))))))) (defn import* [env path & args] - (def newenv (require path)) + (def targs (apply1 table args)) (def { :as as :prefix prefix - } (apply1 table args)) + } targs) + (def newenv (require path targs)) (var k (next newenv nil)) (def {:meta meta} newenv) (def prefix (or (and as (string as ".")) prefix (string path "."))) diff --git a/src/core/os.c b/src/core/os.c index d03001f6..c133a315 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -45,9 +45,10 @@ static int os_execute(DstArgs args) { } static int os_getenv(DstArgs args) { - if (args.n != 1 || !dst_checktype(args.v[0], DST_STRING)) - DST_THROW(args, "expected string"); - const char *cstr = (const char *) dst_unwrap_string(args.v[0]); + const uint8_t *k; + DST_FIXARITY(args, 1); + DST_ARG_STRING(k, args, 0); + const char *cstr = (const char *) k; const char *res = getenv(cstr); DST_RETURN(args, cstr ? dst_cstringv(res) @@ -55,29 +56,27 @@ static int os_getenv(DstArgs args) { } static int os_setenv(DstArgs args) { - int t2; - if (args.n < 2) DST_THROW(args, "expected 2 arguments"); - t2 = dst_type(args.v[1]); - if (!dst_checktype(args.v[0], DST_STRING) - || (t2 != DST_STRING && t2 != DST_NIL)) - DST_THROW(args, "expected string"); - const char *k = (const char *) dst_unwrap_string(args.v[0]); #ifdef DST_WINDOWS - if (t2 == DST_NIL) { - // Investigate best way to delete env vars on windows. Use winapi? - _putenv_s(k, ""); - } else { - const char *v = (const char *) dst_unwrap_string(args.v[1]); - _putenv_s(k, v); - } +#define SETENV(K,V) _putenv_s(K, V) +#define UNSETENV(K) _putenv_s(K, "") #else - if (t2 == DST_NIL) { - unsetenv(k); - } else { - const char *v = (const char *) dst_unwrap_string(args.v[1]); - setenv(k, v, 1); - } +#define SETENV(K,V) setenv(K, V, 1) +#define UNSETENV(K) unsetenv(K) #endif + const uint8_t *k; + const char *ks; + DST_MAXARITY(args, 2); + DST_MINARITY(args, 1); + DST_ARG_STRING(k, args, 0); + ks = (const char *) k; + if (args.n == 1 || dst_checktype(args.v[1], DST_NIL)) { + UNSETENV(ks); + } else { + const uint8_t *v; + DST_ARG_STRING(v, args, 1); + const char *vc = (const char *) v; + SETENV(ks, vc); + } return 0; } @@ -89,8 +88,10 @@ static int os_exit(DstArgs args) { || dst_checktype(args.v[0], DST_FALSE)) { exit(dst_unwrap_boolean(args.v[0]) ? EXIT_SUCCESS : EXIT_FAILURE); return 0; + } else if (dst_checktype(args.v[0], DST_INTEGER)) { + exit(dst_unwrap_integer(args.v[0])); } else { - exit(dst_hash(args.v[0])); + exit(EXIT_FAILURE); } return 0; } diff --git a/src/mainclient/init.dst b/src/mainclient/init.dst index ae44e41e..0c493b4a 100644 --- a/src/mainclient/init.dst +++ b/src/mainclient/init.dst @@ -6,6 +6,7 @@ (var *no-file* :private true) (var *raw-stdin* :private false) (var *handleopts* :private true) +(var *exit-on-error* :private true) # Flag handlers (def handlers :private { @@ -17,12 +18,14 @@ -s Use raw stdin instead of getline like functionality -e Execute a string of dst -r Enter the repl after running all scripts + -p Keep on executing if there is a top level error (persistent) -- Stop handling options`) (os.exit 0) 1) "v" (fn [] (print VERSION) (os.exit 0) 1) "s" (fn [] (:= *raw-stdin* true) (:= *should-repl* true) 1) "r" (fn [] (:= *should-repl* true) 1) + "p" (fn [] (:= *exit-on-error* false) 1) "-" (fn [] (:= *handleopts* false) 1) "e" (fn [i] (:= *no-file* false) @@ -43,7 +46,7 @@ (+= i (dohandler (string.slice arg 1 2) i)) (do (:= *no-file* false) - (import* _env arg) + (import* _env arg :exit *exit-on-error*) (++ i)))) (when (or *should-repl* *no-file*) diff --git a/test/suite0.dst b/test/suite0.dst index 5f7b7862..57d94998 100644 --- a/test/suite0.dst +++ b/test/suite0.dst @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -(import test.helper :prefix "") +(import test.helper :prefix "" :exit true) (start-suite 0) (assert (= 10 (+ 1 2 3 4)) "addition") diff --git a/test/suite1.dst b/test/suite1.dst index d6485099..c115301f 100644 --- a/test/suite1.dst +++ b/test/suite1.dst @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -(import test.helper :prefix "") +(import test.helper :prefix "" :exit true) (start-suite 1) (assert (= 400.0 (sqrt 160000)) "sqrt(160000)=400")