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.
`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.

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;
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) {