From 9ce5c20736185804819625a2bffb7da8c1e99937 Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Thu, 21 Apr 2022 21:15:20 +0200 Subject: [PATCH] No longer evaluate exprs directly --- src/apfl.h | 7 ++- src/context.c | 6 +++ src/context.h | 1 + src/eval.c | 93 ++++++++++++++++++++++++++++++--- src/main.c | 139 ++++++++++++++++++++++++++------------------------ 5 files changed, 172 insertions(+), 74 deletions(-) diff --git a/src/apfl.h b/src/apfl.h index fbd6c57..1366bc2 100644 --- a/src/apfl.h +++ b/src/apfl.h @@ -590,7 +590,12 @@ apfl_ctx apfl_ctx_new(struct apfl_allocator); void apfl_ctx_destroy(apfl_ctx); -enum apfl_result apfl_eval(apfl_ctx, struct apfl_expr); +typedef struct apfl_iterative_runner_data *apfl_iterative_runner; + +apfl_iterative_runner apfl_iterative_runner_new(apfl_ctx, struct apfl_source_reader); +bool apfl_iterative_runner_next(apfl_iterative_runner); +enum apfl_result apfl_iterative_runner_get_result(apfl_iterative_runner); +void apfl_iterative_runner_destroy(apfl_iterative_runner); // Get the type of a value on the stack enum apfl_value_type apfl_get_type(apfl_ctx, apfl_stackidx); diff --git a/src/context.c b/src/context.c index c11e6d5..1c24111 100644 --- a/src/context.c +++ b/src/context.c @@ -167,6 +167,12 @@ apfl_stack_drop(apfl_ctx ctx, apfl_stackidx index) return apfl_stack_pop(ctx, &value, index); } +void +apfl_stack_clear(apfl_ctx ctx) +{ + ctx->stack->len = 0; +} + apfl_ctx apfl_ctx_new(struct apfl_allocator base_allocator) { diff --git a/src/context.h b/src/context.h index fee0614..fe2668c 100644 --- a/src/context.h +++ b/src/context.h @@ -36,6 +36,7 @@ bool apfl_stack_check_index(apfl_ctx, apfl_stackidx *); 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); #ifdef __cplusplus } diff --git a/src/eval.c b/src/eval.c index e9c4bfe..402abaf 100644 --- a/src/eval.c +++ b/src/eval.c @@ -179,13 +179,9 @@ eval_inner(apfl_ctx ctx, struct apfl_expr expr) return evaluate_list(ctx, ilist); } -enum apfl_result -apfl_eval(apfl_ctx ctx, struct apfl_expr expr) +static enum apfl_result +eval_expr(apfl_ctx ctx, struct apfl_expr expr) { - // TODO: expr might have been allocated with another allocator. The apfl_ctx - // should probably also handle parsing and no longer accept - // expressions directly. - size_t tmproots = apfl_gc_tmproots_begin(&ctx->gc); enum apfl_result result = eval_inner(ctx, expr); apfl_gc_tmproots_restore(&ctx->gc, tmproots); @@ -204,3 +200,88 @@ apfl_debug_print_val(apfl_ctx ctx, apfl_stackidx index, FILE *f) apfl_value_print(value, f); } + +struct apfl_iterative_runner_data { + apfl_ctx ctx; + apfl_tokenizer_ptr tokenizer; + apfl_parser_ptr parser; + enum apfl_result result; + bool end; +}; + +apfl_iterative_runner +apfl_iterative_runner_new(apfl_ctx ctx, struct apfl_source_reader reader) +{ + apfl_iterative_runner runner = ALLOC_OBJ(ctx->gc.allocator, struct apfl_iterative_runner_data); + if (runner == NULL) { + return NULL; + } + + apfl_tokenizer_ptr tokenizer = apfl_tokenizer_new(ctx->gc.allocator, reader); + if (tokenizer == NULL) { + FREE_OBJ(ctx->gc.allocator, runner); + return NULL; + } + + apfl_parser_ptr parser = apfl_parser_new(ctx->gc.allocator, apfl_tokenizer_as_token_source(tokenizer)); + if (parser == NULL) { + FREE_OBJ(ctx->gc.allocator, runner); + apfl_tokenizer_destroy(tokenizer); + return NULL; + } + + *runner = (struct apfl_iterative_runner_data) { + .ctx = ctx, + .tokenizer = tokenizer, + .parser = parser, + .result = APFL_RESULT_OK, + .end = false, + }; + + return runner; +} + +bool +apfl_iterative_runner_next(apfl_iterative_runner runner) +{ + if (runner->end) { + return false; + } + + apfl_stack_clear(runner->ctx); + + switch (apfl_parser_next(runner->parser)) { + case APFL_PARSE_OK: + goto ok; + case APFL_PARSE_ERROR: + runner->result = APFL_RESULT_ERR; + return true; + case APFL_PARSE_EOF: + runner->end = true; + return false; + } + + assert(false); + +ok: + runner->result = eval_expr(runner->ctx, apfl_parser_get_expr(runner->parser)); + return true; +} + +enum apfl_result +apfl_iterative_runner_get_result(apfl_iterative_runner runner) +{ + return runner->result; +} + +void +apfl_iterative_runner_destroy(apfl_iterative_runner runner) +{ + if (runner == NULL) { + return; + } + + apfl_parser_destroy(runner->parser); + apfl_tokenizer_destroy(runner->tokenizer); + FREE_OBJ(runner->ctx->gc.allocator, runner); +} diff --git a/src/main.c b/src/main.c index bd3f6f1..a1a0171 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -71,51 +72,92 @@ repl_tokenizer(struct apfl_allocator allocator, apfl_tokenizer_ptr tokenizer) } } -static bool -repl_parser_generic(apfl_parser_ptr parser, struct apfl_expr *expr, int *rv) +static int +repl_parser(struct apfl_allocator allocator, apfl_parser_ptr parser) { while (true) { + struct apfl_expr expr; struct apfl_error err; switch (apfl_parser_next(parser)) { case APFL_PARSE_OK: - *expr = apfl_parser_get_expr(parser); - return true; + expr = apfl_parser_get_expr(parser); + apfl_expr_print(expr, stdout); + apfl_expr_deinit(allocator, &expr); + break; case APFL_PARSE_EOF: - *rv = 0; - return false; + return 0; case APFL_PARSE_ERROR: err = apfl_parser_get_error(parser); apfl_error_print(err, stderr); if (APFL_ERROR_IS_FATAL(err)) { - *rv = 1; - return false; + return 1; } break; } } } -static int -repl_parser(struct apfl_allocator allocator, apfl_parser_ptr parser) +static int repl_parser_or_tokenizer(enum repl_mode mode) { - struct apfl_expr expr; - int rv; - while (repl_parser_generic(parser, &expr, &rv)) { - apfl_expr_print(expr, stdout); - apfl_expr_deinit(allocator, &expr); + int rv = 0; + + struct apfl_allocator allocator = apfl_allocator_default(); + apfl_tokenizer_ptr tokenizer = NULL; + apfl_parser_ptr parser = NULL; + + if ((tokenizer = apfl_tokenizer_new(allocator, repl_source_reader())) == NULL) { + fprintf(stderr, "Failed initializing tokenizer\n"); + return 1; } + + if (mode == REPL_PARSER) { + if ((parser = apfl_parser_new(allocator, apfl_tokenizer_as_token_source(tokenizer))) == NULL) { + fprintf(stderr, "Failed initializing parser\n"); + rv = 1; + goto exit; + } + } + + switch (mode) { + case REPL_TOKENIZER: + rv = repl_tokenizer(allocator, tokenizer); + break; + case REPL_PARSER: + rv = repl_parser(allocator, parser); + break; + default: + assert(false /* repl_parser_or_tokenizer called with wrong mode */); + } + +exit: + apfl_parser_destroy(parser); + apfl_tokenizer_destroy(tokenizer); + return rv; } static int -repl_eval(apfl_parser_ptr parser, apfl_ctx ctx) +repl_eval(void) { - struct apfl_expr expr; - int rv; - while (repl_parser_generic(parser, &expr, &rv)) { - switch (apfl_eval(ctx, expr)) { + int rv = 0; + + apfl_ctx ctx = apfl_ctx_new(apfl_allocator_default()); + if (ctx == NULL) { + fprintf(stderr, "Failed to init the context\n"); + return 1; + } + + apfl_iterative_runner runner = apfl_iterative_runner_new(ctx, repl_source_reader()); + if (runner == NULL) { + apfl_ctx_destroy(ctx); + fprintf(stderr, "Failed to init runner\n"); + return 1; + } + + while (apfl_iterative_runner_next(runner)) { + switch (apfl_iterative_runner_get_result(runner)) { case APFL_RESULT_OK: apfl_debug_print_val(ctx, -1, stdout); break; @@ -124,17 +166,20 @@ repl_eval(apfl_parser_ptr parser, apfl_ctx ctx) break; case APFL_RESULT_ERR_FATAL: fprintf(stderr, "Fatal error occurred during evaluation.\n"); - return 1; + rv = 1; + goto exit; } } + +exit: + apfl_iterative_runner_destroy(runner); + apfl_ctx_destroy(ctx); return rv; } int main(int argc, const char **argv) { - int rv = 0; - enum repl_mode mode = REPL_PARSER; if (argc > 1) { @@ -150,49 +195,9 @@ main(int argc, const char **argv) } } - struct apfl_allocator allocator = apfl_allocator_default(); - apfl_tokenizer_ptr tokenizer = NULL; - apfl_parser_ptr parser = NULL; - apfl_ctx ctx = NULL; - - if ((tokenizer = apfl_tokenizer_new(allocator, repl_source_reader())) == NULL) { - fprintf(stderr, "Failed initializing tokenizer\n"); - rv = 1; - goto exit; + if (mode == REPL_EVAL) { + return repl_eval(); + } else { + return repl_parser_or_tokenizer(mode); } - - if (mode >= REPL_PARSER) { - if ((parser = apfl_parser_new(allocator, apfl_tokenizer_as_token_source(tokenizer))) == NULL) { - fprintf(stderr, "Failed initializing parser\n"); - rv = 1; - goto exit; - } - } - - if (mode >= REPL_EVAL) { - if ((ctx = apfl_ctx_new(allocator)) == NULL) { - fprintf(stderr, "Failed initializing context\n"); - rv = 1; - goto exit; - } - } - - switch (mode) { - case REPL_TOKENIZER: - rv = repl_tokenizer(allocator, tokenizer); - break; - case REPL_PARSER: - rv = repl_parser(allocator, parser); - break; - case REPL_EVAL: - rv = repl_eval(parser, ctx); - break; - } - -exit: - apfl_tokenizer_destroy(tokenizer); - apfl_parser_destroy(parser); - apfl_ctx_destroy(ctx); - - return rv; }