aboutsummaryrefslogtreecommitdiff
path: root/src/repl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/repl.c')
-rw-r--r--src/repl.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/repl.c b/src/repl.c
new file mode 100644
index 0000000..236d9ec
--- /dev/null
+++ b/src/repl.c
@@ -0,0 +1,67 @@
+#include "repl.h"
+
+#include "ast.h"
+#include "object.h"
+#include "token.h"
+#include "vector.h"
+#include "parser.h"
+#include "eval.h"
+
+#define PROMPT ">> "
+
+static void
+print_parser_errors(FILE *out, struct vector *errors)
+{
+ size_t i;
+ char *msg;
+ vector_foreach(errors, i, msg) {
+ fprintf(out, "\t%s\n", msg);
+ }
+}
+
+void
+repl_start(FILE *in, FILE *out)
+{
+ char obuf[2048];
+ struct parser *parser = parser_new();
+ struct environment *env = environment_new();
+ struct vector *history = vector_new();
+ for (;;) {
+ fprintf(out, PROMPT);
+ char *input = malloc(1024);
+ if (!fgets(input, 1024, in)) {
+ if (ferror(in)) {
+ perror("REPL: can't read");
+ free(input);
+ goto end;
+ }
+ fprintf(out, "EOF\n");
+ free(input);
+ goto end;
+ }
+ parser_reset(parser, input);
+ struct program *prog = parser_parse_program(parser);
+ if (parser->errors->len > 0) {
+ print_parser_errors(out, parser->errors);
+ goto skip;
+ }
+ struct object *res = eval(env, prog);
+ if (res) {
+ fprintf(out, "%s\n", object_sprint(res, obuf));
+ object_unref(res);
+ }
+ vector_push(history, input);
+skip:
+ node_destroy(prog);
+ }
+
+end:;
+ size_t i;
+ char *input;
+ vector_foreach(history, i, input) {
+ free(input);
+ }
+ vector_free(history);
+ environment_destroy(env);
+ parser_destroy(parser);
+}