move stuff to Handle

This commit is contained in:
2023-12-27 00:11:31 +01:00
parent 6829aabfa6
commit f6a59c85e8
14 changed files with 257 additions and 250 deletions

View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -19,7 +19,7 @@ struct Cell;
class Parser {
public:
void loadStr(std::string_view input);
MCHandle parseExpr();
Handle parseExpr();
private:
class Tokenizer {

View File

@@ -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

View File

@@ -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
View 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();
});
}

View File

@@ -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";
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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");