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

View File

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