mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 10:47:49 +01:00
repl quit
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user