summaryrefslogtreecommitdiff
path: root/repl.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-10-08 11:08:42 +0200
committerlemon <lsof@mailbox.org>2022-10-08 11:08:42 +0200
commite2283f6c7f5abc60dc7ba7ea59deee94da714da7 (patch)
treeb007ad4820b016ec90c614b218c5e529560e1d8f /repl.c
initial commit
Diffstat (limited to 'repl.c')
-rw-r--r--repl.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/repl.c b/repl.c
new file mode 100644
index 0000000..5a22bff
--- /dev/null
+++ b/repl.c
@@ -0,0 +1,98 @@
+#include "pez.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#define CHECK(x) do { \
+ if (!(x)) { \
+ fprintf(stderr, "%s\n", pez_geterr(cx)); \
+ assert(!#x); \
+ } \
+} while (0)
+
+static bool
+printtop(PezContext *cx) {
+ assert(pez_top(cx) >= 2);
+ return
+ pez_push(cx, 0) // printf was stored here
+ && pez_pushstring(cx, "%a", 2)
+ && pez_push(cx, -3)
+ && pez_apply(cx, 2)
+ && (pez_pop(cx), pez_pop(cx), 1);
+}
+
+static void
+help(void)
+{
+ printf("Usage: pez [OPTION]... [FILE] [ARG]...\n"
+ "With no FILE, enter repl.\n"
+ "\n"
+ " -h, --help show this help message\n"
+ " -db debug: print bytecode\n"
+ "\n");
+}
+
+int
+main(int argc, char **argv) {
+ PezContext *cx = pez_new(NULL, NULL);
+ FILE *fp = NULL;
+ int i, ret = 0;
+
+ for (i = 1; i < argc; ++i) {
+ const char *arg = argv[i];
+ if (*arg == '-') {
+ if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) {
+ help();
+ goto Bye;
+ } else if (arg[1] == 'd') {
+ pez_debug(cx, arg + 2);
+ } else {
+ printf("pez: Invalid option '%s'\n", arg);
+ help();
+ ret = 1;
+ goto Bye;
+ }
+ } else {
+ fp = fopen(arg, "r");
+ if (!fp) {
+ perror(arg);
+ ret = 1;
+ goto Bye;
+ }
+ break;
+ }
+ }
+
+ if (!fp) {
+ char *src;
+ using_history();
+ CHECK(pez_pushglobal(cx, "printf"));
+
+ while ((src = readline("> "))) {
+ add_history(src);
+ if (!pez_eval_str(cx, "<repl>", src)) {
+ fprintf(stderr, "error: %s\n", pez_geterr(cx));
+ } else {
+ assert(pez_top(cx) == 2);
+ CHECK(printtop(cx));
+ printf("\n");
+ }
+ free(src);
+ }
+ } else {
+ if (!pez_eval_file(cx, argv[i], fp)) {
+ fprintf(stderr, "error: %s\n", pez_geterr(cx));
+ ret = 1;
+ goto Bye;
+ }
+ assert(pez_top(cx) == 1);
+ }
+Bye:
+ if (fp) {
+ fclose(fp);
+ }
+ pez_del(cx);
+ return ret;
+}