No longer evaluate exprs directly

This commit is contained in:
Laria 2022-04-21 21:15:20 +02:00
parent b7c88635d9
commit 9ce5c20736
5 changed files with 172 additions and 74 deletions

View file

@ -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);

View file

@ -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)
{

View file

@ -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
}

View file

@ -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);
}

View file

@ -1,3 +1,4 @@
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
@ -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;
}