Make and/or more useful
Now they follow Scheme, they just aren't special forms here.
This commit is contained in:
parent
4358e6f324
commit
735dfd026a
|
@ -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
33
ell.c
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue