Specify argument in which an error happened
This commit is contained in:
parent
dae5622955
commit
9ae0e6dc0e
32
ell.c
32
ell.c
|
@ -734,6 +734,14 @@ set_error (struct context *ctx, const char *format, ...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
can_modify_error (struct context *ctx) {
|
||||||
|
// In that case, `error' is NULL and there's nothing else to do anyway.
|
||||||
|
// Errors starting with an underscore are exceptions and would not work
|
||||||
|
// with stack traces generated this way.
|
||||||
|
return !ctx->memory_failure && ctx->error[0] != '_';
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
assign_arguments (struct context *ctx, struct item *names) {
|
assign_arguments (struct context *ctx, struct item *names) {
|
||||||
struct item *arg = ctx->arguments;
|
struct item *arg = ctx->arguments;
|
||||||
|
@ -757,19 +765,28 @@ static bool execute (struct context *ctx, struct item *body, struct item **);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
execute_args (struct context *ctx, struct item *args, struct item **res) {
|
execute_args (struct context *ctx, struct item *args, struct item **res) {
|
||||||
// TODO: prepend "(argument %d) ->" to any resulting error
|
size_t i = 0;
|
||||||
for (; args; args = args->next) {
|
for (; args; args = args->next) {
|
||||||
struct item *evaluated = NULL;
|
struct item *evaluated = NULL;
|
||||||
if (!execute_statement (ctx, args, &evaluated))
|
|
||||||
return false;
|
|
||||||
// Arguments should not evaporate, default to a nil value
|
// Arguments should not evaporate, default to a nil value
|
||||||
if (!evaluated && !check (ctx, (evaluated = new_list (NULL))))
|
if (!execute_statement (ctx, args, &evaluated)
|
||||||
return false;
|
|| (!evaluated && !check (ctx, (evaluated = new_list (NULL)))))
|
||||||
|
goto error;
|
||||||
item_free_list (evaluated->next);
|
item_free_list (evaluated->next);
|
||||||
evaluated->next = NULL;
|
evaluated->next = NULL;
|
||||||
res = &(*res = evaluated)->next;
|
res = &(*res = evaluated)->next;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
error:
|
||||||
|
// Once the code flows like this, at least make some use of it
|
||||||
|
if (can_modify_error (ctx)) {
|
||||||
|
char *tmp = ctx->error;
|
||||||
|
ctx->error = NULL;
|
||||||
|
set_error (ctx, "(argument %zu) -> %s", i, tmp);
|
||||||
|
free (tmp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -854,10 +871,7 @@ execute_statement
|
||||||
if (statement->head->type == ITEM_STRING)
|
if (statement->head->type == ITEM_STRING)
|
||||||
name = statement->head->value;
|
name = statement->head->value;
|
||||||
|
|
||||||
// In that case, `error' is NULL and there's nothing else to do anyway.
|
if (can_modify_error (ctx)) {
|
||||||
// Errors starting with an underscore are exceptions and would not work
|
|
||||||
// with stack traces generated this way.
|
|
||||||
if (!ctx->memory_failure && ctx->error[0] != '_') {
|
|
||||||
char *tmp = ctx->error;
|
char *tmp = ctx->error;
|
||||||
ctx->error = NULL;
|
ctx->error = NULL;
|
||||||
set_error (ctx, "%s -> %s", name, tmp);
|
set_error (ctx, "%s -> %s", name, tmp);
|
||||||
|
|
Loading…
Reference in New Issue