chore(furdb): initialize furdb

This commit is contained in:
2026-08-12 14:17:16 +02:00
parent c68763f785
commit d419b62225
7 changed files with 222 additions and 0 deletions
+1
View File
@@ -16,6 +16,7 @@ add_subdirectory(furvm)
add_subdirectory(furc)
add_subdirectory(furas)
add_subdirectory(disfuras)
add_subdirectory(furdb)
if(DOXYGEN_FOUND)
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/docs)
+5
View File
@@ -0,0 +1,5 @@
file(GLOB_RECURSE FURDB_SRCS "src/**.cpp")
file(GLOB_RECURSE FURDB_HDRS "include/**.hpp")
add_executable(furdb ${FURDB_SRCS} ${FURDB_HDRS})
target_include_directories(furdb PRIVATE include/)
target_link_libraries(furdb PUBLIC furlang libfurc libfurvm)
+39
View File
@@ -0,0 +1,39 @@
#ifndef COMMAND_HPP
#define COMMAND_HPP
#include "context.hpp"
#include <string_view>
#include <vector>
struct command_info {
std::string_view commandName;
std::vector<std::string_view> args;
};
class command {
public:
command() = default;
virtual ~command() = default;
command(command&&) noexcept = default;
command& operator=(command&&) noexcept = default;
command(const command&) = delete;
command& operator=(const command&) = delete;
public:
virtual void execute(context& ctx, const command_info& info) = 0;
public:
static command_info parse(std::string_view line);
};
class quit_command final : public command {
public:
void execute(context& ctx, const command_info& info) override;
};
class run_command final : public command {
public:
void execute(context& ctx, const command_info& info) override;
};
#endif // COMMAND_HPP
+20
View File
@@ -0,0 +1,20 @@
#ifndef CONTEXT_HPP
#define CONTEXT_HPP
#include <furvm/context.hpp>
#include <furvm/executor.hpp>
#include <furvm/fwd.hpp>
#include <furvm/module.hpp>
struct context {
furvm::context_p context = std::make_shared<furvm::context>();
furvm::mod_h mod;
furvm::executor_h executor;
furvm::function_h mainFunction;
bool running = true;
void run();
};
#endif // CONTEXT_HPP
+55
View File
@@ -0,0 +1,55 @@
#include "command.hpp"
#include <cctype>
#include <cstddef>
#include <iostream>
#include <random>
#include <utility>
command_info command::parse(std::string_view line) {
command_info info;
while (!line.empty() && std::isspace(line.front()) != 0)
line = line.substr(1);
std::size_t length = 0;
while (line.size() > length && std::isalnum(line.at(length)) != 0)
++length;
info.commandName = line.substr(0, length);
line = line.substr(length);
while (true) {
while (!line.empty() && std::isspace(line.front()) != 0)
line = line.substr(1);
if (line.empty()) break;
length = 0;
while (line.size() > length && std::isalnum(line.at(length)) != 0)
++length;
info.args.push_back(line.substr(0, length));
line = line.substr(length);
}
return std::move(info);
}
void quit_command::execute(context& ctx, const command_info& info) {
static std::random_device s_rd;
static std::mt19937 s_gen(s_rd());
static std::uniform_int_distribution<> s_dis(1, 1000);
int roll = s_dis(s_gen);
std::cout << "Farewell";
if (roll == 1) {
std::cout << ", stasiu pensive";
} else if (roll <= 100) {
std::cout << ", kromek-man";
}
std::cout << "!\n";
ctx.running = false;
}
void run_command::execute(context& ctx, const command_info& info) {
ctx.run();
std::cout << "Execution finished\n";
}
+9
View File
@@ -0,0 +1,9 @@
#include "context.hpp"
void context::run() {
if ((executor->flags() & furvm::executor_flags::Done) != furvm::executor_flags::Done)
executor->push_frame(mod, *mainFunction);
while ((executor->flags() & furvm::executor_flags::Done) != furvm::executor_flags::Done) {
executor->step();
}
}
+93
View File
@@ -0,0 +1,93 @@
#include "command.hpp"
#include "context.hpp"
#include "furvm/function.hpp"
#include <fstream>
#include <furvm/fwd.hpp>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
// taken from furvm uwu :3 ^^ nya~ ngh~
static void print_thing(const furvm::thing<furvm::thing_allocator>& thing) {
using namespace furvm;
switch (thing.true_type().type) {
case thing_type::S8: std::cout << thing.cast_to<thing_type::s16>(); break;
case thing_type::S16: std::cout << thing.get<thing_type::s16>(); break;
case thing_type::S32: std::cout << thing.get<thing_type::s32>(); break;
case thing_type::S64: std::cout << thing.get<thing_type::s64>(); break;
case thing_type::U8: std::cout << thing.get<thing_type::u8>(); break;
case thing_type::U16: std::cout << thing.get<thing_type::u16>(); break;
case thing_type::U32: std::cout << thing.get<thing_type::u32>(); break;
case thing_type::U64: std::cout << thing.get<thing_type::u64>(); break;
case thing_type::Array:
std::cout << "{ ";
for (thing_type::u64 i = 0; i < thing.length(); ++i) {
if (i > 0) std::cout << ", ";
print_thing(thing.at(i));
}
std::cout << " }";
break;
default: std::cerr << "{Type not recognized}";
}
}
// TODO: Argument parsing
// TODO: Multiple modules
int main(int argc, char** argv) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <module.fmod>\n";
return 1;
}
static std::unordered_map<std::string_view, command*> s_commands;
s_commands["quit"] = s_commands["q"] = new quit_command();
s_commands["run"] = s_commands["r"] = new run_command();
try {
std::ifstream file(argv[1], std::ios::binary | std::ios::in);
context ctx;
try {
ctx.mod = ctx.context->emplace(argv[1], furvm::mod::load(file));
} catch (std::exception ex) {
std::cerr << "Failed to load module " << argv[1] << ": " << ex.what() << '\n';
return 1;
}
ctx.executor = ctx.context->emplace_executor(ctx.context);
ctx.mainFunction = ctx.mod->function_at("main", furvm::function_sig{});
ctx.mod->set_native_function("println", [](furvm::executor& executor) {
auto arg = executor.load_thing(0);
print_thing(*arg);
std::cout << '\n';
});
std::string inputLine;
std::string prevInput;
while (ctx.running) {
std::swap(inputLine, prevInput);
std::cout << "(furdb) ";
if (!std::getline(std::cin, inputLine)) break;
if (inputLine.empty()) {
inputLine = prevInput;
}
auto info = command::parse(inputLine);
auto it = s_commands.find(info.commandName);
if (it == s_commands.end()) {
std::cerr << "Unknown command \"" << info.commandName << "\"\n";
continue;
}
it->second->execute(ctx, info);
}
} catch (const std::exception& ex) {
std::cerr << "Uncaught exception: " << ex.what() << '\n';
return 1;
}
return 0;
}