#include "pez.h" #include #include #include #include #include #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" " -dG debug: stress GC\n" " -dg debug: print GC info\n" "\n"); } int main(int argc, char **argv) { PezContext *cx = pez_new(NULL, NULL, 32*1024 /* 32KiB stack */); FILE *fp = NULL; int i, ret = 0; assert(cx != NULL && "no context"); 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, "", 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; }