Remove some ancient stupidity

This commit is contained in:
Přemysl Eric Janouch 2017-05-21 17:47:19 +02:00
parent ba2e31d81f
commit dae5622955
Signed by: p
GPG Key ID: B715679E3A361BE6
2 changed files with 39 additions and 44 deletions

View File

@ -48,10 +48,9 @@ Observe that the whole program is enclosed in an implicit pair of `{}` and that
Runtime
-------
All variables are put in a single global namespace with no further scoping.
When calling a command (which is a list of lists), all arguments are
automatically stored in variables named 0, 1, 2, 3, ... n. They are however
effectively inaccessible and you must rename them first using the `arg` special
form.
Arguments to a block (which is a list of lists) must be assigned to variables
first using the `arg` special form, and that must happen before they get
overriden by execution of a different block.
When evaluating a command, the first argument is typically a string with its
name and it is resolved as if `set` was called on it.

76
ell.c
View File

@ -625,6 +625,7 @@ parser_run (struct parser *self, const char **e) {
struct context {
struct item *variables; ///< List of variables
struct native_fn *native; ///< Maps strings to C functions
struct item *arguments; ///< Arguments to last executed block
char *error; ///< Error information
bool error_is_fatal; ///< Whether the error can be catched
@ -654,6 +655,7 @@ context_free (struct context *ctx) {
free (iter);
}
item_free_list (ctx->variables);
item_free_list (ctx->arguments);
free (ctx->error);
}
@ -733,19 +735,19 @@ set_error (struct context *ctx, const char *format, ...) {
}
static bool
rename_arguments (struct context *ctx, struct item *names) {
size_t i = 0;
assign_arguments (struct context *ctx, struct item *names) {
struct item *arg = ctx->arguments;
for (; names; names = names->next) {
if (names->type != ITEM_STRING)
return set_error (ctx, "argument names must be strings");
char buf[64];
(void) snprintf (buf, sizeof buf, "%zu", i++);
struct item *value = get (ctx, buf);
if (value && !check (ctx, (value = new_clone (value))))
struct item *value = NULL;
if (arg && !check (ctx, (value = new_clone (arg))))
return false;
if (!set (ctx, names->value, value))
return false;
if (arg)
arg = arg->next;
}
return true;
}
@ -770,14 +772,6 @@ 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 check (ctx, (value = new_clone (value)))
&& set (ctx, buf, value);
}
static bool
execute_native (struct context *ctx, const char *name, struct item *args,
struct item **result) {
@ -805,16 +799,8 @@ execute_resolved (struct context *ctx, struct item *body, struct item *args,
return false;
}
// TODO: we should probably maintain arguments in a separate list,
// either that or at least remember the count so that we can reset them
// NOTE: it even seems that storing them as numbers is completely useless
size_t i = 0;
for (struct item *arg = evaluated; arg; arg = arg->next)
if (!set_arg (ctx, i++, arg)) {
item_free_list (evaluated);
return false;
}
item_free_list (evaluated);
item_free_list (ctx->arguments);
ctx->arguments = evaluated;
return execute (ctx, body->head, result);
}
@ -827,7 +813,7 @@ execute_item (struct context *ctx, struct item *body, struct item **result) {
if (!strcmp (name, "quote"))
return !args || check (ctx, (*result = new_clone_list (args)));
if (!strcmp (name, "arg"))
return rename_arguments (ctx, args);
return assign_arguments (ctx, args);
if ((body = get (ctx, name)))
return execute_resolved (ctx, body, args, result);
return execute_native (ctx, name, args, result);
@ -897,6 +883,28 @@ execute (struct context *ctx, struct item *body, struct item **result) {
#define defn(name) static bool name \
(struct context *ctx, struct item *args, struct item **result)
static bool
set_single_argument (struct context *ctx, struct item *item) {
struct item *single;
if (!check (ctx, (single = new_clone (item))))
return false;
item_free_list (ctx->arguments);
ctx->arguments = single;
return true;
}
#define E_BREAK "_break"
static bool
eat_error (struct context *ctx, const char *name) {
if (!ctx->error || strcmp (ctx->error, name))
return false;
free (ctx->error);
ctx->error = NULL;
return true;
}
static struct item *
new_number (double n) {
char *s;
@ -914,18 +922,6 @@ new_number (double n) {
return item;
}
#define E_BREAK "_break"
static bool
eat_error (struct context *ctx, const char *name) {
if (!ctx->error || strcmp (ctx->error, name))
return false;
free (ctx->error);
ctx->error = NULL;
return true;
}
static bool
truthy (struct item *item) {
return item
@ -1001,7 +997,7 @@ defn (fn_for) {
(void) result;
for (struct item *v = list->head; v; v = v->next) {
struct item *res = NULL;
bool ok = set_arg (ctx, 0, v)
bool ok = set_single_argument (ctx, v)
&& execute (ctx, body->head, &res);
item_free_list (res);
if (eat_error (ctx, E_BREAK))
@ -1025,7 +1021,7 @@ defn (fn_map) {
struct item *res = NULL, **out = &res;
for (struct item *v = values->head; v; v = v->next) {
if (!set_arg (ctx, 0, v)
if (!set_single_argument (ctx, v)
|| !execute (ctx, body->head, out)) {
item_free_list (res);
return false;
@ -1046,7 +1042,7 @@ defn (fn_filter) {
struct item *res = NULL, **out = &res;
for (struct item *v = values->head; v; v = v->next) {
struct item *keep = NULL;
if (!set_arg (ctx, 0, v)
if (!set_single_argument (ctx, v)
|| !execute (ctx, body->head, &keep)) {
item_free_list (res);
return false;