|
|
@@ -10,10 +10,18 @@ |
|
|
|
#include <stdio.h> |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
#ifdef __unix__ |
|
|
|
#define USE_READLINE |
|
|
|
#include <unistd.h> |
|
|
|
#include <readline/readline.h> |
|
|
|
#include <readline/history.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
static int do_print_bytecode = 0; |
|
|
|
static int do_print_tokens = 0; |
|
|
|
static int do_step = 0; |
|
|
|
static int do_serialize_bytecode = 0; |
|
|
|
static int do_repl = 0; |
|
|
|
static char *input_filename = "-"; |
|
|
|
|
|
|
|
static int parse_text(FILE *inf, struct l2_io_writer *w) { |
|
|
@@ -35,6 +43,7 @@ static int parse_text(FILE *inf, struct l2_io_writer *w) { |
|
|
|
if (l2_parse_program(&lexer, &gen, &err) < 0) { |
|
|
|
fprintf(stderr, "Parse error: %s:%i:%i: %s\n", |
|
|
|
input_filename, err.line, err.ch, err.message); |
|
|
|
l2_parse_error_free(&err); |
|
|
|
l2_gen_free(&gen); |
|
|
|
fclose(inf); |
|
|
|
return -1; |
|
|
@@ -62,6 +71,65 @@ static void step_through(struct l2_vm *vm) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int repl() { |
|
|
|
struct l2_io_mem_writer w = { |
|
|
|
.w.write = l2_io_mem_write, |
|
|
|
}; |
|
|
|
|
|
|
|
struct l2_io_mem_reader r = { |
|
|
|
.r.read = l2_io_mem_read, |
|
|
|
}; |
|
|
|
|
|
|
|
struct l2_lexer lexer; |
|
|
|
|
|
|
|
struct l2_generator gen; |
|
|
|
l2_gen_init(&gen, &w.w); |
|
|
|
|
|
|
|
struct l2_vm vm; |
|
|
|
l2_vm_init(&vm, NULL, 0); |
|
|
|
|
|
|
|
while (1) { |
|
|
|
char line[4096]; |
|
|
|
#ifdef USE_READLINE |
|
|
|
char *rline = readline("> "); |
|
|
|
if (rline == NULL) return -1; |
|
|
|
if (rline[0] == '\0') continue; |
|
|
|
snprintf(line, sizeof(line), "print (%s)", rline); |
|
|
|
free(rline); |
|
|
|
#else |
|
|
|
char rline[4096]; |
|
|
|
if (fgets(rline, sizeof(rline), stdin) == NULL) return -1; |
|
|
|
if (rline[0] == '\n' && rline[1] == '\0') continue; |
|
|
|
snprintf(line, sizeof(line), "print (%s)", rline); |
|
|
|
#endif |
|
|
|
|
|
|
|
r.idx = 0; |
|
|
|
r.len = strlen(line); |
|
|
|
r.mem = line; |
|
|
|
l2_lexer_init(&lexer, &r.r); |
|
|
|
|
|
|
|
size_t prev_len = w.len; |
|
|
|
|
|
|
|
struct l2_parse_error err; |
|
|
|
if (l2_parse_program(&lexer, &gen, &err) < 0) { |
|
|
|
fprintf(stderr, "Parse error: %s\n", err.message); |
|
|
|
l2_parse_error_free(&err); |
|
|
|
w.len = prev_len; |
|
|
|
} else if (w.len > 0) { |
|
|
|
vm.ops = w.mem; |
|
|
|
vm.opcount = w.len / sizeof(l2_word); |
|
|
|
|
|
|
|
while (vm.iptr < vm.opcount) { |
|
|
|
l2_vm_step(&vm); |
|
|
|
} |
|
|
|
|
|
|
|
l2_vm_gc(&vm); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void usage(const char *argv0) { |
|
|
|
printf("Usage: %s [options] [input|-]\n", argv0); |
|
|
|
printf("\n"); |
|
|
@@ -70,6 +138,7 @@ static void usage(const char *argv0) { |
|
|
|
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"); |
|
|
|
printf(" --repl: Start a repl\n"); |
|
|
|
printf(" --output,-o <out>: Write bytecode to file\n"); |
|
|
|
} |
|
|
|
|
|
|
@@ -78,6 +147,10 @@ int main(int argc, char **argv) { |
|
|
|
FILE *inf = stdin; |
|
|
|
FILE *outbc = NULL; |
|
|
|
|
|
|
|
#ifdef __unix__ |
|
|
|
do_repl = isatty(0); |
|
|
|
#endif |
|
|
|
|
|
|
|
int dashes = 0; |
|
|
|
for (int i = 1; i < argc; ++i) { |
|
|
|
if (!dashes && strcmp(argv[i], "--help") == 0) { |
|
|
@@ -89,6 +162,8 @@ int main(int argc, char **argv) { |
|
|
|
do_print_tokens = 1; |
|
|
|
} else if (!dashes && strcmp(argv[i], "--step") == 0) { |
|
|
|
do_step = 1; |
|
|
|
} else if (!dashes && strcmp(argv[i], "--repl") == 0) { |
|
|
|
do_repl = 1; |
|
|
|
} else if (!dashes && ( |
|
|
|
strcmp(argv[i], "--output") == 0 || strcmp(argv[i], "-o") == 0)) { |
|
|
|
if (i == argc - 1) { |
|
|
@@ -110,9 +185,11 @@ int main(int argc, char **argv) { |
|
|
|
} else if (strcmp(argv[i], "--") == 0) { |
|
|
|
dashes = 1; |
|
|
|
} else if (strcmp(argv[i], "-") == 0) { |
|
|
|
do_repl = 0; |
|
|
|
input_filename = "-"; |
|
|
|
inf = stdin; |
|
|
|
} else if (!was_inf_set) { |
|
|
|
do_repl = 0; |
|
|
|
input_filename = argv[i]; |
|
|
|
inf = fopen(argv[i], "r"); |
|
|
|
was_inf_set = 1; |
|
|
@@ -127,10 +204,18 @@ int main(int argc, char **argv) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
struct l2_io_mem_writer bytecode_writer = {0}; |
|
|
|
bytecode_writer.w.write = l2_io_mem_write; |
|
|
|
if (do_repl) { |
|
|
|
if (repl() < 0) { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
struct l2_io_mem_writer bytecode_writer = { |
|
|
|
.w.write = l2_io_mem_write, |
|
|
|
}; |
|
|
|
|
|
|
|
// |
|
|
|
int headerbyte = fgetc(inf); |
|
|
|
if (headerbyte == EOF || ungetc(headerbyte, inf) == EOF) { |
|
|
|
fprintf(stderr, "%s: Reading file failed.\n", input_filename); |