diff --git a/.idea/misc.xml b/.idea/misc.xml
index 79b3c94..7b055cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 484a4fc..0251d91 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,5 @@
+#include "VM.h"
#include
-#include "vm/includes/VM.h"
int main() {
return 0;
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index 522c655..f7c69d9 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -2,6 +2,6 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_library(vm src/VM.cpp src/Cell.cpp
- src/Parser.cpp)
+ src/Parser.cpp src/SParser.cpp src/MemoryContext.cpp src/ConsUtils.cpp)
target_include_directories(vm PUBLIC includes)
diff --git a/src/vm/includes/Cell.h b/src/vm/includes/Cell.h
index 4360ca4..04065f4 100644
--- a/src/vm/includes/Cell.h
+++ b/src/vm/includes/Cell.h
@@ -9,66 +9,29 @@
#include
enum class CellType {
+ NIL,
INT,
CONS
};
struct Cell {
explicit Cell(CellType type) : _type(type) {}
-
virtual ~Cell() = 0;
CellType _type;
-
bool live = false;
};
-struct IntCell : public Cell {
- IntCell() : Cell(CellType::INT) {}
+struct ValueCell : public Cell {
+ ValueCell() = delete;
+ explicit ValueCell(int64_t val) : Cell(CellType::INT), _val(val) {}
- IntCell(int64_t val) : Cell(CellType::INT), _val(val) {}
-
- int64_t _val{};
-};
-
-struct CommandCell : public IntCell {
- enum class CommandNum {
- NIL = 1,
- LDC = 2,
- LD = 3,
- SEL = 4,
- JOIN = 5,
- LDF = 6,
- AP = 7,
- RET = 8,
- DUM = 9,
- RAP = 10,
- STOP = 11,
-
- ADD = 100,
- SUB = 101,
-
- READCHAR = 201,
- PUTCHAR = 202,
- PUTNUM = 203,
-
- CONS = 301,
- END = 1000
- };
-
- CommandCell(CommandNum cmd) : IntCell(static_cast(cmd)) {}
-
- CommandNum intToCmd() {
- assert((_val > 0 && static_cast(_val) <= CommandNum::END));
- return static_cast(_val);
- }
+ int64_t _val;
};
struct ConsCell : public Cell {
ConsCell() : Cell(CellType::CONS) {}
-
- ConsCell(Cell *car) : Cell(CellType::CONS), _car(car) {}
-
+ explicit ConsCell(Cell *car) : Cell(CellType::CONS), _car(car) {}
ConsCell(Cell *car, Cell *cdr) : Cell(CellType::CONS), _car(car), _cdr(cdr) {}
Cell *_car = nullptr;
diff --git a/src/vm/includes/Command.h b/src/vm/includes/Command.h
new file mode 100644
index 0000000..21d4822
--- /dev/null
+++ b/src/vm/includes/Command.h
@@ -0,0 +1,41 @@
+#ifndef PSIL_COMMAND_H
+#define PSIL_COMMAND_H
+
+#include
+
+namespace Command {
+ enum class CommandNum {
+ NIL = 1,
+ LDC = 2,
+ LD = 3,
+ SEL = 4,
+ JOIN = 5,
+ LDF = 6,
+ AP = 7,
+ RET = 8,
+ DUM = 9,
+ RAP = 10,
+ STOP = 11,
+
+ ADD = 100,
+ SUB = 101,
+
+ READCHAR = 201,
+ PUTCHAR = 202,
+ PUTNUM = 203,
+
+ CONS = 301,
+ END = 1000
+ };
+
+ static inline CommandNum int_to_cmd(int64_t _val) {
+ assert((_val > 0 && static_cast(_val) <= CommandNum::END));
+ return static_cast(_val);
+ }
+
+ static inline int64_t cmd_to_int(CommandNum _val) {
+ return static_cast(_val);
+ }
+};// namespace Command
+
+#endif
\ No newline at end of file
diff --git a/src/vm/includes/ConsUtils.h b/src/vm/includes/ConsUtils.h
new file mode 100644
index 0000000..cb3e5c5
--- /dev/null
+++ b/src/vm/includes/ConsUtils.h
@@ -0,0 +1,22 @@
+//
+// Created by Stepan Usatiuk on 25.12.2023.
+//
+
+#ifndef PSIL_CONSUTILS_H
+#define PSIL_CONSUTILS_H
+
+#include "Cell.h"
+#include "MemoryContext.h"
+
+namespace ConsUtils {
+ static inline MCHandle car(const MCHandle &cell) { return dynamic_cast(*cell)._car; }
+ static inline MCHandle cdr(const MCHandle &cell) { return dynamic_cast(*cell)._cdr; }
+ MCHandle cons(const MCHandle &car, const MCHandle &cdr);
+ MCHandle pop(MCHandle &from);
+ MCHandle push(MCHandle &to, const MCHandle &what);
+ void append(MCHandle to, const MCHandle &what);
+ MCHandle makeIntCell(int64_t val);
+};// namespace ConsUtils
+
+
+#endif//PSIL_CONSUTILS_H
diff --git a/src/vm/includes/MemoryContext.h b/src/vm/includes/MemoryContext.h
new file mode 100644
index 0000000..517e137
--- /dev/null
+++ b/src/vm/includes/MemoryContext.h
@@ -0,0 +1,48 @@
+//
+// Created by Stepan Usatiuk on 25.12.2023.
+//
+
+#ifndef PSIL_MEMORYCONTEXT_H
+#define PSIL_MEMORYCONTEXT_H
+
+#include
+#include
+
+#include "Cell.h"
+
+class MemoryContext {
+public:
+ class Handle;
+
+ MemoryContext();
+ ~MemoryContext();
+
+ template
+ Handle create_cell(Args... args) {
+ CT *cell = new CT(std::forward(args)...);
+ _cells.emplace_back(cell);
+ return cell;
+ }
+
+ class Handle {
+ public:
+ Handle(Cell *target) : _target(target), _type(target ? target->_type : CellType::NIL) {}
+
+ Cell *operator->() const { return _target; }
+ Cell &operator*() const { return *_target; }
+ Cell *get() const noexcept { return _target; }
+
+ private:
+ Cell *_target = nullptr;
+ CellType _type;
+ };
+
+private:
+ std::list _cells;
+};
+
+using MCHandle = MemoryContext::Handle;
+
+extern std::atomic CURRENT_MC;
+
+#endif//PSIL_MEMORYCONTEXT_H
diff --git a/src/vm/includes/Parser.h b/src/vm/includes/Parser.h
index 66c5707..aa3732d 100644
--- a/src/vm/includes/Parser.h
+++ b/src/vm/includes/Parser.h
@@ -5,9 +5,12 @@
#ifndef PSIL_PARSER_H
#define PSIL_PARSER_H
-#include
-#include
#include
+#include
+#include
+
+
+#include "MemoryContext.h"
class VM;
@@ -20,8 +23,7 @@ public:
void loadSecd(std::string_view input);
private:
-
- void compileBody(const std::function &sink);
+ void compileBody(const std::function &sink);
VM &_vm;
@@ -43,4 +45,4 @@ private:
};
-#endif //PSIL_PARSER_H
+#endif//PSIL_PARSER_H
diff --git a/src/vm/includes/SParser.h b/src/vm/includes/SParser.h
new file mode 100644
index 0000000..e2bdbdb
--- /dev/null
+++ b/src/vm/includes/SParser.h
@@ -0,0 +1,14 @@
+//
+// Created by Stepan Usatiuk on 25.12.2023.
+//
+
+#ifndef PSIL_SPARSER_H
+#define PSIL_SPARSER_H
+
+
+class SParser {
+ // SParser()
+};
+
+
+#endif//PSIL_SPARSER_H
diff --git a/src/vm/includes/VM.h b/src/vm/includes/VM.h
index 0c2fd8e..4c7d9b6 100644
--- a/src/vm/includes/VM.h
+++ b/src/vm/includes/VM.h
@@ -11,6 +11,7 @@
#include
#include "Cell.h"
+#include "MemoryContext.h"
class VM {
public:
@@ -18,61 +19,21 @@ public:
void run();
+ void loadControl(const MCHandle &h) { _c = h; }
+
void step();
- // template
- // void appendCommand(T cell) {
- // push(_c, makeCell(std::move(cell)));
- // }
-
- template
- void appendCommand(T *cell) {
- push(_c, cell);
- }
-
- template
- CT *makeCell(Args... args) {
- return static_cast(_cells.emplace_back(new CT(std::forward(args)...)));
- }
-
- Cell *car(ConsCell *cell) {
- return cell->_car;
- }
-
- Cell *cdr(ConsCell *cell) {
- return cell->_cdr;
- }
-
- ConsCell *cons(Cell *car, Cell *cdr) {
- return dynamic_cast(makeCell(car, cdr));
- }
-
- Cell *pop(ConsCell *&what) {
- Cell *ret = what->_car;
- what = dynamic_cast(cdr(what));
- return ret;
- }
-
- Cell *push(ConsCell *&what, Cell *toAppend) {
- what = cons(toAppend, what);
- return what;
- }
-
- uint64_t cellCount() const;
-
private:
- std::list _cells;
- ConsCell *_s = nullptr;
- ConsCell *_e = nullptr;
- ConsCell *_c = nullptr;
- ConsCell *_d = nullptr;
+ MCHandle _s = nullptr;
+ MCHandle _e = nullptr;
+ MCHandle _c = nullptr;
+ MCHandle _d = nullptr;
bool _stop = false;
std::istream &_instream;
std::ostream &_outstream;
- void gc();
+ // void gc();
};
-
#endif//PSIL_VM_H
diff --git a/src/vm/src/Cell.cpp b/src/vm/src/Cell.cpp
index eb99cfe..1b51574 100644
--- a/src/vm/src/Cell.cpp
+++ b/src/vm/src/Cell.cpp
@@ -2,6 +2,6 @@
// Created by Stepan Usatiuk on 22.12.2023.
//
-#include "../includes/Cell.h"
+#include "Cell.h"
Cell::~Cell() = default;
\ No newline at end of file
diff --git a/src/vm/src/ConsUtils.cpp b/src/vm/src/ConsUtils.cpp
new file mode 100644
index 0000000..286ca8e
--- /dev/null
+++ b/src/vm/src/ConsUtils.cpp
@@ -0,0 +1,37 @@
+//
+// Created by Stepan Usatiuk on 25.12.2023.
+//
+
+#include "ConsUtils.h"
+
+#include "MemoryContext.h"
+
+MCHandle ConsUtils::cons(const MCHandle &car, const MCHandle &cdr) {
+ auto ret = CURRENT_MC.load()->create_cell(car.get(), cdr.get());
+ return ret;
+}
+
+MCHandle ConsUtils::pop(MCHandle &from) {
+ auto ret = car(from);
+ from = cdr(from);
+ return ret;
+}
+
+MCHandle ConsUtils::push(MCHandle &to, const MCHandle &what) {
+ to = cons(what, to);
+ return to;
+}
+
+void ConsUtils::append(MCHandle to, const MCHandle &what) {
+ assert(to.get() != nullptr);
+ if (car(to).get() == nullptr) {
+ dynamic_cast(*to)._car = what.get();
+ return;
+ }
+ while (dynamic_cast(*to)._cdr != nullptr) to = cdr(to);
+ dynamic_cast(*to)._cdr = cons(what, nullptr).get();
+}
+
+MCHandle ConsUtils::makeIntCell(int64_t val) {
+ return CURRENT_MC.load()->create_cell(val);
+}
\ No newline at end of file
diff --git a/src/vm/src/MemoryContext.cpp b/src/vm/src/MemoryContext.cpp
new file mode 100644
index 0000000..2b74347
--- /dev/null
+++ b/src/vm/src/MemoryContext.cpp
@@ -0,0 +1,23 @@
+//
+// Created by Stepan Usatiuk on 25.12.2023.
+//
+
+#include "MemoryContext.h"
+
+#include
+#include
+
+std::atomic CURRENT_MC = nullptr;
+
+MemoryContext::MemoryContext() {
+ MemoryContext *expected = nullptr;
+ if (!CURRENT_MC.compare_exchange_strong(expected, this)) throw std::runtime_error("MC already exists!");
+}
+
+MemoryContext::~MemoryContext() {
+ MemoryContext *expected = this;
+ if (!CURRENT_MC.compare_exchange_strong(expected, nullptr)) {
+ std::cerr << "Global MC pointer was overwritten!" << std::endl;
+ std::abort();
+ }
+}
diff --git a/src/vm/src/Parser.cpp b/src/vm/src/Parser.cpp
index 6fa981d..068e68c 100644
--- a/src/vm/src/Parser.cpp
+++ b/src/vm/src/Parser.cpp
@@ -7,23 +7,23 @@
#include
#include
+#include "Command.h"
+#include "ConsUtils.h"
+#include "MemoryContext.h"
#include "VM.h"
Parser::Parser(VM &vm) : _vm(vm) {}
void Parser::loadSecd(std::string_view input) {
_tokenizer.load(input);
- std::stack out;
- compileBody([&out](Cell *cmd) { out.emplace(cmd); });
+ MCHandle out(ConsUtils::cons(nullptr, nullptr));
- while (!out.empty()) {
- this->_vm.appendCommand(out.top());
- out.pop();
- }
+ compileBody([&out](MCHandle cmd) { ConsUtils::append(out, cmd); });
+ _vm.loadControl(out);
}
-void Parser::compileBody(const std::function &sink) {
+void Parser::compileBody(const std::function &sink) {
auto token = _tokenizer.getNext();
if (token != "(") throw std::invalid_argument("Expected (");
@@ -31,84 +31,62 @@ void Parser::compileBody(const std::function &sink) {
token = _tokenizer.getNext();
if (token == "NIL") {
- sink(_vm.makeCell(CommandCell::CommandNum::NIL));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::NIL)));
} else if (token == "LDC") {
- sink(_vm.makeCell(CommandCell::CommandNum::LDC));
- sink(_vm.makeCell(std::stoi(_tokenizer.getNext())));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::LDC)));
+ sink(ConsUtils::makeIntCell(std::stoi(_tokenizer.getNext())));
} else if (token == "LD") {
- sink(_vm.makeCell(CommandCell::CommandNum::LD));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::LD)));
if (_tokenizer.getNext() != "(") throw std::invalid_argument("Expected (");
int64_t frame = std::stoi(_tokenizer.getNext());
if (_tokenizer.getNext() != ".") throw std::invalid_argument("Expected .");
int64_t loc = std::stoi(_tokenizer.getNext());
if (_tokenizer.getNext() != ")") throw std::invalid_argument("Expected )");
- sink(_vm.makeCell(_vm.makeCell(frame), _vm.makeCell(loc)));
+ sink(ConsUtils::cons(ConsUtils::makeIntCell(frame), ConsUtils::makeIntCell(loc)));
} else if (token == "SEL") {
- std::stack outt;
- compileBody([&outt](Cell *cmd) { outt.emplace(cmd); });
- std::stack outf;
- compileBody([&outf](Cell *cmd) { outf.emplace(cmd); });
+ MCHandle outt(ConsUtils::cons(nullptr, nullptr));
+ compileBody([&outt](MCHandle cmd) { ConsUtils::append(outt, cmd); });
+ MCHandle outf(ConsUtils::cons(nullptr, nullptr));
+ compileBody([&outf](MCHandle cmd) { ConsUtils::append(outf, cmd);; });
- if (outt.empty()) throw std::invalid_argument("Function body empty");
- if (outf.empty()) throw std::invalid_argument("Function body empty");
+ if (ConsUtils::car(outt).get() == nullptr) throw std::invalid_argument("Function body empty");
+ if (ConsUtils::cdr(outt).get() == nullptr) throw std::invalid_argument("Function body empty");
- ConsCell *ttop = _vm.makeCell(outt.top());
- outt.pop();
- while (!outt.empty()) {
- _vm.push(ttop, outt.top());
- outt.pop();
- }
-
- ConsCell *ftop = _vm.makeCell(outf.top());
- outf.pop();
- while (!outf.empty()) {
- _vm.push(ftop, outf.top());
- outf.pop();
- }
-
- sink(_vm.makeCell(CommandCell::CommandNum::SEL));
- sink(ttop);
- sink(ftop);
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::SEL)));
+ sink(outt);
+ sink(outf);
} else if (token == "JOIN") {
- sink(_vm.makeCell(CommandCell::CommandNum::JOIN));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::JOIN)));
} else if (token == "LDF") {
- std::stack| out;
+ MCHandle outt(ConsUtils::cons(nullptr, nullptr));
+ compileBody([&outt](MCHandle cmd) { ConsUtils::append(outt, cmd); });
- compileBody([&out](Cell *cmd) { out.emplace(cmd); });
+ if (ConsUtils::car(outt).get() == nullptr) throw std::invalid_argument("Function body empty");
- if (out.empty()) throw std::invalid_argument("Function body empty");
-
- ConsCell *fntop = _vm.makeCell(out.top());
- out.pop();
-
- while (!out.empty()) {
- _vm.push(fntop, out.top());
- out.pop();
- }
- sink(_vm.makeCell(CommandCell::CommandNum::LDF));
- sink(fntop);
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::LDF)));
+ sink(outt);
} else if (token == "AP") {
- sink(_vm.makeCell(CommandCell::CommandNum::AP));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::AP)));
} else if (token == "RET") {
- sink(_vm.makeCell(CommandCell::CommandNum::RET));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::RET)));
} else if (token == "DUM") {
- sink(_vm.makeCell(CommandCell::CommandNum::DUM));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::DUM)));
} else if (token == "RAP") {
- sink(_vm.makeCell(CommandCell::CommandNum::RAP));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::RAP)));
} else if (token == "STOP") {
- sink(_vm.makeCell(CommandCell::CommandNum::STOP));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::STOP)));
} else if (token == "ADD") {
- sink(_vm.makeCell(CommandCell::CommandNum::ADD));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::ADD)));
} else if (token == "SUB") {
- sink(_vm.makeCell(CommandCell::CommandNum::SUB));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::SUB)));
} else if (token == "READCHAR") {
- sink(_vm.makeCell(CommandCell::CommandNum::READCHAR));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::READCHAR)));
} else if (token == "PUTCHAR") {
- sink(_vm.makeCell(CommandCell::CommandNum::PUTCHAR));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::PUTCHAR)));
} else if (token == "PUTNUM") {
- sink(_vm.makeCell(CommandCell::CommandNum::PUTNUM));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::PUTNUM)));
} else if (token == "CONS") {
- sink(_vm.makeCell(CommandCell::CommandNum::CONS));
+ sink(ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::CONS)));
} else {
if (token != ")")
throw std::invalid_argument("Unknown token " + token);
@@ -127,11 +105,9 @@ std::string_view Parser::Tokenizer::peek() const {
}
void Parser::Tokenizer::load(std::string_view input) {
- for (const auto &w: input
- | std::views::split(' ')
- | std::views::transform([](auto &&rng) {
- return std::string_view(&*rng.begin(), std::ranges::distance(rng));
- })) {
+ for (const auto &w: input | std::views::split(' ') | std::views::transform([](auto &&rng) {
+ return std::string_view(&*rng.begin(), std::ranges::distance(rng));
+ })) {
_tokens.emplace(w);
}
}
@@ -139,4 +115,3 @@ void Parser::Tokenizer::load(std::string_view input) {
bool Parser::Tokenizer::empty() const {
return _tokens.empty();
}
-
diff --git a/src/vm/src/SParser.cpp b/src/vm/src/SParser.cpp
new file mode 100644
index 0000000..ca55a17
--- /dev/null
+++ b/src/vm/src/SParser.cpp
@@ -0,0 +1,5 @@
+//
+// Created by Stepan Usatiuk on 25.12.2023.
+//
+
+#include "SParser.h"
diff --git a/src/vm/src/VM.cpp b/src/vm/src/VM.cpp
index bd0f505..8e1f2c0 100644
--- a/src/vm/src/VM.cpp
+++ b/src/vm/src/VM.cpp
@@ -2,68 +2,71 @@
// Created by Stepan Usatiuk on 22.12.2023.
//
-#include "VM.h"
-
#include
#include
#include
+#include "Command.h"
+#include "ConsUtils.h"
+#include "VM.h"
+
+VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) {}
+
void VM::run() {
while (!_stop) step();
}
void VM::step() {
- CommandCell *popped = dynamic_cast(pop(_c));
- assert(popped);
+ MCHandle poppedH = ConsUtils::pop(_c);
+ ValueCell &popped = dynamic_cast(*poppedH);
- switch (popped->intToCmd()) {
- case CommandCell::CommandNum::NIL: {
- push(_s, nullptr);
+ switch (Command::int_to_cmd(popped._val)) {
+ case Command::CommandNum::NIL: {
+ ConsUtils::push(_s, nullptr);
break;
}
- case CommandCell::CommandNum::LDC: {
- push(_s, pop(_c));
+ case Command::CommandNum::LDC: {
+ ConsUtils::push(_s, ConsUtils::pop(_c));
break;
}
- case CommandCell::CommandNum::LD: {
- ConsCell *popped2 = dynamic_cast(pop(_c));
- assert(popped2);
+ case Command::CommandNum::LD: {
+ MCHandle poppedH2 = ConsUtils::pop(_c);
+ ConsCell &popped2 = dynamic_cast(*poppedH2);
- assert(dynamic_cast(popped2->_car));
- int64_t frame = dynamic_cast(popped2->_car)->_val;
- assert(dynamic_cast(popped2->_cdr));
- int64_t arg = dynamic_cast(popped2->_cdr)->_val;
+ int64_t frame = dynamic_cast(*popped2._car)._val;
+ int64_t arg = dynamic_cast(*popped2._cdr)._val;
assert(frame > 0);
assert(arg > 0);
- ConsCell *curFrame = _e;
+ ConsCell *curFrame = dynamic_cast(_e.get());
+ assert(curFrame);
for (int i = 1; i < frame; i++) {
- curFrame = dynamic_cast(_e->_cdr);
+ curFrame = dynamic_cast(curFrame->_cdr);
assert(curFrame);
}
ConsCell *curArg = dynamic_cast(curFrame->_car);
+ assert(curArg);
+
for (int i = 1; i < arg; i++) {
curArg = dynamic_cast(curArg->_cdr);
assert(curArg);
}
- push(_s, curArg->_car);
-
+ ConsUtils::push(_s, curArg->_car);
break;
}
- case CommandCell::CommandNum::SEL: {
- IntCell *popped2 = dynamic_cast(pop(_s));
- assert(popped2);
- ConsCell *ct = dynamic_cast(pop(_c));
- assert(ct);
- ConsCell *cf = dynamic_cast(pop(_c));
- assert(cf);
- ConsCell *ret = _c;
- push(_d, ret);
- if (popped2->_val > 0) {
+ case Command::CommandNum::SEL: {
+ MCHandle popped2H = ConsUtils::pop(_s);
+ ValueCell &popped2 = dynamic_cast(*popped2H);
+
+ MCHandle ct = ConsUtils::pop(_c);
+ MCHandle cf = ConsUtils::pop(_c);
+
+ ConsUtils::push(_d, _c);
+ if (popped2._val > 0) {
_c = ct;
} else {
_c = cf;
@@ -71,119 +74,103 @@ void VM::step() {
break;
}
- case CommandCell::CommandNum::JOIN: {
- ConsCell *ret = dynamic_cast(pop(_d));
- assert(ret);
- _c = ret;
+ case Command::CommandNum::JOIN: {
+ _c = ConsUtils::pop(_d);
break;
}
- case CommandCell::CommandNum::LDF: {
- ConsCell *fn = dynamic_cast(pop(_c));
- assert(fn);
- push(_s, makeCell(fn, _e));
+ case Command::CommandNum::LDF: {
+ ConsUtils::push(_s, ConsUtils::cons(ConsUtils::pop(_c), _e));
break;
}
- case CommandCell::CommandNum::AP: {
- ConsCell *closure = dynamic_cast(pop(_s));
- assert(closure);
- ConsCell *args = dynamic_cast(pop(_s));
- assert(args);
+ case Command::CommandNum::AP: {
+ MCHandle closureH = ConsUtils::pop(_s);
+ MCHandle argsH = ConsUtils::pop(_s);
- push(_d, _s);
- push(_d, _e);
- assert(_c);
- push(_d, _c);
+ ConsUtils::push(_d, _s);
+ ConsUtils::push(_d, _e);
+ ConsUtils::push(_d, _c);
- _s = makeCell();
- _c = dynamic_cast(closure->_car);
- assert(_c);
- _e = dynamic_cast(closure->_cdr);
- push(_e, args);
+ _s = ConsUtils::cons(nullptr, nullptr);
+ _c = ConsUtils::car(closureH);
+ _e = ConsUtils::cdr(closureH);
+ ConsUtils::push(_e, argsH);
break;
}
- case CommandCell::CommandNum::RET: {
- ConsCell *c = dynamic_cast(pop(_d));
- assert(c);
- ConsCell *e = dynamic_cast(pop(_d));
- ConsCell *s = dynamic_cast(pop(_d));
+ case Command::CommandNum::RET: {
+ MCHandle c = ConsUtils::pop(_d);
+ MCHandle e = ConsUtils::pop(_d);
+ MCHandle s = ConsUtils::pop(_d);
- Cell *ret = pop(_s);
+ MCHandle ret = ConsUtils::pop(_s);
_c = c;
_e = e;
_s = s;
- push(_s, ret);
- gc();
+ ConsUtils::push(_s, ret);
+ // gc();
break;
}
- case CommandCell::CommandNum::DUM: {
- push(_e, nullptr);
+ case Command::CommandNum::DUM: {
+ ConsUtils::push(_e, nullptr);
break;
}
- case CommandCell::CommandNum::RAP: {
- ConsCell *closure = dynamic_cast(pop(_s));
- assert(closure);
- ConsCell *args = dynamic_cast(pop(_s));
- assert(args);
+ case Command::CommandNum::RAP: {
+ MCHandle closureH = ConsUtils::pop(_s);
+ MCHandle argsH = ConsUtils::pop(_s);
- push(_d, _s);
- ConsCell *e = dynamic_cast(_e->_cdr);
- push(_d, e);
- assert(_c);
- push(_d, _c);
- _s = makeCell();
- _c = dynamic_cast(closure->_car);
- assert(_c);
- ConsCell *fnenv = dynamic_cast(closure->_cdr);
- assert(fnenv);
- assert(_e == fnenv);
- fnenv->_car = args;
+ MCHandle origE = ConsUtils::cdr(_e);
+
+ ConsUtils::push(_d, _s);
+ ConsUtils::push(_d, origE);
+ ConsUtils::push(_d, _c);
+
+ _s = ConsUtils::cons(nullptr, nullptr);
+ _c = ConsUtils::car(closureH);
+ _e = ConsUtils::cdr(closureH);
+
+ MCHandle fnEnv = ConsUtils::cdr(closureH);
+ assert(_e.get() == fnEnv.get());
+ ConsUtils::push(_e, argsH);
+ dynamic_cast(*fnEnv)._car = argsH.get();
break;
}
- case CommandCell::CommandNum::STOP: {
+ case Command::CommandNum::STOP: {
_stop = true;
- gc();
+ // gc();
break;
}
- case CommandCell::CommandNum::ADD: {
- IntCell *a1 = dynamic_cast(pop(_s));
- assert(a1);
- IntCell *a2 = dynamic_cast(pop(_s));
- assert(a2);
- push(_s, makeCell(a1->_val + a2->_val));
+ case Command::CommandNum::ADD: {
+ int64_t ret = dynamic_cast(*ConsUtils::pop(_s))._val + dynamic_cast(*ConsUtils::pop(_s))._val;
+ ConsUtils::push(_s, CURRENT_MC.load()->create_cell(ret));
break;
}
- case CommandCell::CommandNum::SUB: {
+ case Command::CommandNum::SUB: {
break;
}
- case CommandCell::CommandNum::CONS: {
- Cell *a1 = pop(_s);
- Cell *a2 = pop(_s);
+ case Command::CommandNum::CONS: {
+ MCHandle h1 = ConsUtils::pop(_s);
+ MCHandle h2 = ConsUtils::pop(_s);
- push(_s, cons(a1, a2));
+ ConsUtils::push(_s, ConsUtils::cons(h1, h2));
break;
}
- case CommandCell::CommandNum::READCHAR: {
+ case Command::CommandNum::READCHAR: {
char c;
_instream >> c;
- push(_s, makeCell(c));
+ ConsUtils::push(_s, CURRENT_MC.load()->create_cell(c));
break;
}
- case CommandCell::CommandNum::PUTCHAR: {
- IntCell *popped2 = dynamic_cast(pop(_s));
- assert(popped2);
- _outstream << (char) popped2->_val;
+ case Command::CommandNum::PUTCHAR: {
+ _outstream << (char) dynamic_cast(*ConsUtils::pop(_s))._val;
break;
}
- case CommandCell::CommandNum::PUTNUM: {
- IntCell *popped2 = dynamic_cast(pop(_s));
- assert(popped2);
- _outstream << popped2->_val;
+ case Command::CommandNum::PUTNUM: {
+ _outstream << dynamic_cast(*ConsUtils::pop(_s))._val;
break;
}
- case CommandCell::CommandNum::END: {
+ case Command::CommandNum::END: {
assert(false);
break;
}
@@ -192,44 +179,40 @@ void VM::step() {
}
}
-VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) {}
-
-void VM::gc() {
- std::function visit = [&](ConsCell *c) {
- if (c == nullptr) return;
- if (c->live) return;
-
- c->live = true;
-
- if (c->_car) {
- if (c->_car->_type == CellType::CONS) visit(dynamic_cast(c->_car));
- c->_car->live = true;
- }
- if (c->_cdr) {
- if (c->_cdr->_type == CellType::CONS) visit(dynamic_cast(c->_cdr));
- c->_cdr->live = true;
- }
- };
- visit(_s);
- visit(_e);
- visit(_c);
- visit(_d);
-
- uint64_t freed = 0;
-
- _cells.remove_if([&](Cell *l) {
- bool ret = !l->live;
- if (ret) {
- freed += 1;
- delete l;
- } else {
- l->live = false;
- }
- return ret;
- });
-
- std::cout << "GC Freed " << freed << std::endl;
-}
-uint64_t VM::cellCount() const {
- return _cells.size();
-}
+//void VM::gc() {
+// std::function visit = [&](ConsCell *c) {
+// if (c == nullptr) return;
+// if (c->live) return;
+//
+// c->live = true;
+//
+// if (c->_car) {
+// if (c->_car->_type == CellType::CONS) visit(dynamic_cast(c->_car));
+// c->_car->live = true;
+// }
+// if (c->_cdr) {
+// if (c->_cdr->_type == CellType::CONS) visit(dynamic_cast(c->_cdr));
+// c->_cdr->live = true;
+// }
+// };
+// visit(_s);
+// visit(_e);
+// visit(_c);
+// visit(_d);
+//
+// uint64_t freed = 0;
+//
+// _cells.remove_if([&](Cell *l) {
+// bool ret = !l->live;
+// if (ret) {
+// freed += 1;
+// delete l;
+// } else {
+// l->live = false;
+// }
+// return ret;
+// });
+//
+// std::cout << "GC Freed " << freed << std::endl;
+//}
+//
\ No newline at end of file
diff --git a/test/vm/VMTest.cpp b/test/vm/VMTest.cpp
index 0ac756c..8c657d9 100644
--- a/test/vm/VMTest.cpp
+++ b/test/vm/VMTest.cpp
@@ -1,239 +1,244 @@
#include
+#include "Command.h"
+#include "ConsUtils.h"
#include "VM.h"
TEST(VMTest, BasicHello) {
std::stringstream ssin;
std::stringstream ssout;
{
+ MemoryContext mc;
VM vm(ssin, ssout);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::PUTCHAR));
- vm.appendCommand(vm.makeCell('h'));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::NIL));
+ MCHandle newc(ConsUtils::cons(nullptr, nullptr));
+ ConsUtils::append(newc, ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::NIL)));
+ ConsUtils::append(newc, ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::LDC)));
+ ConsUtils::append(newc, ConsUtils::makeIntCell('h'));
+ ConsUtils::append(newc, ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::PUTCHAR)));
+ ConsUtils::append(newc, ConsUtils::makeIntCell(Command::cmd_to_int(Command::CommandNum::STOP)));
+ vm.loadControl(newc);
vm.run();
}
ssout.flush();
EXPECT_EQ(ssout.str(), "h");
}
-TEST(VMTest, SelTest) {
- std::stringstream ssin;
- std::stringstream ssout;
- {
- VM vm(ssin, ssout);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP));
-
- // True branch true test
- ConsCell *tbtt = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(tbtt, vm.makeCell(CommandCell::CommandNum::PUTCHAR));
- vm.push(tbtt, vm.makeCell('1'));
- vm.push(tbtt, vm.makeCell(CommandCell::CommandNum::LDC));
-
- // False branch true test
- ConsCell *fbtt = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(fbtt, vm.makeCell(CommandCell::CommandNum::PUTCHAR));
- vm.push(fbtt, vm.makeCell('2'));
- vm.push(fbtt, vm.makeCell(CommandCell::CommandNum::LDC));
-
- // True branch false test
- ConsCell *tbft = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(tbft, vm.makeCell(CommandCell::CommandNum::PUTCHAR));
- vm.push(tbft, vm.makeCell('3'));
- vm.push(tbft, vm.makeCell(CommandCell::CommandNum::LDC));
-
- // False branch false test
- ConsCell *fbft = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(fbft, vm.makeCell(CommandCell::CommandNum::PUTCHAR));
- vm.push(fbft, vm.makeCell('4'));
- vm.push(fbft, vm.makeCell(CommandCell::CommandNum::LDC));
-
- vm.appendCommand(fbft);
- vm.appendCommand(tbft);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::SEL));
- vm.appendCommand(vm.makeCell(0));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC));
- vm.appendCommand(fbtt);
- vm.appendCommand(tbtt);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::SEL));
- vm.appendCommand(vm.makeCell(1));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC));
- vm.run();
- }
- ssout.flush();
- EXPECT_EQ(ssout.str(), "14");
-}
-
-TEST(VMTest, SimpleFunction) {
- std::stringstream ssin;
- std::stringstream ssout;
- {
- VM vm(ssin, ssout);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::PUTCHAR));
-
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::AP));
-
- // Add function
- ConsCell *addfn = vm.makeCell(vm.makeCell(CommandCell::CommandNum::RET));
- vm.push(addfn, vm.makeCell(CommandCell::CommandNum::ADD));
- vm.push(addfn, vm.makeCell(vm.makeCell(1), vm.makeCell(2)));
- vm.push(addfn, vm.makeCell(CommandCell::CommandNum::LD));
- vm.push(addfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1)));
- vm.push(addfn, vm.makeCell(CommandCell::CommandNum::LD));
- vm.appendCommand(addfn);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDF));
- vm.appendCommand(
- vm.makeCell(vm.makeCell(1), vm.makeCell(vm.makeCell('2'))));
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC));
- vm.run();
- }
- ssout.flush();
- EXPECT_EQ(ssout.str(), "3");
-}
-
-TEST(VMTest, RecursiveFunction) {
- std::stringstream ssin;
- std::stringstream ssout;
- {
- VM vm(ssin, ssout);
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP));
-
- vm.appendCommand(vm.makeCell(CommandCell::CommandNum::RAP));
-
- // Fib function
- ConsCell *fibfn = vm.makeCell(vm.makeCell(CommandCell::CommandNum::RET));
-
- // 0 case
- ConsCell *zcase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(zcase, vm.makeCell(0));
- vm.push(zcase, vm.makeCell(CommandCell::CommandNum::LDC));
-
- // 1 case
- ConsCell *ocase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(ocase, vm.makeCell(1));
- vm.push(ocase, vm.makeCell(CommandCell::CommandNum::LDC));
-
- // >1 case
- ConsCell *gocase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::ADD));
-
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::AP));
- vm.push(gocase, vm.makeCell(vm.makeCell(2), vm.makeCell(1)));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD));
-
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::CONS));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::ADD));
- vm.push(gocase, vm.makeCell(-2));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LDC));
- vm.push(gocase, vm.makeCell(vm.makeCell(1), vm.makeCell(1)));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::NIL));
-
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::AP));
- vm.push(gocase, vm.makeCell(vm.makeCell(2), vm.makeCell(1)));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD));
-
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::CONS));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::ADD));
- vm.push(gocase, vm.makeCell(-1));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LDC));
- vm.push(gocase, vm.makeCell(vm.makeCell(1), vm.makeCell(1)));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD));
- vm.push(gocase, vm.makeCell(CommandCell::CommandNum::NIL));
-
- // >=1 case
- ConsCell *geocase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN));
- vm.push(geocase, ocase);
- vm.push(geocase, gocase);
- vm.push(geocase, vm.makeCell(CommandCell::CommandNum::SEL));
- vm.push(geocase, vm.makeCell(CommandCell::CommandNum::ADD));
- vm.push(geocase, vm.makeCell(-1));
- vm.push(geocase, vm.makeCell(CommandCell::CommandNum::LDC));
- vm.push(geocase, vm.makeCell(vm.makeCell(1), vm.makeCell(1)));
- vm.push(geocase, vm.makeCell(CommandCell::CommandNum::LD));
-
- vm.push(fibfn, zcase);
- vm.push(fibfn, geocase);
- vm.push(fibfn, vm.makeCell(CommandCell::CommandNum::SEL));
- vm.push(fibfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1)));
- vm.push(fibfn, vm.makeCell(CommandCell::CommandNum::LD));
-
- // Fib caller function
- ConsCell *fibcallfn = vm.makeCell(vm.makeCell(CommandCell::CommandNum::RET));
- vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTNUM));
- vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTCHAR));
- vm.push(fibcallfn, vm.makeCell(' '));
- vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC));
- vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::AP));
- vm.push(fibcallfn, vm.makeCell(vm.makeCell(1), vm.makeCell | | | | | |