From 0f6f13687336dc427d5c2cfbfc1970c032812818 Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Thu, 21 Apr 2022 22:40:27 +0200 Subject: [PATCH] Push formatted parser error on stack during evaluation This way we can see the parse errors again in evaluation mode Not fully fleshed out yet: We simply use apfl_debug_print_val to dump the top of the stack (the formatted error) to stderr but don't nicely handle if there is nothing on the stack (apfl_debug_print_val will print a rather cryptic "stack index invalid" error). Also the whole dance we need to do to put the formatted error onto the stack feels rather awkward (there should probably a function for this) and we also should probably try to push an error description on the stack in case this moving-string-to-stack business fails. Now "only" all other errors need to be put on the stack as a string :) --- src/apfl.h | 1 + src/context.c | 34 +++++++++++++++++----------------- src/context.h | 1 + src/error.c | 10 ++++++++++ src/eval.c | 32 +++++++++++++++++++++++++++++++- src/format.c | 16 ++++++++++++++++ src/format.h | 2 ++ src/internal.h | 4 ++++ src/main.c | 3 ++- src/strings.c | 13 +++++++++++++ 10 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/apfl.h b/src/apfl.h index d5b0691..e0df0a3 100644 --- a/src/apfl.h +++ b/src/apfl.h @@ -192,6 +192,7 @@ struct apfl_error { }; bool apfl_error_print(struct apfl_error, FILE *); +bool apfl_error_as_string(struct apfl_error, struct apfl_allocator, struct apfl_string *out); struct apfl_error apfl_error_simple(enum apfl_error_type); bool apfl_error_is_fatal_type(enum apfl_error_type); diff --git a/src/context.c b/src/context.c index 1c24111..eb7040b 100644 --- a/src/context.c +++ b/src/context.c @@ -150,8 +150,8 @@ apfl_stack_get(apfl_ctx ctx, struct apfl_value *value, apfl_stackidx index) return stack_get_and_adjust_index(ctx, value, &index); } -static struct apfl_value * -stack_push_placeholder(apfl_ctx ctx) +struct apfl_value * +apfl_stack_push_placeholder(apfl_ctx ctx) { if (!apfl_stack_push(ctx, (struct apfl_value) {.type = VALUE_NIL})) { return NULL; @@ -224,20 +224,20 @@ apfl_ctx_destroy(apfl_ctx ctx) FREE_OBJ(base_allocator, ctx); } -#define CREATE_GC_OBJECT_VALUE_ON_STACK(ctx, TYPE, MEMB, NEW) \ - struct apfl_value *value = stack_push_placeholder(ctx); \ - if (value == NULL) { \ - return APFL_RESULT_ERR_FATAL; \ - } \ - \ - struct apfl_value new_value = {.type = TYPE}; \ - if ((new_value.MEMB = NEW) == NULL) { \ - assert(apfl_stack_drop(ctx, -1)); \ - return APFL_RESULT_ERR_FATAL; \ - } \ - \ - *value = new_value; \ - \ +#define CREATE_GC_OBJECT_VALUE_ON_STACK(ctx, TYPE, MEMB, NEW) \ + struct apfl_value *value = apfl_stack_push_placeholder(ctx); \ + if (value == NULL) { \ + return APFL_RESULT_ERR_FATAL; \ + } \ + \ + struct apfl_value new_value = {.type = TYPE}; \ + if ((new_value.MEMB = NEW) == NULL) { \ + assert(apfl_stack_drop(ctx, -1)); \ + return APFL_RESULT_ERR_FATAL; \ + } \ + \ + *value = new_value; \ + \ return APFL_RESULT_OK; enum apfl_result @@ -371,7 +371,7 @@ apfl_get_member_inner( struct apfl_value container, struct apfl_value k ) { - struct apfl_value *value = stack_push_placeholder(ctx); + struct apfl_value *value = apfl_stack_push_placeholder(ctx); if (value == NULL) { return APFL_RESULT_ERR; } diff --git a/src/context.h b/src/context.h index fe2668c..d783751 100644 --- a/src/context.h +++ b/src/context.h @@ -37,6 +37,7 @@ bool apfl_stack_pop(apfl_ctx, struct apfl_value *value, apfl_stackidx); bool apfl_stack_get(apfl_ctx, struct apfl_value *value, apfl_stackidx); bool apfl_stack_drop(apfl_ctx, apfl_stackidx); void apfl_stack_clear(apfl_ctx); +struct apfl_value *apfl_stack_push_placeholder(apfl_ctx); #ifdef __cplusplus } diff --git a/src/error.c b/src/error.c index 52b1165..f8040cd 100644 --- a/src/error.c +++ b/src/error.c @@ -197,6 +197,16 @@ apfl_error_print(struct apfl_error error, FILE *file) return true; } +bool +apfl_error_as_string(struct apfl_error error, struct apfl_allocator allocator, struct apfl_string *out) +{ + struct apfl_string_builder builder; + apfl_string_builder_init(allocator, &builder); + TRY(format_error(apfl_format_string_writer(&builder), error)); + *out = apfl_string_builder_move_string(&builder); + return true; +} + struct apfl_error apfl_error_simple(enum apfl_error_type type) { diff --git a/src/eval.c b/src/eval.c index 402abaf..8cab423 100644 --- a/src/eval.c +++ b/src/eval.c @@ -241,6 +241,36 @@ apfl_iterative_runner_new(apfl_ctx ctx, struct apfl_source_reader reader) return runner; } +static enum apfl_result +handle_parse_error(apfl_ctx ctx, struct apfl_error error) +{ + enum apfl_result result = APFL_RESULT_ERR; + if (apfl_error_is_fatal_type(error.type)) { + result = APFL_RESULT_ERR_FATAL; + } + + // TODO: Putting the string on the stack should be easier. It's rather awkward now... + + struct apfl_string string; + if (!apfl_error_as_string(error, ctx->gc.allocator, &string)) { + // TODO: Maybe try to push something on the stack in case of error (also for other error cases below)? + return APFL_RESULT_ERR_FATAL; + } + + struct apfl_value *value = apfl_stack_push_placeholder(ctx); + if (value == NULL) { + return APFL_RESULT_ERR_FATAL; + } + + if ((value->string = apfl_string_move_into_new_gc_string(&ctx->gc, &string)) == NULL) { + return APFL_RESULT_ERR_FATAL; + } + + value->type = VALUE_STRING; + + return result; +} + bool apfl_iterative_runner_next(apfl_iterative_runner runner) { @@ -254,7 +284,7 @@ apfl_iterative_runner_next(apfl_iterative_runner runner) case APFL_PARSE_OK: goto ok; case APFL_PARSE_ERROR: - runner->result = APFL_RESULT_ERR; + runner->result = handle_parse_error(runner->ctx, apfl_parser_get_error(runner->parser)); return true; case APFL_PARSE_EOF: runner->end = true; diff --git a/src/format.c b/src/format.c index ecf1c7a..ecb2470 100644 --- a/src/format.c +++ b/src/format.c @@ -17,6 +17,13 @@ write_file(void *opaque, const char *buf, size_t len) return fwrite(buf, len, 1, f) == 1; } +static bool +write_string(void *opaque, const char *buf, size_t len) +{ + struct apfl_string_builder *sb = opaque; + return apfl_string_builder_append(sb, (struct apfl_string_view) {.bytes = buf, .len = len}); +} + struct apfl_format_writer apfl_format_file_writer(FILE *f) { @@ -26,6 +33,15 @@ apfl_format_file_writer(FILE *f) }; } +struct apfl_format_writer +apfl_format_string_writer(struct apfl_string_builder *sb) +{ + return (struct apfl_format_writer) { + .write = write_string, + .opaque = sb, + }; +} + bool apfl_format_put_string_view(struct apfl_format_writer w, struct apfl_string_view sv) { diff --git a/src/format.h b/src/format.h index 2157def..8e5c05e 100644 --- a/src/format.h +++ b/src/format.h @@ -18,6 +18,8 @@ struct apfl_format_writer { struct apfl_format_writer apfl_format_file_writer(FILE *f); +struct apfl_format_writer apfl_format_string_writer(struct apfl_string_builder *sb); + bool apfl_format_put_string_view(struct apfl_format_writer, struct apfl_string_view); #define apfl_format_put_string(w, s) apfl_format_put_string_view((w), apfl_string_view_from(s)) bool apfl_format_put_int(struct apfl_format_writer, int); diff --git a/src/internal.h b/src/internal.h index aea725e..869eb60 100644 --- a/src/internal.h +++ b/src/internal.h @@ -8,6 +8,8 @@ extern "C" { #include #include +#include "gc.h" + #define DEINIT_CAP_LIST(allocator, items, len, cap, item_deinit) \ do { \ if ((items) == NULL) { \ @@ -87,6 +89,8 @@ do { \ void apfl_print_indented(unsigned indent, FILE *, const char* fmt, ...); +struct apfl_string *apfl_string_move_into_new_gc_string(struct gc *gc, struct apfl_string *in); + #ifdef __cplusplus } #endif diff --git a/src/main.c b/src/main.c index a1a0171..5d0bb5c 100644 --- a/src/main.c +++ b/src/main.c @@ -158,10 +158,11 @@ repl_eval(void) while (apfl_iterative_runner_next(runner)) { switch (apfl_iterative_runner_get_result(runner)) { - case APFL_RESULT_OK: + case APFL_RESULT_OK : apfl_debug_print_val(ctx, -1, stdout); break; case APFL_RESULT_ERR: + apfl_debug_print_val(ctx, -1, stderr); fprintf(stderr, "Error occurred during evaluation.\n"); break; case APFL_RESULT_ERR_FATAL: diff --git a/src/strings.c b/src/strings.c index e634994..8d2d7fd 100644 --- a/src/strings.c +++ b/src/strings.c @@ -6,6 +6,7 @@ #include "apfl.h" #include "alloc.h" +#include "gc.h" #include "internal.h" #include "resizable.h" @@ -153,3 +154,15 @@ apfl_string_builder_move_string(struct apfl_string_builder *builder) return str; } + +struct apfl_string * +apfl_string_move_into_new_gc_string(struct gc *gc, struct apfl_string *in) +{ + struct apfl_string *str = apfl_gc_new_string(gc); + if (str == NULL) { + return NULL; + } + + *str = apfl_string_move(in); + return str; +}