diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-26 01:27:30 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-26 01:27:30 +0200 |
commit | 735dfd026abaeee93c4e9b90db73661076ccafa3 (patch) | |
tree | 49e809674195b2699f71d4d0f08712a73b787913 | |
parent | 4358e6f324a6765b7da69ba28b891584531e710e (diff) | |
download | ell-735dfd026abaeee93c4e9b90db73661076ccafa3.tar.gz ell-735dfd026abaeee93c4e9b90db73661076ccafa3.tar.xz ell-735dfd026abaeee93c4e9b90db73661076ccafa3.zip |
Make and/or more useful
Now they follow Scheme, they just aren't special forms here.
-rw-r--r-- | README.adoc | 8 | ||||
-rw-r--r-- | ell.c | 33 |
2 files changed, 31 insertions, 10 deletions
diff --git a/README.adoc b/README.adoc index b68b948..792429d 100644 --- a/README.adoc +++ b/README.adoc @@ -129,6 +129,14 @@ Execute the body and pass any error to the handler instead of propagating it. Throw an error. Messages starting on an underscore don't generate backtraces. +`not <value>` + +Return a boolean with the opposite truthiness. + +`and [<body>]...`, `or [<body>]...` + +Short-circuit evaluation, trying to return whatever the bodies result in. + `+`, `-`, `*`, `/` Arithmetic operations on floating point numbers. @@ -839,7 +839,7 @@ execute_item (struct context *ctx, struct item *body, struct item **result) { struct item *args = body->next; if (body->type == ITEM_STRING) { const char *name = body->value; - // TODO: these could be just regular handlers, only top priority + // These could be just regular handlers, only top priority if (!strcmp (name, "quote")) return !args || check (ctx, (*result = new_clone_list (args))); if (!strcmp (name, "arg")) @@ -1168,19 +1168,32 @@ defn (fn_not) { return check (ctx, (*result = new_boolean (!truthy (args)))); } -// TODO: "and" and "or" should be short-circuiting special forms defn (fn_and) { - bool res = true; - for (; args; args = args->next) - res &= truthy (args); - return check (ctx, (*result = new_boolean (res))); + if (!args) + return check (ctx, (*result = new_boolean (true))); + for (; args; args = args->next) { + item_free_list (*result); + *result = NULL; + + if (!execute_any (ctx, args, result)) + return false; + if (!truthy (*result)) + return check (ctx, (*result = new_boolean (false))); + } + return true; } defn (fn_or) { - bool res = false; - for (; args; args = args->next) - res |= truthy (args); - return check (ctx, (*result = new_boolean (res))); + for (; args; args = args->next) { + if (!execute_any (ctx, args, result)) + return false; + if (truthy (*result)) + return true; + + item_free_list (*result); + *result = NULL; + } + return check (ctx, (*result = new_boolean (false))); } defn (fn_eq) { |