/*
* syntax.c:
*
- * Copyright (C) 2007-2011 David Lutterkort
+ * Copyright (C) 2007-2015 David Lutterkort
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
struct binding *local;
};
+static int init_fatal_exn(struct error *error) {
+ if (error->exn != NULL)
+ return 0;
+ error->exn = make_exn_value(ref(error->info), "Error during evaluation");
+ if (error->exn == NULL)
+ return -1;
+ error->exn->exn->seen = 1;
+ error->exn->exn->error = 1;
+ error->exn->exn->lines = NULL;
+ error->exn->exn->nlines = 0;
+ error->exn->ref = REF_MAX;
+ return 0;
+}
+
static void format_error(struct info *info, aug_errcode_t code,
const char *format, va_list ap) {
struct error *error = info->error;
exn_add_lines(exn, 1, line);
}
-struct value *exn_error(void) {
- static const struct exn exn = {
- .info = NULL, .seen = 1, .error = 1,
- .message = (char *) "Error during evaluation",
- .nlines = 0, .lines = NULL };
- static const struct value value = {
- .ref = REF_MAX, /* Protect against being freed */
- .info = NULL, .tag = V_EXN,
- { .exn = (struct exn *) &exn } };
- return (struct value *) &value;
-}
-
/*
* Modules
*/
/*
* Values
*/
-static void print_tree(FILE *out, int indent, struct tree *tree) {
+void print_tree_braces(FILE *out, int indent, struct tree *tree) {
if (tree == NULL) {
fprintf(out, "(null tree)\n");
return;
fprintf(out, " = \"%s\"", t->value);
if (t->children != NULL) {
fputc('\n', out);
- print_tree(out, indent + 2, t->children);
+ print_tree_braces(out, indent + 2, t->children);
for (int i=0; i < indent; i++) fputc(' ', out);
} else {
fputc(' ', out);
fprintf(out, ">");
break;
case V_TREE:
- print_tree(out, 0, v->origin);
+ print_tree_braces(out, 0, v->origin);
break;
case V_FILTER:
fprintf(out, "<filter:");
v->regexp = re;
}
} else {
+ v = NULL;
fatal_error(info, "Tried to subtract a %s and a %s to yield a %s",
type_name(exp->left->type), type_name(exp->right->type),
type_name(t));
/* Build lambda x: exp->right (exp->left x) as a closure */
char *var = strdup("@0");
- struct term *param = make_param(var, ref(exp->left->type->dom),
- ref(info));
- param->type = ref(exp->left->type);
+ struct term *func = make_param(var, ref(exp->left->type->dom),
+ ref(info));
+ func->type = make_arrow_type(exp->left->type->dom,
+ exp->right->type->img);
struct term *ident = make_term(A_IDENT, ref(info));
- ident->ident = ref(param->param->name);
- ident->type = ref(param->type);
+ ident->ident = ref(func->param->name);
+ ident->type = ref(func->param->type);
struct term *app = make_app_term(ref(exp->left), ident, ref(info));
app->type = ref(app->left->type->img);
app = make_app_term(ref(exp->right), app, ref(info));
- app->type = ref(app->left->type->img);
+ app->type = ref(app->right->type->img);
- struct term *func = build_func(param, app);
+ build_func(func, app);
if (!type_equal(func->type, exp->type)) {
char *f = type_string(func->type);
free(f);
free(e);
unref(func, term);
- return exn_error();
+ return info->error->exn;
}
v = make_closure(func, ctx->local);
unref(func, term);
struct lens *l2 = v2->lens;
v = lns_make_concat(ref(info), ref(l1), ref(l2), LNS_TYPE_CHECK(ctx));
} else {
+ v = NULL;
fatal_error(info, "Tried to concat a %s and a %s to yield a %s",
type_name(exp->left->type), type_name(exp->right->type),
type_name(t));
if (term->tr_tag == TR_EXN) {
if (!EXN(actual)) {
+ print_info(stdout, term->info);
printf("Test run should have produced exception, but produced\n");
print_value(stdout, actual);
printf("\n");
print_info(stdout, term->info);
printf("\n");
if (actual->tag == V_TREE) {
- print_tree(stdout, 2, actual->origin->children);
+ print_tree_braces(stdout, 2, actual->origin->children);
} else {
print_value(stdout, actual);
}
free(error->details);
error->details = ms.buf;
}
- result = ! EXN(v);
+ result = !(EXN(v) || HAS_ERR(ctx->aug));
unref(v, value);
return result;
} else if (term->tag == A_TEST) {
return filename;
}
-int load_module_file(struct augeas *aug, const char *filename) {
+int load_module_file(struct augeas *aug, const char *filename,
+ const char *name) {
struct term *term = NULL;
int result = -1;
+ if (aug->flags & AUG_TRACE_MODULE_LOADING)
+ printf("Module %s", filename);
augl_parse_file(aug, filename, &term);
+ if (aug->flags & AUG_TRACE_MODULE_LOADING)
+ printf(HAS_ERR(aug) ? " failed\n" : " loaded\n");
ERR_BAIL(aug);
if (! typecheck(term, aug))
goto error;
struct module *module = compile(term, aug);
- ERR_THROW(module == NULL, aug, AUG_ESYNTAX,
- "Failed to load %s", filename);
+ bool bad_module = (module == NULL);
+ if (bad_module && name != NULL) {
+ /* Put an empty placeholder on the module list so that
+ * we don't retry loading this module everytime its mentioned
+ */
+ module = module_create(name);
+ }
+ if (module != NULL)
+ list_append(aug->modules, module);
+
+ ERR_THROW(bad_module, aug, AUG_ESYNTAX, "Failed to load %s", filename);
- list_append(aug->modules, module);
result = 0;
error:
// FIXME: This leads to a bad free of a string used in a del lens
if ((filename = module_filename(aug, name)) == NULL)
return -1;
- if (load_module_file(aug, filename) == -1)
+ if (load_module_file(aug, filename, name) == -1)
goto error;
free(filename);
int interpreter_init(struct augeas *aug) {
int r;
- aug->modules = builtin_init(aug->error);
+ r = init_fatal_exn(aug->error);
+ if (r < 0)
+ return -1;
+ aug->modules = builtin_init(aug->error);
if (aug->flags & AUG_NO_MODL_AUTOLOAD)
return 0;