From 02fe73f42fb86048f995f4fb7a574302140239c4 Mon Sep 17 00:00:00 2001 From: Stepan Usatiuk Date: Wed, 3 Jan 2024 21:18:01 +0100 Subject: [PATCH] coffee! --- clitests/.gitignore | 1 + clitests/coffee.psil | 28 +++++++++++++++++++++++++++- clitests/coffee.psil.ex | 16 ++++++++++++++++ clitests/coffee.res | 3 --- clitests/testall.sh | 2 -- src/vm/include/Cell.h | 2 +- src/vm/include/Command.h | 7 ++++--- src/vm/include/Handle.h | 10 ++++++++-- src/vm/include/VM.h | 2 ++ src/vm/src/Compiler.cpp | 7 ++++--- src/vm/src/Parser.cpp | 2 +- src/vm/src/VM.cpp | 26 ++++++++++++++++++++++++-- 12 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 clitests/.gitignore create mode 100644 clitests/coffee.psil.ex delete mode 100644 clitests/coffee.res diff --git a/clitests/.gitignore b/clitests/.gitignore new file mode 100644 index 0000000..bc1c138 --- /dev/null +++ b/clitests/.gitignore @@ -0,0 +1 @@ +*.res \ No newline at end of file diff --git a/clitests/coffee.psil b/clitests/coffee.psil index ff51e7e..88d7c7d 100644 --- a/clitests/coffee.psil +++ b/clitests/coffee.psil @@ -2,10 +2,19 @@ (if (> a b) a b) ) +(define (equal a b) + (if (nil? a) (if (nil? b) 1 0) + (if (atom a) + (if (atom b) (= a b) 0) + (if (atom b) 0 (if (equal (car a) (car b)) (equal (cdr a) (cdr b)) 0)) + ) + ) +) + (define (coffee-shop-impl times last cur max) (if (= times (nil)) (getmax cur max) - (if (= last (car times)) + (if (equal last (car times)) (coffee-shop-impl (cdr times) last (+ cur 1) max) (coffee-shop-impl (cdr times) (car times) 1 (getmax cur max)) ) @@ -16,6 +25,23 @@ (coffee-shop-impl times (nil) 0 0) ) +(equal (nil) (nil)) +(equal (nil) ()) +(equal () (nil)) +(equal (nil) (quote())) +(equal () (nil)) +(equal () (quote())) + +(equal (quote(a))(quote())) +(equal (quote(a)) ()) +(equal (quote(a)) (nil)) + +(equal (quote(a)) (quote(a.))) +(equal (quote(a.)) (quote(a b))) + +(equal (quote(a b)) (quote(a.b))) +(equal (quote(a b)) (quote(a b))) + (coffee-shop (nil)) (coffee-shop (quote( (8 0) (8 10) (8 10) (8 45) ))) (coffee-shop (quote( (8 12) (10 11) (10 11) (15 15) (15 15) (15 15) (22 22) (22 22) (22 59) ))) \ No newline at end of file diff --git a/clitests/coffee.psil.ex b/clitests/coffee.psil.ex new file mode 100644 index 0000000..7ed06bb --- /dev/null +++ b/clitests/coffee.psil.ex @@ -0,0 +1,16 @@ +1 +1 +1 +1 +1 +1 +0 +0 +0 +1 +0 +0 +1 +0 +2 +3 diff --git a/clitests/coffee.res b/clitests/coffee.res deleted file mode 100644 index ac0ea60..0000000 --- a/clitests/coffee.res +++ /dev/null @@ -1,3 +0,0 @@ -0 -2 -3 \ No newline at end of file diff --git a/clitests/testall.sh b/clitests/testall.sh index 2dd360b..c38909c 100755 --- a/clitests/testall.sh +++ b/clitests/testall.sh @@ -3,8 +3,6 @@ cd "$(dirname "$0")" FAILED=() -PSIL="../cmake-build-debug/src/psil" - for FILE in *.psil; do echo "TESTING $FILE" $PSIL -f $FILE --repl- > $FILE.res diff --git a/src/vm/include/Cell.h b/src/vm/include/Cell.h index 7ee25db..71c1803 100644 --- a/src/vm/include/Cell.h +++ b/src/vm/include/Cell.h @@ -89,7 +89,7 @@ struct ConsCell : public Cell { void print(std::ostream &out) override { std::stringstream res; - std::set seen; + std::set seen{this}; if (_car) { if (_car.load()->_type == CellType::CONS) { res << "("; diff --git a/src/vm/include/Command.h b/src/vm/include/Command.h index 3dc794b..7c84f62 100644 --- a/src/vm/include/Command.h +++ b/src/vm/include/Command.h @@ -43,19 +43,20 @@ namespace Command { CDR = 24, EQ = 25, LT = 26, - GT = 27 + GT = 27, + NILC = 28 }; 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}}; + {"LDG", 22}, {"CAR", 23}, {"CDR", 24}, {"EQ", 25}, {"LT", 26}, {"GT", 27}, {"NILC", 28}}; 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"}}; + {22, "LDG"}, {23, "CAR"}, {24, "CDR"}, {25, "EQ"}, {26, "LT"}, {27, "GT"}, {28, "NILC"}}; static inline Handle make_cmd(CellValType cmd) { if (Options::get_bool("command_strs")) { diff --git a/src/vm/include/Handle.h b/src/vm/include/Handle.h index 99d5687..a276749 100644 --- a/src/vm/include/Handle.h +++ b/src/vm/include/Handle.h @@ -37,8 +37,14 @@ public: static Handle cons(const Handle &car, const Handle &cdr); - Handle car() const { return dynamic_cast(*_target)._car.load(); } - Handle cdr() const { return dynamic_cast(*_target)._cdr.load(); } + Handle car() const { + if (!_target) return Handle(nullptr); + return dynamic_cast(*_target)._car.load(); + } + Handle cdr() const { + if (!_target) return Handle(nullptr); + return dynamic_cast(*_target)._cdr.load(); + } CellValType val() { return dynamic_cast(*_target)._val; } std::string_view strval() { return dynamic_cast(*_target)._val; } diff --git a/src/vm/include/VM.h b/src/vm/include/VM.h index afb88e8..4e6aa04 100644 --- a/src/vm/include/VM.h +++ b/src/vm/include/VM.h @@ -31,6 +31,8 @@ public: private: Handle _globals_names = Handle::cons(Handle::cons(nullptr, nullptr), nullptr); Handle _globals_vals = Handle::cons(nullptr, nullptr); + std::vector> _globals_names_map; + size_t _cur_global = 0; Handle _s = Handle::cons(nullptr, nullptr); Handle _e = Handle::cons(_globals_vals, nullptr); Handle _c = Handle::cons(nullptr, nullptr); diff --git a/src/vm/src/Compiler.cpp b/src/vm/src/Compiler.cpp index 180090f..12cb2d5 100644 --- a/src/vm/src/Compiler.cpp +++ b/src/vm/src/Compiler.cpp @@ -16,8 +16,9 @@ using namespace Command; -static std::unordered_map builtins{{"+", ADD}, {"-", SUB}, {"cons", CONS}, {"car", CAR}, {"cdr", CDR}, - {"=", EQ}, {">", GT}, {"<", LT}, {"nil", NIL}}; +static std::unordered_map builtins{{"+", ADD}, {"-", SUB}, {"cons", CONS}, {"car", CAR}, + {"cdr", CDR}, {"=", EQ}, {">", GT}, {"<", LT}, + {"nil", NIL}, {"nil?", NILC}, {"atom", ATOM}}; Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffix) { Handle out; @@ -80,7 +81,7 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi if (car.atom()) { if (car.strval() == "quote") { out.append(make_cmd(LDC)); - out.splice(cdr); + out.splice(Handle::cons(cdr.car(), cdr.cdr())); } else if (builtins.find(car.strval()) != builtins.end()) { out.splice(compileArgsRaw(cdr)); out.append(make_cmd(builtins.at(car.strval()))); diff --git a/src/vm/src/Parser.cpp b/src/vm/src/Parser.cpp index b1944df..7ffb39e 100644 --- a/src/vm/src/Parser.cpp +++ b/src/vm/src/Parser.cpp @@ -23,7 +23,7 @@ Handle Parser::parseExpr() { if (token == ".") { _tokenizer.getNext(); - out.setcdr(parseExpr()); + if (_tokenizer.peek() != ")") out.setcdr(parseExpr()); if (_tokenizer.getNext() != ")") throw std::invalid_argument("Missing ) after pair"); diff --git a/src/vm/src/VM.cpp b/src/vm/src/VM.cpp index 12fa256..933066c 100644 --- a/src/vm/src/VM.cpp +++ b/src/vm/src/VM.cpp @@ -41,7 +41,9 @@ void VM::step() { } else if (poppedCmd == LDC) { _s.push(_c.pop()); } else if (poppedCmd == ATOM) { - _s.push(_c.pop().atom() ? 1 : 0); + _s.push(_s.pop().atom() ? 1 : 0); + } else if (poppedCmd == NILC) { + _s.push(_s.pop().null() ? 1 : 0); } else if (poppedCmd == LD) { Handle poppedH2 = _c.pop(); @@ -87,6 +89,19 @@ void VM::step() { _s = Handle::cons(nullptr, nullptr); _c = closureH.car(); _e = closureH.cdr(); + + Logger::log( + "VM", + [&](std::ostream &out) { + out << "Applying "; + for (const auto &p: _globals_names_map) { + if (p.first == closureH) out << p.second; + } + out << " with args " << argsH; + }, + Logger::DEBUG); + + _e.push(argsH); } else if (poppedCmd == RET) { Handle c = _d.pop(); @@ -170,7 +185,14 @@ void VM::step() { newc.splice(_c); _c = newc; } else if (poppedCmd == LDG) { - _globals_vals.append(Handle::cons(_c.pop(), _e)); + Handle newclosure = Handle::cons(_c.pop(), _e); + + Handle curName = _globals_names.car(); + for (int i = 0; i < _cur_global; i++) { curName = curName.cdr(); } + _globals_names_map.emplace_back(newclosure, curName.car().strval()); + _cur_global++; + + _globals_vals.append(newclosure); } else if (poppedCmd == PRINT) { if (!_s.null()) { Handle val = _s.pop();