From cbce0d649816cb782f2d2932e8aa74edfda64da1 Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Sun, 21 May 2017 00:23:51 +0200 Subject: Fix for, map, filter --- ell.c | 51 +++++++++++++++++++++++++++++---------------------- greet.ell | 9 +++++++-- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/ell.c b/ell.c index 0e6b550..cc38579 100755 --- a/ell.c +++ b/ell.c @@ -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; diff --git a/greet.ell b/greet.ell index bd29d93..b53f21d 100644 --- a/greet.ell +++ b/greet.ell @@ -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 +} -- cgit v1.2.3-70-g09d2