102 lines
2 KiB
C
102 lines
2 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "chunk.h"
|
|
#include "compile.h"
|
|
#include "debug.h"
|
|
#include "parser.h"
|
|
#include "vm.h"
|
|
|
|
#include "vendor/mpc.h"
|
|
|
|
#define REPL_BUFFER_SIZE 4096
|
|
|
|
I repl(void) {
|
|
Vm vm = {0};
|
|
vm_init(&vm);
|
|
|
|
char input[REPL_BUFFER_SIZE];
|
|
|
|
for (;;) {
|
|
printf("> ");
|
|
fflush(stdout);
|
|
if (fgets(input, REPL_BUFFER_SIZE, stdin) == NULL) {
|
|
printf("\n");
|
|
break;
|
|
}
|
|
I is_empty = 1;
|
|
for (char *p = input; *p; p++) {
|
|
if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') {
|
|
is_empty = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (is_empty)
|
|
continue;
|
|
if (strncmp(input, "bye", 3) == 0 || strncmp(input, "quit", 4) == 0)
|
|
break;
|
|
mpc_result_t res;
|
|
if (!mpc_parse("<repl>", input, Program, &res)) {
|
|
mpc_err_print(res.error);
|
|
mpc_err_delete(res.error);
|
|
continue;
|
|
}
|
|
Cm cm = {0};
|
|
compiler_init(&cm, &vm, "<repl>");
|
|
Bc *chunk = compile_program(&cm, res.output);
|
|
mpc_ast_delete(res.output);
|
|
if (chunk != NULL) {
|
|
vm_run(&vm, chunk, 0);
|
|
chunk_release(chunk);
|
|
}
|
|
compiler_deinit(&cm);
|
|
}
|
|
vm_deinit(&vm);
|
|
return 0;
|
|
}
|
|
|
|
I loadfile(const char *fname) {
|
|
Vm vm = {0};
|
|
vm_init(&vm);
|
|
|
|
mpc_result_t res;
|
|
if (!mpc_parse_contents(fname, Program, &res)) {
|
|
mpc_err_print_to(res.error, stderr);
|
|
mpc_err_delete(res.error);
|
|
return 1;
|
|
}
|
|
|
|
Cm cm = {0};
|
|
compiler_init(&cm, &vm, fname);
|
|
|
|
Bc *chunk = compile_program(&cm, res.output);
|
|
mpc_ast_delete(res.output);
|
|
|
|
if (chunk != NULL) {
|
|
#if COMPILER_DEBUG
|
|
disassemble(chunk, fname, &vm.dictionary);
|
|
#endif
|
|
I res = vm_run(&vm, chunk, 0);
|
|
chunk_release(chunk);
|
|
vm_deinit(&vm);
|
|
return !res;
|
|
} else {
|
|
vm_deinit(&vm);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int main(int argc, const char *argv[]) {
|
|
parser_init();
|
|
atexit(parser_deinit);
|
|
|
|
switch (argc) {
|
|
case 1:
|
|
return repl();
|
|
case 2:
|
|
return loadfile(argv[1]);
|
|
default:
|
|
fprintf(stderr, "usage: growl [file]\n");
|
|
return 64;
|
|
}
|
|
}
|