#include "vm/vm.h" #include "vm/print.h" #include "parse/parse.h" #include "parse/lex.h" #include "io.h" #include "bitset.h" #include #include void step_through(struct l2_vm *vm) { printf("=====\n\nInitial state:\n"); l2_vm_print_state(vm); char buf[16]; while ((enum l2_opcode)vm->ops[vm->iptr] != L2_OP_HALT) { size_t iptr = vm->iptr; printf("\n======\n\n(%d) Will run instr: ", vm->iptr); l2_vm_print_op(vm->ops, vm->opcount, &iptr); fgets(buf, sizeof(buf), stdin); l2_vm_step(vm); l2_vm_print_state(vm); } } static void usage(const char *argv0) { printf("Usage: %s [options] [input|-]\n", argv0); printf("\n"); printf("Options:\n"); printf(" --help: Print this help text\n"); printf(" --bytecode: Print the generated bytecode, don't execute\n"); printf(" --tokens: Print the tokens as the program is parsed, don't execute\n"); printf(" --step: Step through the program\n"); } int main(int argc, char **argv) { int do_print_bytecode = 0; int do_print_tokens = 0; int do_step = 0; int was_inf_set = 0; FILE *inf = stdin; int dashes = 0; for (int i = 1; i < argc; ++i) { if (!dashes && strcmp(argv[i], "--help") == 0) { usage(argv[0]); return 0; } else if (!dashes && strcmp(argv[i], "--bytecode") == 0) { do_print_bytecode = 1; } else if (!dashes && strcmp(argv[i], "--tokens") == 0) { do_print_tokens = 1; } else if (!dashes && strcmp(argv[i], "--step") == 0) { do_step = 1; } else if (strcmp(argv[i], "--") == 0) { dashes = 1; } else if (strcmp(argv[i], "-") == 0) { inf = stdin; } else if (!was_inf_set) { inf = fopen(argv[i], "r"); was_inf_set = 1; if (inf == NULL) { perror(argv[i]); return 1; } } else { printf("Unexpected argument: %s\n", argv[i]); usage(argv[0]); return 1; } } // Init lexer with its input reader struct l2_io_file_reader r; r.r.read = l2_io_file_read; r.f = inf; struct l2_lexer lexer; l2_lexer_init(&lexer, &r.r); if (do_print_tokens) { lexer.do_log_tokens = 1; } // Init gen with its output writer struct l2_io_mem_writer w = {0}; w.w.write = l2_io_mem_write; struct l2_generator gen; l2_gen_init(&gen, &w.w); struct l2_parse_error err; if (l2_parse_program(&lexer, &gen, &err) < 0) { fprintf(stderr, "Parse error: %s:%i:%i: %s\n", (argc == 2 ? argv[1] : "-"), err.line, err.ch, err.message); l2_gen_free(&gen); fclose(inf); return 1; } l2_gen_free(&gen); fclose(inf); if (do_print_bytecode) { l2_vm_print_bytecode((l2_word *)w.mem, w.len / sizeof(l2_word)); } if (do_print_bytecode || do_print_tokens) { free(w.mem); return 0; } struct l2_vm vm; l2_vm_init(&vm, (void *)w.mem, w.len / sizeof(l2_word)); if (do_step) { step_through(&vm); } else { l2_vm_run(&vm); } l2_vm_free(&vm); free(w.mem); }