diff --git a/README.md b/README.md index fba11fb..8f49edd 100644 --- a/README.md +++ b/README.md @@ -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 `, 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. diff --git a/src/main.cpp b/src/main.cpp index 1c06168..f90aa2d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -94,7 +94,7 @@ int main(int argc, char *argv[]) { } if (Options::get("repl")) - while (true) { + while (true && !vm.is_quit()) { std::cout << "> "; vm.loadControl(repl); vm.run(); diff --git a/src/vm/include/Command.h b/src/vm/include/Command.h index e911157..b79cfe0 100644 --- a/src/vm/include/Command.h +++ b/src/vm/include/Command.h @@ -47,21 +47,22 @@ namespace Command { GT = 27, NILC = 28, MULT = 29, - DIV = 30 + DIV = 30, + QUIT = 31 }; static inline std::unordered_map 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 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("command_strs")) { diff --git a/src/vm/include/VM.h b/src/vm/include/VM.h index b9facc9..d6e9415 100644 --- a/src/vm/include/VM.h +++ b/src/vm/include/VM.h @@ -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; diff --git a/src/vm/src/Compiler.cpp b/src/vm/src/Compiler.cpp index ef81f81..e93ce80 100644 --- a/src/vm/src/Compiler.cpp +++ b/src/vm/src/Compiler.cpp @@ -18,8 +18,9 @@ using namespace Command; static std::unordered_map 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))); diff --git a/src/vm/src/VM.cpp b/src/vm/src/VM.cpp index 781361f..bb060fc 100644 --- a/src/vm/src/VM.cpp +++ b/src/vm/src/VM.cpp @@ -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;