mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 18:57:48 +01:00
move stuff to Handle
This commit is contained in:
@@ -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/MemoryContext.cpp src/ConsUtils.cpp)
|
||||
src/Parser.cpp src/MemoryContext.cpp src/Handle.cpp)
|
||||
|
||||
target_include_directories(vm PUBLIC includes)
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// 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<ConsCell &>(*cell)._car.load(); }
|
||||
static inline MCHandle cdr(const MCHandle &cell) { return dynamic_cast<ConsCell &>(*cell)._cdr.load(); }
|
||||
static inline CellValType val(const MCHandle &cell) { return dynamic_cast<NumAtomCell &>(*cell)._val; }
|
||||
static inline std::string_view strval(const MCHandle &cell) { return dynamic_cast<StrAtomCell &>(*cell)._val; }
|
||||
MCHandle cons(const MCHandle &car, const MCHandle &cdr);
|
||||
MCHandle pop(MCHandle &from);
|
||||
void push(MCHandle &to, const MCHandle &what);
|
||||
void append(MCHandle to, const MCHandle &what);
|
||||
MCHandle makeNumCell(int64_t val);
|
||||
MCHandle makeStrCell(std::string val);
|
||||
void setcar(const MCHandle &to, const MCHandle &car);
|
||||
void setcdr(const MCHandle &to, const MCHandle &cdr);
|
||||
};// namespace ConsUtils
|
||||
|
||||
|
||||
#endif//PSIL_CONSUTILS_H
|
||||
49
src/vm/includes/Handle.h
Normal file
49
src/vm/includes/Handle.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 26.12.2023.
|
||||
//
|
||||
|
||||
#ifndef PSIL_HANDLE_H
|
||||
#define PSIL_HANDLE_H
|
||||
|
||||
#include "Cell.h"
|
||||
|
||||
class MemoryContext;
|
||||
|
||||
class Handle {
|
||||
public:
|
||||
friend MemoryContext;
|
||||
|
||||
Handle(Cell *target);
|
||||
~Handle();
|
||||
|
||||
Handle(Handle const &other);
|
||||
Handle &operator=(Handle other);
|
||||
|
||||
bool operator==(const Handle &rhs) const {
|
||||
return _target == rhs._target;
|
||||
}
|
||||
|
||||
Handle car() { return dynamic_cast<ConsCell &>(*_target)._car.load(); }
|
||||
Handle cdr() { return dynamic_cast<ConsCell &>(*_target)._cdr.load(); }
|
||||
CellValType val() { return dynamic_cast<NumAtomCell &>(*_target)._val; }
|
||||
std::string_view strval() { return dynamic_cast<StrAtomCell &>(*_target)._val; }
|
||||
|
||||
|
||||
static Handle cons(const Handle &car, const Handle &cdr);
|
||||
static Handle pop(Handle &from);
|
||||
static void push(Handle &to, const Handle &what);
|
||||
static void append(Handle to, const Handle &what);
|
||||
static Handle makeNumCell(int64_t val);
|
||||
static Handle makeStrCell(std::string val);
|
||||
void setcar(const Handle &car);
|
||||
void setcdr(const Handle &cdr);
|
||||
|
||||
private:
|
||||
Cell *operator->() const { return _target; }
|
||||
Cell &operator*() const { return *_target; }
|
||||
Cell *get() const noexcept { return _target; }
|
||||
|
||||
Cell *_target = nullptr;
|
||||
};
|
||||
|
||||
#endif//PSIL_HANDLE_H
|
||||
@@ -16,10 +16,13 @@
|
||||
#include <thread>
|
||||
|
||||
#include "Cell.h"
|
||||
#include "Handle.h"
|
||||
|
||||
class Handle;
|
||||
|
||||
class MemoryContext {
|
||||
public:
|
||||
class Handle;
|
||||
friend Handle;
|
||||
|
||||
MemoryContext();
|
||||
~MemoryContext();
|
||||
@@ -73,25 +76,6 @@ public:
|
||||
return newc;
|
||||
}
|
||||
|
||||
class Handle {
|
||||
public:
|
||||
Handle(Cell *target);
|
||||
~Handle();
|
||||
|
||||
Handle(Handle const &other);
|
||||
Handle &operator=(Handle other);
|
||||
|
||||
Cell *operator->() const { return _target; }
|
||||
Cell &operator*() const { return *_target; }
|
||||
Cell *get() const noexcept { return _target; }
|
||||
|
||||
bool operator==(const Handle &rhs) const {
|
||||
return _target == rhs._target;
|
||||
}
|
||||
|
||||
private:
|
||||
Cell *_target = nullptr;
|
||||
};
|
||||
|
||||
void request_gc_and_wait() {
|
||||
std::unique_lock l(_gc_done_m);
|
||||
@@ -193,8 +177,6 @@ private:
|
||||
std::atomic<bool> _gc_thread_stop = false;
|
||||
};
|
||||
|
||||
using MCHandle = MemoryContext::Handle;
|
||||
|
||||
extern std::atomic<MemoryContext *> CURRENT_MC;
|
||||
|
||||
#endif//PSIL_MEMORYCONTEXT_H
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Cell;
|
||||
class Parser {
|
||||
public:
|
||||
void loadStr(std::string_view input);
|
||||
MCHandle parseExpr();
|
||||
Handle parseExpr();
|
||||
|
||||
private:
|
||||
class Tokenizer {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Cell.h"
|
||||
#include "ConsUtils.h"
|
||||
#include "MemoryContext.h"
|
||||
|
||||
class VM {
|
||||
@@ -20,40 +19,40 @@ public:
|
||||
|
||||
void run();
|
||||
|
||||
void loadControl(const MCHandle &h) { _c = h; }
|
||||
void loadControl(const Handle &h) { _c = h; }
|
||||
|
||||
void step();
|
||||
|
||||
private:
|
||||
MCHandle _s = ConsUtils::cons(nullptr, nullptr);
|
||||
MCHandle _e = ConsUtils::cons(nullptr, nullptr);
|
||||
MCHandle _c = ConsUtils::cons(nullptr, nullptr);
|
||||
MCHandle _d = ConsUtils::cons(nullptr, nullptr);
|
||||
Handle _s = Handle::cons(nullptr, nullptr);
|
||||
Handle _e = Handle::cons(nullptr, nullptr);
|
||||
Handle _c = Handle::cons(nullptr, nullptr);
|
||||
Handle _d = Handle::cons(nullptr, nullptr);
|
||||
bool _stop = false;
|
||||
|
||||
std::istream &_instream;
|
||||
std::ostream &_outstream;
|
||||
|
||||
MCHandle NIL = ConsUtils::makeStrCell("NIL");
|
||||
MCHandle LDC = ConsUtils::makeStrCell("LDC");
|
||||
MCHandle LD = ConsUtils::makeStrCell("LD");
|
||||
MCHandle SEL = ConsUtils::makeStrCell("SEL");
|
||||
MCHandle JOIN = ConsUtils::makeStrCell("JOIN");
|
||||
MCHandle LDF = ConsUtils::makeStrCell("LDF");
|
||||
MCHandle AP = ConsUtils::makeStrCell("AP");
|
||||
MCHandle RET = ConsUtils::makeStrCell("RET");
|
||||
MCHandle DUM = ConsUtils::makeStrCell("DUM");
|
||||
MCHandle RAP = ConsUtils::makeStrCell("RAP");
|
||||
MCHandle STOP = ConsUtils::makeStrCell("STOP");
|
||||
Handle NIL = Handle::makeStrCell("NIL");
|
||||
Handle LDC = Handle::makeStrCell("LDC");
|
||||
Handle LD = Handle::makeStrCell("LD");
|
||||
Handle SEL = Handle::makeStrCell("SEL");
|
||||
Handle JOIN = Handle::makeStrCell("JOIN");
|
||||
Handle LDF = Handle::makeStrCell("LDF");
|
||||
Handle AP = Handle::makeStrCell("AP");
|
||||
Handle RET = Handle::makeStrCell("RET");
|
||||
Handle DUM = Handle::makeStrCell("DUM");
|
||||
Handle RAP = Handle::makeStrCell("RAP");
|
||||
Handle STOP = Handle::makeStrCell("STOP");
|
||||
|
||||
MCHandle ADD = ConsUtils::makeStrCell("ADD");
|
||||
MCHandle SUB = ConsUtils::makeStrCell("SUB");
|
||||
Handle ADD = Handle::makeStrCell("ADD");
|
||||
Handle SUB = Handle::makeStrCell("SUB");
|
||||
|
||||
MCHandle READCHAR = ConsUtils::makeStrCell("READCHAR");
|
||||
MCHandle PUTCHAR = ConsUtils::makeStrCell("PUTCHAR");
|
||||
MCHandle PUTNUM = ConsUtils::makeStrCell("PUTNUM");
|
||||
Handle READCHAR = Handle::makeStrCell("READCHAR");
|
||||
Handle PUTCHAR = Handle::makeStrCell("PUTCHAR");
|
||||
Handle PUTNUM = Handle::makeStrCell("PUTNUM");
|
||||
|
||||
MCHandle CONS = ConsUtils::makeStrCell("CONS");
|
||||
Handle CONS = Handle::makeStrCell("CONS");
|
||||
};
|
||||
|
||||
#endif//PSIL_VM_H
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// 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<ConsCell>(car.get(), cdr.get());
|
||||
return ret;
|
||||
}
|
||||
|
||||
MCHandle ConsUtils::pop(MCHandle &from) {
|
||||
auto ret = car(from);
|
||||
from = cdr(from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ConsUtils::push(MCHandle &to, const MCHandle &what) {
|
||||
to = cons(what, to);
|
||||
}
|
||||
|
||||
void ConsUtils::append(MCHandle to, const MCHandle &what) {
|
||||
assert(to.get() != nullptr);
|
||||
if (car(to).get() == nullptr) {
|
||||
setcar(to, what);
|
||||
return;
|
||||
}
|
||||
while (cdr(to).get() != nullptr) to = cdr(to);
|
||||
setcdr(to, cons(what, nullptr));
|
||||
}
|
||||
|
||||
MCHandle ConsUtils::makeNumCell(int64_t val) {
|
||||
return CURRENT_MC.load()->create_cell<NumAtomCell>(val);
|
||||
}
|
||||
|
||||
MCHandle ConsUtils::makeStrCell(std::string val) {
|
||||
return CURRENT_MC.load()->create_cell<StrAtomCell>(std::move(val));
|
||||
}
|
||||
|
||||
void ConsUtils::setcar(const MCHandle &to, const MCHandle &car) {
|
||||
CURRENT_MC.load()->run_dirty<void>([&](std::function<void(Cell *)> dirty) -> void {
|
||||
dirty(car.get());
|
||||
dynamic_cast<ConsCell &>(*to)._car = car.get();
|
||||
});
|
||||
}
|
||||
|
||||
void ConsUtils::setcdr(const MCHandle &to, const MCHandle &cdr) {
|
||||
CURRENT_MC.load()->run_dirty<void>([&](std::function<void(Cell *)> dirty) -> void {
|
||||
dirty(cdr.get());
|
||||
dynamic_cast<ConsCell &>(*to)._cdr = cdr.get();
|
||||
});
|
||||
}
|
||||
74
src/vm/src/Handle.cpp
Normal file
74
src/vm/src/Handle.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 26.12.2023.
|
||||
//
|
||||
|
||||
#include "Handle.h"
|
||||
|
||||
#include "MemoryContext.h"
|
||||
|
||||
Handle::Handle(Cell *target) : _target(target) {
|
||||
if (target != nullptr)
|
||||
CURRENT_MC.load()->add_root(target);
|
||||
}
|
||||
|
||||
Handle::~Handle() {
|
||||
if (_target != nullptr)
|
||||
CURRENT_MC.load()->remove_root(_target);
|
||||
}
|
||||
|
||||
Handle::Handle(Handle const &other) : _target(other._target) {
|
||||
if (_target != nullptr)
|
||||
CURRENT_MC.load()->add_root(_target);
|
||||
}
|
||||
|
||||
Handle &Handle::operator=(Handle other) {
|
||||
std::swap(_target, other._target);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Handle Handle::cons(const Handle &car, const Handle &cdr) {
|
||||
auto ret = CURRENT_MC.load()->create_cell<ConsCell>(car.get(), cdr.get());
|
||||
return ret;
|
||||
}
|
||||
|
||||
Handle Handle::pop(Handle &from) {
|
||||
auto ret = from.car();
|
||||
from = from.cdr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Handle::push(Handle &to, const Handle &what) {
|
||||
to = cons(what, to);
|
||||
}
|
||||
|
||||
void Handle::append(Handle to, const Handle &what) {
|
||||
assert(to.get() != nullptr);
|
||||
if (to.car().get() == nullptr) {
|
||||
to.setcar(what);
|
||||
return;
|
||||
}
|
||||
while (to.cdr().get() != nullptr) to = to.cdr();
|
||||
to.setcdr(cons(what, nullptr));
|
||||
}
|
||||
|
||||
Handle Handle::makeNumCell(int64_t val) {
|
||||
return CURRENT_MC.load()->create_cell<NumAtomCell>(val);
|
||||
}
|
||||
|
||||
Handle Handle::makeStrCell(std::string val) {
|
||||
return CURRENT_MC.load()->create_cell<StrAtomCell>(std::move(val));
|
||||
}
|
||||
|
||||
void Handle::setcar(const Handle &car) {
|
||||
CURRENT_MC.load()->run_dirty<void>([&](std::function<void(Cell *)> dirty) -> void {
|
||||
dirty(dynamic_cast<ConsCell &>(*_target)._car);
|
||||
dynamic_cast<ConsCell &>(*_target)._car = car.get();
|
||||
});
|
||||
}
|
||||
|
||||
void Handle::setcdr(const Handle &cdr) {
|
||||
CURRENT_MC.load()->run_dirty<void>([&](std::function<void(Cell *)> dirty) -> void {
|
||||
dirty(dynamic_cast<ConsCell &>(*_target)._cdr);
|
||||
dynamic_cast<ConsCell &>(*_target)._cdr = cdr.get();
|
||||
});
|
||||
}
|
||||
@@ -29,25 +29,6 @@ MemoryContext::~MemoryContext() {
|
||||
_gc_thread.join();
|
||||
}
|
||||
|
||||
MemoryContext::Handle::Handle(Cell *target) : _target(target) {
|
||||
if (target != nullptr)
|
||||
CURRENT_MC.load()->add_root(target);
|
||||
}
|
||||
|
||||
MemoryContext::Handle::~Handle() {
|
||||
if (_target != nullptr)
|
||||
CURRENT_MC.load()->remove_root(_target);
|
||||
}
|
||||
|
||||
MemoryContext::Handle::Handle(MemoryContext::Handle const &other) : _target(other._target) {
|
||||
if (_target != nullptr)
|
||||
CURRENT_MC.load()->add_root(_target);
|
||||
}
|
||||
|
||||
MemoryContext::Handle &MemoryContext::Handle::operator=(MemoryContext::Handle other) {
|
||||
std::swap(_target, other._target);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MemoryContext::add_root(Cell *c) {
|
||||
{
|
||||
@@ -118,7 +99,6 @@ void MemoryContext::gc_thread_entry() {
|
||||
}
|
||||
_cells.insert(temp_cells.begin(), temp_cells.end());
|
||||
}
|
||||
_cells_num = _cells.size();
|
||||
|
||||
|
||||
for (auto const &r: new_roots) {
|
||||
@@ -205,6 +185,7 @@ void MemoryContext::gc_thread_entry() {
|
||||
|
||||
stop = std::chrono::high_resolution_clock::now();
|
||||
std::cerr << "Sweep time: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << "\n";
|
||||
_cells_num = _cells.size();
|
||||
std::cerr << "GC Freed " << freed << " cells left: " << _cells_num << " \n";
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <ranges>
|
||||
#include <stack>
|
||||
|
||||
#include "ConsUtils.h"
|
||||
#include "MemoryContext.h"
|
||||
#include "VM.h"
|
||||
|
||||
@@ -17,24 +16,23 @@ void Parser::loadStr(std::string_view input) {
|
||||
_tokenizer.load(input);
|
||||
}
|
||||
|
||||
MCHandle Parser::parseExpr() {
|
||||
Handle Parser::parseExpr() {
|
||||
while (!_tokenizer.empty()) {
|
||||
std::string token = std::string(_tokenizer.peek());
|
||||
if (token == "(") {
|
||||
_tokenizer.getNext();
|
||||
MCHandle out(ConsUtils::cons(nullptr, nullptr));
|
||||
Handle out(Handle::cons(nullptr, nullptr));
|
||||
while (token != ")") {
|
||||
if (token == ".") {
|
||||
_tokenizer.getNext();
|
||||
|
||||
ConsUtils::setcdr(out, parseExpr());
|
||||
out.setcdr(parseExpr());
|
||||
|
||||
if (_tokenizer.getNext() != ")")
|
||||
throw std::invalid_argument("Missing ) after pair");
|
||||
if (_tokenizer.getNext() != ")") throw std::invalid_argument("Missing ) after pair");
|
||||
|
||||
return out;
|
||||
}
|
||||
ConsUtils::append(out, parseExpr());
|
||||
Handle::append(out, parseExpr());
|
||||
token = _tokenizer.peek();
|
||||
}
|
||||
_tokenizer.getNext();
|
||||
@@ -43,9 +41,9 @@ MCHandle Parser::parseExpr() {
|
||||
token = _tokenizer.getNext();
|
||||
try {
|
||||
CellValType val = std::stoi(token);
|
||||
return ConsUtils::makeNumCell(val);
|
||||
return Handle::makeNumCell(val);
|
||||
} catch (...) {
|
||||
return ConsUtils::makeStrCell(token);
|
||||
return Handle::makeStrCell(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include "ConsUtils.h"
|
||||
#include "VM.h"
|
||||
|
||||
using namespace ConsUtils;
|
||||
|
||||
VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) {}
|
||||
|
||||
@@ -18,118 +16,118 @@ void VM::run() {
|
||||
}
|
||||
|
||||
void VM::step() {
|
||||
MCHandle poppedH = pop(_c);
|
||||
Handle poppedH = Handle::pop(_c);
|
||||
if (poppedH == NIL) {
|
||||
push(_s, nullptr);
|
||||
Handle::push(_s, nullptr);
|
||||
} else if (poppedH == LDC) {
|
||||
push(_s, pop(_c));
|
||||
Handle::push(_s, Handle::pop(_c));
|
||||
} else if (poppedH == LD) {
|
||||
MCHandle poppedH2 = pop(_c);
|
||||
Handle poppedH2 = Handle::pop(_c);
|
||||
|
||||
int64_t frame = val(car(poppedH2));
|
||||
int64_t arg = val(cdr(poppedH2));
|
||||
int64_t frame = poppedH2.car().val();
|
||||
int64_t arg = poppedH2.cdr().val();
|
||||
|
||||
assert(frame > 0);
|
||||
assert(arg > 0);
|
||||
|
||||
MCHandle curFrame = _e;
|
||||
Handle curFrame = _e;
|
||||
|
||||
for (int i = 1; i < frame; i++) {
|
||||
curFrame = cdr(curFrame);
|
||||
curFrame = curFrame.cdr();
|
||||
}
|
||||
|
||||
MCHandle curArg = car(curFrame);
|
||||
Handle curArg = curFrame.car();
|
||||
|
||||
for (int i = 1; i < arg; i++) {
|
||||
curArg = cdr(curArg);
|
||||
curArg = curArg.cdr();
|
||||
}
|
||||
|
||||
push(_s, car(curArg));
|
||||
Handle::push(_s, curArg.car());
|
||||
} else if (poppedH == SEL) {
|
||||
|
||||
MCHandle popped2H = pop(_s);
|
||||
Handle popped2H = Handle::pop(_s);
|
||||
|
||||
MCHandle ct = pop(_c);
|
||||
MCHandle cf = pop(_c);
|
||||
Handle ct = Handle::pop(_c);
|
||||
Handle cf = Handle::pop(_c);
|
||||
|
||||
push(_d, _c);
|
||||
if (val(popped2H) > 0) {
|
||||
Handle::push(_d, _c);
|
||||
if (popped2H.val() > 0) {
|
||||
_c = ct;
|
||||
} else {
|
||||
_c = cf;
|
||||
}
|
||||
} else if (poppedH == JOIN) {
|
||||
_c = pop(_d);
|
||||
_c = Handle::pop(_d);
|
||||
} else if (poppedH == LDF) {
|
||||
push(_s, cons(pop(_c), _e));
|
||||
Handle::push(_s, Handle::cons(Handle::pop(_c), _e));
|
||||
} else if (poppedH == AP) {
|
||||
MCHandle closureH = pop(_s);
|
||||
MCHandle argsH = pop(_s);
|
||||
Handle closureH = Handle::pop(_s);
|
||||
Handle argsH = Handle::pop(_s);
|
||||
|
||||
push(_d, _s);
|
||||
push(_d, _e);
|
||||
push(_d, _c);
|
||||
Handle::push(_d, _s);
|
||||
Handle::push(_d, _e);
|
||||
Handle::push(_d, _c);
|
||||
|
||||
_s = cons(nullptr, nullptr);
|
||||
_c = car(closureH);
|
||||
_e = cdr(closureH);
|
||||
push(_e, argsH);
|
||||
_s = Handle::cons(nullptr, nullptr);
|
||||
_c = closureH.car();
|
||||
_e = closureH.cdr();
|
||||
Handle::push(_e, argsH);
|
||||
} else if (poppedH == RET) {
|
||||
MCHandle c = pop(_d);
|
||||
MCHandle e = pop(_d);
|
||||
MCHandle s = pop(_d);
|
||||
Handle c = Handle::pop(_d);
|
||||
Handle e = Handle::pop(_d);
|
||||
Handle s = Handle::pop(_d);
|
||||
|
||||
MCHandle ret = pop(_s);
|
||||
Handle ret = Handle::pop(_s);
|
||||
|
||||
_c = c;
|
||||
_e = e;
|
||||
_s = s;
|
||||
|
||||
push(_s, ret);
|
||||
Handle::push(_s, ret);
|
||||
} else if (poppedH == DUM) {
|
||||
push(_e, nullptr);
|
||||
Handle::push(_e, nullptr);
|
||||
} else if (poppedH == RAP) {
|
||||
MCHandle closureH = pop(_s);
|
||||
MCHandle argsH = pop(_s);
|
||||
Handle closureH = Handle::pop(_s);
|
||||
Handle argsH = Handle::pop(_s);
|
||||
|
||||
|
||||
MCHandle origE = cdr(_e);
|
||||
Handle origE = _e.cdr();
|
||||
|
||||
push(_d, _s);
|
||||
push(_d, origE);
|
||||
push(_d, _c);
|
||||
Handle::push(_d, _s);
|
||||
Handle::push(_d, origE);
|
||||
Handle::push(_d, _c);
|
||||
|
||||
_s = cons(nullptr, nullptr);
|
||||
_c = car(closureH);
|
||||
_e = cdr(closureH);
|
||||
_s = Handle::cons(nullptr, nullptr);
|
||||
_c = closureH.car();
|
||||
_e = closureH.cdr();
|
||||
|
||||
MCHandle fnEnv = cdr(closureH);
|
||||
assert(_e.get() == fnEnv.get());
|
||||
Handle fnEnv = closureH.cdr();
|
||||
// assert(_e.get() == fnEnv.get());
|
||||
|
||||
push(_e, argsH);
|
||||
setcar(fnEnv, argsH);
|
||||
Handle::push(_e, argsH);
|
||||
fnEnv.setcar(argsH);
|
||||
} else if (poppedH == STOP) {
|
||||
_stop = true;
|
||||
} else if (poppedH == ADD) {
|
||||
int64_t ret = val(pop(_s)) + val(pop(_s));
|
||||
push(_s, makeNumCell(ret));
|
||||
int64_t ret = Handle::pop(_s).val() + Handle::pop(_s).val();
|
||||
Handle::push(_s, Handle::makeNumCell(ret));
|
||||
} else if (poppedH == SUB) {
|
||||
assert(false);
|
||||
int64_t ret = val(pop(_s)) + val(pop(_s));
|
||||
push(_s, makeNumCell(ret));
|
||||
int64_t ret = Handle::pop(_s).val() + Handle::pop(_s).val();
|
||||
Handle::push(_s, Handle::makeNumCell(ret));
|
||||
} else if (poppedH == CONS) {
|
||||
MCHandle h1 = pop(_s);
|
||||
MCHandle h2 = pop(_s);
|
||||
Handle h1 = Handle::pop(_s);
|
||||
Handle h2 = Handle::pop(_s);
|
||||
|
||||
push(_s, cons(h1, h2));
|
||||
Handle::push(_s, Handle::cons(h1, h2));
|
||||
} else if (poppedH == READCHAR) {
|
||||
char c;
|
||||
_instream >> c;
|
||||
push(_s, makeNumCell(c));
|
||||
Handle::push(_s, Handle::makeNumCell(c));
|
||||
} else if (poppedH == PUTCHAR) {
|
||||
_outstream << (char) val(pop(_s));
|
||||
_outstream << (char) Handle::pop(_s).val();
|
||||
} else if (poppedH == PUTNUM) {
|
||||
_outstream << val(pop(_s));
|
||||
_outstream << Handle::pop(_s).val();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -4,89 +4,98 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "ConsUtils.h"
|
||||
#include "MemoryContext.h"
|
||||
|
||||
using namespace ConsUtils;
|
||||
|
||||
TEST(GCTest, GCTest) {
|
||||
MemoryContext mc;
|
||||
{
|
||||
MCHandle c = cons(nullptr, nullptr);
|
||||
Handle c = Handle::cons(nullptr, nullptr);
|
||||
mc.request_gc_and_wait();
|
||||
append(c, makeNumCell(1));
|
||||
append(c, makeNumCell(2));
|
||||
Handle::append(c, Handle::makeNumCell(1));
|
||||
Handle::append(c, Handle::makeNumCell(2));
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(val(car(c)), 1);
|
||||
EXPECT_EQ(val(car(cdr(c))), 2);
|
||||
EXPECT_EQ(c.car().val(), 1);
|
||||
EXPECT_EQ(c.cdr().car().val(), 2);
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
{
|
||||
MCHandle c = cons(nullptr, nullptr);
|
||||
Handle c = Handle::cons(nullptr, nullptr);
|
||||
mc.request_gc_and_wait();
|
||||
push(c, makeNumCell(1));
|
||||
push(c, makeNumCell(2));
|
||||
Handle::push(c, Handle::makeNumCell(1));
|
||||
Handle::push(c, Handle::makeNumCell(2));
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(val(car(c)), 2);
|
||||
EXPECT_EQ(val(car(cdr(c))), 1);
|
||||
EXPECT_EQ(c.car().val(), 2);
|
||||
EXPECT_EQ(c.cdr().car().val(), 1);
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
}
|
||||
|
||||
TEST(GCTest, GCTestAppend) {
|
||||
MemoryContext mc;
|
||||
for (int i = 0; i < 25000; i++) {
|
||||
MCHandle c = cons(nullptr, nullptr);
|
||||
Handle c = Handle::cons(nullptr, nullptr);
|
||||
mc.request_gc();
|
||||
append(c, makeNumCell(1));
|
||||
Handle::append(c, Handle::makeNumCell(1));
|
||||
mc.request_gc();
|
||||
EXPECT_EQ(val(car(c)), 1);
|
||||
EXPECT_EQ(c.car().val(), 1);
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
}
|
||||
TEST(GCTest, GCTestPop) {
|
||||
MemoryContext mc;
|
||||
{
|
||||
MCHandle c = cons(nullptr, nullptr);
|
||||
Handle c = Handle::cons(nullptr, nullptr);
|
||||
static constexpr int test_size = 20000;
|
||||
for (int i = 0; i < test_size; i++) {
|
||||
mc.request_gc();
|
||||
push(c, makeNumCell(i));
|
||||
Handle::push(c, Handle::makeNumCell(i));
|
||||
}
|
||||
for (int i = test_size - 1; i >= 0; i--) {
|
||||
mc.request_gc();
|
||||
EXPECT_EQ(i, val(pop(c)));
|
||||
EXPECT_EQ(i, Handle::pop(c).val());
|
||||
}
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
}
|
||||
|
||||
TEST(GCTest, GCTestAppend2) {
|
||||
MemoryContext mc;
|
||||
MCHandle c = cons(nullptr, nullptr);
|
||||
Handle c = Handle::cons(nullptr, nullptr);
|
||||
static constexpr int test_size = 2000;
|
||||
for (int i = 0; i < test_size; i++) {
|
||||
mc.request_gc();
|
||||
append(c, makeNumCell(i));
|
||||
Handle::append(c, Handle::makeNumCell(i));
|
||||
}
|
||||
for (int i = 0; i < test_size; i++) {
|
||||
mc.request_gc();
|
||||
EXPECT_EQ(i, val(pop(c)));
|
||||
EXPECT_EQ(i, Handle::pop(c).val());
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
}
|
||||
|
||||
TEST(GCTest, GCTestAppend3) {
|
||||
MemoryContext mc;
|
||||
for (int i = 0; i < 250000; i++) {
|
||||
Handle c = Handle::cons(nullptr, nullptr);
|
||||
Handle::append(c, Handle::makeNumCell(1));
|
||||
Handle::append(c, Handle::makeNumCell(2));
|
||||
mc.request_gc();
|
||||
Handle n = c.cdr();
|
||||
c.setcdr(nullptr);
|
||||
EXPECT_EQ(n.car().val(), 2);
|
||||
EXPECT_EQ(c.car().val(), 1);
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "ConsUtils.h"
|
||||
#include "VM.h"
|
||||
|
||||
TEST(VMTest, BasicHello) {
|
||||
@@ -9,12 +8,12 @@ TEST(VMTest, BasicHello) {
|
||||
{
|
||||
MemoryContext mc;
|
||||
VM vm(ssin, ssout);
|
||||
MCHandle newc(ConsUtils::cons(nullptr, nullptr));
|
||||
ConsUtils::append(newc, ConsUtils::makeStrCell("NIL"));
|
||||
ConsUtils::append(newc, ConsUtils::makeStrCell("LDC"));
|
||||
ConsUtils::append(newc, ConsUtils::makeNumCell('h'));
|
||||
ConsUtils::append(newc, ConsUtils::makeStrCell("PUTCHAR"));
|
||||
ConsUtils::append(newc, ConsUtils::makeStrCell("STOP"));
|
||||
Handle newc(Handle::cons(nullptr, nullptr));
|
||||
Handle::append(newc, Handle::makeStrCell("NIL"));
|
||||
Handle::append(newc, Handle::makeStrCell("LDC"));
|
||||
Handle::append(newc, Handle::makeNumCell('h'));
|
||||
Handle::append(newc, Handle::makeStrCell("PUTCHAR"));
|
||||
Handle::append(newc, Handle::makeStrCell("STOP"));
|
||||
vm.loadControl(newc);
|
||||
vm.run();
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ TEST(VMWithParserTest, RecFunction) {
|
||||
}
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
mc.request_gc_and_wait();
|
||||
EXPECT_EQ(mc.cell_count(), 0);
|
||||
ssout.flush();
|
||||
EXPECT_EQ(ssout.str(), "6765");
|
||||
|
||||
Reference in New Issue
Block a user