Make and/or more useful

Now they follow Scheme, they just aren't special forms here.
This commit is contained in:
Přemysl Eric Janouch 2017-05-26 01:27:30 +02:00
parent 4358e6f324
commit 735dfd026a
Signed by: p
GPG Key ID: B715679E3A361BE6
2 changed files with 31 additions and 10 deletions

View File

@ -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. 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. Arithmetic operations on floating point numbers.

33
ell.c
View File

@ -839,7 +839,7 @@ execute_item (struct context *ctx, struct item *body, struct item **result) {
struct item *args = body->next; struct item *args = body->next;
if (body->type == ITEM_STRING) { if (body->type == ITEM_STRING) {
const char *name = body->value; 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")) if (!strcmp (name, "quote"))
return !args || check (ctx, (*result = new_clone_list (args))); return !args || check (ctx, (*result = new_clone_list (args)));
if (!strcmp (name, "arg")) if (!strcmp (name, "arg"))
@ -1168,19 +1168,32 @@ defn (fn_not) {
return check (ctx, (*result = new_boolean (!truthy (args)))); return check (ctx, (*result = new_boolean (!truthy (args))));
} }
// TODO: "and" and "or" should be short-circuiting special forms
defn (fn_and) { defn (fn_and) {
bool res = true; if (!args)
for (; args; args = args->next) return check (ctx, (*result = new_boolean (true)));
res &= truthy (args); for (; args; args = args->next) {
return check (ctx, (*result = new_boolean (res))); 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) { defn (fn_or) {
bool res = false; for (; args; args = args->next) {
for (; args; args = args->next) if (!execute_any (ctx, args, result))
res |= truthy (args); return false;
return check (ctx, (*result = new_boolean (res))); if (truthy (*result))
return true;
item_free_list (*result);
*result = NULL;
}
return check (ctx, (*result = new_boolean (false)));
} }
defn (fn_eq) { defn (fn_eq) {