Add a simple REPL
This commit is contained in:
parent
c7a3e820e0
commit
a3db5aa285
8 changed files with 442 additions and 32 deletions
|
@ -22,6 +22,7 @@ target_sources(vm_lib
|
||||||
src/opcode.cpp
|
src/opcode.cpp
|
||||||
src/fio.cpp
|
src/fio.cpp
|
||||||
src/stdlib.cpp
|
src/stdlib.cpp
|
||||||
|
src/lineedit.cpp
|
||||||
|
|
||||||
PUBLIC
|
PUBLIC
|
||||||
FILE_SET HEADERS
|
FILE_SET HEADERS
|
||||||
|
@ -41,6 +42,7 @@ target_sources(vm_lib
|
||||||
src/opcode.hpp
|
src/opcode.hpp
|
||||||
src/fio.hpp
|
src/fio.hpp
|
||||||
src/stdlib.hpp
|
src/stdlib.hpp
|
||||||
|
src/lineedit.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(vli src/vli.cpp)
|
add_executable(vli src/vli.cpp)
|
||||||
|
|
|
@ -204,7 +204,7 @@ class Array : public Object {
|
||||||
return Array(TRY(MkGcRoot(pod)));
|
return Array(TRY(MkGcRoot(pod)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Array> slice(uint64_t start, uint64_t end) {
|
Result<Array> slice(uint64_t start, uint64_t end) const {
|
||||||
if (start > end) return ERROR(IndexOutOfRange);
|
if (start > end) return ERROR(IndexOutOfRange);
|
||||||
uint64_t res_size = end - start;
|
uint64_t res_size = end - start;
|
||||||
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
|
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
|
||||||
|
@ -315,7 +315,7 @@ class ByteArray : public Object {
|
||||||
return ByteArray(TRY(MkGcRoot(pod)));
|
return ByteArray(TRY(MkGcRoot(pod)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ByteArray> slice(uint64_t start, uint64_t end) {
|
Result<ByteArray> slice(uint64_t start, uint64_t end) const {
|
||||||
if (start > end) return ERROR(IndexOutOfRange);
|
if (start > end) return ERROR(IndexOutOfRange);
|
||||||
uint64_t res_size = end - start;
|
uint64_t res_size = end - start;
|
||||||
auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
|
auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
|
||||||
|
@ -510,7 +510,7 @@ class String : public Object {
|
||||||
return String(TRY(MkGcRoot(pod)));
|
return String(TRY(MkGcRoot(pod)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> slice(uint64_t start, uint64_t end) {
|
Result<String> slice(uint64_t start, uint64_t end) const {
|
||||||
if (start > end) return ERROR(IndexOutOfRange);
|
if (start > end) return ERROR(IndexOutOfRange);
|
||||||
uint64_t res_size = end - start;
|
uint64_t res_size = end - start;
|
||||||
auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
|
auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
|
||||||
|
|
|
@ -16,6 +16,7 @@ enum class ErrorCode {
|
||||||
CompilationError,
|
CompilationError,
|
||||||
ArgumentCountMismatch,
|
ArgumentCountMismatch,
|
||||||
IOError,
|
IOError,
|
||||||
|
Interrupt,
|
||||||
};
|
};
|
||||||
|
|
||||||
void seterr(const char* err);
|
void seterr(const char* err);
|
||||||
|
|
394
src/lineedit.cpp
Normal file
394
src/lineedit.cpp
Normal file
|
@ -0,0 +1,394 @@
|
||||||
|
#include "lineedit.hpp"
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "fio.hpp"
|
||||||
|
|
||||||
|
enum class TtyEscape {
|
||||||
|
Null = 0,
|
||||||
|
CtrlA = 1,
|
||||||
|
CtrlB = 2,
|
||||||
|
CtrlC = 3,
|
||||||
|
CtrlD = 4,
|
||||||
|
CtrlE = 5,
|
||||||
|
CtrlF = 6,
|
||||||
|
CtrlH = 8,
|
||||||
|
Tab = 9,
|
||||||
|
CtrlK = 11,
|
||||||
|
CtrlL = 12,
|
||||||
|
Enter = 13,
|
||||||
|
CtrlN = 14,
|
||||||
|
CtrlP = 16,
|
||||||
|
CtrlT = 20,
|
||||||
|
CtrlU = 21,
|
||||||
|
CtrlW = 23,
|
||||||
|
Esc = 27,
|
||||||
|
Backspace = 127,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct termios orig_termios;
|
||||||
|
static int rawmode = 0;
|
||||||
|
|
||||||
|
template <uint64_t buflen>
|
||||||
|
class CharBuf {
|
||||||
|
public:
|
||||||
|
CharBuf() : _len(0) {}
|
||||||
|
|
||||||
|
Result<void> append(char c) {
|
||||||
|
if (_len + 1 >= buflen) return ERROR(IndexOutOfRange);
|
||||||
|
_buf[_len] = c;
|
||||||
|
_len++;
|
||||||
|
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
Result<void> append(const char* s) {
|
||||||
|
uint64_t slen = strlen(s);
|
||||||
|
if (_len + slen >= buflen) return ERROR(IndexOutOfRange);
|
||||||
|
|
||||||
|
memcpy(_buf + _len, s, slen);
|
||||||
|
_len += slen;
|
||||||
|
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t len() { return _len; }
|
||||||
|
const char* buf() { return _buf; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
char _buf[buflen];
|
||||||
|
uint64_t _len;
|
||||||
|
};
|
||||||
|
|
||||||
|
Result<void> enableRawMode(int fd) {
|
||||||
|
struct termios raw;
|
||||||
|
|
||||||
|
if (!isatty(STDIN_FILENO)) return ERROR(IOError);
|
||||||
|
if (tcgetattr(fd, &orig_termios) == -1) return ERROR(IOError);
|
||||||
|
|
||||||
|
raw = orig_termios; /* modify the original mode */
|
||||||
|
/* input modes: no break, no CR to NL, no parity check, no strip char,
|
||||||
|
* no start/stop output control. */
|
||||||
|
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||||
|
/* output modes - disable post processing */
|
||||||
|
raw.c_oflag &= ~(OPOST);
|
||||||
|
/* control modes - set 8 bit chars */
|
||||||
|
raw.c_cflag |= (CS8);
|
||||||
|
/* local modes - choing off, canonical off, no extended functions,
|
||||||
|
* no signal chars (^Z,^C) */
|
||||||
|
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||||
|
/* control chars - set return condition: min number of bytes and timer.
|
||||||
|
* We want read to return every single byte, without timeout. */
|
||||||
|
raw.c_cc[VMIN] = 1;
|
||||||
|
raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
|
||||||
|
|
||||||
|
/* put terminal in raw mode after flushing */
|
||||||
|
if (tcsetattr(fd, TCSAFLUSH, &raw) < 0) return ERROR(IOError);
|
||||||
|
rawmode = 1;
|
||||||
|
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableRawMode(int fd) {
|
||||||
|
/* Don't even check the return value as it's too late. */
|
||||||
|
if (rawmode && tcsetattr(fd, TCSAFLUSH, &orig_termios) != -1) rawmode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RawModeGuard {
|
||||||
|
public:
|
||||||
|
RawModeGuard() : fd(-1) {}
|
||||||
|
RawModeGuard(int fd) : fd(fd) {}
|
||||||
|
RawModeGuard(RawModeGuard&& rhs) {
|
||||||
|
fd = rhs.fd;
|
||||||
|
rhs.fd = -1;
|
||||||
|
}
|
||||||
|
RawModeGuard(const RawModeGuard&) = delete;
|
||||||
|
~RawModeGuard() {
|
||||||
|
if (fd >= 0) disableRawMode(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<RawModeGuard> create(int fd) {
|
||||||
|
auto res = RawModeGuard(fd);
|
||||||
|
TRY(enableRawMode(fd));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
RawModeGuard raw_mode_guard(STDIN_FILENO);
|
||||||
|
|
||||||
|
struct RefreshState {
|
||||||
|
uint64_t num_rows = 0;
|
||||||
|
uint64_t cursor_pos = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LineEdit {
|
||||||
|
public:
|
||||||
|
LineEdit()
|
||||||
|
: prompt(""),
|
||||||
|
cursor_pos(0),
|
||||||
|
line_len(0),
|
||||||
|
term_width(0),
|
||||||
|
input_fd(STDIN_FILENO),
|
||||||
|
output_fd(STDOUT_FILENO) {
|
||||||
|
buf[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineEdit(const char* prompt, int input_fd = STDIN_FILENO,
|
||||||
|
int output_fd = STDOUT_FILENO)
|
||||||
|
: prompt(prompt),
|
||||||
|
cursor_pos(0),
|
||||||
|
line_len(0),
|
||||||
|
term_width(0),
|
||||||
|
input_fd(input_fd),
|
||||||
|
output_fd(output_fd) {
|
||||||
|
buf[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineEdit(const LineEdit& rhs) {
|
||||||
|
prompt = rhs.prompt;
|
||||||
|
memcpy(buf, rhs.buf, buflen);
|
||||||
|
cursor_pos = rhs.cursor_pos;
|
||||||
|
line_len = rhs.line_len;
|
||||||
|
term_width = rhs.term_width;
|
||||||
|
input_fd = rhs.input_fd;
|
||||||
|
output_fd = rhs.output_fd;
|
||||||
|
last_refresh = rhs.last_refresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<LineEdit> create(const char* prompt) {
|
||||||
|
LineEdit res(prompt);
|
||||||
|
|
||||||
|
TRY(res.init());
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<uint64_t> get_term_width() {
|
||||||
|
winsize ws;
|
||||||
|
|
||||||
|
if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
|
||||||
|
/* ioctl() failed. Try to query the terminal itself. */
|
||||||
|
int start, cols;
|
||||||
|
|
||||||
|
/* Get the initial position so we can restore it later. */
|
||||||
|
start = TRY(get_cursor_column());
|
||||||
|
|
||||||
|
/* Go to right margin and get position. */
|
||||||
|
if (write(output_fd, "\x1b[999C", 6) != 6) return ERROR(IOError);
|
||||||
|
cols = TRY(get_cursor_column());
|
||||||
|
|
||||||
|
/* Restore position. */
|
||||||
|
if (cols > start) {
|
||||||
|
char seq[32];
|
||||||
|
snprintf(seq, 32, "\x1b[%dD", cols - start);
|
||||||
|
if (write(output_fd, seq, strlen(seq)) == -1) {
|
||||||
|
return ERROR(IOError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cols;
|
||||||
|
} else {
|
||||||
|
return ws.ws_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<uint64_t> get_cursor_column() {
|
||||||
|
char buf[32];
|
||||||
|
int cols, rows;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
/* Report cursor location */
|
||||||
|
if (write(output_fd, "\x1b[6n", 4) != 4) return -1;
|
||||||
|
|
||||||
|
/* Read the response: ESC [ rows ; cols R */
|
||||||
|
while (i < sizeof(buf) - 1) {
|
||||||
|
if (read(input_fd, buf + i, 1) != 1) break;
|
||||||
|
if (buf[i] == 'R') break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
buf[i] = '\0';
|
||||||
|
|
||||||
|
/* Parse it. */
|
||||||
|
if (buf[0] != (char)TtyEscape::Esc || buf[1] != '[') return -1;
|
||||||
|
if (sscanf(buf + 2, "%d;%d", &rows, &cols) != 2) return -1;
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<String> read_one() {
|
||||||
|
{
|
||||||
|
auto guard = TRY(RawModeGuard::create(input_fd));
|
||||||
|
if (write(output_fd, prompt, strlen(prompt)) == -1) return ERROR(IOError);
|
||||||
|
|
||||||
|
while (TRY(step()));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
auto res = TRY(String::create(buf));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<bool> step() {
|
||||||
|
char c;
|
||||||
|
int nread;
|
||||||
|
char seq[3];
|
||||||
|
|
||||||
|
nread = read(input_fd, &c, 1);
|
||||||
|
if (nread <= 0) return false;
|
||||||
|
|
||||||
|
switch (TtyEscape(c)) {
|
||||||
|
case TtyEscape::Enter:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case TtyEscape::Backspace:
|
||||||
|
TRY(handle_backspace());
|
||||||
|
break;
|
||||||
|
case TtyEscape::CtrlC:
|
||||||
|
return ERROR(Interrupt);
|
||||||
|
default:
|
||||||
|
TRY(handle_regular_char(c));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> handle_regular_char(char c) {
|
||||||
|
if (line_len >= buflen) return Result<void>();
|
||||||
|
|
||||||
|
if (line_len == cursor_pos) {
|
||||||
|
buf[cursor_pos] = c;
|
||||||
|
cursor_pos++;
|
||||||
|
line_len++;
|
||||||
|
buf[cursor_pos] = 0;
|
||||||
|
|
||||||
|
// if (strlen(prompt) + line_len < term_width) {
|
||||||
|
// if (write(output_fd, &c, 1) == -1) return ERROR(IOError);
|
||||||
|
// } else {
|
||||||
|
TRY(refresh_line());
|
||||||
|
//}
|
||||||
|
} else {
|
||||||
|
memmove(buf + cursor_pos + 1, buf + cursor_pos, line_len - cursor_pos);
|
||||||
|
buf[cursor_pos] = c;
|
||||||
|
cursor_pos++;
|
||||||
|
line_len++;
|
||||||
|
buf[line_len] = 0;
|
||||||
|
|
||||||
|
TRY(refresh_line());
|
||||||
|
}
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> handle_backspace() {
|
||||||
|
if (cursor_pos == 0) return Result<void>();
|
||||||
|
memmove(buf + cursor_pos - 1, buf + cursor_pos, line_len - cursor_pos);
|
||||||
|
cursor_pos--;
|
||||||
|
line_len--;
|
||||||
|
buf[line_len] = 0;
|
||||||
|
|
||||||
|
TRY(refresh_line());
|
||||||
|
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> refresh_line() {
|
||||||
|
char seq[64];
|
||||||
|
CharBuf<1024> cbuf;
|
||||||
|
|
||||||
|
RefreshState new_refresh = last_refresh;
|
||||||
|
|
||||||
|
uint64_t prompt_len = strlen(prompt);
|
||||||
|
|
||||||
|
uint64_t num_rows = (prompt_len + line_len + term_width - 1) / term_width;
|
||||||
|
uint64_t cursor_row =
|
||||||
|
(prompt_len + last_refresh.cursor_pos + term_width) / term_width;
|
||||||
|
uint64_t new_relative_row = 0;
|
||||||
|
|
||||||
|
new_refresh.num_rows = num_rows;
|
||||||
|
new_refresh.cursor_pos = cursor_pos;
|
||||||
|
|
||||||
|
// Go to last row
|
||||||
|
if (last_refresh.num_rows - cursor_row > 0) {
|
||||||
|
snprintf(seq, 64, "\x1b[%luB", last_refresh.num_rows - cursor_row);
|
||||||
|
TRY(cbuf.append(seq));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all rows one by one (except the first one)
|
||||||
|
if (last_refresh.num_rows > 1) {
|
||||||
|
for (uint64_t i = 0; i < last_refresh.num_rows - 1; i++) {
|
||||||
|
snprintf(seq, 64, "\r\x1b[0K\x1b[1A");
|
||||||
|
TRY(cbuf.append(seq));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the first line
|
||||||
|
snprintf(seq, 64, "\r\x1b[0K");
|
||||||
|
TRY(cbuf.append(seq));
|
||||||
|
|
||||||
|
// Write the prompt
|
||||||
|
cbuf.append(prompt);
|
||||||
|
|
||||||
|
// Write the buffer content
|
||||||
|
cbuf.append(buf);
|
||||||
|
|
||||||
|
if (cursor_pos > 0 && cursor_pos == line_len &&
|
||||||
|
(cursor_pos + prompt_len) % term_width == 0) {
|
||||||
|
cbuf.append("\n");
|
||||||
|
cbuf.append("\r");
|
||||||
|
num_rows++;
|
||||||
|
if (num_rows > last_refresh.num_rows) new_refresh.num_rows = num_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor_row = (prompt_len + cursor_pos + term_width) / term_width;
|
||||||
|
|
||||||
|
// Go up to the cursor row
|
||||||
|
if (num_rows - cursor_row > 0) {
|
||||||
|
snprintf(seq, 64, "\x1b[%luA", num_rows - cursor_row);
|
||||||
|
TRY(cbuf.append(seq));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to the cursor column
|
||||||
|
uint64_t col = (prompt_len + cursor_pos) % term_width;
|
||||||
|
if (col > 0) {
|
||||||
|
snprintf(seq, 64, "\r\x1b[%luC", col);
|
||||||
|
TRY(cbuf.append(seq));
|
||||||
|
} else {
|
||||||
|
TRY(cbuf.append("\r"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(output_fd, cbuf.buf(), cbuf.len()) == -1) return ERROR(IOError);
|
||||||
|
|
||||||
|
last_refresh = new_refresh;
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result<void> init() {
|
||||||
|
term_width = TRY(get_term_width());
|
||||||
|
|
||||||
|
if (!stdin_isatty()) return ERROR(IOError);
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* prompt;
|
||||||
|
static const uint64_t buflen = 1024;
|
||||||
|
char buf[buflen + 1];
|
||||||
|
uint64_t cursor_pos;
|
||||||
|
uint64_t line_len;
|
||||||
|
uint64_t term_width;
|
||||||
|
int input_fd;
|
||||||
|
int output_fd;
|
||||||
|
RefreshState last_refresh;
|
||||||
|
};
|
||||||
|
|
||||||
|
Result<String> read_line(const char* prompt) {
|
||||||
|
auto rl = TRY(LineEdit::create(prompt));
|
||||||
|
|
||||||
|
return rl.read_one();
|
||||||
|
}
|
6
src/lineedit.hpp
Normal file
6
src/lineedit.hpp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "result.hpp"
|
||||||
|
|
||||||
|
class String;
|
||||||
|
Result<String> read_line(const char* prompt);
|
|
@ -409,12 +409,12 @@ bool Reader::forward_exponent() {
|
||||||
return forward_decimal_number();
|
return forward_decimal_number();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> read_one(Value& value) {
|
Result<Value> read_one(const Value& value) {
|
||||||
if (!value.is<String>()) return ERROR(TypeMismatch);
|
if (!value.is<String>()) return ERROR(TypeMismatch);
|
||||||
auto r = Reader(*value.to<String>());
|
auto r = Reader(*value.to<String>());
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
Result<Value> read_one(String& value) {
|
Result<Value> read_one(const String& value) {
|
||||||
auto r = Reader(value);
|
auto r = Reader(value);
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ Result<Value> read_one(const char* value) {
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> read_multiple(String& value) {
|
Result<Value> read_multiple(const String& value) {
|
||||||
auto r = Reader(value);
|
auto r = Reader(value);
|
||||||
return r.read_multiple();
|
return r.read_multiple();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
public:
|
public:
|
||||||
Reader(String& str) : _str(str) {}
|
Reader(const String& str) : _str(str) {}
|
||||||
|
|
||||||
Result<Value> read_one();
|
Result<Value> read_one();
|
||||||
Result<Value> read_multiple();
|
Result<Value> read_multiple();
|
||||||
|
@ -38,12 +38,12 @@ class Reader {
|
||||||
bool match(const char* str);
|
bool match(const char* str);
|
||||||
bool match(char c);
|
bool match(char c);
|
||||||
|
|
||||||
String& _str;
|
const String& _str;
|
||||||
SourcePosition position_{1, 1, 0};
|
SourcePosition position_{1, 1, 0};
|
||||||
};
|
};
|
||||||
|
|
||||||
Result<Value> read_one(Value& value);
|
Result<Value> read_one(const Value& value);
|
||||||
Result<Value> read_one(String& value);
|
Result<Value> read_one(const String& value);
|
||||||
Result<Value> read_one(const char* value);
|
Result<Value> read_one(const char* value);
|
||||||
|
|
||||||
Result<Value> read_multiple(String& value);
|
Result<Value> read_multiple(const String& value);
|
||||||
|
|
49
src/vli.cpp
49
src/vli.cpp
|
@ -5,44 +5,51 @@
|
||||||
#include "compiler.hpp"
|
#include "compiler.hpp"
|
||||||
#include "die.hpp"
|
#include "die.hpp"
|
||||||
#include "fio.hpp"
|
#include "fio.hpp"
|
||||||
|
#include "lineedit.hpp"
|
||||||
#include "reader.hpp"
|
#include "reader.hpp"
|
||||||
#include "vm.hpp"
|
#include "vm.hpp"
|
||||||
#include "writer.hpp"
|
#include "writer.hpp"
|
||||||
|
|
||||||
StaticArena<64 * 1024 * 1024> arena;
|
StaticArena<64 * 1024 * 1024> arena;
|
||||||
|
|
||||||
Result<void> run(int argc, const char* argv[]) {
|
Result<Value> run_string(const String& src) {
|
||||||
String src = DIEX(String::create(""));
|
|
||||||
if (argc == 1) {
|
|
||||||
if (stdin_isatty()) {
|
|
||||||
die("Code expected at stdin, not a tty.\n");
|
|
||||||
}
|
|
||||||
src = TRY(read_stdin());
|
|
||||||
} else {
|
|
||||||
src = TRY(read_file(argv[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// auto code_str = TRY(String::create("(* (+ 1 2 3) (/ 4 2))"));
|
|
||||||
// auto code_str =
|
|
||||||
// TRY(String::create("((lambda (f y) (f y)) (lambda (x) (* x x)) 2)"));
|
|
||||||
|
|
||||||
auto parsed = TRY(read_multiple(src));
|
auto parsed = TRY(read_multiple(src));
|
||||||
// auto code_str_written = TRY(write_multiple(parsed));
|
|
||||||
|
|
||||||
TRY(arena_gc());
|
TRY(arena_gc());
|
||||||
|
|
||||||
// TRY(debug_print(code_str_written));
|
|
||||||
|
|
||||||
auto compiled = TRY(compile(parsed));
|
auto compiled = TRY(compile(parsed));
|
||||||
Module& mod = *compiled.to<Module>();
|
Module& mod = *compiled.to<Module>();
|
||||||
|
|
||||||
// TRY(debug_print(TRY(mod.globals())));
|
|
||||||
|
|
||||||
auto vm = TRY(VM::create());
|
auto vm = TRY(VM::create());
|
||||||
|
|
||||||
auto res = TRY(vm.run(mod));
|
auto res = TRY(vm.run(mod));
|
||||||
|
|
||||||
// TRY(debug_print(res));
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> run_repl() {
|
||||||
|
while (true) {
|
||||||
|
auto src = TRY(read_line("vli> "));
|
||||||
|
debug_print(src);
|
||||||
|
auto res = TRY(run_string(src));
|
||||||
|
debug_print(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> run(int argc, const char* argv[]) {
|
||||||
|
String src = DIEX(String::create(""));
|
||||||
|
if (argc == 1) {
|
||||||
|
if (stdin_isatty()) {
|
||||||
|
return run_repl();
|
||||||
|
}
|
||||||
|
src = TRY(read_stdin());
|
||||||
|
TRY(run_string(src));
|
||||||
|
} else {
|
||||||
|
src = TRY(read_file(argv[1]));
|
||||||
|
TRY(run_string(src));
|
||||||
|
}
|
||||||
|
|
||||||
return Result<void>();
|
return Result<void>();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue