This commit is contained in:
2024-01-03 17:03:06 +01:00
parent eeb6ca5f34
commit ddf7eeed4e
9 changed files with 134 additions and 36 deletions

View File

@@ -29,6 +29,8 @@ public:
static void set_out(std::ostream &out);
static void set_out_err(std::ostream &out_err);
static void reset();
private:
static Logger &get();

View File

@@ -44,3 +44,4 @@ void Logger::set_level(const std::string &tag, int level) { get()._levels[tag] =
void Logger::set_out(std::ostream &out) { get()._out = out; }
void Logger::set_out_err(std::ostream &out_err) { get()._out_err = out_err; }
void Logger::set_default_level(int level) { get()._default_level = level; }
void Logger::reset() { get()._levels = {}; }

View File

@@ -2,7 +2,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_library(vm src/VM.cpp src/Cell.cpp
src/Parser.cpp src/MemoryContext.cpp src/Handle.cpp src/Compiler.cpp)
src/Parser.cpp src/MemoryContext.cpp src/Handle.cpp src/Compiler.cpp src/Options.cpp)
target_link_libraries(vm PUBLIC logger)

View File

@@ -8,6 +8,8 @@
#include <unordered_map>
#include "Cell.h"
#include "Handle.h"
#include "Options.h"
namespace Command {
enum Command : CellValType {
@@ -40,9 +42,19 @@ namespace Command {
};
static inline std::unordered_map<std::string_view, CellValType> 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},
{"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}};
static inline std::unordered_map<CellValType, std::string> 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"}};
static inline Handle make_cmd(CellValType cmd) {
if (Options::get_bool("command_strs")) {
return Handle(cmd_to_str.at(cmd));
} else
return Handle(cmd);
};
};// namespace Command

View File

@@ -19,6 +19,7 @@
#include "Cell.h"
#include "Handle.h"
#include "Logger.h"
#include "Options.h"
class Handle;
@@ -72,17 +73,17 @@ private:
tcellnum = _temp_cells.size();
}
if ((_cells_num + tcellnum) >= (_cell_limit)) {
if ((_cells_num + tcellnum) >= (Options::get_int("cell_limit"))) {
// We might need to run GC twice as it has to process the messages;
Logger::log("MemoryContext", "Running forced gc", Logger::ERROR);
for (int i = 0; i < 3 && (_cells_num + tcellnum) >= (_cell_limit); i++) {
for (int i = 0; i < 3 && (_cells_num + tcellnum) >= (Options::get_int("cell_limit")); i++) {
request_gc_and_wait();
{
std::lock_guard tmplg(_new_roots_lock);
tcellnum = _temp_cells.size();
}
}
if ((_cells_num + tcellnum) >= (_cell_limit)) {
if ((_cells_num + tcellnum) >= (Options::get_int("cell_limit"))) {
Logger::log("MemoryContext", "Out of cells", Logger::ERROR);
throw std::runtime_error("Out of cells");
@@ -95,7 +96,7 @@ private:
std::lock_guard tmplg(_new_roots_lock);
Handle ret(cell);
_temp_cells.emplace_back(cell);
if ((_cells_num + _temp_cells.size() + 1) >= (size_t) (_cell_limit / 2)) { request_gc(); }
if ((_cells_num + _temp_cells.size() + 1) >= (size_t) (Options::get_int("cell_limit") / 2)) { request_gc(); }
return ret;
}
}
@@ -108,8 +109,6 @@ private:
std::atomic<size_t> _cells_num = 0;
std::list<Cell *> _temp_cells;
static constexpr size_t _cell_limit = {50000};
void gc_thread_entry();
std::map<Cell *, int64_t> _roots;

30
src/vm/include/Options.h Normal file
View File

@@ -0,0 +1,30 @@
//
// Created by stepus53 on 3.1.24.
//
#ifndef PSIL_OPTIONS_H
#define PSIL_OPTIONS_H
#include <string>
#include <unordered_map>
#include <variant>
class Options {
public:
static bool get_bool(const std::string &opt);
static size_t get_int(const std::string &opt);
static void set_bool(const std::string &opt, bool val);
static void set_int(const std::string &opt, size_t val);
static void reset();
private:
const static inline std::unordered_map<std::string, std::variant<size_t, bool>> _defaults{{"cell_limit", 50000U},
{"command_strs", false}};
std::unordered_map<std::string, std::variant<size_t, bool>> _current = _defaults;
static Options &get();
};
#endif//PSIL_OPTIONS_H

View File

@@ -25,10 +25,10 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
std::function<Handle(Handle, Handle)> compileArgsList = [&](Handle args, Handle env) {
Handle out;
out.append(Handle(NIL));
out.append(make_cmd(NIL));
while (!args.null()) {
out.splice(compile(args.car(), env));
out.append(Handle(CONS));
out.append(make_cmd(CONS));
args = args.cdr();
}
return out;
@@ -37,18 +37,18 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
Handle expr = src;
if (expr.null()) {
out.append(Handle(NIL));
out.append(make_cmd(NIL));
} else if (expr.atom()) {
if (expr.type() == CellType::NUMATOM) {
out.append(Handle(LDC));
out.append(make_cmd(LDC));
out.append(expr);
} else if (expr.type() == CellType::STRATOM) {
Handle idx = findIndex(expr, fake_env);
if (idx == nullptr) {
out.append(Handle(LDC));
out.append(make_cmd(LDC));
out.append(expr);
} else {
out.append(Handle(LD));
out.append(make_cmd(LD));
out.append(idx);
}
}
@@ -58,21 +58,21 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
if (car.atom()) {
if (car.strval() == "+") {
out.splice(compileArgsRaw(cdr));
out.append(Handle(ADD));
out.append(make_cmd(ADD));
} else if (car.strval() == "read") {
out.append(Handle(READ));
out.append(make_cmd(READ));
} else if (car.strval() == "lambda") {
out.append(Handle(LDF));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car(), fake_env), Handle(RET)));
out.append(make_cmd(LDF));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car(), fake_env), make_cmd(RET)));
} else if (car.strval() == "if") {
out.splice(compile(cdr.car(), fake_env));
out.append(Handle(SEL));
out.append(compile(cdr.cdr().car(), fake_env, Handle(JOIN)));
out.append(compile(cdr.cdr().cdr().car(), fake_env, Handle(JOIN)));
out.append(make_cmd(SEL));
out.append(compile(cdr.cdr().car(), fake_env, make_cmd(JOIN)));
out.append(compile(cdr.cdr().cdr().car(), fake_env, make_cmd(JOIN)));
} else if (car.strval() == "define") {
fake_env.car().append(Handle(std::string(cdr.car().car().strval())));
out.append(Handle(LDG));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car().cdr(), fake_env), Handle(RET)));
out.append(make_cmd(LDG));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car().cdr(), fake_env), make_cmd(RET)));
} else if (car.strval() == "let" || car.strval() == "letrec") {
std::vector<std::pair<Handle, Handle>> argBody;
@@ -93,27 +93,27 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
Handle newenv = Handle::cons(argNames, fake_env);
if (car.strval() == "let") {
out.splice(compileArgsList(argBodies, fake_env));
out.append(Handle(LDF));
out.append(compile(body, newenv, Handle(RET)));
out.append(Handle(AP));
out.append(make_cmd(LDF));
out.append(compile(body, newenv, make_cmd(RET)));
out.append(make_cmd(AP));
} else if (car.strval() == "letrec") {
out.append(Handle(DUM));
out.append(make_cmd(DUM));
out.splice(compileArgsList(argBodies, newenv));
out.append(Handle(LDF));
out.append(compile(body, newenv, Handle(RET)));
out.append(Handle(RAP));
out.append(make_cmd(LDF));
out.append(compile(body, newenv, make_cmd(RET)));
out.append(make_cmd(RAP));
}
} else {
out.splice(compileArgsList(cdr, fake_env));
out.append(Handle(LD));
out.append(make_cmd(LD));
Handle idx = findIndex(car, fake_env);
out.append(idx);
out.append(Handle(AP));
out.append(make_cmd(AP));
}
} else {
out.splice(compileArgsList(cdr, fake_env));
out.splice(compile(car, fake_env, Handle(AP)));
out.splice(compile(car, fake_env, make_cmd(AP)));
}
}
out.splice(suffix);

