mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 10:47:49 +01:00
options
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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 = {}; }
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
30
src/vm/include/Options.h
Normal 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
|
||||
@@ -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
37
src/vm/src/Options.cpp
Normal 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; }
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user