diff options
Diffstat (limited to 'ell.c')
-rwxr-xr-x | ell.c | 125 |
1 files changed, 73 insertions, 52 deletions
@@ -774,8 +774,53 @@ rename_arguments (struct context *ctx, struct item *names) { return true; } +static bool execute_statement (struct context *, struct item *, struct item **); static bool execute (struct context *ctx, struct item *body, struct item **); +static bool +execute_args_list (struct context *ctx, struct item *args, struct item **res) { + for (struct item *arg = args; arg; arg = arg->next) { + struct item *evaluated = NULL; + if (!execute_statement (ctx, arg, &evaluated)) + return false; + if (evaluated) { + item_free_list (evaluated->next); + evaluated->next = NULL; + *res = evaluated; + res = &evaluated->next; + } + } + return true; +} + +static bool +execute_native (struct context *ctx, + struct native_fn *fn, struct item *next, struct item **res) { + struct item *args = NULL; + bool ok = execute_args_list (ctx, next, &args) + && fn->handler (ctx, args, res); + item_free_list (args); + return ok; +} + +static bool +execute_args (struct context *ctx, struct item *next) { + struct item *args = NULL; + if (!execute_args_list (ctx, next, &args)) { + item_free_list (args); + return false; + } + + char buf[64]; + size_t i = 0; + for (struct item *arg = args; arg; arg = arg->next) { + (void) snprintf (buf, sizeof buf, "%zu", i++); + set (ctx, buf, arg); + } + item_free_list (args); + return true; +} + // 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 @@ -794,68 +839,43 @@ execute_statement if (!(body = statement->head)) return true; + struct item *following = body->next; const char *name = "(anonymous)"; if (body->type == ITEM_STRING) { name = body->value; + // TODO: these could be just regular handlers, only top priority if (!strcmp (name, "quote")) { - if ((*result = new_clone_list (body->next))) + if ((*result = new_clone_list (following))) return true; ctx->memory_failure = true; return false; } if (!strcmp (name, "arg")) - return rename_arguments (ctx, body->next); - - if (!(body = get (ctx, body->value))) { - struct native_fn *fn; - for (fn = g_native; fn; fn = fn->next) - if (!strcmp (name, fn->name)) - break; - if (!fn) - return set_error (ctx, "unknown function: %s", name); - - struct item *args = NULL, **tail = &args; - for (struct item *arg = statement->head->next; - arg; arg = arg->next) { - struct item *evaluated = NULL; - if (!execute_statement (ctx, arg, &evaluated)) - return false; - - if (evaluated) { - item_free_list (evaluated->next); - evaluated->next = NULL; - *tail = evaluated; - tail = &evaluated->next; - } - } - bool ok = fn->handler (ctx, args, result); - item_free_list (args); - if (ok) - return true; - goto error; - } + return rename_arguments (ctx, following); + body = get (ctx, name); } - // Recursion could be pretty fatal, let's not do that - if (body->type == ITEM_STRING) - return new_clone (body); - size_t i = 0; - for (struct item *arg = statement->head->next; arg; arg = arg->next) { - struct item *evaluated = NULL; - if (!execute_statement (ctx, arg, &evaluated)) - return false; - - item_free_list (evaluated->next); - evaluated->next = NULL; - - char buf[64]; - (void) snprintf (buf, sizeof buf, "%zu", i++); - set (ctx, buf, evaluated); + if (!body) { + // TODO: this could be a function + struct native_fn *fn; + for (fn = g_native; fn; fn = fn->next) + if (!strcmp (name, fn->name)) + break; + if (!fn) + return set_error (ctx, "unknown function: %s", name); + if (execute_native (ctx, fn, following, result)) + return true; + } else if (body->type == ITEM_STRING) { + // Recursion could be pretty fatal, let's not do that + if ((*result = new_clone (body))) + return true; + ctx->memory_failure = true; + } else { + if (execute_args (ctx, following) + && execute (ctx, body->head, result)) + return true; } - if (execute (ctx, body->head, result)) - return true; -error: // In this case, `error' is NULL if (ctx->memory_failure) return false; @@ -906,7 +926,7 @@ init_runtime_library_scripts (struct context *ctx) { free (e); ok = false; } else - set (ctx, functions[i].name, body); + ok &= set (ctx, functions[i].name, body); } return ok; } @@ -928,9 +948,10 @@ defn (fn_set) { defn (fn_print) { (void) result; + // TODO: error on list struct buffer buf = BUFFER_INITIALIZER; - struct item *item = args; - buffer_append (&buf, item->value, item->len); + for (; args; args = args->next) + buffer_append (&buf, args->value, args->len); buffer_append_c (&buf, '\0'); if (buf.memory_failure) { ctx->memory_failure = true; |