From d419b62225b3b0fb10888d3336be3870b2129595 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Wed, 12 Aug 2026 14:17:16 +0200 Subject: [PATCH] chore(furdb): initialize furdb --- CMakeLists.txt | 1 + furdb/CMakeLists.txt | 5 +++ furdb/include/command.hpp | 39 ++++++++++++++++ furdb/include/context.hpp | 20 +++++++++ furdb/src/command.cpp | 55 +++++++++++++++++++++++ furdb/src/context.cpp | 9 ++++ furdb/src/main.cpp | 93 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 222 insertions(+) create mode 100644 furdb/CMakeLists.txt create mode 100644 furdb/include/command.hpp create mode 100644 furdb/include/context.hpp create mode 100644 furdb/src/command.cpp create mode 100644 furdb/src/context.cpp create mode 100644 furdb/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f808cf..0864963 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/furdb/CMakeLists.txt b/furdb/CMakeLists.txt new file mode 100644 index 0000000..f26f5a5 --- /dev/null +++ b/furdb/CMakeLists.txt @@ -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) diff --git a/furdb/include/command.hpp b/furdb/include/command.hpp new file mode 100644 index 0000000..37fb67d --- /dev/null +++ b/furdb/include/command.hpp @@ -0,0 +1,39 @@ +#ifndef COMMAND_HPP +#define COMMAND_HPP + +#include "context.hpp" + +#include +#include + +struct command_info { + std::string_view commandName; + std::vector 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 diff --git a/furdb/include/context.hpp b/furdb/include/context.hpp new file mode 100644 index 0000000..3eb2ec9 --- /dev/null +++ b/furdb/include/context.hpp @@ -0,0 +1,20 @@ +#ifndef CONTEXT_HPP +#define CONTEXT_HPP + +#include +#include +#include +#include + +struct context { + furvm::context_p context = std::make_shared(); + furvm::mod_h mod; + furvm::executor_h executor; + furvm::function_h mainFunction; + + bool running = true; + + void run(); +}; + +#endif // CONTEXT_HPP diff --git a/furdb/src/command.cpp b/furdb/src/command.cpp new file mode 100644 index 0000000..1eee327 --- /dev/null +++ b/furdb/src/command.cpp @@ -0,0 +1,55 @@ +#include "command.hpp" + +#include +#include +#include +#include +#include + +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"; +} diff --git a/furdb/src/context.cpp b/furdb/src/context.cpp new file mode 100644 index 0000000..9f4d1ee --- /dev/null +++ b/furdb/src/context.cpp @@ -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(); + } +} diff --git a/furdb/src/main.cpp b/furdb/src/main.cpp new file mode 100644 index 0000000..fad14e8 --- /dev/null +++ b/furdb/src/main.cpp @@ -0,0 +1,93 @@ +#include "command.hpp" +#include "context.hpp" +#include "furvm/function.hpp" + +#include +#include +#include +#include +#include +#include + +// taken from furvm uwu :3 ^^ nya~ ngh~ +static void print_thing(const furvm::thing& thing) { + using namespace furvm; + + switch (thing.true_type().type) { + case thing_type::S8: std::cout << thing.cast_to(); break; + case thing_type::S16: std::cout << thing.get(); break; + case thing_type::S32: std::cout << thing.get(); break; + case thing_type::S64: std::cout << thing.get(); break; + case thing_type::U8: std::cout << thing.get(); break; + case thing_type::U16: std::cout << thing.get(); break; + case thing_type::U32: std::cout << thing.get(); break; + case thing_type::U64: std::cout << thing.get(); 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] << " \n"; + return 1; + } + + static std::unordered_map 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; +}