Browse Source

add a REPL

master
Martin Dørum 3 years ago
parent
commit
bc29640896
3 changed files with 89 additions and 5 deletions
  1. 88
    3
      cmd/main.c
  2. 1
    1
      include/lang2/loader.h
  3. 0
    1
      lib/loader.c

+ 88
- 3
cmd/main.c View File

@@ -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);

+ 1
- 1
include/lang2/loader.h View File

@@ -7,6 +7,6 @@
#include <stdio.h>

int l2_bc_serialize(FILE *outf, l2_word *data, size_t len);
int l2_bc_load(FILE *outf, struct l2_io_writer *w);
int l2_bc_load(FILE *inf, struct l2_io_writer *w);

#endif

+ 0
- 1
lib/loader.c View File

@@ -77,6 +77,5 @@ int l2_bc_load(FILE *inf, struct l2_io_writer *w) {
((unsigned int)buffer[i + 3]) << 0;
l2_bufio_put_n(&writer, &word, 4);
}

}
}

Loading…
Cancel
Save