37
src/vm/src/Options.cpp Normal file
View File

@@ -0,0 +1,37 @@
//
// Created by stepus53 on 3.1.24.
//
#include "Options.h"
#include <stdexcept>
Options &Options::get() {
static Options opts;
return opts;
}
bool Options::get_bool(const std::string &opt) {
Options &o = get();
if (_defaults.find(opt) == _defaults.end()) throw std::invalid_argument("Unknown option " + opt);
if (!std::holds_alternative<bool>(_defaults.at(opt))) throw std::invalid_argument("Bad option type " + opt);
return std::get<bool>(o._current.at(opt));
}
size_t Options::get_int(const std::string &opt) {
Options &o = get();
if (_defaults.find(opt) == _defaults.end()) throw std::invalid_argument("Unknown option " + opt);
if (!std::holds_alternative<size_t>(_defaults.at(opt))) throw std::invalid_argument("Bad option type " + opt);
return std::get<size_t>(o._current.at(opt));
}
void Options::set_bool(const std::string &opt, bool val) {
Options &o = get();
if (_defaults.find(opt) == _defaults.end()) throw std::invalid_argument("Unknown option " + opt);
if (!std::holds_alternative<bool>(_defaults.at(opt))) throw std::invalid_argument("Bad option type " + opt);
o._current[opt] = val;
}
void Options::set_int(const std::string &opt, size_t val) {
Options &o = get();
if (_defaults.find(opt) == _defaults.end()) throw std::invalid_argument("Unknown option " + opt);
if (!std::holds_alternative<size_t>(_defaults.at(opt))) throw std::invalid_argument("Bad option type " + opt);
o._current[opt] = val;
}
void Options::reset() { get()._current = _defaults; }

View File

@@ -4,9 +4,27 @@
#include <gtest/gtest.h>
#include "MemoryContext.h"
#include "Options.h"
#include "Parser.h"
#include "VM.h"
class Environment : public ::testing::Environment {
public:
~Environment() override {}
void SetUp() override {
Options::set_bool("command_strs", true);
Logger::set_level("Compiler", Logger::DEBUG);
}
void TearDown() override {
Options::reset();
Logger::reset();
}
};
testing::Environment *const env = testing::AddGlobalTestEnvironment(new Environment);
TEST(CompilerTest, BasicHello) {
std::stringstream ssin;
std::stringstream ssout;
@@ -146,7 +164,6 @@ TEST(CompilerTest, GlobalDefineFnRec) {
std::stringstream ssin;
std::stringstream ssout;
{
VM vm(ssin, ssout);
Parser parser;
parser.loadStr(