aboutsummaryrefslogtreecommitdiff
path: root/ell.c
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2017-05-21 16:20:39 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2017-05-21 16:20:39 +0200
commit1c2db8ad6b2629197543547bba4a056e3fb6bfde (patch)
tree4955d8feb589532b76a6cce192d275b126c9ae23 /ell.c
parentd1d598f96835eb2b644bcbf4b9551f9ca89057aa (diff)
downloadell-1c2db8ad6b2629197543547bba4a056e3fb6bfde.tar.gz
ell-1c2db8ad6b2629197543547bba4a056e3fb6bfde.tar.xz
ell-1c2db8ad6b2629197543547bba4a056e3fb6bfde.zip
Allow calling literal blocks
Diffstat (limited to 'ell.c')
-rw-r--r--ell.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/ell.c b/ell.c
index 7c3b78a..d73ddc1 100644
--- a/ell.c
+++ b/ell.c
@@ -819,6 +819,7 @@ execute_statement
struct item *following = body->next;
const char *name = "(anonymous)";
+ struct item *destroy = NULL;
if (body->type == ITEM_STRING) {
name = body->value;
// TODO: these could be just regular handlers, only top priority
@@ -829,16 +830,21 @@ execute_statement
if (!strcmp (name, "arg"))
return rename_arguments (ctx, following);
body = get (ctx, name);
- }
+ } else {
+ // When someone tries to call a block directly, we must evaluate it;
+ // e.g. something like `{ choose [@f1 @f2 @f3] } arg1 arg2 arg3`.
+ struct item *evaluated = NULL;
+ if (!execute_statement (ctx, body, &evaluated))
+ return false;
+ // It might a bit confusing that this doesn't evaluate arguments
+ // but neither does "quote" and there's nothing to do here
+ if (!evaluated)
+ return true;
- // XXX: not sure whether it makes more sense to evaluate a list
- // instead of leaving it as it is -> probably evaluate, since then
- // lambdas will be better: { arg _n; print @_n } 'hello\n'
- //
- // Even though it's practically useless being able to dereference
- // function names directly that way: `@list 1 2 3` vs `list 1 2 3`
- //
- // Maybe something like (choose [@f1 @f2 @f3]) arg1 arg2 arg3
+ item_free_list (evaluated->next);
+ evaluated->next = NULL;
+ destroy = body = evaluated;
+ }
if (!body) {
struct native_fn *fn = native_find (ctx, name);
@@ -848,15 +854,20 @@ execute_statement
return true;
} else if (body->type == ITEM_STRING) {
// Recursion could be pretty fatal, let's not do that
- if (check (ctx, (*result = new_clone (body))))
+ if (check (ctx, (*result = new_clone (body)))) {
+ item_free_list (destroy);
return true;
+ }
} else {
// FIXME: this creates a confusing backtrace for argument evaluation
if (execute_and_set_args (ctx, following)
- && execute (ctx, body->head, result))
+ && execute (ctx, body->head, result)) {
+ item_free_list (destroy);
return true;
+ }
}
+ item_free_list (destroy);
item_free_list (*result);
*result = NULL;