diff --git a/furvm/include/furvm/constant.hpp b/furvm/include/furvm/constant.hpp new file mode 100644 index 0000000..419aba5 --- /dev/null +++ b/furvm/include/furvm/constant.hpp @@ -0,0 +1,112 @@ +#ifndef FURVM_CONSTANT_HPP +#define FURVM_CONSTANT_HPP + +#include "furvm/fwd.hpp" + +#include +#include + +namespace furvm { + +/** + * @brief Bad constant access exception. + */ +class bad_constant_access : public std::exception { +public: + bad_constant_access() = default; + ~bad_constant_access() override = default; + + /** + * @brief Move constructor. + */ + bad_constant_access(bad_constant_access&&) noexcept = default; + + /** + * @brief Move constructor. + */ + bad_constant_access& operator=(bad_constant_access&&) noexcept = default; + + /** + * @brief Copy constructor. + */ + bad_constant_access(const bad_constant_access&) = default; + + /** + * @brief Copy constructor. + */ + bad_constant_access& operator=(const bad_constant_access&) = default; +public: + /** + * @brief Returns a C-style string describing the cause of the error. + * + * @return The cause of the error. + */ + const char* what() const noexcept override { return "bad constant access"; } +}; + +enum class constant_t : std::uint8_t { + String, /**< String constant. */ +}; + +class constant { +public: + using string_type = std::string_view; /**< String constant type. */ +public: + /** + * @brief Construct a new string constant. + * + * @param string String. + */ + constant(string_type string) + : m_type(constant_t::String), m_value(string) {} + + ~constant() = default; + + /** + * @brief Move constructor. + */ + constant(constant&&) = default; + + /** + * @brief Move constructor. + */ + constant& operator=(constant&&) = default; + + constant(const constant&) = delete; + constant& operator=(const constant&) = delete; +public: + /** + * @brief Returns this constant's type. + * @see constant_t + * + * @return The constant type. + */ + constexpr constant_t type() const { return m_type; } + + /** + * @brief Returns this constant's string value. + * @throws bad_constant_access if this constant's type is not constant_t::String. + * + * @return The string value. + */ + constexpr string_type string() const { + require_type(constant_t::String); + return m_value.string; + } +private: + void require_type(constant_t type) const { + if (m_type != type) throw bad_constant_access(); + } +private: + constant_t m_type{}; + union value { + string_type string; + + value(string_type sv) + : string(sv) {} + } m_value; +}; + +} // namespace furvm + +#endif // FURVM_CONSTANT_HPP \ No newline at end of file diff --git a/furvm/include/furvm/context.hpp b/furvm/include/furvm/context.hpp index 499c1f4..496ab47 100644 --- a/furvm/include/furvm/context.hpp +++ b/furvm/include/furvm/context.hpp @@ -1,14 +1,18 @@ #ifndef FURVM_CONTEXT_HPP #define FURVM_CONTEXT_HPP +#include "furvm/fwd.hpp" +#include "furvm/module.hpp" + +#include +#include +#include + namespace furvm { -/** - * @brief Context. - * - * A furvm context. - */ class context { +public: + using value_type = std::unique_ptr; public: context() = default; ~context() = default; @@ -25,7 +29,71 @@ public: context(const context&) = delete; context& operator=(const context&) = delete; +public: + /** + * @brief Adds a module to this context. + * + * @param args Arguments to forward to module's constructor. + * @return An index to the emplaced module. + */ + template >> + constexpr module_index emplace(Args&&... args) { + module_index index = m_modules.size(); + m_modules.emplace_back(std::make_unique(std::forward(args)...)); + return index; + } + + /** + * @brief Erases a module from this context. + * + * @param index Index to the module. + * @return Old value. + */ + value_type erase(module_index index) { + if (index >= m_modules.size()) return nullptr; + return std::move(m_modules[index]); + } + + /** + * @brief Returns a module of this context. + * + * @param index Position of the module. + * @return The module. + */ + constexpr value_type& operator[](module_index index) { return m_modules[index]; } + + /** + * @brief Returns a module of this context. + * + * @param index Position of the module. + * @return The module. + */ + constexpr const value_type& operator[](module_index index) const { return m_modules[index]; } + + /** + * @brief Returns a module of this context. + * + * @param index Position of the module. + * @return The module. + */ + constexpr value_type& at(module_index index) { return m_modules.at(index); } + + /** + * @brief Returns a module of this context. + * + * @param index Position of the module. + * @return The module. + */ + constexpr const value_type& at(module_index index) const { return m_modules.at(index); } + + /** + * @brief Returns how many does this context have modules. + * + * @return The module count. + */ + constexpr size_t size() const { return m_modules.size(); } private: + std::vector> m_modules; }; } // namespace furvm diff --git a/furvm/include/furvm/fwd.hpp b/furvm/include/furvm/fwd.hpp new file mode 100644 index 0000000..5b1a9ee --- /dev/null +++ b/furvm/include/furvm/fwd.hpp @@ -0,0 +1,74 @@ +#ifndef FURVM_FWD_HPP +#define FURVM_FWD_HPP + +#include // IWYU pragma: export +#include // IWYU pragma: export + +/** + * @brief Furlang's virtual machine. + */ +namespace furvm { + +// constant.hpp + +/** + * @brief Constant index. + * + * An index to the constant in module's constant pool. + */ +using constant_index = std::uint16_t; + +/** + * @enum constant_t + * @brief Constant type. + */ +enum class constant_t : std::uint8_t; + +/** + * @class constant + * @brief Constant. + */ +class constant; + +// instruction.hpp + +/** + * @enum instruction_t + * @brief Furvm's instruction type. + */ +enum class instruction_t : std::uint8_t; + +/** + * @struct instruction + * @brief Furvm's instruction. + */ +struct instruction; + +// module.hpp + +/** + * @class mod + * @brief Module. + * + * A furvm module. Translation unit of furlang. + */ +class mod; + +/** + * @brief Furvm module's index. + */ +using module_index = std::size_t; + +// context.hpp + +/** + * @class context + * @brief Context. + * + * A furvm context. + */ +class context; + +} // namespace furvm + +#endif // FURVM_FWD_HPP \ No newline at end of file diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp new file mode 100644 index 0000000..1e6b4f5 --- /dev/null +++ b/furvm/include/furvm/instruction.hpp @@ -0,0 +1,45 @@ +#ifndef FURVM_INSTRUCTION_HPP +#define FURVM_INSTRUCTION_HPP + +#include "furvm/fwd.hpp" + +namespace furvm { + +enum class instruction_t : std::uint8_t { + /** + * @brief No operation. + */ + NoOperation = 0, + + /** + * @brief Pushes a constant onto the stack. + * + * Pushes a constant from the constant pool denoted by two next bytes in low-endian onto the stack. + */ + PushConstant, + + /** + * @brief Pops top element from the stack. + */ + Drop, + + /** + * @brief Duplicates top element on the stack. + */ + Duplicate, +}; + +struct instruction { + instruction_t type; /**< Instruction type. */ + + /** + * @brief Instruction value. + */ + union value { + constant_index constant; /**< Constant instruction argument. */ + } value; /**< Instruction value. */ +}; + +} // namespace furvm + +#endif // FURVM_INSTRUCTION_HPP \ No newline at end of file diff --git a/furvm/include/furvm/module.hpp b/furvm/include/furvm/module.hpp new file mode 100644 index 0000000..5c67b30 --- /dev/null +++ b/furvm/include/furvm/module.hpp @@ -0,0 +1,28 @@ +#ifndef FURVM_MODULE_HPP +#define FURVM_MODULE_HPP + +namespace furvm { + +class mod { +public: + mod() = default; + ~mod() = default; + + /** + * @brief Move constructor. + */ + mod(mod&&) = default; + + /** + * @brief Move constructor. + */ + mod& operator=(mod&&) = default; + + mod(const mod&) = delete; + mod& operator=(const mod&) = delete; +private: +}; + +} // namespace furvm + +#endif // FURVM_MODULE_HPP \ No newline at end of file diff --git a/furvm/src/main.cpp b/furvm/src/main.cpp index 001cc5f..6b537b2 100644 --- a/furvm/src/main.cpp +++ b/furvm/src/main.cpp @@ -5,6 +5,8 @@ int main(void) { furvm::context context; + auto mainModule = context.emplace(); + return 0; } diff --git a/furvm/src/module.cpp b/furvm/src/module.cpp new file mode 100644 index 0000000..ce10db3 --- /dev/null +++ b/furvm/src/module.cpp @@ -0,0 +1,3 @@ +#include "furvm/module.hpp" + +namespace furvm {} \ No newline at end of file