Various cleanup

This commit is contained in:
Přemysl Eric Janouch 2017-05-18 23:08:55 +02:00
parent 365d6e69e1
commit 7f9e8b2cbc
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 73 additions and 52 deletions

111
ell.c
View File

@ -774,8 +774,53 @@ rename_arguments (struct context *ctx, struct item *names) {
return true; 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 (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, // TODO: we should probably maintain arguments in a separate list,
// either that or at least remember the count so that we can reset them // either that or at least remember the count so that we can reset them
static bool static bool
@ -794,68 +839,43 @@ execute_statement
if (!(body = statement->head)) if (!(body = statement->head))
return true; return true;
struct item *following = body->next;
const char *name = "(anonymous)"; const char *name = "(anonymous)";
if (body->type == ITEM_STRING) { if (body->type == ITEM_STRING) {
name = body->value; name = body->value;
// TODO: these could be just regular handlers, only top priority
if (!strcmp (name, "quote")) { if (!strcmp (name, "quote")) {
if ((*result = new_clone_list (body->next))) if ((*result = new_clone_list (following)))
return true; return true;
ctx->memory_failure = true; ctx->memory_failure = true;
return false; return false;
} }
if (!strcmp (name, "arg")) 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; struct native_fn *fn;
for (fn = g_native; fn; fn = fn->next) for (fn = g_native; fn; fn = fn->next)
if (!strcmp (name, fn->name)) if (!strcmp (name, fn->name))
break; break;
if (!fn) if (!fn)
return set_error (ctx, "unknown function: %s", name); return set_error (ctx, "unknown function: %s", name);
if (execute_native (ctx, fn, following, result))
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; return true;
goto error; } else if (body->type == ITEM_STRING) {
}
}
// Recursion could be pretty fatal, let's not do that // Recursion could be pretty fatal, let's not do that
if (body->type == ITEM_STRING) if ((*result = new_clone (body)))
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))
return true; 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 // In this case, `error' is NULL
if (ctx->memory_failure) if (ctx->memory_failure)
return false; return false;
@ -906,7 +926,7 @@ init_runtime_library_scripts (struct context *ctx) {
free (e); free (e);
ok = false; ok = false;
} else } else
set (ctx, functions[i].name, body); ok &= set (ctx, functions[i].name, body);
} }
return ok; return ok;
} }
@ -928,9 +948,10 @@ defn (fn_set) {
defn (fn_print) { defn (fn_print) {
(void) result; (void) result;
// TODO: error on list
struct buffer buf = BUFFER_INITIALIZER; struct buffer buf = BUFFER_INITIALIZER;
struct item *item = args; for (; args; args = args->next)
buffer_append (&buf, item->value, item->len); buffer_append (&buf, args->value, args->len);
buffer_append_c (&buf, '\0'); buffer_append_c (&buf, '\0');
if (buf.memory_failure) { if (buf.memory_failure) {
ctx->memory_failure = true; ctx->memory_failure = true;