Fix for, map, filter

This commit is contained in:
Přemysl Eric Janouch 2017-05-21 00:23:51 +02:00
parent 7e8bfbf9b9
commit cbce0d6498
Signed by: p
GPG Key ID: B715679E3A361BE6
2 changed files with 36 additions and 24 deletions

51
ell.c
View File

@ -765,6 +765,13 @@ execute_args (struct context *ctx, struct item *args, struct item **res) {
return true;
}
static bool
set_arg (struct context *ctx, size_t arg, struct item *value) {
char buf[64];
(void) snprintf (buf, sizeof buf, "%zu", arg);
return set (ctx, buf, value);
}
// TODO: we should probably maintain arguments in a separate list,
// either that or at least remember the count so that we can reset them
static bool
@ -776,12 +783,9 @@ execute_and_set_args (struct context *ctx, struct item *following) {
}
size_t i = 0;
for (struct item *arg = args; arg; arg = arg->next) {
char buf[64];
(void) snprintf (buf, sizeof buf, "%zu", i++);
if (!set (ctx, buf, arg))
for (struct item *arg = args; arg; arg = arg->next)
if (!set_arg (ctx, i++, arg))
return false;
}
item_free_list (args);
return true;
}
@ -822,6 +826,15 @@ execute_statement
body = get (ctx, name);
}
// 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
if (!body) {
struct native_fn *fn = native_find (name);
if (!fn)
@ -935,14 +948,10 @@ defn (fn_for) {
return set_error (ctx, "second argument must be a function");
(void) result;
for (struct item *iter = list->head; iter; iter = iter->next) {
struct item *copy;
if (!check (ctx, (copy = new_clone (iter))))
return false;
for (struct item *v = list->head; v; v = v->next) {
struct item *res = NULL;
// FIXME: wrong thing is executed, see fn_map
bool ok = execute_statement (ctx, body, &res);
bool ok = set_arg (ctx, 0, v)
&& execute (ctx, body->head, &res);
item_free_list (res);
if (!ok)
return false;
@ -959,14 +968,12 @@ defn (fn_map) {
struct item *res = NULL, **out = &res;
for (struct item *v = values->head; v; v = v->next) {
// FIXME: wrong thing is executed
// -> either temporarily append the value to the body
// -> or modify execute_statement()
if (!execute_statement (ctx, v, out)) {
if (!set_arg (ctx, 0, v)
|| !execute (ctx, body->head, out)) {
item_free_list (res);
return false;
}
while (*out && (*out)->next)
while (*out)
out = &(*out)->next;
}
return check (ctx, (*result = new_list (res)));
@ -981,14 +988,14 @@ defn (fn_filter) {
struct item *res = NULL, **out = &res;
for (struct item *v = values->head; v; v = v->next) {
struct item *res = NULL;
// FIXME: wrong thing is executed, see fn_map
if (!execute_statement (ctx, body, &res)) {
struct item *keep = NULL;
if (!set_arg (ctx, 0, v)
|| !execute (ctx, body->head, &keep)) {
item_free_list (res);
return false;
}
bool match = truthy (res);
item_free_list (res);
bool match = truthy (keep);
item_free_list (keep);
if (!match)
continue;

View File

@ -2,5 +2,10 @@ set greet {
arg _name
print 'hello ' @_name '\n'
}
greet world
greet creator
for (map { arg _x; .. @_x ! } [
world
creator
]) {
arg _whom
greet @_whom
}