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