Various cleanup
This commit is contained in:
parent
365d6e69e1
commit
7f9e8b2cbc
111
ell.c
111
ell.c
|
@ -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);
|
||||
return rename_arguments (ctx, following);
|
||||
body = get (ctx, name);
|
||||
}
|
||||
|
||||
if (!(body = get (ctx, body->value))) {
|
||||
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);
|
||||
|
||||
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)
|
||||
if (execute_native (ctx, fn, following, result))
|
||||
return true;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
} else if (body->type == ITEM_STRING) {
|
||||
// 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 (execute (ctx, body->head, result))
|
||||
if ((*result = new_clone (body)))
|
||||
return true;
|
||||
ctx->memory_failure = true;
|
||||
} else {
|
||||
if (execute_args (ctx, following)
|
||||
&& 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;
|
||||
|
|
Loading…
Reference in New Issue