diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-21 00:23:51 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-21 13:19:47 +0200 |
commit | cbce0d649816cb782f2d2932e8aa74edfda64da1 (patch) | |
tree | 1a1a0cba753ea0db42e7cae1acf54cd2c8ba5245 | |
parent | 7e8bfbf9b952915f9c1c4bb58081b45620714e3f (diff) | |
download | ell-cbce0d649816cb782f2d2932e8aa74edfda64da1.tar.gz ell-cbce0d649816cb782f2d2932e8aa74edfda64da1.tar.xz ell-cbce0d649816cb782f2d2932e8aa74edfda64da1.zip |
Fix for, map, filter
-rwxr-xr-x | ell.c | 51 | ||||
-rw-r--r-- | greet.ell | 9 |
2 files changed, 36 insertions, 24 deletions
@@ -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; @@ -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 +} |