repl quit

This commit is contained in:
2024-01-04 12:50:26 +01:00
parent 8f5294fea7
commit efc60b4c23
6 changed files with 27 additions and 20 deletions

View File

@@ -31,7 +31,7 @@ PSIL="../build/src/psil" clitests/testall.sh
# How to use
You can just run the executable and you'll be in REPL mode (ctrl-c to exit should work),
You can just run the executable and you'll be in REPL mode (ctrl-c to exit should work, or `(quit)`),
or specify an input file like `-f <file>`, the effect is the same as if you
had put it there yourself.
@@ -91,10 +91,10 @@ build/src/psil -f clitests/decorate.psil --repl- --command_strs+ --default_log_l
# Some notes on the implementation
The implementation is rather straightforward, based mostly on the compiler from "THE ARCHITECTURE OF SYMBOLIC
COMPUTERS", with little modification and some additions. Notably, the let/letrec is more lisp-like, using racket-like
The implementation is rather straightforward, based mostly on the compiler from "The Architecture of Symbolic
Computers", with little modification and some additions. Notably, the let/letrec is more lisp-like, using racket-like
name-value pairs instead of them being in separate lists like in the book. Also, there's support for top-level functions
using `define`, and a simple concurrent garbage collector.
using `define`, quoting using `(quote value)`, and a simple concurrent garbage collector.
There are three basic value types which is a string atom, number atom, and a cons cell.

View File

@@ -94,7 +94,7 @@ int main(int argc, char *argv[]) {
}
if (Options::get<bool>("repl"))
while (true) {
while (true && !vm.is_quit()) {
std::cout << "> ";
vm.loadControl(repl);
vm.run();

View File

@@ -47,21 +47,22 @@ namespace Command {
GT = 27,
NILC = 28,
MULT = 29,
DIV = 30
DIV = 30,
QUIT = 31
};
static inline std::unordered_map<std::string_view, CellValType> str_to_cmd{
{"NIL", 1}, {"LDC", 2}, {"LD", 3}, {"SEL", 4}, {"JOIN", 5}, {"LDF", 6},
{"AP", 7}, {"RET", 8}, {"DUM", 9}, {"RAP", 10}, {"STOP", 11}, {"ATOM", 12},
{"ADD", 13}, {"SUB", 14}, {"READCHAR", 15}, {"PUTCHAR", 16}, {"PUTNUM", 17}, {"EVAL", 18},
{"PRINT", 19}, {"READ", 20}, {"CONS", 21}, {"LDG", 22}, {"CAR", 23}, {"CDR", 24},
{"EQ", 25}, {"LT", 26}, {"GT", 27}, {"NILC", 28}, {"MULT", 29}, {"DIV", 30}};
{"NIL", 1}, {"LDC", 2}, {"LD", 3}, {"SEL", 4}, {"JOIN", 5}, {"LDF", 6}, {"AP", 7},
{"RET", 8}, {"DUM", 9}, {"RAP", 10}, {"STOP", 11}, {"ATOM", 12}, {"ADD", 13}, {"SUB", 14},
{"READCHAR", 15}, {"PUTCHAR", 16}, {"PUTNUM", 17}, {"EVAL", 18}, {"PRINT", 19}, {"READ", 20}, {"CONS", 21},
{"LDG", 22}, {"CAR", 23}, {"CDR", 24}, {"EQ", 25}, {"LT", 26}, {"GT", 27}, {"NILC", 28},
{"MULT", 29}, {"DIV", 30}, {"QUIT", 31}};
static inline std::unordered_map<CellValType, std::string> cmd_to_str{
{1, "NIL"}, {2, "LDC"}, {3, "LD"}, {4, "SEL"}, {5, "JOIN"}, {6, "LDF"},
{7, "AP"}, {8, "RET"}, {9, "DUM"}, {10, "RAP"}, {11, "STOP"}, {12, "ATOM"},
{13, "ADD"}, {14, "SUB"}, {15, "READCHAR"}, {16, "PUTCHAR"}, {17, "PUTNUM"}, {18, "EVAL"},
{19, "PRINT"}, {20, "READ"}, {21, "CONS"}, {22, "LDG"}, {23, "CAR"}, {24, "CDR"},
{25, "EQ"}, {26, "LT"}, {27, "GT"}, {28, "NILC"}, {29, "MULT"}, {30, "DIV"}};
{1, "NIL"}, {2, "LDC"}, {3, "LD"}, {4, "SEL"}, {5, "JOIN"}, {6, "LDF"}, {7, "AP"},
{8, "RET"}, {9, "DUM"}, {10, "RAP"}, {11, "STOP"}, {12, "ATOM"}, {13, "ADD"}, {14, "SUB"},
{15, "READCHAR"}, {16, "PUTCHAR"}, {17, "PUTNUM"}, {18, "EVAL"}, {19, "PRINT"}, {20, "READ"}, {21, "CONS"},
{22, "LDG"}, {23, "CAR"}, {24, "CDR"}, {25, "EQ"}, {26, "LT"}, {27, "GT"}, {28, "NILC"},
{29, "MULT"}, {30, "DIV"}, {31, "QUIT"}};
static inline Handle make_cmd(CellValType cmd) {
if (Options::get<bool>("command_strs")) {

View File

@@ -26,6 +26,7 @@ public:
void loadStack(const Handle &h) { _s = h; }
bool is_quit() const { return _quit; }
void step();
private:
@@ -39,6 +40,7 @@ private:
Handle _c = Handle::cons(nullptr, nullptr);
Handle _d = Handle::cons(nullptr, nullptr);
bool _stop = false;
bool _quit = false;
std::istream &_instream;
std::ostream &_outstream;

View File

@@ -18,8 +18,9 @@ using namespace Command;
static std::unordered_map<std::string_view, CommandE> builtins{
{"+", ADD}, {"-", SUB}, {"cons", CONS}, {"car", CAR}, {"cdr", CDR}, {"=", EQ}, {">", GT},
{"<", LT}, {"nil", NIL}, {"nil?", NILC}, {"atom", ATOM}, {"*", MULT}, {"/", DIV}};
{"+", ADD}, {"-", SUB}, {"cons", CONS}, {"car", CAR}, {"cdr", CDR}, {"=", EQ},
{">", GT}, {"<", LT}, {"nil", NIL}, {"nil?", NILC}, {"atom", ATOM}, {"*", MULT},
{"/", DIV}, {"read", READ}, {"eval", EVAL}, {"print", PRINT}, {"quit", QUIT}};
Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffix) {
Handle out;
@@ -82,8 +83,6 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
} else if (builtins.find(car.strval()) != builtins.end()) {
out.splice(compileArgsRaw(cdr));
out.append(make_cmd(builtins.at(car.strval())));
} else if (car.strval() == "read") {
out.append(make_cmd(READ));
} else if (car.strval() == "lambda") {
out.append(make_cmd(LDF));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car(), fake_env), make_cmd(RET)));

View File

@@ -194,6 +194,11 @@ void VM::step() {
_stop = true;
break;
}
case QUIT: {
_stop = true;
_quit = true;
break;
}
case ADD: {
_s.push(_s.pop().val() + _s.pop().val());
break;