No longer evaluate exprs directly
This commit is contained in:
parent
b7c88635d9
commit
9ce5c20736
5 changed files with 172 additions and 74 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
93
src/eval.c
93
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);
|
||||
}
|
||||
|
|
|
|||
139
src/main.c
139
src/main.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue